easylink 0.1.9__py3-none-any.whl → 0.1.11__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.9"
1
+ __version__ = "0.1.11"
@@ -12,7 +12,8 @@ from __future__ import annotations
12
12
 
13
13
  from abc import ABC, abstractmethod
14
14
  from collections.abc import Callable
15
- from dataclasses import dataclass
15
+ from dataclasses import dataclass, field
16
+ from types import NotImplementedType
16
17
  from typing import TYPE_CHECKING, Any
17
18
 
18
19
  import networkx as nx
@@ -22,7 +23,7 @@ if TYPE_CHECKING:
22
23
  from easylink.step import Step
23
24
 
24
25
 
25
- @dataclass(frozen=True)
26
+ @dataclass()
26
27
  class InputSlot:
27
28
  """A single input slot to a specific node.
28
29
 
@@ -41,20 +42,48 @@ class InputSlot:
41
42
  env_var: str | None
42
43
  """The environment variable that is used to pass a list of data filepaths to
43
44
  an ``Implementation``."""
44
- validator: Callable[[str], None]
45
+ validator: Callable[[str], None] = field(compare=False)
45
46
  """A function that validates the input data being passed into the pipeline via
46
47
  this ``InputSlot``. If the data is invalid, the function should raise an exception
47
48
  with a descriptive error message which will then be reported to the user.
48
49
  **Note that the function *must* be defined in the** :mod:`easylink.utilities.validation_utils`
49
50
  **module!**"""
50
- splitter: Callable[[list[str], str, Any], None] | None = None
51
+ splitter: Callable[[list[str], str, Any], None] | None = field(
52
+ default=None, compare=False
53
+ )
51
54
  """A function that splits the incoming data to this ``InputSlot`` into smaller
52
55
  pieces. The primary purpose of this functionality is to run sections of the
53
56
  pipeline in an embarrassingly parallel manner. **Note that the function *must*
54
57
  be defined in the **:mod:`easylink.utilities.splitter_utils`** module!**"""
55
58
 
59
+ def __eq__(self, other: Any) -> bool | NotImplementedType:
60
+ """Checks if two ``InputSlots`` are equal.
56
61
 
57
- @dataclass(frozen=True)
62
+ Two ``InputSlots`` are considered equal if their names, ``env_vars``, and
63
+ names of their ``validators`` and ``splitters`` are all the same.
64
+ """
65
+ if not isinstance(other, InputSlot):
66
+ return NotImplemented
67
+ splitter_name = self.splitter.__name__ if self.splitter else None
68
+ other_splitter_name = other.splitter.__name__ if other.splitter else None
69
+ return (
70
+ self.name == other.name
71
+ and self.env_var == other.env_var
72
+ and self.validator.__name__ == other.validator.__name__
73
+ and splitter_name == other_splitter_name
74
+ )
75
+
76
+ def __hash__(self) -> int:
77
+ """Hashes an ``InputSlot``.
78
+
79
+ The hash is based on the name of the ``InputSlot``, its ``env_var``, and
80
+ the names of its ``validator`` and ``splitter``.
81
+ """
82
+ splitter_name = self.splitter.__name__ if self.splitter else None
83
+ return hash((self.name, self.env_var, self.validator.__name__, splitter_name))
84
+
85
+
86
+ @dataclass()
58
87
  class OutputSlot:
59
88
  """A single output slot from a specific node.
60
89
 
@@ -75,12 +104,32 @@ class OutputSlot:
75
104
 
76
105
  name: str
77
106
  """The name of the ``OutputSlot``."""
78
- aggregator: Callable[[list[str], str], None] = None
107
+ aggregator: Callable[[list[str], str], None] = field(default=None, compare=False)
79
108
  """A function that aggregates all of the generated data to be passed out via this
80
109
  ``OutputSlot``. The primary purpose of this functionality is to run sections
81
110
  of the pipeline in an embarrassingly parallel manner. **Note that the function
82
111
  *must* be defined in the **:py:mod:`easylink.utilities.aggregator_utils`** module!**"""
83
112
 
