13
13
import pathlib
14
14
import uuid
15
15
from enum import Enum
16
- from types import ModuleType
16
+ from types import FunctionType , ModuleType
17
17
from typing import Any , Callable , Collection , Dict , FrozenSet , List , Optional , Set , Tuple , Type
18
18
19
19
import hamilton .lifecycle .base as lifecycle_base
@@ -142,17 +142,18 @@ def update_dependencies(
142
142
return nodes
143
143
144
144
145
- def create_function_graph (
145
+ def compile_to_nodes (
146
146
* functions : List [Tuple [str , Callable ]],
147
147
config : Dict [str , Any ],
148
148
adapter : lifecycle_base .LifecycleAdapterSet = None ,
149
149
fg : Optional ["FunctionGraph" ] = None ,
150
- allow_module_overrides : bool = False ,
150
+ allow_node_leveL_overrides : bool = False ,
151
151
) -> Dict [str , node .Node ]:
152
152
"""Creates a graph of all available functions & their dependencies.
153
153
:param modules: A set of modules over which one wants to compute the function graph
154
154
:param config: Dictionary that we will inspect to get values from in building the function graph.
155
155
:param adapter: The adapter that adapts our node type checking based on the context.
156
+ :param allow_node_leveL_overrides: Whether or not to allow node names to override each other
156
157
:return: list of nodes in the graph.
157
158
If it needs to be more complicated, we'll return an actual networkx graph and get all the rest of the logic for free
158
159
"""
@@ -170,7 +171,7 @@ def create_function_graph(
170
171
for n in fm_base .resolve_nodes (f , config ):
171
172
if n .name in config :
172
173
continue # This makes sure we overwrite things if they're in the config...
173
- if n .name in nodes and not allow_module_overrides :
174
+ if n .name in nodes and not allow_node_leveL_overrides :
174
175
raise ValueError (
175
176
f"Cannot define function { n .name } more than once."
176
177
f" Already defined by function { f } "
@@ -713,13 +714,43 @@ def __init__(
713
714
self .nodes = nodes
714
715
self .adapter = adapter
715
716
717
+ @staticmethod
718
+ def compile (
719
+ modules : List [ModuleType ],
720
+ functions : List [FunctionType ],
721
+ config : Dict [str , Any ],
722
+ adapter : lifecycle_base .LifecycleAdapterSet = None ,
723
+ allow_node_overrides : bool = False ,
724
+ ) -> "FunctionGraph" :
725
+ """Base level static function for compiling a function graph. Note
726
+ that this can both use functions (E.G. passing them directly) and modules
727
+ (passing them in and crawling.
728
+
729
+ :param modules: Modules to use
730
+ :param functions: Functions to use
731
+ :param config: Config to use for setting up the DAG
732
+ :param adapter: Adapter to use for node resolution
733
+ :param allow_node_overrides: Whether or not to allow node level overrides.
734
+ :return: The compiled function graph
735
+ """
736
+ module_functions = sum ([find_functions (module ) for module in modules ], [])
737
+ nodes = compile_to_nodes (
738
+ * module_functions ,
739
+ * functions ,
740
+ config = config ,
741
+ adapter = adapter ,
742
+ allow_node_leveL_overrides = allow_node_overrides ,
743
+ )
744
+ return FunctionGraph (nodes , config , adapter )
745
+
716
746
@staticmethod
717
747
def from_modules (
718
748
* modules : ModuleType ,
719
749
config : Dict [str , Any ],
720
750
adapter : lifecycle_base .LifecycleAdapterSet = None ,
721
751
allow_module_overrides : bool = False ,
722
- ):
752
+ additional_functions : List [FunctionType ],
753
+ ) -> "FunctionGraph" :
723
754
"""Initializes a function graph from the specified modules. Note that this was the old
724
755
way we constructed FunctionGraph -- this is not a public-facing API, so we replaced it
725
756
with a constructor that takes in nodes directly. If you hacked in something using
@@ -732,28 +763,28 @@ def from_modules(
732
763
:return: a function graph.
733
764
"""
734
765
735
- functions = sum ([ find_functions ( module ) for module in modules ], [])
736
- return FunctionGraph . from_functions (
737
- * functions ,
766
+ return FunctionGraph . compile (
767
+ modules = modules ,
768
+ functions = [] ,
738
769
config = config ,
739
770
adapter = adapter ,
740
- allow_module_overrides = allow_module_overrides ,
771
+ allow_node_overrides = allow_module_overrides ,
741
772
)
742
773
743
774
@staticmethod
744
775
def from_functions (
745
- * functions ,
776
+ * functions : FunctionType ,
746
777
config : Dict [str , Any ],
747
778
adapter : lifecycle_base .LifecycleAdapterSet = None ,
748
779
allow_module_overrides : bool = False ,
749
780
) -> "FunctionGraph" :
750
- nodes = create_function_graph (
751
- * functions ,
781
+ return FunctionGraph .compile (
782
+ modules = [],
783
+ functions = functions ,
752
784
config = config ,
753
785
adapter = adapter ,
754
- allow_module_overrides = allow_module_overrides ,
786
+ allow_node_overrides = allow_module_overrides ,
755
787
)
756
- return FunctionGraph (nodes , config , adapter )
757
788
758
789
def with_nodes (self , nodes : Dict [str , Node ]) -> "FunctionGraph" :
759
790
"""Creates a new function graph with the additional specified nodes.
0 commit comments