11from __future__ import annotations
22
3+ import fnmatch
34import typing as t
45from pathlib import Path
56
@@ -18,11 +19,19 @@ def __init__(
1819 state_reader : StateReader ,
1920 models : UniqueKeyDict [str , Model ],
2021 context_path : Path = Path ("." ),
22+ dag : t .Optional [DAG [str ]] = None ,
2123 ):
2224 self ._state_reader = state_reader
2325 self ._models = models
2426 self ._context_path = context_path
2527
28+ if dag is None :
29+ self ._dag : DAG [str ] = DAG ()
30+ for model in models .values ():
31+ self ._dag .add (model .name , model .depends_on )
32+ else :
33+ self ._dag = dag
34+
2635 def select_models (
2736 self ,
2837 model_selections : t .Iterable [str ],
@@ -58,8 +67,7 @@ def select_models(
5867 ).values ()
5968 }
6069
61- # TODO: Support selection expressions.
62- all_selected_models = set (model_selections )
70+ all_selected_models = self ._expand_model_selections (model_selections )
6371
6472 dag : DAG [str ] = DAG ()
6573 models : UniqueKeyDict [str , Model ] = UniqueKeyDict ("models" )
@@ -82,3 +90,35 @@ def select_models(
8290 update_model_schemas (dag , models , self ._context_path )
8391
8492 return models
93+
94+ def _expand_model_selections (self , model_selections : t .Iterable [str ]) -> t .Set [str ]:
95+ result : t .Set [str ] = set ()
96+
97+ def _add_model (model_name : str , include_upstream : bool , include_downstream : bool ) -> None :
98+ result .add (model_name )
99+ if include_upstream :
100+ result .update (self ._dag .upstream (model_name ))
101+ if include_downstream :
102+ result .update (self ._dag .downstream (model_name ))
103+
104+ for selection in model_selections :
105+ if not selection :
106+ continue
107+
108+ include_upstream = False
109+ include_downstream = False
110+ if selection [0 ] == "+" :
111+ selection = selection [1 :]
112+ include_upstream = True
113+ if selection [- 1 ] == "+" :
114+ selection = selection [:- 1 ]
115+ include_downstream = True
116+
117+ if "*" in selection :
118+ for name in self ._models :
119+ if fnmatch .fnmatch (name , selection ):
120+ _add_model (name , include_upstream , include_downstream )
121+ else :
122+ _add_model (selection , include_upstream , include_downstream )
123+
124+ return result
0 commit comments