easylink 0.1.4__py3-none-any.whl → 0.1.6__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.
easylink/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.4"
1
+ __version__ = "0.1.6"
easylink/configuration.py CHANGED
@@ -97,7 +97,7 @@ class Config(LayeredConfigTree):
97
97
  def __init__(
98
98
  self,
99
99
  config_params: dict[str, Any],
100
- potential_schemas: list[PipelineSchema] | PipelineSchema = PIPELINE_SCHEMAS,
100
+ potential_schemas: PipelineSchema | list[PipelineSchema] = PIPELINE_SCHEMAS,
101
101
  ) -> None:
102
102
  super().__init__(layers=["initial_data", "default", "user_configured"])
103
103
  self.update(DEFAULT_ENVIRONMENT, layer="default")
@@ -1,11 +1,12 @@
1
- from easylink.pipeline_schema_constants import development, tests
1
+ from easylink.pipeline_schema_constants import development, testing
2
2
 
3
3
  ALLOWED_SCHEMA_PARAMS = {
4
4
  "development": development.SCHEMA_PARAMS,
5
5
  }
6
6
 
7
7
  TESTING_SCHEMA_PARAMS = {
8
- "integration": tests.SINGLE_STEP_SCHEMA_PARAMS,
9
- "combined_bad_topology": tests.BAD_COMBINED_TOPOLOGY_SCHEMA_PARAMS,
10
- "combined_bad_implementation_names": tests.BAD_COMBINED_TOPOLOGY_SCHEMA_PARAMS,
8
+ "integration": testing.SINGLE_STEP_SCHEMA_PARAMS,
9
+ "combine_bad_topology": testing.BAD_COMBINED_TOPOLOGY_SCHEMA_PARAMS,
10
+ "combine_bad_implementation_names": testing.BAD_COMBINED_TOPOLOGY_SCHEMA_PARAMS,
11
+ "nested_templated_steps": testing.NESTED_TEMPLATED_STEPS_SCHEMA_PARAMS,
11
12
  }
@@ -11,7 +11,14 @@ from easylink.graph_components import (
11
11
  OutputSlot,
12
12
  OutputSlotMapping,
13
13
  )
14
- from easylink.step import HierarchicalStep, InputStep, LoopStep, OutputStep, Step
14
+ from easylink.step import (
15
+ HierarchicalStep,
16
+ InputStep,
17
+ LoopStep,
18
+ OutputStep,
19
+ ParallelStep,
20
+ Step,
21
+ )
15
22
  from easylink.utilities.validation_utils import validate_input_file_dummy
16
23
 