113
+ def __eq__(self, other: Any) -> bool | NotImplementedType:
114
+ """Checks if two ``OutputSlots`` are equal.
115
+
116
+ Two ``OutputSlots`` are considered equal if their names and the names of their
117
+ ``aggregators`` are the same.
118
+ """
119
+ if not isinstance(other, OutputSlot):
120
+ return NotImplemented
121
+ aggregator_name = self.aggregator.__name__ if self.aggregator else None
122
+ other_aggregator_name = other.aggregator.__name__ if other.aggregator else None
123
+ return self.name == other.name and aggregator_name == other_aggregator_name
124
+
125
+ def __hash__(self) -> int:
126
+ """Hashes an ``OutputSlot``.
127
+
128
+ The hash is based on the name of the ``OutputSlot`` and the name of its ``aggregator``.
129
+ """
130
+ aggregator_name = self.aggregator.__name__ if self.aggregator else None
131
+ return hash((self.name, aggregator_name))
132
+
84
133
 
85
134
  @dataclass(frozen=True)
86
135
  class EdgeParams:
@@ -13,7 +13,7 @@ from pathlib import Path
13
13
 
14
14
  from layered_config_tree import LayeredConfigTree
15
15
 
16
- from easylink.graph_components import EdgeParams
16
+ from easylink.graph_components import EdgeParams, ImplementationGraph
17
17
  from easylink.pipeline_schema_constants import ALLOWED_SCHEMA_PARAMS
18
18
  from easylink.step import HierarchicalStep, NonLeafConfigurationState, Step
19
19
 
@@ -54,6 +54,26 @@ class PipelineSchema(HierarchicalStep):
54
54
  def __repr__(self) -> str:
55
55
  return f"PipelineSchema.{self.name}"
56
56
 
57
+ def get_implementation_graph(self) -> ImplementationGraph:
58
+ """Gets the :class:`~easylink.graph_components.ImplementationGraph`.
59
+
60
+ The ``PipelineSchema`` is by definition a :class:`~easylink.step.HierarchicalStep`
61
+ which has a :class:`~easylink.graph_components.StepGraph` containing
62
+ sub-:class:`Steps<easylink.step.Step>` that need to be unrolled. This method
63
+ recursively traverses that ``StepGraph`` and its childrens' ``StepGraphs``
64
+ until all sub-``Steps`` are in a :class:`~easylink.step.LeafConfigurationState`,
65
+ i.e. all ``Steps`` are implemented by a single ``Implementation`` and we
66
+ have the desired ``ImplementationGraph``.
67
+
68
+ Returns
69
+ -------
70
+ The ``ImplementationGraph`` of this ``PipelineSchema``.
71
+ """
72
+ implementation_graph = ImplementationGraph()
73
+ self.add_nodes_to_implementation_graph(implementation_graph)
74
+ self.add_edges_to_implementation_graph(implementation_graph)
75
+ return implementation_graph
76
+
57
77
  def validate_step(
58
78
  self, pipeline_config: LayeredConfigTree, input_data_config: LayeredConfigTree
59
79
  ) -> dict[str, list[str]]:
easylink/step.py CHANGED
@@ -15,7 +15,6 @@ import copy
15
15
  from abc import ABC, abstractmethod
16
16
  from collections import defaultdict
17
17
  from collections.abc import Iterable
18
- from typing import Any
19
18
 
20
19
  from layered_config_tree import LayeredConfigTree
21
20
 
@@ -250,18 +249,25 @@ class Step:
250
249
  ]
251
250
  return errors
252
251
 
253
- def get_implementation_graph(self) -> ImplementationGraph:
254
- """Gets this ``Step's`` :class:`~easylink.graph_components.ImplementationGraph`.
252
+ def add_nodes_to_implementation_graph(
253
+ self, implementation_graph: ImplementationGraph
254
+ ) -> None:
255
+ """Adds the ``Implementations`` related to this ``Step`` as nodes to the :class:`~easylink.graph_components.ImplementationGraph`.
255
256
 
