hgraph 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. hgraph/__about__.py +1 -0
  2. hgraph/__init__.py +6 -0
  3. hgraph/_builder/__init__.py +7 -0
  4. hgraph/_builder/_builder.py +29 -0
  5. hgraph/_builder/_graph_builder.py +82 -0
  6. hgraph/_builder/_input_builder.py +21 -0
  7. hgraph/_builder/_node_builder.py +38 -0
  8. hgraph/_builder/_output_builder.py +21 -0
  9. hgraph/_builder/_scalar_builder.py +19 -0
  10. hgraph/_builder/_ts_builder.py +210 -0
  11. hgraph/_impl/__init__.py +4 -0
  12. hgraph/_impl/_builder/__init__.py +5 -0
  13. hgraph/_impl/_builder/_graph_builder.py +56 -0
  14. hgraph/_impl/_builder/_map_builder.py +44 -0
  15. hgraph/_impl/_builder/_node_builder.py +87 -0
  16. hgraph/_impl/_builder/_switch_builder.py +46 -0
  17. hgraph/_impl/_builder/_ts_builder.py +296 -0
  18. hgraph/_impl/_impl_configuration.py +9 -0
  19. hgraph/_impl/_runtime/__init__.py +6 -0
  20. hgraph/_impl/_runtime/_common.py +34 -0
  21. hgraph/_impl/_runtime/_evaluation_clock.py +140 -0
  22. hgraph/_impl/_runtime/_evaluation_engine.py +122 -0
  23. hgraph/_impl/_runtime/_graph.py +134 -0
  24. hgraph/_impl/_runtime/_graph_executor.py +54 -0
  25. hgraph/_impl/_runtime/_map_node.py +152 -0
  26. hgraph/_impl/_runtime/_node.py +334 -0
  27. hgraph/_impl/_runtime/_switch_node.py +116 -0
  28. hgraph/_impl/_types/__init__.py +9 -0
  29. hgraph/_impl/_types/_input.py +169 -0
  30. hgraph/_impl/_types/_output.py +92 -0
  31. hgraph/_impl/_types/_ref.py +207 -0
  32. hgraph/_impl/_types/_scalar_value.py +49 -0
  33. hgraph/_impl/_types/_signal.py +17 -0
  34. hgraph/_impl/_types/_ts.py +73 -0
  35. hgraph/_impl/_types/_tsb.py +175 -0
  36. hgraph/_impl/_types/_tsd.py +260 -0
  37. hgraph/_impl/_types/_tsl.py +168 -0
  38. hgraph/_impl/_types/_tss.py +252 -0
  39. hgraph/_impl/graph_construction.md +40 -0
  40. hgraph/_runtime/__init__.py +11 -0
  41. hgraph/_runtime/_constants.py +10 -0
  42. hgraph/_runtime/_evaluation_clock.py +169 -0
  43. hgraph/_runtime/_evaluation_engine.py +339 -0
  44. hgraph/_runtime/_global_state.py +83 -0
  45. hgraph/_runtime/_graph.py +86 -0
  46. hgraph/_runtime/_graph_executor.py +90 -0
  47. hgraph/_runtime/_graph_runner.py +51 -0
  48. hgraph/_runtime/_lifecycle.py +149 -0
  49. hgraph/_runtime/_map.py +450 -0
  50. hgraph/_runtime/_node.py +227 -0
  51. hgraph/_runtime/_switch.py +134 -0
  52. hgraph/_types/__init__.py +20 -0
  53. hgraph/_types/_ref_meta_data.py +89 -0
  54. hgraph/_types/_ref_type.py +54 -0
  55. hgraph/_types/_scalar_type_meta_data.py +643 -0
  56. hgraph/_types/_scalar_types.py +94 -0
  57. hgraph/_types/_scalar_value.py +56 -0
  58. hgraph/_types/_schema_type.py +128 -0
  59. hgraph/_types/_time_series_meta_data.py +58 -0
  60. hgraph/_types/_time_series_types.py +406 -0
  61. hgraph/_types/_ts_meta_data.py +83 -0
  62. hgraph/_types/_ts_signal_meta_data.py +46 -0
  63. hgraph/_types/_ts_type.py +38 -0
  64. hgraph/_types/_ts_type_var_meta_data.py +62 -0
  65. hgraph/_types/_tsb_meta_data.py +154 -0
  66. hgraph/_types/_tsb_type.py +290 -0
  67. hgraph/_types/_tsd_meta_data.py +98 -0
  68. hgraph/_types/_tsd_type.py +202 -0
  69. hgraph/_types/_tsl_meta_data.py +118 -0
  70. hgraph/_types/_tsl_type.py +172 -0
  71. hgraph/_types/_tss_meta_data.py +77 -0
  72. hgraph/_types/_tss_type.py +106 -0
  73. hgraph/_types/_type_meta_data.py +95 -0
  74. hgraph/_types/_typing_utils.py +24 -0
  75. hgraph/_wiring/__init__.py +10 -0
  76. hgraph/_wiring/_decorators.py +245 -0
  77. hgraph/_wiring/_graph_builder.py +89 -0
  78. hgraph/_wiring/_map_wiring_node.py +64 -0
  79. hgraph/_wiring/_source_code_details.py +14 -0
  80. hgraph/_wiring/_stub_wiring_node.py +95 -0
  81. hgraph/_wiring/_switch_wiring_node.py +45 -0
  82. hgraph/_wiring/_wiring.py +743 -0
  83. hgraph/_wiring/_wiring_context.py +61 -0
  84. hgraph/_wiring/_wiring_errors.py +152 -0
  85. hgraph/_wiring/_wiring_node_signature.py +215 -0
  86. hgraph/_wiring/_wiring_utils.py +101 -0
  87. hgraph/nodes/__init__.py +14 -0
  88. hgraph/nodes/_const.py +22 -0
  89. hgraph/nodes/_drop_dups.py +13 -0
  90. hgraph/nodes/_format.py +16 -0
  91. hgraph/nodes/_graph.py +9 -0
  92. hgraph/nodes/_math.py +35 -0
  93. hgraph/nodes/_operators.py +42 -0
  94. hgraph/nodes/_pass_through.py +10 -0
  95. hgraph/nodes/_print.py +19 -0
  96. hgraph/nodes/_record.py +30 -0
  97. hgraph/nodes/_replay.py +53 -0
  98. hgraph/nodes/_set_operators.py +35 -0
  99. hgraph/nodes/_stream_operators.py +30 -0
  100. hgraph/nodes/_tsd_operators.py +40 -0
  101. hgraph/nodes/_tsl_operators.py +20 -0
  102. hgraph/nodes/_write.py +32 -0
  103. hgraph/test/__init__.py +1 -0
  104. hgraph/test/_node_unit_tester.py +93 -0
  105. hgraph/test/testing.md +19 -0
  106. hgraph-0.0.1.dist-info/METADATA +42 -0
  107. hgraph-0.0.1.dist-info/RECORD +109 -0
  108. hgraph-0.0.1.dist-info/WHEEL +4 -0
  109. hgraph-0.0.1.dist-info/licenses/LICENSE +21 -0