17
24
  SINGLE_STEP_NODES = [
@@ -128,3 +135,85 @@ BAD_COMBINED_TOPOLOGY_NODES = [
128
135
  ]
129
136
 
130
137
  BAD_COMBINED_TOPOLOGY_SCHEMA_PARAMS = (BAD_COMBINED_TOPOLOGY_NODES, SINGLE_STEP_EDGES)
138
+
139
+
140
+ NESTED_TEMPLATED_STEPS_NODES = [
141
+ InputStep(),
142
+ LoopStep(
143
+ template_step=ParallelStep(
144
+ template_step=HierarchicalStep(
145
+ step_name="step_1",
146
+ input_slots=[
147
+ InputSlot(
148
+ name="step_1_main_input",
149
+ env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
150
+ validator=validate_input_file_dummy,
151
+ ),
152
+ ],
153
+ output_slots=[OutputSlot("step_1_main_output")],
154
+ nodes=[
155
+ Step(
156
+ step_name="step_1a",
157
+ input_slots=[
158
+ InputSlot(
159
+ name="step_1a_main_input",
160
+ env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
161
+ validator=validate_input_file_dummy,
162
+ ),
163
+ ],
164
+ output_slots=[OutputSlot("step_1a_main_output")],
165
+ ),
166
+ Step(
167
+ step_name="step_1b",
168
+ input_slots=[
169
+ InputSlot(
170
+ name="step_1b_main_input",
171
+ env_var="DUMMY_CONTAINER_MAIN_INPUT_FILE_PATHS",
172
+ validator=validate_input_file_dummy,
173
+ ),
174
+ ],
175
+ output_slots=[OutputSlot("step_1b_main_output")],
176
+ ),
177
+ ],
178
+ edges=[
179
+ EdgeParams(
180
+ source_node="step_1a",
181
+ target_node="step_1b",
182
+ output_slot="step_1a_main_output",
183
+ input_slot="step_1b_main_input",
184
+ ),
185
+ ],
186
+ input_slot_mappings=[
187
+ InputSlotMapping(
188
+ parent_slot="step_1_main_input",
189
+ child_node="step_1a",
190
+ child_slot="step_1a_main_input",
191
+ ),
192
+ ],
193
+ output_slot_mappings=[
194
+ OutputSlotMapping(
195
+ parent_slot="step_1_main_output",
196
+ child_node="step_1b",
197
+ child_slot="step_1b_main_output",
198
+ ),
199
+ ],
200
+ ),
201
+ ),
202
+ self_edges=[
203
+ EdgeParams(
204
+ source_node="step_1",
205
+ target_node="step_1",
206
+ output_slot="step_1_main_output",
207
+ input_slot="step_1_main_input",
208
+ ),
209
+ ],
210
+ ),
211
+ OutputStep(
212
+ input_slots=[
213
+ InputSlot(name="result", env_var=None, validator=validate_input_file_dummy)
214
+ ],
215
+ ),
216
+ ]
217
+
218
+
219
+ NESTED_TEMPLATED_STEPS_SCHEMA_PARAMS = (NESTED_TEMPLATED_STEPS_NODES, SINGLE_STEP_EDGES)
easylink/step.py CHANGED
@@ -282,6 +282,17 @@ class Step:
282
282
  ) -> None:
283
283
  """Sets the configuration state for this ``Step``.
284
284
 
285
+ The so-called 'configuration state' for a given ``Step`` is backed up by
286
+ a :class:`ConfigurationState` class and is assigned to its :attr:`_configuration_state`
287
+ attribute. There are two possible ``ConfigurationStates``:
288
+ :class:`LeafConfigurationState` and :class:`NonLeafConfigurationState`.
289
+
290
+ This method sets the configuration state of this ``Step`` based on whether
291
+ or not a :attr:`config_key` is set *and exists is the ``Step's`` configuration*
292
+ (i.e. its portion of the user-suppled pipeline specification
293
+ file); any required deviation from this behavior requires special
294
+ handling.
295
+
285
296
  Parameters
286
297
  ----------
287
298
  parent_config
@@ -378,8 +389,9 @@ class Step:
378
389
  ) -> dict[str, list[str]]:
379
390
  """Validates a non-leaf ``Step``."""
380
391
  errors = {}
381
- for node in self.step_graph.nodes:
382
- step = self.step_graph.nodes[node]["step"]
392
+ nodes = self.step_graph.nodes
393
+ for node in nodes:
394
+ step = nodes[node]["step"]
383
395
  if isinstance(step, IOStep):
384
396
  continue
385
397
  if step.name not in step_config:
@@ -390,7 +402,7 @@ class Step:
390
402
  )
391
403
  if step_errors:
392
404
  errors.update(step_errors)
393
- extra_steps = set(step_config.keys()) - set(self.step_graph.nodes)
405
+ extra_steps = set(step_config.keys()) - set(nodes)
394
406
  for extra_step in extra_steps:
395
407
  errors[f"step {extra_step}"] = [f"{extra_step} is not a valid step."]
396
408
  return errors
@@ -807,12 +819,42 @@ class TemplatedStep(Step, ABC):
807
819
  The configuration for any implementations to be combined.
808
820
  input_data_config
809
821
  The input data configuration for the entire pipeline.
822
+
823
+ Notes
824
+ -----
825
+ A ``TemplatedStep`` is *always* assigned a :class:`NonLeafConfigurationState`
826
+ even if it has no multiplicity since (despite having no copies to make) we
827
+ still need to traverse the sub-``Steps`` to get to the one with a single
828
+ :class:`~easylink.implementation.Implementation`, i.e. the one with a
829
+ :class:`LeafConfigurationState`.
810
830
  """