256
- The ``ImplementationGraph`` and how it is determined depends on whether
257
- this ``Step`` is a leaf or a non-leaf, i.e. what its :attr:`configuration_state`
258
- is.
257
+ How the nodes get added depends on whether this ``Step`` is a leaf or a non-leaf,
258
+ i.e. what its :attr:`configuration_state` is.
259
+ """
260
+ self.configuration_state.add_nodes_to_implementation_graph(implementation_graph)
259
261
 
260
- Returns
261
- -------
262
- The ``ImplementationGraph`` of this ``Step`` based on its ``configuration_state``.
262
+ def add_edges_to_implementation_graph(
263
+ self, implementation_graph: ImplementationGraph
264
+ ) -> None:
265
+ """Adds the edges of this ``Step's`` ``Implementation(s)`` to the :class:`~easylink.graph_components.ImplementationGraph`.
266
+
267
+ How the edges get added depends on whether this ``Step`` is a leaf or a non-leaf,
268
+ i.e. what its :attr:`configuration_state` is.
263
269
  """
264
- return self.configuration_state.get_implementation_graph()
270
+ self.configuration_state.add_edges_to_implementation_graph(implementation_graph)
265
271
 
266
272
  def get_implementation_edges(self, edge: EdgeParams) -> list[EdgeParams]:
267
273
  """Gets the edge information for the ``Implementation`` related to this ``Step``.
@@ -387,7 +393,7 @@ class IOStep(Step):
387
393
  The internal configuration of this ``Step``, i.e. it should not include
388
394
  the ``Step's`` name.
389
395
  combined_implementations
390
- The configuration for any implementations to be combined.
396
+ The configuration for any ``Implementations`` to be combined.
391
397
  input_data_config
392
398
  The input data configuration for the entire pipeline.
393
399
  """
@@ -395,8 +401,10 @@ class IOStep(Step):
395
401
  self, step_config, combined_implementations, input_data_config
396
402
  )
397
403
 
398
- def get_implementation_graph(self) -> ImplementationGraph:
399
- """Gets this ``Step's`` :class:`~easylink.graph_components.ImplementationGraph`.
404
+ def add_nodes_to_implementation_graph(
405
+ self, implementation_graph: ImplementationGraph
406
+ ) -> None:
407
+ """Adds this ``IOStep's`` ``Implementation`` as a node to the :class:`~easylink.graph_components.ImplementationGraph`.
400
408
 
401
409
  Notes
402
410
  -----
@@ -404,19 +412,22 @@ class IOStep(Step):
404
412
  via an :class:`~easylink.implementation.Implementation`. As such, we
405
413
  leverage the :class:`~easylink.implementation.NullImplementation` class
406
414
  to generate the graph node.
407
-
408
- Returns
409
- -------
410
- The ``ImplementationGraph`` of this ``Step``.
411
415
  """
412
- implementation_graph = ImplementationGraph()
413
416
  implementation_graph.add_node_from_implementation(
414
417
  self.name,
415
418
  implementation=NullImplementation(
416
419
  self.name, self.input_slots.values(), self.output_slots.values()
417
420
  ),
418
421
  )
419
- return implementation_graph
422
+
423
+ def add_edges_to_implementation_graph(self, implementation_graph):
424
+ """Adds the edges of this ``Step's`` ``Implementation`` to the ``ImplementationGraph``.
425
+
426
+ ``IOSteps`` do not have edges within them in the ``ImplementationGraph``,
427
+ since they are represented by a single ``NullImplementation`` node, and so we
428
+ simply pass.
429
+ """
430
+ pass
420
431
 
421
432
 
422
433
  class InputStep(IOStep):
@@ -1394,8 +1405,17 @@ class ConfigurationState(ABC):
1394
1405
  """The input data configuration for the entire pipeline."""
1395
1406
 
1396
1407
  @abstractmethod
