easylink 0.1.10__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 +1 -1
- easylink/pipeline_schema.py +21 -1
- easylink/step.py +119 -71
- {easylink-0.1.10.dist-info → easylink-0.1.11.dist-info}/METADATA +1 -1
- {easylink-0.1.10.dist-info → easylink-0.1.11.dist-info}/RECORD +8 -8
- {easylink-0.1.10.dist-info → easylink-0.1.11.dist-info}/WHEEL +1 -1
- {easylink-0.1.10.dist-info → easylink-0.1.11.dist-info}/entry_points.txt +0 -0
- {easylink-0.1.10.dist-info → easylink-0.1.11.dist-info}/top_level.txt +0 -0
easylink/_version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "0.1.
|
1
|
+
__version__ = "0.1.11"
|
easylink/pipeline_schema.py
CHANGED
@@ -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
|
254
|
-
|
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
|
-
|
257
|
-
|
258
|
-
|
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
|
-
|
261
|
-
|
262
|
-
|
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
|
-
|
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
|
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
|
399
|
-
|
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
|
-
|
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
|
1398
|
-
|
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
|
1442
|
-
|
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
|
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
|
-
|
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
|
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
|
1589
|
-
|
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
|
-
|
1592
|
-
|
1593
|
-
|
1594
|
-
|
1595
|
-
|
1596
|
-
|
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
|
-
|
1599
|
-
|
1600
|
-
|
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
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
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
|
-
|
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
|
-
|
1626
|
-
|
1646
|
+
source_step = self._nodes[source]["step"]
|
1647
|
+
target_step = self._nodes[target]["step"]
|
1627
1648
|
|
1628
|
-
source_edges =
|
1649
|
+
source_edges = source_step.get_implementation_edges(edge)
|
1629
1650
|
for source_edge in source_edges:
|
1630
|
-
for target_edge in
|
1631
|
-
|
1651
|
+
for target_edge in target_step.get_implementation_edges(source_edge):
|
1652
|
+
implementation_graph.add_edge_from_params(target_edge)
|
1632
1653
|
|
1633
|
-
|
1634
|
-
|
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
|
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
|
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
|
-
|
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
1
|
easylink/__about__.py,sha256=2-oxCfu9t9yUJouLDwqYRZ0eii8kN25SxRzsawjWjho,440
|
2
2
|
easylink/__init__.py,sha256=gGMcIVfiVnHtlDw5mZwhevcDb2wt-kuP6F64gnkFack,159
|
3
|
-
easylink/_version.py,sha256=
|
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
6
|
easylink/graph_components.py,sha256=PhMKxpgZjorhubS7vcta1pgXgXSGplmPulQpV0YZhqo,14811
|
@@ -8,10 +8,10 @@ easylink/implementation.py,sha256=AwGl5YCKCSQo91owWj-gg9_5lBz7H_4q2z7jF0BhXs4,89
|
|
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=
|
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=
|
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.
|
47
|
-
easylink-0.1.
|
48
|
-
easylink-0.1.
|
49
|
-
easylink-0.1.
|
50
|
-
easylink-0.1.
|
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,,
|
File without changes
|
File without changes
|