811
- num_repeats = len(self._get_config(parent_config[self.name]))
812
- self.step_graph = self._update_step_graph(num_repeats)
813
- self.slot_mappings = self._update_slot_mappings(num_repeats)
814
- super().set_configuration_state(
815
- parent_config, combined_implementations, input_data_config
831
+ step_config = parent_config[self.name]
832
+ if self.config_key not in step_config:
833
+ # Special handle the step_graph update
834
+ self.step_graph = StepGraph()
835
+ self.template_step.name = self.name
836
+ self.step_graph.add_node_from_step(self.template_step)
837
+ # Special handle the slot_mappings update
838
+ input_mappings = [
839
+ InputSlotMapping(slot, self.name, slot) for slot in self.input_slots
840
+ ]
841
+ output_mappings = [
842
+ OutputSlotMapping(slot, self.name, slot) for slot in self.output_slots
843
+ ]
844
+ self.slot_mappings = {"input": input_mappings, "output": output_mappings}
845
+ # Add the key back to the expanded config
846
+ expanded_config = LayeredConfigTree({self.name: step_config})
847
+ else:
848
+ expanded_config = self._get_config(step_config)
849
+ num_repeats = len(expanded_config)
850
+ self.step_graph = self._update_step_graph(num_repeats)
851
+ self.slot_mappings = self._update_slot_mappings(num_repeats)
852
+ # Manually set the configuration state to non-leaf instead of relying
853
+ # on super().get_configuration_state() because that method will erroneously
854
+ # set to leaf state in the event the user didn't include the config_key
855
+ # in the pipeline specification.
856
+ self._configuration_state = NonLeafConfigurationState(
857
+ self, expanded_config, combined_implementations, input_data_config
816
858
  )
817
859
 
818
860
  def _duplicate_template_step(self) -> Step:
@@ -1105,9 +1147,10 @@ class ChoiceStep(Step):
1105
1147
  initial ones are handled.
1106
1148
 
1107
1149
  We update the :class:`easylink.graph_components.StepGraph` and ``SlotMappings``
1108
- here as opposed to in :meth:`set_configuration_state` (as is done in :class:`TemplatedStep`)
1109
- because ``ChoiceStep`` validation happens prior to setting the configuration
1110
- state and actually requires the ``StepGraph`` and ``SlotMappings``.
1150
+ in :meth:`validate_step` (as opposed to in :meth:`set_configuration_state`
1151
+ as is done in :class:`TemplatedStep`) because :meth:`validate_step` is called
1152
+ prior to :meth:`set_configuration_state`, but the validations itself actually
1153
+ requires the updated ``StepGraph`` and ``SlotMappings``.
1111
1154
 
1112
1155
  We do not attempt to validate the subgraph here if the 'type' key is unable
1113
1156
  to be validated.
@@ -1136,7 +1179,7 @@ class ChoiceStep(Step):
1136
1179
  ]
1137
1180
  }
1138
1181
 
1139
- # Handle the actual chosen step_config
1182
+ # HACK: Update the step graph and mappings here because we need them for validation
1140
1183
  self.step_graph = self._update_step_graph(subgraph)
1141
1184
  self.slot_mappings = self._update_slot_mappings(subgraph)
1142
1185
  # NOTE: A ChoiceStep is by definition non-leaf step
@@ -1163,11 +1206,11 @@ class ChoiceStep(Step):
1163
1206
 
1164
1207
  Notes
1165
1208
  -----