1397
- def get_implementation_graph(self) -> ImplementationGraph:
1398
- """Resolves the graph composed of ``Steps`` into one composed of ``Implementations``."""
1408
+ def add_nodes_to_implementation_graph(
1409
+ self, implementation_graph: ImplementationGraph
1410
+ ) -> None:
1411
+ """Adds this ``Step's`` ``Implementation(s)`` as nodes to the :class:`~easylink.graph_components.ImplementationGraph`."""
1412
+ pass
1413
+
1414
+ @abstractmethod
1415
+ def add_edges_to_implementation_graph(
1416
+ self, implementation_graph: ImplementationGraph
1417
+ ) -> None:
1418
+ """Adds the edges of this ``Step's`` ``Implementation(s)`` to the :class:`~easylink.graph_components.ImplementationGraph`."""
1399
1419
  pass
1400
1420
 
1401
1421
  @abstractmethod
@@ -1438,19 +1458,16 @@ class LeafConfigurationState(ConfigurationState):
1438
1458
  else self.step_config.implementation
1439
1459
  )
1440
1460
 
1441
- def get_implementation_graph(self) -> ImplementationGraph:
1442
- """Gets this ``Step's`` :class:`~easylink.graph_components.ImplementationGraph`.
1461
+ def add_nodes_to_implementation_graph(
1462
+ self, implementation_graph: ImplementationGraph
1463
+ ) -> None:
1464
+ """Adds this ``Step's`` :class:`~easylink.implementation.Implementation` as a node to the :class:`~easylink.graph_components.ImplementationGraph`.
1443
1465
 
1444
1466
  A ``Step`` in a leaf configuration state by definition has no sub-``Steps``
1445
1467
  to unravel; we are able to directly instantiate an :class:`~easylink.implementation.Implementation`
1446
- and generate an ``ImplementationGraph`` from it.
1447
-
1448
- Returns
1449
- -------
1450
- The ``ImplementationGraph`` related to this ``Step``.
1468
+ and add it to the ``ImplementationGraph``.
1451
1469
  """
1452
1470
  step = self._step
1453
- implementation_graph = ImplementationGraph()
1454
1471
  if self.is_combined:
1455
1472
  if isinstance(step, EmbarrassinglyParallelStep):
1456
1473
  raise NotImplementedError(
@@ -1475,7 +1492,15 @@ class LeafConfigurationState(ConfigurationState):
1475
1492
  step.implementation_node_name,
1476
1493
  implementation=implementation,
1477
1494
  )
1478
- return implementation_graph
1495
+
1496
+ def add_edges_to_implementation_graph(self, implementation_graph) -> None:
1497
+ """Adds the edges for this ``Step's`` ``Implementation`` to the ``ImplementationGraph``.
1498
+
1499
+ ``Steps`` in a ``LeafConfigurationState`` do not actually have edges within them
1500
+ (they are represented by a single node in the ``ImplementationGraph``) and so
1501
+ we simply pass.
1502
+ """
1503
+ pass
1479
1504
 
1480
1505
  def get_implementation_edges(self, edge: EdgeParams) -> list[EdgeParams]:
1481
1506
  """Gets the edge information for the ``Implementation`` related to this ``Step``.
@@ -1543,7 +1568,8 @@ class NonLeafConfigurationState(ConfigurationState):
1543
1568
  for; it should not include the ``Step's`` name (though it must include
1544
1569
  the sub-step names).
1545
1570
  combined_implementations
1546
- The configuration for any implementations to be combined.
1571
+ The configuration for any :class:`Implementations<easylink.implementation.Implementation>`
1572
+ to be combined.
1547
1573
  input_data_config
1548
1574
  The input data configuration for the entire pipeline.
1549
1575
 
@@ -1585,61 +1611,62 @@ class NonLeafConfigurationState(ConfigurationState):
1585
1611
  self._nodes = step.step_graph.nodes
1586
1612
  self._configure_subgraph_steps()
1587
1613
 
1588
- def get_implementation_graph(self) -> ImplementationGraph:
1589
- """Gets this ``Step's`` :class:`~easylink.graph_components.ImplementationGraph`.
1614
+ def add_nodes_to_implementation_graph(
1615
+ self, implementation_graph: ImplementationGraph
1616
+ ) -> None:
1617
+ """Adds this ``Step's`` ``Implementations`` as nodes to the ``ImplementationGraph``.
1590
1618
 
