66from collections import defaultdict
77from dataclasses import dataclass , field
88from pathlib import Path
9- from typing import Any , Iterable , List , Literal , TypeAlias , Union
9+ from typing import Any , Iterable , Literal , TypeAlias , Union
1010
1111from dbt_score .dbt_utils import dbt_ls
1212
@@ -156,6 +156,7 @@ def _get_columns(
156156
157157# Type annotation for parent references
158158ParentType = Union ["Model" , "Source" , "Snapshot" , "Seed" ]
159+ ChildType = Union ["Model" , "Snapshot" ]
159160
160161
161162@dataclass
@@ -184,6 +185,7 @@ class Model(HasColumnsMixin):
184185 tests: The list of tests attached to the model.
185186 depends_on: Dictionary of models/sources/macros that the model depends on.
186187 parents: The list of models, sources, and snapshots this model depends on.
188+ children: The list of models and snapshots that depend on this model.
187189 _raw_values: The raw values of the model (node) in the manifest.
188190 _raw_test_values: The raw test values of the model (node) in the manifest.
189191 """
@@ -209,7 +211,8 @@ class Model(HasColumnsMixin):
209211 tests : list [Test ] = field (default_factory = list )
210212 depends_on : dict [str , list [str ]] = field (default_factory = dict )
211213 constraints : list [Constraint ] = field (default_factory = list )
212- parents : List [ParentType ] = field (default_factory = list )
214+ parents : list [ParentType ] = field (default_factory = list )
215+ children : list [ChildType ] = field (default_factory = list )
213216 _raw_values : dict [str , Any ] = field (default_factory = dict )
214217 _raw_test_values : list [dict [str , Any ]] = field (default_factory = list )
215218
@@ -319,6 +322,7 @@ class Source(HasColumnsMixin):
319322 patch_path: The yml path of the source definition.
320323 tags: The list of tags attached to the source table.
321324 tests: The list of tests attached to the source table.
325+ children: The list of models and snapshots that depend on this source.
322326 _raw_values: The raw values of the source definition in the manifest.
323327 _raw_test_values: The raw test values of the source definition in the manifest.
324328 """
@@ -342,6 +346,7 @@ class Source(HasColumnsMixin):
342346 patch_path : str | None = None
343347 tags : list [str ] = field (default_factory = list )
344348 tests : list [Test ] = field (default_factory = list )
349+ children : list [ChildType ] = field (default_factory = list )
345350 _raw_values : dict [str , Any ] = field (default_factory = dict )
346351 _raw_test_values : list [dict [str , Any ]] = field (default_factory = list )
347352
@@ -424,6 +429,7 @@ class Snapshot(HasColumnsMixin):
424429 strategy: The strategy of the snapshot.
425430 unique_key: The unique key of the snapshot.
426431 parents: The list of models, sources, and snapshots this snapshot depends on.
432+ children: The list of models and snapshots that depend on this snapshot.
427433 _raw_values: The raw values of the snapshot (node) in the manifest.
428434 _raw_test_values: The raw test values of the snapshot (node) in the manifest.
429435 """
@@ -448,7 +454,8 @@ class Snapshot(HasColumnsMixin):
448454 depends_on : dict [str , list [str ]] = field (default_factory = dict )
449455 strategy : str | None = None
450456 unique_key : list [str ] | None = None
451- parents : List [ParentType ] = field (default_factory = list )
457+ parents : list [ParentType ] = field (default_factory = list )
458+ children : list [ChildType ] = field (default_factory = list )
452459 _raw_values : dict [str , Any ] = field (default_factory = dict )
453460 _raw_test_values : list [dict [str , Any ]] = field (default_factory = list )
454461
@@ -512,6 +519,7 @@ class Seed(HasColumnsMixin):
512519 patch_path: The yml path of the seed, e.g. `seeds.yml`.
513520 tags: The list of tags attached to the seed.
514521 tests: The list of tests attached to the seed.
522+ children: The list of models and snapshots that depend on this seed.
515523 _raw_values: The raw values of the seed (node) in the manifest.
516524 _raw_test_values: The raw test values of the seed (node) in the manifest.
517525 """
@@ -531,6 +539,7 @@ class Seed(HasColumnsMixin):
531539 patch_path : str | None = None
532540 tags : list [str ] = field (default_factory = list )
533541 tests : list [Test ] = field (default_factory = list )
542+ children : list [ChildType ] = field (default_factory = list )
534543 _raw_values : dict [str , Any ] = field (default_factory = dict )
535544 _raw_test_values : list [dict [str , Any ]] = field (default_factory = list )
536545
@@ -607,7 +616,7 @@ def __init__(self, file_path: Path, select: Iterable[str] | None = None):
607616 self ._load_sources ()
608617 self ._load_snapshots ()
609618 self ._load_seeds ()
610- self ._populate_parents ()
619+ self ._populate_relatives ()
611620
612621 if select :
613622 self ._filter_evaluables (select )
@@ -661,18 +670,22 @@ def _reindex_tests(self) -> None:
661670 ):
662671 self .tests [node_unique_id ].append (node_values )
663672
664- def _populate_parents (self ) -> None :
665- """Populate `parents` for all models and snapshots ."""
673+ def _populate_relatives (self ) -> None :
674+ """Populate `parents` and `children` for all evaluables ."""
666675 for node in list (self .models .values ()) + list (self .snapshots .values ()):
667676 for parent_id in node .depends_on .get ("nodes" , []):
668677 if parent_id in self .models :
669678 node .parents .append (self .models [parent_id ])
679+ self .models [parent_id ].children .append (node )
670680 elif parent_id in self .snapshots :
671681 node .parents .append (self .snapshots [parent_id ])
682+ self .snapshots [parent_id ].children .append (node )
672683 elif parent_id in self .sources :
673684 node .parents .append (self .sources [parent_id ])
685+ self .sources [parent_id ].children .append (node )
674686 elif parent_id in self .seeds :
675687 node .parents .append (self .seeds [parent_id ])
688+ self .seeds [parent_id ].children .append (node )
676689
677690 def _filter_evaluables (self , select : Iterable [str ]) -> None :
678691 """Filter evaluables like dbt's --select."""
0 commit comments