1166
- We update the :class:`~easylink.graph_components.StepGraph` and
1167
- :class:`SlotMappings<easylink.graph_components.SlotMapping>` in
1168
- :meth:`validate_step` as opposed to here (as is done with
1169
- :class:`TemplatedSteps<TemplatedStep>`) because ``ChoiceStep`` validation
1170
- happens prior to this but requires the ``StepGraph`` and ``SlotMappings``.
1209
+ We update the :class:`easylink.graph_components.StepGraph` and ``SlotMappings``
1210
+ in :meth:`validate_step` (as opposed to in :meth:`set_configuration_state`
1211
+ as is done in :class:`TemplatedStep`) because :meth:`validate_step` is called
1212
+ prior to :meth:`set_configuration_state`, but the validations itself actually
1213
+ requires the updated ``StepGraph`` and ``SlotMappings``.
1171
1214
  """
1172
1215
 
1173
1216
  chosen_parent_config = LayeredConfigTree(
@@ -1364,7 +1407,6 @@ class LeafConfigurationState(ConfigurationState):
1364
1407
  for mapping in mappings:
1365
1408
  imp_edge = mapping.remap_edge(edge)
1366
1409
  implementation_edges.append(imp_edge)
1367
-
1368
1410
  elif edge.target_node == self._step.name:
1369
1411
  mappings = [
1370
1412
  mapping
@@ -1520,7 +1562,6 @@ class NonLeafConfigurationState(ConfigurationState):
1520
1562
  new_step = self._step.step_graph.nodes[mapping.child_node]["step"]
1521
1563
  imp_edges = new_step.get_implementation_edges(new_edge)
1522
1564
  implementation_edges.extend(imp_edges)
1523
-
1524
1565
  elif edge.target_node == self._step.name:
1525
1566
  mappings = [
1526
1567
  mapping
@@ -1544,8 +1585,9 @@ class NonLeafConfigurationState(ConfigurationState):
1544
1585
  This method recursively traverses the ``StepGraph`` and sets the configuration
1545
1586
  state for each ``Step`` until reaching all leaf nodes.
1546
1587
  """