1591
- A ``Step`` in a non-leaf configuration state by definition has a ``StepGraph``
1592
- containing sub-``Steps`` that need to be unrolled. This method recursively
1593
- traverses that ``StepGraph`` and its childrens' ``StepGraphs`` until all
1594
- sub-``Steps`` are in a :class:`LeafConfigurationState`, i.e. all ``Steps``
1595
- are implemented by a single ``Implementation`` and we have our desired
1596
- ``ImplementationGraph``.
1619
+ This is a recursive function; it calls itself until all sub-``Steps``
1620
+ are of a ``LeafConfigurationState`` and have had their corresponding
1621
+ ``Implementations`` added as nodes to the ``ImplementationGraph``.
1622
+ """
1623
+ for node in self._step.step_graph.nodes:
1624
+ substep = self._step.step_graph.nodes[node]["step"]
1625
+ substep.add_nodes_to_implementation_graph(implementation_graph)
1597
1626
 
1598
- Returns
1599
- -------
1600
- The ``ImplementationGraph`` of this ``Step``.
1627
+ def add_edges_to_implementation_graph(
1628
+ self, implementation_graph: ImplementationGraph
1629
+ ) -> None:
1630
+ """Adds the edges of this ``Step's`` ``Implementations`` to the ``ImplementationGraph``.
1601
1631
 
1602
- Notes
1603
- -----
1604
- This method is first called on the entire :class:`~easylink.pipeline_schema.PipelineSchema`
1605
- when constructing the :class:`~easylink.pipeline_graph.PipelineGraph`
1606
- to run.
1632
+ This method does two things:
1633
+ 1. Adds the edges *at this level* (i.e. at the ``Step`` tied to this
1634
+ ``NonLeafConfigurationState``) to the ``ImplementationGraph``.
1635
+ 2. Recursively traverses all sub-steps and adds their edges to the
1636
+ ``ImplementationGraph``.
1607
1637
 