hgraph/__about__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "0.0.1"
hgraph/__init__.py ADDED
@@ -0,0 +1,6 @@
1
+ from hgraph._builder import *
2
+ from hgraph._runtime import *
3
+ from hgraph._types import *
4
+ from hgraph._wiring import *
5
+ from hgraph._impl import *
6
+
@@ -0,0 +1,7 @@
1
+ from hgraph._builder._builder import *
2
+ from hgraph._builder._graph_builder import *
3
+ from hgraph._builder._input_builder import *
4
+ from hgraph._builder._node_builder import *
5
+ from hgraph._builder._output_builder import *
6
+ from hgraph._builder._scalar_builder import *
7
+ from hgraph._builder._ts_builder import *
@@ -0,0 +1,29 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import TypeVar, Generic
3
+
4
+ ITEM = TypeVar('ITEM')
5
+
6
+ __all__ = ("Builder",)
7
+
8
+
9
+ class Builder(ABC, Generic[ITEM]):
10
+ """
11
+ The builder is responsible for constructing and initialising the item type it is responsible for.
12
+ It is also responsible for destroying and cleaning up the resources associated to the item.
13
+ These can be thought of as life-cycle methods.
14
+ """
15
+
16
+ @abstractmethod
17
+ def make_instance(self, **kwargs) -> ITEM:
18
+ """
19
+ Create a new instance of the item.
20
+ And additional attributes required for construction are passed in as kwargs.
21
+ Actual instance of the builder will fix these args for all instances of builder for the type.
22
+ """
23
+
24
+ @abstractmethod
25
+ def release_instance(self, item: ITEM):
26
+ """
27
+ Release the item and it's resources.
28
+ """
29
+
@@ -0,0 +1,82 @@
1
+ import typing
2
+ from abc import abstractmethod
3
+ from dataclasses import dataclass
4
+
5
+ from hgraph._builder._builder import Builder
6
+ from hgraph._runtime._graph import Graph
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from hgraph._runtime._node import Node
10
+ from hgraph._builder._node_builder import NodeBuilder
11
+ from hgraph._types._scalar_types import SCALAR
12
+
13
+ __all__ = ("Edge", "GraphBuilder", "GraphBuilderFactory")
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class Edge:
18
+ src_node: int
19
+ output_path: tuple["SCALAR", ...]
20
+ dst_node: int
21
+ input_path: tuple["SCALAR", ...]
22
+
23
+
24
+ @dataclass(frozen=True)
25
+ class GraphBuilder(Builder["Graph"]):
26
+ node_builders: tuple["NodeBuilder", ...]
27
+ edges: tuple[Edge, ...]
28
+
29
+ @abstractmethod
30
+ def make_instance(self, graph_id: tuple[int, ...], parent_node: "Node" = None) -> "Graph":
31
+ """
32
+ Construct an instance of a graph. The id provided is the id for the graph instance to be constructed.
33
+ """
34
+
35
+ @abstractmethod
36
+ def release_instance(self, item: "Graph"):
37
+ """
38
+ Release resources constructed during the build process, plus the graph.
39
+ """
40
+
41
+
42
+ class GraphBuilderFactory:
43
+
44
+ _graph_builder_class: typing.Optional[typing.Type[GraphBuilder]] = None
45
+
46
+ @staticmethod
47
+ def default():
48
+ from hgraph._impl._builder._graph_builder import PythonGraphBuilder
49
+ return PythonGraphBuilder
50
+
51
+ @staticmethod
52
+ def is_declared() -> bool:
53
+ return GraphBuilderFactory._graph_builder_class is not None
54
+
55
+ @staticmethod
56
+ def declared() -> typing.Type[GraphBuilder]:
57
+ if GraphBuilderFactory._graph_builder_class is None:
58
+ raise RuntimeError("No graph builder type has been declared")
59
+ return GraphBuilderFactory._graph_builder_class
60
+
61
+ @staticmethod
62
+ def declare(cls: typing.Type[GraphBuilder]):
63
+ if GraphBuilderFactory._graph_builder_class is not None:
64
+ raise RuntimeError("A graph builder type has already been declared")
65
+ GraphBuilderFactory._graph_builder_class = cls
66
+
67
+ @staticmethod
68
+ def un_declare():
69
+ GraphBuilderFactory._graph_builder_class = None
70
+
71
+ @staticmethod
72
+ def make(node_builders: tuple["NodeBuilder", ...], edges: tuple[Edge, ...]) -> GraphBuilder:
73
+ """
74
+ Make a graph builder instance. If no graph builder class is declared, the default builder will be used.
75
+ :param node_builders: The node builders to use
76
+ :param edges: The edges to use for binding the node outputs to inputs.
77
+ :return: The GraphBuilder instance.
78
+ """
79
+ if GraphBuilderFactory.is_declared():
80
+ return GraphBuilderFactory.declared()(node_builders=node_builders, edges=edges)
81
+ else:
82
+ return GraphBuilderFactory.default()(node_builders=node_builders, edges=edges)
@@ -0,0 +1,21 @@
1
+ import typing
2
+
3
+ from _pytest.nodes import Node
4
+
5
+ from hgraph._builder._builder import Builder
6
+
7
+ if typing.TYPE_CHECKING:
8
+ from hgraph._types._time_series_types import TimeSeriesInput
9
+
10
+
11
+ __all__ = ('InputBuilder',)
12
+
13
+
14
+ class InputBuilder(Builder["TimeSeriesInput"]):
15
+
16
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
17
+ """One of owning_node or owning_input must be defined."""
18
+ pass
19
+
20
+ def release_instance(self, item: "TimeSeriesInput"):
21
+ pass
@@ -0,0 +1,38 @@
1
+ from abc import abstractmethod
2
+ from dataclasses import dataclass
3
+ from typing import Optional, Any, Mapping, List, Tuple, TypeVar
4
+
5
+ from hgraph._builder._builder import Builder
6
+ from hgraph._builder._input_builder import InputBuilder
7
+ from hgraph._builder._output_builder import OutputBuilder
8
+ from hgraph._runtime._node import NodeSignature, Node
9
+
10
+ __all__ = ("NodeBuilder",)
11
+
12
+
13
+ NODE = TypeVar("NODE", bound=Node)
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class NodeBuilder(Builder[NODE]):
18
+ node_ndx: int
19
+ signature: NodeSignature
20
+ scalars: Mapping[str, Any]
21
+ input_builder: Optional[InputBuilder] = None
22
+ output_builder: Optional[OutputBuilder] = None
23
+
24
+ @abstractmethod
25
+ def make_instance(self, owning_graph_id: tuple[int, ...]) -> NODE:
26
+ """
27
+ Construct an instance of a node. The id provided is the id for the node instance to be constructed.
28
+ """
29
+
30
+ @abstractmethod
31
+ def release_instance(self, item: NODE):
32
+ """
33
+ Release any resources constructed during the build process, plus the node.
34
+ """
35
+
36
+
37
+ # TODO: Need to ensure that each type of NodeBuilder is described in the abstract and a factory is provided
38
+ # to provide instances of the builder to allow us to support multiple engines.
@@ -0,0 +1,21 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from hgraph._builder._builder import Builder
4
+
5
+ if TYPE_CHECKING:
6
+ from hgraph._runtime._node import Node
7
+ from hgraph._types._time_series_types import TimeSeriesOutput
8
+
9
+
10
+ __all__ = ('OutputBuilder',)
11
+
12
+
13
+ class OutputBuilder(Builder["TimeSeriesOutput"]):
14
+
15
+ def make_instance(self, owning_node: "Node" = None, owning_output: "TimeSeriesOutput" = None) -> "TimeSeriesOutput":
16
+ """One of owning_node or owning_output must be defined."""
17
+ pass
18
+
19
+ def release_instance(self, item: "TimeSeriesOutput"):
20
+ pass
21
+
@@ -0,0 +1,19 @@
1
+ from typing import TYPE_CHECKING
2
+
3
+ from hgraph._builder._builder import Builder
4
+
5
+ if TYPE_CHECKING:
6
+ from hgraph._types._scalar_value import ScalarValue
7
+
8
+
9
+ __all__ = ('ScalarValueBuilder',)
10
+
11
+
12
+ class ScalarValueBuilder(Builder["ScalarValue"]):
13
+
14
+ def make_instance(self) -> "ScalarValue":
15
+ """A scalar value is a basic type"""
16
+ pass
17
+
18
+ def release_instance(self, item: "ScalarValue"):
19
+ pass
@@ -0,0 +1,210 @@
1
+ from abc import ABC, abstractmethod
2
+ from dataclasses import dataclass
3
+ from typing import Optional, TYPE_CHECKING
4
+
5
+ from _pytest.nodes import Node
6
+
7
+ from hgraph._builder._input_builder import InputBuilder
8
+ from hgraph._builder._output_builder import OutputBuilder
9
+
10
+ if TYPE_CHECKING:
11
+ from hgraph._types._scalar_type_meta_data import HgScalarTypeMetaData
12
+ from hgraph._types._time_series_meta_data import HgTimeSeriesTypeMetaData
13
+ from hgraph._types._time_series_types import TimeSeriesInput, TimeSeriesOutput
14
+ from hgraph._types._tsb_type import TimeSeriesSchema
15
+
16
+ __all__ = ("TSOutputBuilder", "TSInputBuilder", "TimeSeriesBuilderFactory", "TSSInputBuilder", "TSLOutputBuilder",
17
+ "TSLInputBuilder", "TSBOutputBuilder", "TSBInputBuilder", "TSSOutputBuilder", "TSSInputBuilder",
18
+ "TSSignalInputBuilder", "TSDOutputBuilder", "TSDInputBuilder")
19
+
20
+
21
+ @dataclass(frozen=True)
22
+ class TSOutputBuilder(OutputBuilder):
23
+
24
+ value_tp: "HgScalarTypeMetaData"
25
+
26
+ def make_instance(self, owning_node=None, owning_output=None) -> "TimeSeriesOutput":
27
+ pass
28
+
29
+ def release_instance(self, item: "TimeSeriesOutput"):
30
+ pass
31
+
32
+
33
+ @dataclass(frozen=True)
34
+ class TSInputBuilder(InputBuilder):
35
+
36
+ value_tp: "HgScalarTypeMetaData"
37
+
38
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
39
+ ...
40
+
41
+ def release_instance(self, item: "TimeSeriesInput"):
42
+ ...
43
+
44
+
45
+ class TSSignalInputBuilder(InputBuilder):
46
+
47
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
48
+ ...
49
+
50
+ def release_instance(self, item: "TimeSeriesInput"):
51
+ ...
52
+
53
+
54
+ @dataclass(frozen=True)
55
+ class TSBInputBuilder(InputBuilder):
56
+
57
+ schema: "TimeSeriesSchema"
58
+
59
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
60
+ ...
61
+
62
+ def release_instance(self, item: "TimeSeriesInput"):
63
+ ...
64
+
65
+
66
+ @dataclass(frozen=True)
67
+ class TSBOutputBuilder(OutputBuilder):
68
+
69
+ schema: "TimeSeriesSchema"
70
+
71
+ def make_instance(self, owning_node: Node = None, owning_output: "TimeSeriesOutput" = None) -> "TimeSeriesOutput":
72
+ ...
73
+
74
+ def release_instance(self, item: "TimeSeriesOutput"):
75
+ ...
76
+
77
+
78
+ @dataclass(frozen=True)
79
+ class TSLInputBuilder(InputBuilder):
80
+
81
+ value_tp: "HgTimeSeriesTypeMetaData"
82
+ size_tp: "HgScalarTypeMetaData"
83
+
84
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
85
+ ...
86
+
87
+ def release_instance(self, item: "TimeSeriesInput"):
88
+ ...
89
+
90
+
91
+ @dataclass(frozen=True)
92
+ class TSLOutputBuilder(OutputBuilder):
93
+
94
+ value_tp: "HgTimeSeriesTypeMetaData"
95
+ size_tp: "HgScalarTypeMetaData"
96
+
97
+ def make_instance(self, owning_node: Node = None, owning_output: "TimeSeriesOutput" = None) -> "TimeSeriesOutput":
98
+ ...
99
+
100
+ def release_instance(self, item: "TimeSeriesOutput"):
101
+ ...
102
+
103
+
104
+ class TSDInputBuilder(InputBuilder):
105
+
106
+ key_tp: "HgScalarTypeMetaData"
107
+ value_tp: "HgTimeSeriesTypeMetaData"
108
+
109
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
110
+ ...
111
+
112
+ def release_instance(self, item: "TimeSeriesInput"):
113
+ ...
114
+
115
+
116
+ @dataclass(frozen=True)
117
+ class TSDOutputBuilder(OutputBuilder):
118
+
119
+ key_tp: "HgScalarTypeMetaData"
120
+ value_tp: "HgTimeSeriesTypeMetaData"
121
+
122
+ def make_instance(self, owning_node: Node = None, owning_output: "TimeSeriesOutput" = None) -> "TimeSeriesOutput":
123
+ ...
124
+
125
+ def release_instance(self, item: "TimeSeriesOutput"):
126
+ ...
127
+
128
+
129
+ @dataclass(frozen=True)
130
+ class TSSOutputBuilder(OutputBuilder):
131
+
132
+ value_tp: "HgScalarTypeMetaData"
133
+
134
+ def make_instance(self, owning_node: Node = None, owning_output: "TimeSeriesOutput" = None) -> "TimeSeriesOutput":
135
+ ...
136
+
137
+ def release_instance(self, item: "TimeSeriesOutput"):
138
+ ...
139
+
140
+
141
+ @dataclass(frozen=True)
142
+ class TSSInputBuilder(InputBuilder):
143
+
144
+ value_tp: "HgScalarTypeMetaData"
145
+
146
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
147
+ ...
148
+
149
+ def release_instance(self, item: "TimeSeriesInput"):
150
+ ...
151
+
152
+
153
+ class REFInputBuilder(InputBuilder):
154
+ value_tp: "HgTimeSeriesTypeMetaData"
155
+
156
+ def make_instance(self, owning_node: Node = None, owning_input: "TimeSeriesInput" = None) -> "TimeSeriesInput":
157
+ ...
158
+
159
+ def release_instance(self, item: "TimeSeriesInput"):
160
+ ...
161
+
162
+
163
+ @dataclass(frozen=True)
164
+ class REFOutputBuilder(OutputBuilder):
165
+ value_tp: "HgTimeSeriesTypeMetaData"
166
+
167
+ def make_instance(self, owning_node: Node = None, owning_output: "TimeSeriesOutput" = None) -> "TimeSeriesOutput":
168
+ ...
169
+
170
+ def release_instance(self, item: "TimeSeriesOutput"):
171
+ ...
172
+
173
+
174
+ class TimeSeriesBuilderFactory:
175
+
176
+ _instance: Optional["TimeSeriesBuilderFactory"] = None
177
+
178
+ @staticmethod
179
+ def declare_default_factory():
180
+ from hgraph._impl._builder._ts_builder import PythonTimeSeriesBuilderFactory
181
+ TimeSeriesBuilderFactory.declare(PythonTimeSeriesBuilderFactory())
182
+
183
+ @staticmethod
184
+ def has_instance() -> bool:
185
+ return TimeSeriesBuilderFactory._instance is not None
186
+
187
+ @staticmethod
188
+ def instance() -> "TimeSeriesBuilderFactory":
189
+ if TimeSeriesBuilderFactory._instance is None:
190
+ raise RuntimeError("No time-series builder factory has been declared")
191
+ return TimeSeriesBuilderFactory._instance
192
+
193
+ @staticmethod
194
+ def declare(factory: "TimeSeriesBuilderFactory"):
195
+ if TimeSeriesBuilderFactory._instance is not None:
196
+ raise RuntimeError("A time-series builder factory has already been declared")
197
+ TimeSeriesBuilderFactory._instance = factory
198
+
199
+ @staticmethod
200
+ def un_declare():
201
+ TimeSeriesBuilderFactory._instance = None
202
+
203
+ @abstractmethod
204
+ def make_input_builder(self, value_tp: "HgTimeSeriesTypeMetaData") -> TSInputBuilder:
205
+ """Return an instance of an input builder for the given type"""
206
+
207
+ @abstractmethod
208
+ def make_output_builder(self, value_tp: "HgTimeSeriesTypeMetaData") -> TSOutputBuilder:
209
+ """Return an instance of an output builder for the given type"""
210
+
@@ -0,0 +1,4 @@
1
+ from hgraph._impl._builder import *
2
+ from hgraph._impl._runtime import *
3
+ from hgraph._impl._types import *
4
+ from hgraph._impl._impl_configuration import *
@@ -0,0 +1,5 @@
1
+ from hgraph._impl._builder._graph_builder import *
2
+ from hgraph._impl._builder._map_builder import *
3
+ from hgraph._impl._builder._node_builder import *
4
+ from hgraph._impl._builder._switch_builder import *
5
+ from hgraph._impl._builder._ts_builder import *
@@ -0,0 +1,56 @@
1
+ from dataclasses import dataclass
2
+
3
+ from hgraph._builder._graph_builder import GraphBuilder
4
+ from hgraph._impl._runtime._graph import PythonGraph
5
+ from hgraph._runtime._graph import Graph
6
+ from hgraph._runtime._node import Node
7
+
8
+
9
+ __all__ = ("PythonGraphBuilder",)
10
+
11
+
12
+ @dataclass(frozen=True)
13
+ class PythonGraphBuilder(GraphBuilder):
14
+ """
15
+ Builds a graph (set of nodes with edges)
16
+ """
17
+
18
+ @staticmethod
19
+ def _extract_output(node: Node, path: [int]):
20
+ if not path:
21
+ raise RuntimeError("No path to find an output for")
22
+ output = node.output
23
+ for item in path:
24
+ output = output[item]
25
+ return output
26
+
27
+ @staticmethod
28
+ def _extract_input(node: Node, path: [int]):
29
+ if not path:
30
+ raise RuntimeError("No path to find an input for")
31
+ input = node.input
32
+ for item in path:
33
+ input = input[item]
34
+ return input
35
+
36
+ def make_instance(self, graph_id: tuple[int, ...], parent_node: Node = None) -> Graph:
37
+ nodes = [nb.make_instance(graph_id) for nb in self.node_builders]
38
+ for edge in self.edges:
39
+ src_node: Node = nodes[edge.src_node]
40
+ dst_node: Node = nodes[edge.dst_node]
41
+ # TODO: Should we normalise outputs to always be an UnnamedBundleOutput? For now if the path is tuple() assume
42
+ # the output is the node output
43
+ output = src_node.output if edge.output_path == tuple() else self._extract_output(src_node, edge.output_path)
44
+ input_ = self._extract_input(dst_node, edge.input_path)
45
+ input_.bind_output(output)
46
+ # The nodes are initialised within the context of the graph
47
+ return PythonGraph(graph_id=graph_id, nodes=tuple(nodes), parent_node=parent_node)
48
+
49
+ def release_instance(self, item: Graph):
50
+ for node, node_builder in zip(item.nodes, self.node_builders):
51
+ node_builder.release_instance(node)
52
+ item.dispose()
53
+
54
+
55
+
56
+
@@ -0,0 +1,44 @@
1
+ from dataclasses import dataclass
2
+ from typing import TYPE_CHECKING, Mapping, cast
3
+
4
+ from hgraph._builder._node_builder import NodeBuilder
5
+ from hgraph._impl._runtime._map_node import PythonMapNodeImpl
6
+ from hgraph._types._time_series_types import TimeSeriesOutput
7
+ from hgraph._types._tsb_type import TimeSeriesBundleInput
8
+
9
+ if TYPE_CHECKING:
10
+ from hgraph._builder._graph_builder import GraphBuilder
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class PythonMapNodeBuilder(NodeBuilder):
15
+ nested_graph: "GraphBuilder" = None # This is the generator function
16
+ input_node_ids: Mapping[str, int] = None # The nodes representing the stub inputs in the nested graph.
17
+ output_node_id: int = None # The node representing the stub output in the nested graph.
18
+ multiplexed_args: frozenset[str] =None # The inputs that need to be de-multiplexed.
19
+
20
+ def make_instance(self, owning_graph_id: tuple[int, ...]) -> PythonMapNodeImpl:
21
+ node = PythonMapNodeImpl(
22
+ node_ndx=self.node_ndx,
23
+ owning_graph_id=owning_graph_id,
24
+ signature=self.signature,
25
+ scalars=self.scalars,
26
+ nested_graph_builder=self.nested_graph,
27
+ input_node_ids=self.input_node_ids,
28
+ output_node_id=self.output_node_id,
29
+ multiplexed_args=self.multiplexed_args
30
+ )
31
+
32
+ if self.input_builder:
33
+ ts_input: TimeSeriesBundleInput = cast(TimeSeriesBundleInput,
34
+ self.input_builder.make_instance(owning_node=node))
35
+ node.input = ts_input
36
+
37
+ if self.output_builder:
38
+ ts_output: TimeSeriesOutput = self.output_builder.make_instance(owning_node=node)
39
+ node.output = ts_output
40
+
41
+ return node
42
+
43
+ def release_instance(self, item: PythonMapNodeImpl):
44
+ pass
@@ -0,0 +1,87 @@
1
+ from dataclasses import dataclass
2
+ from typing import Callable
3
+
4
+ from hgraph._builder._node_builder import NodeBuilder
5
+ from hgraph._impl._runtime._node import NodeImpl, GeneratorNodeImpl, PythonPushQueueNodeImpl
6
+ from hgraph._types._time_series_types import TimeSeriesOutput
7
+ from hgraph._types._tsb_type import TimeSeriesBundleInput
8
+
9
+
10
+ __all__ = ("PythonNodeBuilder", "PythonGeneratorNodeBuilder", "PythonPushQueueNodeBuilder")
11
+
12
+
13
+ @dataclass(frozen=True)
14
+ class PythonNodeBuilder(NodeBuilder):
15
+ eval_fn: Callable = None # The eval fn must be supplied.
16
+ start_fn: Callable = None
17
+ stop_fn: Callable = None
18
+
19
+ def make_instance(self, owning_graph_id: tuple[int, ...]) -> NodeImpl:
20
+ node = NodeImpl(
21
+ node_ndx=self.node_ndx,
22
+ owning_graph_id=owning_graph_id,
23
+ signature=self.signature,
24
+ scalars=self.scalars,
25
+ eval_fn=self.eval_fn,
26
+ start_fn=self.start_fn,
27
+ stop_fn=self.stop_fn
28
+ )
29
+
30
+ if self.input_builder:
31
+ ts_input: TimeSeriesBundleInput = self.input_builder.make_instance(owning_node=node)
32
+ node.input = ts_input
33
+
34
+ if self.output_builder:
35
+ ts_output: TimeSeriesOutput = self.output_builder.make_instance(owning_node=node)
36
+ node.output = ts_output
37
+
38
+ return node
39
+
40
+ def release_instance(self, item: NodeImpl):
41
+ pass
42
+
43
+
44
+ @dataclass(frozen=True)
45
+ class PythonGeneratorNodeBuilder(NodeBuilder):
46
+ eval_fn: Callable = None # This is the generator function
47
+
48
+ def make_instance(self, owning_graph_id: tuple[int, ...]) -> GeneratorNodeImpl:
49
+ node = GeneratorNodeImpl(
50
+ node_ndx=self.node_ndx,
51
+ owning_graph_id=owning_graph_id,
52
+ signature=self.signature,
53
+ scalars=self.scalars,
54
+ eval_fn=self.eval_fn
55
+ )
56
+
57
+ if self.output_builder:
58
+ ts_output: TimeSeriesOutput = self.output_builder.make_instance(owning_node=node)
59
+ node.output = ts_output
60
+
61
+ return node
62
+
63
+ def release_instance(self, item: GeneratorNodeImpl):
64
+ pass
65
+
66
+
67
+ @dataclass(frozen=True)
68
+ class PythonPushQueueNodeBuilder(NodeBuilder):
69
+ eval_fn: Callable = None # This is the generator function
70
+
71
+ def make_instance(self, owning_graph_id: tuple[int, ...]) -> PythonPushQueueNodeImpl:
72
+ node = PythonPushQueueNodeImpl(
73
+ node_ndx=self.node_ndx,
74
+ owning_graph_id=owning_graph_id,
75
+ signature=self.signature,
76
+ scalars=self.scalars,
77
+ eval_fn=self.eval_fn
78
+ )
79
+
80
+ if self.output_builder:
81
+ ts_output: TimeSeriesOutput = self.output_builder.make_instance(owning_node=node)
82
+ node.output = ts_output
83
+
84
+ return node
85
+
86
+ def release_instance(self, item: PythonPushQueueNodeImpl):
87
+ pass