executorlib 1.7.2__tar.gz → 1.7.4__tar.gz
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.
- {executorlib-1.7.2 → executorlib-1.7.4}/PKG-INFO +13 -12
- {executorlib-1.7.2 → executorlib-1.7.4}/README.md +1 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/pyproject.toml +13 -13
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/_version.py +2 -2
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/executor/base.py +46 -3
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/executor/flux.py +8 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/executor/single.py +8 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/executor/slurm.py +8 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/serialize.py +8 -1
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/base.py +37 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/dependency.py +17 -6
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/dependency_plot.py +134 -15
- {executorlib-1.7.2 → executorlib-1.7.4}/.gitignore +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/LICENSE +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/api.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/backend/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/backend/cache_parallel.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/backend/cache_serial.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/backend/interactive_parallel.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/backend/interactive_serial.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/executor/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/batched.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/command.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/error.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/hdf.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/inputcheck.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/interactive/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/interactive/arguments.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/interactive/backend.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/interactive/communication.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/interactive/spawner.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/queue.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/scheduler.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/select.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/backend.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/shared.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/spawner_pysqa.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/spawner_subprocess.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/task_scheduler.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/__init__.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/blockallocation.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/onetoone.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/shared.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/spawner_flux.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/spawner_pysqa.py +0 -0
- {executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/spawner_slurm.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: executorlib
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.4
|
|
4
4
|
Summary: Up-scale python functions for high performance computing (HPC) with executorlib.
|
|
5
5
|
Project-URL: Homepage, https://github.com/pyiron/executorlib
|
|
6
6
|
Project-URL: Documentation, https://executorlib.readthedocs.io
|
|
@@ -47,26 +47,26 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
47
47
|
Classifier: Programming Language :: Python :: 3.13
|
|
48
48
|
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
49
49
|
Requires-Python: <3.14,>3.9
|
|
50
|
-
Requires-Dist: cloudpickle<=3.1.
|
|
50
|
+
Requires-Dist: cloudpickle<=3.1.2,>=2.0.0
|
|
51
51
|
Requires-Dist: pyzmq<=27.1.0,>=25.0.0
|
|
52
52
|
Provides-Extra: all
|
|
53
|
-
Requires-Dist: h5py<=3.15.
|
|
54
|
-
Requires-Dist: ipython<=9.0
|
|
53
|
+
Requires-Dist: h5py<=3.15.1,>=3.6.0; extra == 'all'
|
|
54
|
+
Requires-Dist: ipython<=9.9.0,>=7.33.0; extra == 'all'
|
|
55
55
|
Requires-Dist: mpi4py<=4.1.1,>=3.1.4; extra == 'all'
|
|
56
|
-
Requires-Dist: networkx<=3.
|
|
56
|
+
Requires-Dist: networkx<=3.6.1,>=2.8.8; extra == 'all'
|
|
57
57
|
Requires-Dist: pygraphviz<=1.14,>=1.10; extra == 'all'
|
|
58
|
-
Requires-Dist: pysqa==0.3.
|
|
58
|
+
Requires-Dist: pysqa==0.3.3; extra == 'all'
|
|
59
59
|
Provides-Extra: cache
|
|
60
|
-
Requires-Dist: h5py<=3.15.
|
|
60
|
+
Requires-Dist: h5py<=3.15.1,>=3.6.0; extra == 'cache'
|
|
61
61
|
Provides-Extra: cluster
|
|
62
|
-
Requires-Dist: h5py<=3.15.
|
|
63
|
-
Requires-Dist: pysqa==0.3.
|
|
62
|
+
Requires-Dist: h5py<=3.15.1,>=3.6.0; extra == 'cluster'
|
|
63
|
+
Requires-Dist: pysqa==0.3.3; extra == 'cluster'
|
|
64
64
|
Provides-Extra: graph
|
|
65
|
-
Requires-Dist: networkx<=3.
|
|
65
|
+
Requires-Dist: networkx<=3.6.1,>=2.8.8; extra == 'graph'
|
|
66
66
|
Requires-Dist: pygraphviz<=1.14,>=1.10; extra == 'graph'
|
|
67
67
|
Provides-Extra: graphnotebook
|
|
68
|
-
Requires-Dist: ipython<=9.0
|
|
69
|
-
Requires-Dist: networkx<=3.
|
|
68
|
+
Requires-Dist: ipython<=9.9.0,>=7.33.0; extra == 'graphnotebook'
|
|
69
|
+
Requires-Dist: networkx<=3.6.1,>=2.8.8; extra == 'graphnotebook'
|
|
70
70
|
Requires-Dist: pygraphviz<=1.14,>=1.10; extra == 'graphnotebook'
|
|
71
71
|
Provides-Extra: mpi
|
|
72
72
|
Requires-Dist: mpi4py<=4.1.1,>=3.1.4; extra == 'mpi'
|
|
@@ -208,6 +208,7 @@ as hierarchical job scheduler within the allocations.
|
|
|
208
208
|
* [Basic Functionality](https://executorlib.readthedocs.io/en/latest/1-single-node.html#basic-functionality)
|
|
209
209
|
* [Parallel Functions](https://executorlib.readthedocs.io/en/latest/1-single-node.html#parallel-functions)
|
|
210
210
|
* [Performance Optimization](https://executorlib.readthedocs.io/en/latest/1-single-node.html#performance-optimization)
|
|
211
|
+
* [Advanced Scheduling](https://executorlib.readthedocs.io/en/latest/1-single-node.html#advanced-scheduling)
|
|
211
212
|
* [Testing and Debugging](https://executorlib.readthedocs.io/en/latest/1-single-node.html#testing-and-debugging)
|
|
212
213
|
* [HPC Cluster Executor](https://executorlib.readthedocs.io/en/latest/2-hpc-cluster.html)
|
|
213
214
|
* [SLURM](https://executorlib.readthedocs.io/en/latest/2-hpc-cluster.html#slurm)
|
|
@@ -134,6 +134,7 @@ as hierarchical job scheduler within the allocations.
|
|
|
134
134
|
* [Basic Functionality](https://executorlib.readthedocs.io/en/latest/1-single-node.html#basic-functionality)
|
|
135
135
|
* [Parallel Functions](https://executorlib.readthedocs.io/en/latest/1-single-node.html#parallel-functions)
|
|
136
136
|
* [Performance Optimization](https://executorlib.readthedocs.io/en/latest/1-single-node.html#performance-optimization)
|
|
137
|
+
* [Advanced Scheduling](https://executorlib.readthedocs.io/en/latest/1-single-node.html#advanced-scheduling)
|
|
137
138
|
* [Testing and Debugging](https://executorlib.readthedocs.io/en/latest/1-single-node.html#testing-and-debugging)
|
|
138
139
|
* [HPC Cluster Executor](https://executorlib.readthedocs.io/en/latest/2-hpc-cluster.html)
|
|
139
140
|
* [SLURM](https://executorlib.readthedocs.io/en/latest/2-hpc-cluster.html#slurm)
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
[build-system]
|
|
2
2
|
requires = [
|
|
3
|
-
"hatchling
|
|
3
|
+
"hatchling>=1.27.0,<=1.28.0",
|
|
4
4
|
"hatch-vcs==0.5.0",
|
|
5
|
-
"cloudpickle>=2.0.0,<=3.1.
|
|
5
|
+
"cloudpickle>=2.0.0,<=3.1.2",
|
|
6
6
|
"pyzmq>=25.0.0,<=27.1.0",
|
|
7
7
|
]
|
|
8
8
|
build-backend = "hatchling.build"
|
|
@@ -29,7 +29,7 @@ classifiers = [
|
|
|
29
29
|
"Programming Language :: Python :: 3.13",
|
|
30
30
|
]
|
|
31
31
|
dependencies = [
|
|
32
|
-
"cloudpickle>=2.0.0,<=3.1.
|
|
32
|
+
"cloudpickle>=2.0.0,<=3.1.2",
|
|
33
33
|
"pyzmq>=25.0.0,<=27.1.0",
|
|
34
34
|
]
|
|
35
35
|
dynamic = ["version"]
|
|
@@ -40,28 +40,28 @@ Documentation = "https://executorlib.readthedocs.io"
|
|
|
40
40
|
Repository = "https://github.com/pyiron/executorlib"
|
|
41
41
|
|
|
42
42
|
[project.optional-dependencies]
|
|
43
|
-
cache = ["h5py>=3.6.0,<=3.15.
|
|
43
|
+
cache = ["h5py>=3.6.0,<=3.15.1"]
|
|
44
44
|
graph = [
|
|
45
45
|
"pygraphviz>=1.10,<=1.14",
|
|
46
|
-
"networkx>=2.8.8,<=3.
|
|
46
|
+
"networkx>=2.8.8,<=3.6.1",
|
|
47
47
|
]
|
|
48
48
|
graphnotebook = [
|
|
49
49
|
"pygraphviz>=1.10,<=1.14",
|
|
50
|
-
"networkx>=2.8.8,<=3.
|
|
51
|
-
"ipython>=7.33.0,<=9.0
|
|
50
|
+
"networkx>=2.8.8,<=3.6.1",
|
|
51
|
+
"ipython>=7.33.0,<=9.9.0",
|
|
52
52
|
]
|
|
53
53
|
mpi = ["mpi4py>=3.1.4,<=4.1.1"]
|
|
54
54
|
cluster = [
|
|
55
|
-
"pysqa==0.3.
|
|
56
|
-
"h5py>=3.6.0,<=3.15.
|
|
55
|
+
"pysqa==0.3.3",
|
|
56
|
+
"h5py>=3.6.0,<=3.15.1",
|
|
57
57
|
]
|
|
58
58
|
all = [
|
|
59
59
|
"mpi4py>=3.1.4,<=4.1.1",
|
|
60
|
-
"pysqa==0.3.
|
|
61
|
-
"h5py>=3.6.0,<=3.15.
|
|
60
|
+
"pysqa==0.3.3",
|
|
61
|
+
"h5py>=3.6.0,<=3.15.1",
|
|
62
62
|
"pygraphviz>=1.10,<=1.14",
|
|
63
|
-
"networkx>=2.8.8,<=3.
|
|
64
|
-
"ipython>=7.33.0,<=9.0
|
|
63
|
+
"networkx>=2.8.8,<=3.6.1",
|
|
64
|
+
"ipython>=7.33.0,<=9.9.0",
|
|
65
65
|
]
|
|
66
66
|
|
|
67
67
|
[tool.ruff]
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '1.7.
|
|
32
|
-
__version_tuple__ = version_tuple = (1, 7,
|
|
31
|
+
__version__ = version = '1.7.4'
|
|
32
|
+
__version_tuple__ = version_tuple = (1, 7, 4)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -21,6 +21,7 @@ class BaseExecutor(FutureExecutor, ABC):
|
|
|
21
21
|
|
|
22
22
|
def __init__(self, executor: TaskSchedulerBase):
|
|
23
23
|
self._task_scheduler = executor
|
|
24
|
+
self._is_active = True
|
|
24
25
|
|
|
25
26
|
@property
|
|
26
27
|
def max_workers(self) -> Optional[int]:
|
|
@@ -99,9 +100,49 @@ class BaseExecutor(FutureExecutor, ABC):
|
|
|
99
100
|
Returns:
|
|
100
101
|
Future: A Future representing the given call.
|
|
101
102
|
"""
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
if self._is_active:
|
|
104
|
+
return self._task_scheduler.submit(
|
|
105
|
+
*([fn] + list(args)), resource_dict=resource_dict, **kwargs
|
|
106
|
+
)
|
|
107
|
+
else:
|
|
108
|
+
raise RuntimeError("cannot schedule new futures after shutdown")
|
|
109
|
+
|
|
110
|
+
def map(
|
|
111
|
+
self,
|
|
112
|
+
fn: Callable,
|
|
113
|
+
*iterables,
|
|
114
|
+
timeout: Optional[float] = None,
|
|
115
|
+
chunksize: int = 1,
|
|
116
|
+
):
|
|
117
|
+
"""Returns an iterator equivalent to map(fn, iter).
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
fn: A callable that will take as many arguments as there are
|
|
121
|
+
passed iterables.
|
|
122
|
+
timeout: The maximum number of seconds to wait. If None, then there
|
|
123
|
+
is no limit on the wait time.
|
|
124
|
+
chunksize: The size of the chunks the iterable will be broken into
|
|
125
|
+
before being passed to a child process. This argument is only
|
|
126
|
+
used by ProcessPoolExecutor; it is ignored by
|
|
127
|
+
ThreadPoolExecutor.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
An iterator equivalent to: map(func, *iterables) but the calls may
|
|
131
|
+
be evaluated out-of-order.
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
TimeoutError: If the entire result iterator could not be generated
|
|
135
|
+
before the given timeout.
|
|
136
|
+
Exception: If fn(*args) raises for any values.
|
|
137
|
+
"""
|
|
138
|
+
if self._is_active:
|
|
139
|
+
return self._task_scheduler.map(
|
|
140
|
+
*([fn] + list(iterables)),
|
|
141
|
+
timeout=timeout,
|
|
142
|
+
chunksize=chunksize,
|
|
143
|
+
)
|
|
144
|
+
else:
|
|
145
|
+
raise RuntimeError("cannot schedule new futures after shutdown")
|
|
105
146
|
|
|
106
147
|
def shutdown(self, wait: bool = True, *, cancel_futures: bool = False):
|
|
107
148
|
"""
|
|
@@ -119,6 +160,7 @@ class BaseExecutor(FutureExecutor, ABC):
|
|
|
119
160
|
cancelled.
|
|
120
161
|
"""
|
|
121
162
|
self._task_scheduler.shutdown(wait=wait, cancel_futures=cancel_futures)
|
|
163
|
+
self._is_active = False
|
|
122
164
|
|
|
123
165
|
def __len__(self) -> int:
|
|
124
166
|
"""
|
|
@@ -143,3 +185,4 @@ class BaseExecutor(FutureExecutor, ABC):
|
|
|
143
185
|
Exit method called when exiting the context manager.
|
|
144
186
|
"""
|
|
145
187
|
self._task_scheduler.__exit__(*args, **kwargs)
|
|
188
|
+
self._is_active = False
|
|
@@ -65,6 +65,7 @@ class FluxJobExecutor(BaseExecutor):
|
|
|
65
65
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
66
66
|
debugging purposes and to get an overview of the specified dependencies.
|
|
67
67
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
68
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
68
69
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
69
70
|
|
|
70
71
|
Examples:
|
|
@@ -105,6 +106,7 @@ class FluxJobExecutor(BaseExecutor):
|
|
|
105
106
|
refresh_rate: float = 0.01,
|
|
106
107
|
plot_dependency_graph: bool = False,
|
|
107
108
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
109
|
+
export_workflow_filename: Optional[str] = None,
|
|
108
110
|
log_obj_size: bool = False,
|
|
109
111
|
):
|
|
110
112
|
"""
|
|
@@ -152,6 +154,7 @@ class FluxJobExecutor(BaseExecutor):
|
|
|
152
154
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
153
155
|
debugging purposes and to get an overview of the specified dependencies.
|
|
154
156
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
157
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
155
158
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
156
159
|
|
|
157
160
|
"""
|
|
@@ -189,6 +192,7 @@ class FluxJobExecutor(BaseExecutor):
|
|
|
189
192
|
refresh_rate=refresh_rate,
|
|
190
193
|
plot_dependency_graph=plot_dependency_graph,
|
|
191
194
|
plot_dependency_graph_filename=plot_dependency_graph_filename,
|
|
195
|
+
export_workflow_filename=export_workflow_filename,
|
|
192
196
|
)
|
|
193
197
|
)
|
|
194
198
|
else:
|
|
@@ -255,6 +259,7 @@ class FluxClusterExecutor(BaseExecutor):
|
|
|
255
259
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
256
260
|
debugging purposes and to get an overview of the specified dependencies.
|
|
257
261
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
262
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
258
263
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
259
264
|
|
|
260
265
|
Examples:
|
|
@@ -293,6 +298,7 @@ class FluxClusterExecutor(BaseExecutor):
|
|
|
293
298
|
refresh_rate: float = 0.01,
|
|
294
299
|
plot_dependency_graph: bool = False,
|
|
295
300
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
301
|
+
export_workflow_filename: Optional[str] = None,
|
|
296
302
|
log_obj_size: bool = False,
|
|
297
303
|
):
|
|
298
304
|
"""
|
|
@@ -338,6 +344,7 @@ class FluxClusterExecutor(BaseExecutor):
|
|
|
338
344
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
339
345
|
debugging purposes and to get an overview of the specified dependencies.
|
|
340
346
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
347
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
341
348
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
342
349
|
|
|
343
350
|
"""
|
|
@@ -420,6 +427,7 @@ class FluxClusterExecutor(BaseExecutor):
|
|
|
420
427
|
refresh_rate=refresh_rate,
|
|
421
428
|
plot_dependency_graph=plot_dependency_graph,
|
|
422
429
|
plot_dependency_graph_filename=plot_dependency_graph_filename,
|
|
430
|
+
export_workflow_filename=export_workflow_filename,
|
|
423
431
|
)
|
|
424
432
|
)
|
|
425
433
|
|
|
@@ -58,6 +58,7 @@ class SingleNodeExecutor(BaseExecutor):
|
|
|
58
58
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
59
59
|
debugging purposes and to get an overview of the specified dependencies.
|
|
60
60
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
61
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
61
62
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
62
63
|
|
|
63
64
|
Examples:
|
|
@@ -94,6 +95,7 @@ class SingleNodeExecutor(BaseExecutor):
|
|
|
94
95
|
refresh_rate: float = 0.01,
|
|
95
96
|
plot_dependency_graph: bool = False,
|
|
96
97
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
98
|
+
export_workflow_filename: Optional[str] = None,
|
|
97
99
|
log_obj_size: bool = False,
|
|
98
100
|
):
|
|
99
101
|
"""
|
|
@@ -138,6 +140,7 @@ class SingleNodeExecutor(BaseExecutor):
|
|
|
138
140
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
139
141
|
debugging purposes and to get an overview of the specified dependencies.
|
|
140
142
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
143
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
141
144
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
142
145
|
|
|
143
146
|
"""
|
|
@@ -171,6 +174,7 @@ class SingleNodeExecutor(BaseExecutor):
|
|
|
171
174
|
refresh_rate=refresh_rate,
|
|
172
175
|
plot_dependency_graph=plot_dependency_graph,
|
|
173
176
|
plot_dependency_graph_filename=plot_dependency_graph_filename,
|
|
177
|
+
export_workflow_filename=export_workflow_filename,
|
|
174
178
|
)
|
|
175
179
|
)
|
|
176
180
|
else:
|
|
@@ -226,6 +230,7 @@ class TestClusterExecutor(BaseExecutor):
|
|
|
226
230
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
227
231
|
debugging purposes and to get an overview of the specified dependencies.
|
|
228
232
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
233
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
229
234
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
230
235
|
|
|
231
236
|
Examples:
|
|
@@ -262,6 +267,7 @@ class TestClusterExecutor(BaseExecutor):
|
|
|
262
267
|
refresh_rate: float = 0.01,
|
|
263
268
|
plot_dependency_graph: bool = False,
|
|
264
269
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
270
|
+
export_workflow_filename: Optional[str] = None,
|
|
265
271
|
log_obj_size: bool = False,
|
|
266
272
|
):
|
|
267
273
|
"""
|
|
@@ -299,6 +305,7 @@ class TestClusterExecutor(BaseExecutor):
|
|
|
299
305
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
300
306
|
debugging purposes and to get an overview of the specified dependencies.
|
|
301
307
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
308
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
302
309
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
303
310
|
|
|
304
311
|
"""
|
|
@@ -358,6 +365,7 @@ class TestClusterExecutor(BaseExecutor):
|
|
|
358
365
|
refresh_rate=refresh_rate,
|
|
359
366
|
plot_dependency_graph=plot_dependency_graph,
|
|
360
367
|
plot_dependency_graph_filename=plot_dependency_graph_filename,
|
|
368
|
+
export_workflow_filename=export_workflow_filename,
|
|
361
369
|
)
|
|
362
370
|
)
|
|
363
371
|
|
|
@@ -63,6 +63,7 @@ class SlurmClusterExecutor(BaseExecutor):
|
|
|
63
63
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
64
64
|
debugging purposes and to get an overview of the specified dependencies.
|
|
65
65
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
66
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
66
67
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
67
68
|
|
|
68
69
|
Examples:
|
|
@@ -101,6 +102,7 @@ class SlurmClusterExecutor(BaseExecutor):
|
|
|
101
102
|
refresh_rate: float = 0.01,
|
|
102
103
|
plot_dependency_graph: bool = False,
|
|
103
104
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
105
|
+
export_workflow_filename: Optional[str] = None,
|
|
104
106
|
log_obj_size: bool = False,
|
|
105
107
|
):
|
|
106
108
|
"""
|
|
@@ -146,6 +148,7 @@ class SlurmClusterExecutor(BaseExecutor):
|
|
|
146
148
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
147
149
|
debugging purposes and to get an overview of the specified dependencies.
|
|
148
150
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
151
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
149
152
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
150
153
|
|
|
151
154
|
"""
|
|
@@ -225,6 +228,7 @@ class SlurmClusterExecutor(BaseExecutor):
|
|
|
225
228
|
refresh_rate=refresh_rate,
|
|
226
229
|
plot_dependency_graph=plot_dependency_graph,
|
|
227
230
|
plot_dependency_graph_filename=plot_dependency_graph_filename,
|
|
231
|
+
export_workflow_filename=export_workflow_filename,
|
|
228
232
|
)
|
|
229
233
|
)
|
|
230
234
|
|
|
@@ -275,6 +279,7 @@ class SlurmJobExecutor(BaseExecutor):
|
|
|
275
279
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
276
280
|
debugging purposes and to get an overview of the specified dependencies.
|
|
277
281
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
282
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
278
283
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
279
284
|
|
|
280
285
|
Examples:
|
|
@@ -312,6 +317,7 @@ class SlurmJobExecutor(BaseExecutor):
|
|
|
312
317
|
refresh_rate: float = 0.01,
|
|
313
318
|
plot_dependency_graph: bool = False,
|
|
314
319
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
320
|
+
export_workflow_filename: Optional[str] = None,
|
|
315
321
|
log_obj_size: bool = False,
|
|
316
322
|
):
|
|
317
323
|
"""
|
|
@@ -360,6 +366,7 @@ class SlurmJobExecutor(BaseExecutor):
|
|
|
360
366
|
plot_dependency_graph (bool): Plot the dependencies of multiple future objects without executing them. For
|
|
361
367
|
debugging purposes and to get an overview of the specified dependencies.
|
|
362
368
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
369
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
363
370
|
log_obj_size (bool): Enable debug mode which reports the size of the communicated objects.
|
|
364
371
|
|
|
365
372
|
"""
|
|
@@ -394,6 +401,7 @@ class SlurmJobExecutor(BaseExecutor):
|
|
|
394
401
|
refresh_rate=refresh_rate,
|
|
395
402
|
plot_dependency_graph=plot_dependency_graph,
|
|
396
403
|
plot_dependency_graph_filename=plot_dependency_graph_filename,
|
|
404
|
+
export_workflow_filename=export_workflow_filename,
|
|
397
405
|
)
|
|
398
406
|
)
|
|
399
407
|
else:
|
|
@@ -75,7 +75,7 @@ def serialize_funct(
|
|
|
75
75
|
"kwargs": fn_kwargs,
|
|
76
76
|
}
|
|
77
77
|
)
|
|
78
|
-
task_key = fn
|
|
78
|
+
task_key = _get_function_name(fn=fn) + _get_hash(binary=binary_all)
|
|
79
79
|
data = {
|
|
80
80
|
"fn": fn,
|
|
81
81
|
"args": fn_args,
|
|
@@ -99,3 +99,10 @@ def _get_hash(binary: bytes) -> str:
|
|
|
99
99
|
# Remove specification of jupyter kernel from hash to be deterministic
|
|
100
100
|
binary_no_ipykernel = re.sub(b"(?<=/ipykernel_)(.*)(?=/)", b"", binary)
|
|
101
101
|
return str(hashlib.md5(binary_no_ipykernel).hexdigest())
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _get_function_name(fn: Callable) -> str:
|
|
105
|
+
if hasattr(fn, "__name__"):
|
|
106
|
+
return fn.__name__
|
|
107
|
+
else:
|
|
108
|
+
return str(fn.__class__).split("'")[-2].split(".")[-1]
|
|
@@ -143,6 +143,43 @@ class TaskSchedulerBase(FutureExecutor):
|
|
|
143
143
|
)
|
|
144
144
|
return f
|
|
145
145
|
|
|
146
|
+
def map(
|
|
147
|
+
self,
|
|
148
|
+
fn: Callable,
|
|
149
|
+
*iterables,
|
|
150
|
+
timeout: Optional[float] = None,
|
|
151
|
+
chunksize: int = 1,
|
|
152
|
+
):
|
|
153
|
+
"""Returns an iterator equivalent to map(fn, iter).
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
fn: A callable that will take as many arguments as there are
|
|
157
|
+
passed iterables.
|
|
158
|
+
timeout: The maximum number of seconds to wait. If None, then there
|
|
159
|
+
is no limit on the wait time.
|
|
160
|
+
chunksize: The size of the chunks the iterable will be broken into
|
|
161
|
+
before being passed to a child process. This argument is only
|
|
162
|
+
used by ProcessPoolExecutor; it is ignored by
|
|
163
|
+
ThreadPoolExecutor.
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
An iterator equivalent to: map(func, *iterables) but the calls may
|
|
167
|
+
be evaluated out-of-order.
|
|
168
|
+
|
|
169
|
+
Raises:
|
|
170
|
+
TimeoutError: If the entire result iterator could not be generated
|
|
171
|
+
before the given timeout.
|
|
172
|
+
Exception: If fn(*args) raises for any values.
|
|
173
|
+
"""
|
|
174
|
+
if isinstance(iterables, (list, tuple)) and any(
|
|
175
|
+
isinstance(i, Future) for i in iterables
|
|
176
|
+
):
|
|
177
|
+
iterables = tuple(
|
|
178
|
+
i.result() if isinstance(i, Future) else i for i in iterables
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
return super().map(fn, *iterables, timeout=timeout, chunksize=chunksize)
|
|
182
|
+
|
|
146
183
|
def shutdown(self, wait: bool = True, *, cancel_futures: bool = False):
|
|
147
184
|
"""
|
|
148
185
|
Clean-up the resources associated with the Executor.
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/dependency.py
RENAMED
|
@@ -13,6 +13,7 @@ from executorlib.standalone.interactive.arguments import (
|
|
|
13
13
|
)
|
|
14
14
|
from executorlib.task_scheduler.base import TaskSchedulerBase
|
|
15
15
|
from executorlib.task_scheduler.interactive.dependency_plot import (
|
|
16
|
+
export_dependency_graph_function,
|
|
16
17
|
generate_nodes_and_edges_for_plotting,
|
|
17
18
|
generate_task_hash_for_plotting,
|
|
18
19
|
plot_dependency_graph_function,
|
|
@@ -28,6 +29,7 @@ class DependencyTaskScheduler(TaskSchedulerBase):
|
|
|
28
29
|
refresh_rate (float, optional): The refresh rate for updating the executor queue. Defaults to 0.01.
|
|
29
30
|
plot_dependency_graph (bool, optional): Whether to generate and plot the dependency graph. Defaults to False.
|
|
30
31
|
plot_dependency_graph_filename (str): Name of the file to store the plotted graph in.
|
|
32
|
+
export_workflow_filename (str): Name of the file to store the exported workflow graph in.
|
|
31
33
|
|
|
32
34
|
Attributes:
|
|
33
35
|
_future_hash_dict (Dict[str, Future]): A dictionary mapping task hash to future object.
|
|
@@ -44,6 +46,7 @@ class DependencyTaskScheduler(TaskSchedulerBase):
|
|
|
44
46
|
refresh_rate: float = 0.01,
|
|
45
47
|
plot_dependency_graph: bool = False,
|
|
46
48
|
plot_dependency_graph_filename: Optional[str] = None,
|
|
49
|
+
export_workflow_filename: Optional[str] = None,
|
|
47
50
|
) -> None:
|
|
48
51
|
super().__init__(max_cores=max_cores)
|
|
49
52
|
self._process_kwargs = {
|
|
@@ -61,7 +64,8 @@ class DependencyTaskScheduler(TaskSchedulerBase):
|
|
|
61
64
|
self._future_hash_dict: dict = {}
|
|
62
65
|
self._task_hash_dict: dict = {}
|
|
63
66
|
self._plot_dependency_graph_filename = plot_dependency_graph_filename
|
|
64
|
-
|
|
67
|
+
self._export_workflow_filename = export_workflow_filename
|
|
68
|
+
if plot_dependency_graph_filename is None and export_workflow_filename is None:
|
|
65
69
|
self._generate_dependency_graph = plot_dependency_graph
|
|
66
70
|
else:
|
|
67
71
|
self._generate_dependency_graph = True
|
|
@@ -209,11 +213,18 @@ class DependencyTaskScheduler(TaskSchedulerBase):
|
|
|
209
213
|
v: k for k, v in self._future_hash_dict.items()
|
|
210
214
|
},
|
|
211
215
|
)
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
216
|
+
if self._export_workflow_filename is not None:
|
|
217
|
+
return export_dependency_graph_function(
|
|
218
|
+
node_lst=node_lst,
|
|
219
|
+
edge_lst=edge_lst,
|
|
220
|
+
file_name=self._export_workflow_filename,
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
return plot_dependency_graph_function(
|
|
224
|
+
node_lst=node_lst,
|
|
225
|
+
edge_lst=edge_lst,
|
|
226
|
+
filename=self._plot_dependency_graph_filename,
|
|
227
|
+
)
|
|
217
228
|
else:
|
|
218
229
|
return None
|
|
219
230
|
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import json
|
|
1
3
|
import os.path
|
|
2
4
|
from concurrent.futures import Future
|
|
3
5
|
from typing import Optional
|
|
4
6
|
|
|
5
7
|
import cloudpickle
|
|
8
|
+
import numpy as np
|
|
6
9
|
|
|
7
10
|
from executorlib.standalone.select import FutureSelector
|
|
8
11
|
|
|
@@ -24,6 +27,12 @@ def generate_nodes_and_edges_for_plotting(
|
|
|
24
27
|
edge_lst: list = []
|
|
25
28
|
hash_id_dict: dict = {}
|
|
26
29
|
|
|
30
|
+
def extend_args(funct_dict):
|
|
31
|
+
sig = inspect.signature(funct_dict["fn"])
|
|
32
|
+
args = sig.bind(*funct_dict["args"], **funct_dict["kwargs"])
|
|
33
|
+
funct_dict["signature"] = args.arguments
|
|
34
|
+
return funct_dict
|
|
35
|
+
|
|
27
36
|
def add_element(arg, link_to, label=""):
|
|
28
37
|
"""
|
|
29
38
|
Add element to the node and edge lists.
|
|
@@ -39,6 +48,8 @@ def generate_nodes_and_edges_for_plotting(
|
|
|
39
48
|
"start": hash_id_dict[future_hash_inverse_dict[arg._future]],
|
|
40
49
|
"end": link_to,
|
|
41
50
|
"label": label + str(arg._selector),
|
|
51
|
+
"end_label": label,
|
|
52
|
+
"start_label": str(arg._selector),
|
|
42
53
|
}
|
|
43
54
|
)
|
|
44
55
|
elif isinstance(arg, Future):
|
|
@@ -53,39 +64,71 @@ def generate_nodes_and_edges_for_plotting(
|
|
|
53
64
|
lst_no_future = [a if not isinstance(a, Future) else "$" for a in arg]
|
|
54
65
|
node_id = len(node_lst)
|
|
55
66
|
node_lst.append(
|
|
56
|
-
{
|
|
67
|
+
{
|
|
68
|
+
"name": str(lst_no_future),
|
|
69
|
+
"value": "python_workflow_definition.shared.get_list",
|
|
70
|
+
"id": node_id,
|
|
71
|
+
"type": "function",
|
|
72
|
+
"shape": "box",
|
|
73
|
+
}
|
|
57
74
|
)
|
|
58
75
|
edge_lst.append({"start": node_id, "end": link_to, "label": label})
|
|
59
76
|
for i, a in enumerate(arg):
|
|
60
77
|
if isinstance(a, Future):
|
|
61
|
-
add_element(arg=a, link_to=node_id, label=
|
|
78
|
+
add_element(arg=a, link_to=node_id, label=str(i))
|
|
62
79
|
elif isinstance(arg, dict) and any(isinstance(a, Future) for a in arg.values()):
|
|
63
80
|
dict_no_future = {
|
|
64
81
|
kt: vt if not isinstance(vt, Future) else "$" for kt, vt in arg.items()
|
|
65
82
|
}
|
|
66
83
|
node_id = len(node_lst)
|
|
67
84
|
node_lst.append(
|
|
68
|
-
{
|
|
85
|
+
{
|
|
86
|
+
"name": str(dict_no_future),
|
|
87
|
+
"value": "python_workflow_definition.shared.get_dict",
|
|
88
|
+
"id": node_id,
|
|
89
|
+
"type": "function",
|
|
90
|
+
"shape": "box",
|
|
91
|
+
}
|
|
69
92
|
)
|
|
70
93
|
edge_lst.append({"start": node_id, "end": link_to, "label": label})
|
|
71
94
|
for kt, vt in arg.items():
|
|
72
|
-
|
|
73
|
-
add_element(arg=vt, link_to=node_id, label="key: " + kt)
|
|
95
|
+
add_element(arg=vt, link_to=node_id, label=kt)
|
|
74
96
|
else:
|
|
75
|
-
|
|
76
|
-
|
|
97
|
+
value_dict = {
|
|
98
|
+
str(n["value"]): n["id"] for n in node_lst if n["type"] == "input"
|
|
99
|
+
}
|
|
100
|
+
if str(arg) not in value_dict:
|
|
101
|
+
node_id = len(node_lst)
|
|
102
|
+
node_lst.append(
|
|
103
|
+
{
|
|
104
|
+
"name": label,
|
|
105
|
+
"value": arg,
|
|
106
|
+
"id": node_id,
|
|
107
|
+
"type": "input",
|
|
108
|
+
"shape": "circle",
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
else:
|
|
112
|
+
node_id = value_dict[str(arg)]
|
|
77
113
|
edge_lst.append({"start": node_id, "end": link_to, "label": label})
|
|
78
114
|
|
|
79
|
-
|
|
115
|
+
task_hash_modified_dict = {
|
|
116
|
+
k: extend_args(funct_dict=v) for k, v in task_hash_dict.items()
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
for k, v in task_hash_modified_dict.items():
|
|
80
120
|
hash_id_dict[k] = len(node_lst)
|
|
81
121
|
node_lst.append(
|
|
82
|
-
{
|
|
122
|
+
{
|
|
123
|
+
"name": v["fn"].__name__,
|
|
124
|
+
"type": "function",
|
|
125
|
+
"value": v["fn"].__module__ + "." + v["fn"].__name__,
|
|
126
|
+
"id": hash_id_dict[k],
|
|
127
|
+
"shape": "box",
|
|
128
|
+
}
|
|
83
129
|
)
|
|
84
|
-
for k, task_dict in
|
|
85
|
-
for
|
|
86
|
-
add_element(arg=arg, link_to=hash_id_dict[k], label="")
|
|
87
|
-
|
|
88
|
-
for kw, v in task_dict["kwargs"].items():
|
|
130
|
+
for k, task_dict in task_hash_modified_dict.items():
|
|
131
|
+
for kw, v in task_dict["signature"].items():
|
|
89
132
|
add_element(arg=v, link_to=hash_id_dict[k], label=str(kw))
|
|
90
133
|
|
|
91
134
|
return node_lst, edge_lst
|
|
@@ -175,7 +218,10 @@ def plot_dependency_graph_function(
|
|
|
175
218
|
|
|
176
219
|
graph = nx.DiGraph()
|
|
177
220
|
for node in node_lst:
|
|
178
|
-
|
|
221
|
+
if node["type"] == "input":
|
|
222
|
+
graph.add_node(node["id"], label=str(node["value"]), shape=node["shape"])
|
|
223
|
+
else:
|
|
224
|
+
graph.add_node(node["id"], label=str(node["name"]), shape=node["shape"])
|
|
179
225
|
for edge in edge_lst:
|
|
180
226
|
graph.add_edge(edge["start"], edge["end"], label=edge["label"])
|
|
181
227
|
if filename is not None:
|
|
@@ -186,3 +232,76 @@ def plot_dependency_graph_function(
|
|
|
186
232
|
from IPython.display import SVG, display # noqa
|
|
187
233
|
|
|
188
234
|
display(SVG(nx.nx_agraph.to_agraph(graph).draw(prog="dot", format="svg")))
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def export_dependency_graph_function(
|
|
238
|
+
node_lst: list, edge_lst: list, file_name: str = "workflow.json"
|
|
239
|
+
):
|
|
240
|
+
"""
|
|
241
|
+
Export the graph visualization of nodes and edges as a JSON dictionary.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
node_lst (list): List of nodes.
|
|
245
|
+
edge_lst (list): List of edges.
|
|
246
|
+
file_name (str): Name of the file to store the exported graph in.
|
|
247
|
+
"""
|
|
248
|
+
pwd_nodes_lst = []
|
|
249
|
+
for n in node_lst:
|
|
250
|
+
if n["type"] == "function":
|
|
251
|
+
pwd_nodes_lst.append(
|
|
252
|
+
{"id": n["id"], "type": n["type"], "value": n["value"]}
|
|
253
|
+
)
|
|
254
|
+
elif n["type"] == "input" and isinstance(n["value"], np.ndarray):
|
|
255
|
+
pwd_nodes_lst.append(
|
|
256
|
+
{
|
|
257
|
+
"id": n["id"],
|
|
258
|
+
"type": n["type"],
|
|
259
|
+
"value": n["value"].tolist(),
|
|
260
|
+
"name": n["name"],
|
|
261
|
+
}
|
|
262
|
+
)
|
|
263
|
+
else:
|
|
264
|
+
pwd_nodes_lst.append(
|
|
265
|
+
{
|
|
266
|
+
"id": n["id"],
|
|
267
|
+
"type": n["type"],
|
|
268
|
+
"value": n["value"],
|
|
269
|
+
"name": n["name"],
|
|
270
|
+
}
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
final_node = {"id": len(pwd_nodes_lst), "type": "output", "name": "result"}
|
|
274
|
+
pwd_nodes_lst.append(final_node)
|
|
275
|
+
pwd_edges_lst = [
|
|
276
|
+
(
|
|
277
|
+
{
|
|
278
|
+
"target": e["end"],
|
|
279
|
+
"targetPort": e["label"],
|
|
280
|
+
"source": e["start"],
|
|
281
|
+
"sourcePort": None,
|
|
282
|
+
}
|
|
283
|
+
if "start_label" not in e
|
|
284
|
+
else {
|
|
285
|
+
"target": e["end"],
|
|
286
|
+
"targetPort": e["end_label"],
|
|
287
|
+
"source": e["start"],
|
|
288
|
+
"sourcePort": e["start_label"],
|
|
289
|
+
}
|
|
290
|
+
)
|
|
291
|
+
for e in edge_lst
|
|
292
|
+
]
|
|
293
|
+
pwd_edges_lst.append(
|
|
294
|
+
{
|
|
295
|
+
"target": final_node["id"],
|
|
296
|
+
"targetPort": None,
|
|
297
|
+
"source": max([e["target"] for e in pwd_edges_lst]),
|
|
298
|
+
"sourcePort": None,
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
pwd_dict = {
|
|
302
|
+
"version": "0.1.0",
|
|
303
|
+
"nodes": pwd_nodes_lst,
|
|
304
|
+
"edges": pwd_edges_lst,
|
|
305
|
+
}
|
|
306
|
+
with open(file_name, "w") as f:
|
|
307
|
+
json.dump(pwd_dict, f, indent=4)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/standalone/interactive/communication.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/spawner_pysqa.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/spawner_subprocess.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/file/task_scheduler.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/onetoone.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/shared.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/spawner_flux.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/spawner_pysqa.py
RENAMED
|
File without changes
|
{executorlib-1.7.2 → executorlib-1.7.4}/src/executorlib/task_scheduler/interactive/spawner_slurm.py
RENAMED
|
File without changes
|