1638
+ Note that to achieve (1), edges must be mapped from being between steps at
1639
+ this level of the hierarchy, all the way down to being between concrete implementations.
1640
+ Mapping each edge down to the implementation level is *itself* a recursive
1641
+ operation (see ``get_implementation_edges``).
1608
1642
  """
1609
- implementation_graph = ImplementationGraph()
1610
- self.add_nodes(implementation_graph)
1611
- self.add_edges(implementation_graph)
1612
- return implementation_graph
1613
-
1614
- def add_nodes(self, implementation_graph: ImplementationGraph) -> None:
1615
- """Adds nodes for each ``Step`` to the ``ImplementationGraph``."""
1616
- for node in self._nodes:
1617
- step = self._nodes[node]["step"]
1618
- implementation_graph.update(step.get_implementation_graph())
1619
-
1620
- def add_edges(self, implementation_graph: ImplementationGraph) -> None:
1621
- """Adds the edges to the ``ImplementationGraph``."""
1643
+ # Add the edges at this level (i.e. the edges at this `self._step`)
1622
1644
  for source, target, edge_attrs in self._step.step_graph.edges(data=True):
1623
- all_edges = []
1624
1645
  edge = EdgeParams.from_graph_edge(source, target, edge_attrs)
1625
- parent_source_step = self._nodes[source]["step"]
1626
- parent_target_step = self._nodes[target]["step"]
1646
+ source_step = self._nodes[source]["step"]
1647
+ target_step = self._nodes[target]["step"]
1627
1648
 
1628
- source_edges = parent_source_step.get_implementation_edges(edge)
1649
+ source_edges = source_step.get_implementation_edges(edge)
1629
1650
  for source_edge in source_edges:
1630
- for target_edge in parent_target_step.get_implementation_edges(source_edge):
1631
- all_edges.append(target_edge)
1651
+ for target_edge in target_step.get_implementation_edges(source_edge):
1652
+ implementation_graph.add_edge_from_params(target_edge)
1632
1653
 
1633
- for edge in all_edges:
1634
- implementation_graph.add_edge_from_params(edge)
1654
+ # Recurse through all sub-steps and add the edges between them
1655
+ for node in self._step.step_graph.nodes:
1656
+ substep = self._step.step_graph.nodes[node]["step"]
1657
+ substep.add_edges_to_implementation_graph(implementation_graph)
1635
1658
 
1636
1659
  def get_implementation_edges(self, edge: EdgeParams) -> list[EdgeParams]:
1637
- """Gets the edge information for the ``Implementation`` related to this ``Step``.
1660
+ """Gets the edges for the ``Implementation`` related to this ``Step``.
1661
+
1662
+ This method maps an edge between ``Steps`` in this ``Step's`` ``StepGraph``
1663
+ to one or more edges between ``Implementations`` by applying ``SlotMappings``.
1638
1664
 
1639
1665
  Parameters
1640
1666
  ----------
1641
1667
  edge
1642
- The ``Step's`` edge information to be propagated to the ``ImplementationGraph``.
1668
+ The edge information of the edge in the ``StepGraph`` to be mapped to
1669
+ the ``Implementation`` level.
1643
1670
 
1644
1671
  Raises
1645
1672
  ------
@@ -1648,7 +1675,28 @@ class NonLeafConfigurationState(ConfigurationState):
1648
1675
 
1649
1676
  Returns
1650
1677
  -------
1651
- The ``Implementation's`` edge information.
1678
+ A list of edges between ``Implementations`` which are ready to add to
1679
+ the ``ImplementationGraph``.
1680
+
1681
+ Notes
1682
+ -----
1683
+ In EasyLink, an edge (in either a ``StepGraph`` or ``ImplementationGraph``)
1684
+ sconnects two ``Slot``.
1685
+
1686
+ The core of this method is to map the ``Slots`` on the ``StepGraph`` edge
1687
+ to the corresponding ``Slots`` on ``Implementations``.
1688
+
1689
+ At each level in the step hierarchy, ``SlotMappings`` indicate how to map
1690
+ a ``Slot`` to the level below in the hierarchy.
1691
+
1692
+ This method recurses through the step hierarchy until it reaches the leaf
1693
+ ``Steps`` relevant to this edge in order to compose all the ``SlotMappings``
1694
+ that should apply to it.
1695
+
1696
+ Because a single ``Step`` can become multiple nodes in the ``ImplementationGraph``
1697
+ (e.g. a :class:`TemplatedStep`), a single edge between ``Steps`` may actually
1698
+ become multiple edges between ``Implementations``, which is why this method
1699
+ can return a list.
1652
1700
  """
1653
1701
  implementation_edges = []
1654
1702
  if edge.source_node == self._step.name:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: easylink
3
- Version: 0.1.9
3
+ Version: 0.1.11
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,17 +1,17 @@
1
1
  easylink/__about__.py,sha256=2-oxCfu9t9yUJouLDwqYRZ0eii8kN25SxRzsawjWjho,440
2
2
  easylink/__init__.py,sha256=gGMcIVfiVnHtlDw5mZwhevcDb2wt-kuP6F64gnkFack,159
3
- easylink/_version.py,sha256=XIaxbMbyiP-L3kguR1GhxirFblTXiHR1lMfDVITvHUI,22
3
+ easylink/_version.py,sha256=nllDrH0jyChMuuYrK0CC55iTBKUNTUjejtcwxyUF2EQ,23
4
4
  easylink/cli.py,sha256=ARSKAljepNOEYd1VCS_QqBJQIBLzE3IgKiOb5-OROdY,6380
5
5
  easylink/configuration.py,sha256=Ire2pMZNZ6wtSwhcWnQpYa-snX4KrhXgovlQwQ2Wxf4,12530
6
- easylink/graph_components.py,sha256=6OipaUkCW2ESBW6bxwZVgpRAX8RuL15m4x_mGE7i4R8,12669
6
+ easylink/graph_components.py,sha256=PhMKxpgZjorhubS7vcta1pgXgXSGplmPulQpV0YZhqo,14811
7
7
  easylink/implementation.py,sha256=AwGl5YCKCSQo91owWj-gg9_5lBz7H_4q2z7jF0BhXs4,8992