1547
- for node in self._step.step_graph.nodes:
1548
- step = self._step.step_graph.nodes[node]["step"]
1588
+ nodes = self._step.step_graph.nodes
1589
+ for node in nodes:
1590
+ step = nodes[node]["step"]
1549
1591
  step.set_configuration_state(
1550
1592
  self.pipeline_config, self.combined_implementations, self.input_data_config
1551
1593
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: easylink
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Research repository for the EasyLink ER ecosystem project.
5
5
  Home-page: https://github.com/ihmeuw/easylink
6
6
  Author: The EasyLink developers
@@ -1,8 +1,8 @@
1
1
  easylink/__about__.py,sha256=2-oxCfu9t9yUJouLDwqYRZ0eii8kN25SxRzsawjWjho,440
2
2
  easylink/__init__.py,sha256=gGMcIVfiVnHtlDw5mZwhevcDb2wt-kuP6F64gnkFack,159
3
- easylink/_version.py,sha256=Wzf5T3NBDfhQoTnhnRNHSlAsE0XMqbclXG-M81Vas70,22
3
+ easylink/_version.py,sha256=n3oM6B_EMz93NsTI18NNZd-jKFcUPzUkbIKj5VFK5ok,22
4
4
  easylink/cli.py,sha256=O0YvFnjxM3N8ox6wMi5-SSQZ6bS4_VcRT3apCIY7u0I,6117
5
- easylink/configuration.py,sha256=raF7-sRE4ImM85LIyetNcrMy0LXWGLkfBD58T_BowJM,12530
5
+ easylink/configuration.py,sha256=Ire2pMZNZ6wtSwhcWnQpYa-snX4KrhXgovlQwQ2Wxf4,12530
6
6
  easylink/graph_components.py,sha256=LIHLrASrppTr9XHUFZymtT9rE7_cFzCB1LVxyO3pCWk,11554
7
7
  easylink/implementation.py,sha256=1TFbsUxOkDkyyMtCwYQtA6uwZb5TawEw4CHjjSot0_s,8873
8
8
  easylink/implementation_metadata.yaml,sha256=VvlEu3Dvlmeh1MpzeYx91j22GiV-9mu3hZP5yVuW04o,6763
@@ -11,12 +11,12 @@ easylink/pipeline_graph.py,sha256=K8padPqQG6kSupYCQgbjYn_gs51tE1CmOvWmZ49EKLc,19
11
11
  easylink/pipeline_schema.py,sha256=ckvA4deRYalY5dLLbJDrO_pKttMuWnEUvSn5fSdu4jc,5900
12
12
  easylink/rule.py,sha256=dHr95tI4O39makPp9nEGFaIsGhOoa93RwuVzIVXUhak,7606
13
13
  easylink/runner.py,sha256=CSqYDWzY4pBvaklUUvj75UeJ4VxqwW9MYgcwGrAlspo,6222
14
- easylink/step.py,sha256=bui2J_V9J8Is2RUliOTacUHEJ01OyEA91oGL0au8_9I,60324
14
+ easylink/step.py,sha256=NCN1L5ojpfJ1CgV_Ih4duQL_aUFL3ri_XiNguH20JDE,62709
15
15
  easylink/images/spark_cluster/Dockerfile,sha256=3PHotbR4jdjVYRHOJ0VQW55b5Qd4tQ1pLLQMrTKWVA0,576
16
16
  easylink/images/spark_cluster/README.md,sha256=KdgSttZRplNNWqHn4K1GTsTIab3dTOSG4V99QPLxSp8,569
17
- easylink/pipeline_schema_constants/__init__.py,sha256=APGQ8iHgDgi76HByVRRM1cUfs0Q1uF1SwgbNglh60Is,378
17
+ easylink/pipeline_schema_constants/__init__.py,sha256=gVg8_0xv4FxG3B-Jy5MwiXIVntu4m36uCdA3ohVTN7w,460
18
18
  easylink/pipeline_schema_constants/development.py,sha256=WaS6EQzgCI6opnY-7OCHpT0JpP2OvRmYrWVdt_ND_bk,10915
19
- easylink/pipeline_schema_constants/tests.py,sha256=Vtj-1CB_uaEEQaZN0HZ79A8cKPQva9_fps-HfvM97Hw,3989
19
+ easylink/pipeline_schema_constants/testing.py,sha256=GUJtVGIzLd71j7hX_qaSuMT3FCxwFOGzZwWc_1Tbtsk,7016
20
20
  easylink/steps/dev/README.md,sha256=u9dZUggpY2Lf2qb-xkDLWWgHjcmi4osbQtzSNo4uklE,4549
21
21
  easylink/steps/dev/build-containers-local.sh,sha256=Wy3pfcyt7I-BNvHcr7ZXDe0g5Ihd00BIPqt9YuRbLeA,259
22
22
  easylink/steps/dev/build-containers-remote.sh,sha256=Hy-kaaXf-ta6n8SzOz_ahByjMY5T7J71MvzXRXDvQw8,271
@@ -41,8 +41,8 @@ easylink/utilities/general_utils.py,sha256=PSlTiHmafuI_dDSH0cW7iSCkTV0WgqX9ZgzlT
41
41
  easylink/utilities/paths.py,sha256=yl0cuWChJmB6YKMCQavTKw9jIl-VQhH6cnsM6D5c0Zk,599
42
42
  easylink/utilities/spark.smk,sha256=tQ7RArNQzhjbaBQQcRORB4IxxkuDx4gPHUBcWHDYJ_U,5795
43
43
  easylink/utilities/validation_utils.py,sha256=qOgn1n3_m5blFN7eHJ9MbOt5DkFA6DWucAOUAjvGvco,764
44
- easylink-0.1.4.dist-info/METADATA,sha256=rmjAl2vMMuK3pED9MWxpwDJbA39loKO6EZPAnsxUNrQ,2804
45
- easylink-0.1.4.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
46
- easylink-0.1.4.dist-info/entry_points.txt,sha256=OGMZDFltg3yMboT7XjJt3joiPhRfV_7jnREVtrAIQNU,51
47
- easylink-0.1.4.dist-info/top_level.txt,sha256=oHcOpcF_jDMWFiJRzfGQvuskENGDjSPC_Agu9Z_Xvik,9
48
- easylink-0.1.4.dist-info/RECORD,,
44
+ easylink-0.1.6.dist-info/METADATA,sha256=Jbmi6F9PaLYIOqs63ViVjqaO6-3StEA7d_PE5N1UYik,2804
45
+ easylink-0.1.6.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
46
+ easylink-0.1.6.dist-info/entry_points.txt,sha256=OGMZDFltg3yMboT7XjJt3joiPhRfV_7jnREVtrAIQNU,51
47
+ easylink-0.1.6.dist-info/top_level.txt,sha256=oHcOpcF_jDMWFiJRzfGQvuskENGDjSPC_Agu9Z_Xvik,9
48
+ easylink-0.1.6.dist-info/RECORD,,