8
8
  easylink/implementation_metadata.yaml,sha256=VvlEu3Dvlmeh1MpzeYx91j22GiV-9mu3hZP5yVuW04o,6763
9
9
  easylink/pipeline.py,sha256=EyCXv5p9WzTqcndXK6ukBJE6jY_fWIP_DGZQUl1wRcY,12284
10
10
  easylink/pipeline_graph.py,sha256=vsY6nW_iEwZCNf_N_3CsixsKBUy_5JxGEi61-1Q-KAw,22842
11
- easylink/pipeline_schema.py,sha256=kINpvy2Fl2S3FBqgdgZCCFHEk237_36X4ltLOtk5-dE,5862
11
+ easylink/pipeline_schema.py,sha256=Q2sCpsC-F2W0yxVP7ufunowDepOBrRVENXOdap9J5iY,6921
12
12
  easylink/rule.py,sha256=W97LMI-vkEPipJbnSZLn2BxfYfFtvzGTKzq6YgDVri0,19913
13
13
  easylink/runner.py,sha256=k9ICTToHj2xr6MGIuvlWf6YMeZ47UGgseaMByMgUGac,6271
14
- easylink/step.py,sha256=8EhoFOXBLWgDfb3OhmQu5g03fqElIJCWg8-Y_5azKEA,67100
14
+ easylink/step.py,sha256=ttteoyIiwnlDjc6QxWKO85GI9ubVGu9Oy5XDG2u4YrY,69885
15
15
  easylink/images/spark_cluster/Dockerfile,sha256=3PHotbR4jdjVYRHOJ0VQW55b5Qd4tQ1pLLQMrTKWVA0,576
16
16
  easylink/images/spark_cluster/README.md,sha256=KdgSttZRplNNWqHn4K1GTsTIab3dTOSG4V99QPLxSp8,569
17
17
  easylink/pipeline_schema_constants/__init__.py,sha256=uRVjQw7_Ff5IBQw0_Jc93Fzfa-MnbPVPKsy18CCaW7E,1021
@@ -43,8 +43,8 @@ easylink/utilities/paths.py,sha256=KM1GlnsAcKbUJrC4LZKpeJfPljxe_aXP1ZhVp43TYRA,9
43
43
  easylink/utilities/spark.smk,sha256=tQ7RArNQzhjbaBQQcRORB4IxxkuDx4gPHUBcWHDYJ_U,5795
44
44
  easylink/utilities/splitter_utils.py,sha256=y4CbbTBgRaoXFxy-9Eu5eWx4lA4ZEcbrYpxgLIzG_kc,2602
45
45
  easylink/utilities/validation_utils.py,sha256=W9r_RXcivJjfpioLhONirfwdByYttxNsVY489_sbrYQ,1683
46
- easylink-0.1.9.dist-info/METADATA,sha256=kc6QCMEr_QU7QtZNnQu-Ic20wmV2OzoN_23Ndw6ArEc,2804
47
- easylink-0.1.9.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
48
- easylink-0.1.9.dist-info/entry_points.txt,sha256=OGMZDFltg3yMboT7XjJt3joiPhRfV_7jnREVtrAIQNU,51
49
- easylink-0.1.9.dist-info/top_level.txt,sha256=oHcOpcF_jDMWFiJRzfGQvuskENGDjSPC_Agu9Z_Xvik,9
50
- easylink-0.1.9.dist-info/RECORD,,
46
+ easylink-0.1.11.dist-info/METADATA,sha256=LCqBkp3ndZAQF8Dwo-4ugO2yLyyduY7oRwg8EcBX0lY,2805
47
+ easylink-0.1.11.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
48
+ easylink-0.1.11.dist-info/entry_points.txt,sha256=OGMZDFltg3yMboT7XjJt3joiPhRfV_7jnREVtrAIQNU,51
49
+ easylink-0.1.11.dist-info/top_level.txt,sha256=oHcOpcF_jDMWFiJRzfGQvuskENGDjSPC_Agu9Z_Xvik,9
50
+ easylink-0.1.11.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.0.0)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5