mantatech-sdk 0.5b0.dev65__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.
- manta/__init__.light.py +22 -0
- manta/__init__.py +83 -0
- manta/__main__.py +21 -0
- manta/apis/__init__.py +7 -0
- manta/apis/async_user_api.py +6458 -0
- manta/apis/graph.py +498 -0
- manta/apis/module.py +316 -0
- manta/apis/results.py +251 -0
- manta/apis/swarm.py +206 -0
- manta/apis/user_api.py +1016 -0
- manta/cli/__init__.py +1 -0
- manta/cli/commands/__init__.py +1 -0
- manta/cli/commands/base_handler.py +229 -0
- manta/cli/commands/doc.py +192 -0
- manta/cli/commands/install.py +346 -0
- manta/cli/commands/sdk.py +9 -0
- manta/cli/commands/sdk_cluster.py +211 -0
- manta/cli/commands/sdk_config.py +347 -0
- manta/cli/commands/sdk_globals.py +280 -0
- manta/cli/commands/sdk_logs.py +174 -0
- manta/cli/commands/sdk_main.py +167 -0
- manta/cli/commands/sdk_module.py +516 -0
- manta/cli/commands/sdk_nodes.py +168 -0
- manta/cli/commands/sdk_original.py +3873 -0
- manta/cli/commands/sdk_results.py +265 -0
- manta/cli/commands/sdk_swarm.py +454 -0
- manta/cli/commands/sdk_user.py +234 -0
- manta/cli/commands/status.py +292 -0
- manta/cli/component_detector.py +112 -0
- manta/cli/config_manager.py +445 -0
- manta/cli/main.py +265 -0
- manta/cli/utils/__init__.py +27 -0
- manta/cli/utils/converters.py +140 -0
- manta/clients/cluster_management_client.py +486 -0
- manta/clients/local_client.py +149 -0
- manta/clients/module_management_client.py +217 -0
- manta/clients/swarm_management_client.py +562 -0
- manta/clients/user_management_client.py +395 -0
- manta/clients/world_client.py +195 -0
- manta/light/__init__.py +31 -0
- manta/light/globals.py +245 -0
- manta/light/local.py +407 -0
- manta/light/logging_config.py +39 -0
- manta/light/path.py +116 -0
- manta/light/results.py +236 -0
- manta/light/task.py +100 -0
- manta/light/utils.py +217 -0
- manta/light/world.py +177 -0
- mantatech_sdk-0.5b0.dev65.dist-info/METADATA +1039 -0
- mantatech_sdk-0.5b0.dev65.dist-info/RECORD +54 -0
- mantatech_sdk-0.5b0.dev65.dist-info/WHEEL +5 -0
- mantatech_sdk-0.5b0.dev65.dist-info/entry_points.txt +2 -0
- mantatech_sdk-0.5b0.dev65.dist-info/licenses/LICENSE +683 -0
- mantatech_sdk-0.5b0.dev65.dist-info/top_level.txt +1 -0
manta/apis/graph.py
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
import uuid
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
from enum import Enum
|
|
4
|
+
from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Union
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from manta_common.conversions import ID, u64x, x2u64
|
|
8
|
+
from .module import Module, Scheduling
|
|
9
|
+
|
|
10
|
+
__all__ = ["Graph", "Edge", "Condition", "merge", "Driver", "Task"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Condition(Enum):
|
|
14
|
+
FINISHED = "FINISHED"
|
|
15
|
+
RESULT = "RESULT"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Driver(Enum):
|
|
19
|
+
HOST = "host"
|
|
20
|
+
BRIDGE = "bridge"
|
|
21
|
+
OVERLAY = "overlay"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(unsafe_hash=True)
|
|
25
|
+
class Edge:
|
|
26
|
+
"""
|
|
27
|
+
Edge between two module IDs
|
|
28
|
+
|
|
29
|
+
Attributes
|
|
30
|
+
----------
|
|
31
|
+
start : UUID
|
|
32
|
+
Head Module ID
|
|
33
|
+
end : UUID
|
|
34
|
+
Tail Module ID
|
|
35
|
+
condition : Condition
|
|
36
|
+
Condition for going from head module to tail module
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
start: UUID
|
|
40
|
+
end: UUID
|
|
41
|
+
condition: Condition
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class Connection:
|
|
46
|
+
"""
|
|
47
|
+
Class which holds connection before and after a node in the `Graph`
|
|
48
|
+
|
|
49
|
+
Attributes
|
|
50
|
+
----------
|
|
51
|
+
previous : Set[Edge]
|
|
52
|
+
Downstream edges
|
|
53
|
+
next : Set[Edge]
|
|
54
|
+
Upstream edges
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
previous: Set[Edge] = field(default_factory=set)
|
|
58
|
+
next: Set[Edge] = field(default_factory=set)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Graph:
|
|
62
|
+
"""
|
|
63
|
+
The :code:`Graph` is a task graph where a task is described by a
|
|
64
|
+
:class:`Task <manta.graph.Task>` in order to be sent to
|
|
65
|
+
the Manager
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
task_table : Optional[Dict[UUID, Task]]
|
|
70
|
+
Table for descriptions of :class:`Task <manta.graph.Task>`
|
|
71
|
+
connectivity_table : Optional[Dict[UUID, Connection]]
|
|
72
|
+
Table for connectivities between :class:`Task <manta.graph.Task>`
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
__slots__ = ["task_table", "connectivity_table"]
|
|
76
|
+
|
|
77
|
+
def __init__(
|
|
78
|
+
self,
|
|
79
|
+
task_table: Optional[Dict[UUID, "Task"]] = None,
|
|
80
|
+
connectivity_table: Optional[Dict[UUID, Connection]] = None,
|
|
81
|
+
):
|
|
82
|
+
self.connectivity_table = connectivity_table or {}
|
|
83
|
+
self.task_table = task_table or {}
|
|
84
|
+
|
|
85
|
+
def add_to_task_table(self, uuid: UUID, task: "Task"):
|
|
86
|
+
"""
|
|
87
|
+
Add a task description associated to its ID
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
uuid : UUID
|
|
92
|
+
ID of the task
|
|
93
|
+
task : Task
|
|
94
|
+
Description of the task
|
|
95
|
+
|
|
96
|
+
Raises
|
|
97
|
+
------
|
|
98
|
+
KeyError
|
|
99
|
+
If the ID already exists, it cannot be added twice.
|
|
100
|
+
"""
|
|
101
|
+
if uuid in self.task_table:
|
|
102
|
+
raise KeyError(f"{uuid} already in the task table.")
|
|
103
|
+
self.task_table[uuid] = task
|
|
104
|
+
|
|
105
|
+
def add_to_connectivity_table(self, edge: Edge):
|
|
106
|
+
"""
|
|
107
|
+
Add an edge
|
|
108
|
+
|
|
109
|
+
Parameters
|
|
110
|
+
----------
|
|
111
|
+
edge : Edge
|
|
112
|
+
Edge between two IDs
|
|
113
|
+
|
|
114
|
+
Raises
|
|
115
|
+
------
|
|
116
|
+
KeyError
|
|
117
|
+
If one of the IDs into the edge is not in the task table
|
|
118
|
+
"""
|
|
119
|
+
# Check if IDs are associated to a module
|
|
120
|
+
if edge.start not in self.task_table:
|
|
121
|
+
raise KeyError(f"{edge.start} missing in the task table.")
|
|
122
|
+
if edge.end not in self.task_table:
|
|
123
|
+
raise KeyError(f"{edge.end} missing in the task table.")
|
|
124
|
+
|
|
125
|
+
# Set connection if they don't exist in the connectivity table
|
|
126
|
+
connection_start = self.connectivity_table.setdefault(edge.start, Connection())
|
|
127
|
+
connection_end = self.connectivity_table.setdefault(edge.end, Connection())
|
|
128
|
+
|
|
129
|
+
# Add edges to them
|
|
130
|
+
connection_start.next.add(edge)
|
|
131
|
+
connection_end.previous.add(edge)
|
|
132
|
+
|
|
133
|
+
def check_networks(self, networks: Dict[str, str]):
|
|
134
|
+
"""
|
|
135
|
+
Check if all network names are found in :code:`networks`
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
networks : Dict[str, str]
|
|
140
|
+
Networks from the :code:`Swarm`
|
|
141
|
+
|
|
142
|
+
Raises
|
|
143
|
+
------
|
|
144
|
+
RuntimeError
|
|
145
|
+
Network name in a :code:`Task` was not found in :code:`networks`
|
|
146
|
+
"""
|
|
147
|
+
for task in self.task_table.values():
|
|
148
|
+
if (network := task.network) and network not in networks:
|
|
149
|
+
raise RuntimeError(
|
|
150
|
+
f"Network {network} not found in declared swarm networks"
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
def starting_uuids(self) -> Iterator[UUID]:
|
|
154
|
+
"""
|
|
155
|
+
Yield the starting UUIDs of the graph
|
|
156
|
+
|
|
157
|
+
Returns
|
|
158
|
+
-------
|
|
159
|
+
Iterator[UUID]
|
|
160
|
+
IDs of starting nodes in the graph
|
|
161
|
+
"""
|
|
162
|
+
for task_uuid, connection in self.connectivity_table.items():
|
|
163
|
+
if len(connection.previous) == 0:
|
|
164
|
+
yield task_uuid
|
|
165
|
+
|
|
166
|
+
def propagation(
|
|
167
|
+
self, acc: list, uuid: UUID, visited_uuids: set, order: int
|
|
168
|
+
) -> Tuple[List[Dict[str, Any]], set]:
|
|
169
|
+
"""
|
|
170
|
+
Recursive function which explore a UUID in the graph and returns a succession
|
|
171
|
+
of tasks ordered by the definition of the graph
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
acc : list
|
|
176
|
+
Output
|
|
177
|
+
uuid : UUID
|
|
178
|
+
UUID to explore
|
|
179
|
+
visited_uuids : set
|
|
180
|
+
Already visited uuids
|
|
181
|
+
order : int
|
|
182
|
+
Depth variable
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
Tuple[list, set]
|
|
187
|
+
:code:`(acc, visited_uuids)` updated
|
|
188
|
+
"""
|
|
189
|
+
connection = self.connectivity_table[uuid]
|
|
190
|
+
task = self.task_table[uuid]
|
|
191
|
+
|
|
192
|
+
task_dict = {
|
|
193
|
+
"task_id": ID(uuid.hex).oid,
|
|
194
|
+
"module": task.module,
|
|
195
|
+
"scheduling": task.scheduling.to_proto(),
|
|
196
|
+
"previous_tasks": [ID(edge.start.hex).oid for edge in connection.previous],
|
|
197
|
+
"next_tasks": [ID(edge.end.hex).oid for edge in connection.next],
|
|
198
|
+
"conditions": [str(edge.condition) for edge in connection.next],
|
|
199
|
+
"order": order,
|
|
200
|
+
"network": task.network,
|
|
201
|
+
"alias": task.alias,
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
acc.append(task_dict)
|
|
205
|
+
|
|
206
|
+
next_uuids = [edge.end for edge in connection.next]
|
|
207
|
+
visited_uuids.add(uuid)
|
|
208
|
+
if len(next_uuids) != 0:
|
|
209
|
+
for uuid in next_uuids:
|
|
210
|
+
if uuid not in visited_uuids:
|
|
211
|
+
acc, visited_uuids = self.propagation(
|
|
212
|
+
acc, uuid, visited_uuids, order + 1
|
|
213
|
+
)
|
|
214
|
+
return acc, visited_uuids
|
|
215
|
+
|
|
216
|
+
def to_proto(self) -> List[Dict[str, Any]]:
|
|
217
|
+
"""
|
|
218
|
+
Make the graph as a protobuf structure
|
|
219
|
+
|
|
220
|
+
Returns
|
|
221
|
+
-------
|
|
222
|
+
List[Dict[str, Any]]
|
|
223
|
+
List of tasks
|
|
224
|
+
"""
|
|
225
|
+
acc: List[Dict[str, Any]] = []
|
|
226
|
+
visited_uuids = set()
|
|
227
|
+
|
|
228
|
+
if len(self.connectivity_table) == 0:
|
|
229
|
+
assert len(self.task_table) == 1, (
|
|
230
|
+
"Swarm without connectivity must have only one task."
|
|
231
|
+
)
|
|
232
|
+
main_uuid = next(iter(self.task_table))
|
|
233
|
+
self.connectivity_table[main_uuid] = Connection()
|
|
234
|
+
|
|
235
|
+
for starting_uuid in self.starting_uuids():
|
|
236
|
+
acc, visited_uuids = self.propagation(acc, starting_uuid, visited_uuids, 0)
|
|
237
|
+
|
|
238
|
+
return acc
|
|
239
|
+
|
|
240
|
+
def __str__(self) -> str:
|
|
241
|
+
"""
|
|
242
|
+
Organize the graph structure into a string by showing the UUIDs of the
|
|
243
|
+
tasks and their connections.
|
|
244
|
+
|
|
245
|
+
It will print the UUID of each task and how they are connected through the
|
|
246
|
+
`connectivity_table`, showing both the previous and next connections. Additionally,
|
|
247
|
+
it will display the associated network for each task (if applicable).
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
def alias_or_uuid(uuid):
|
|
251
|
+
task = self.task_table[uuid]
|
|
252
|
+
return str(task.alias or uuid)
|
|
253
|
+
|
|
254
|
+
if len(self.connectivity_table) == 0:
|
|
255
|
+
return "Graph()"
|
|
256
|
+
|
|
257
|
+
string = "Graph(\n"
|
|
258
|
+
for task_uuid, connection in self.connectivity_table.items():
|
|
259
|
+
string += (
|
|
260
|
+
f" {alias_or_uuid(task_uuid)!r}: (\n"
|
|
261
|
+
f" previous : {[alias_or_uuid(edge.start) for edge in connection.previous]},\n"
|
|
262
|
+
f" next : {[alias_or_uuid(edge.end) for edge in connection.next]},\n"
|
|
263
|
+
" ),\n"
|
|
264
|
+
)
|
|
265
|
+
string += ")"
|
|
266
|
+
return string
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def merge(graph_list: List[Graph]) -> Graph:
|
|
270
|
+
"""
|
|
271
|
+
Merge a list of graphs into one graph
|
|
272
|
+
|
|
273
|
+
Parameters
|
|
274
|
+
----------
|
|
275
|
+
graph_list : List[Graph]
|
|
276
|
+
List of graphs to be merged
|
|
277
|
+
|
|
278
|
+
Returns
|
|
279
|
+
-------
|
|
280
|
+
Graph
|
|
281
|
+
Merged graph
|
|
282
|
+
|
|
283
|
+
Raises
|
|
284
|
+
------
|
|
285
|
+
ValueError
|
|
286
|
+
If two graphs contain the same :code`TaskID`
|
|
287
|
+
"""
|
|
288
|
+
task_table = {}
|
|
289
|
+
connectivity_table = {}
|
|
290
|
+
for graph in graph_list:
|
|
291
|
+
# if task_table.keys() & graph.task_table.keys():
|
|
292
|
+
# print(task_table.keys())
|
|
293
|
+
# print(graph.task_table.keys())
|
|
294
|
+
# raise ValueError("Not allow to merge two graphs with same `IDs`")
|
|
295
|
+
task_table.update(graph.task_table)
|
|
296
|
+
connectivity_table.update(graph.connectivity_table)
|
|
297
|
+
|
|
298
|
+
# print(task_table)
|
|
299
|
+
# print(connectivity_table)
|
|
300
|
+
|
|
301
|
+
return Graph(task_table, connectivity_table)
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
def fold(graph_list: List[Graph]) -> Graph:
|
|
305
|
+
"""
|
|
306
|
+
Like :code:`merge` function, it generates a graph from a list
|
|
307
|
+
of graphs. However similarities, such as same `TaskIDs` are
|
|
308
|
+
put together
|
|
309
|
+
|
|
310
|
+
Parameters
|
|
311
|
+
----------
|
|
312
|
+
graph_list : List[Graph]
|
|
313
|
+
List of graphs to be merged
|
|
314
|
+
|
|
315
|
+
Returns
|
|
316
|
+
-------
|
|
317
|
+
Graph
|
|
318
|
+
Merged graph based on similarities
|
|
319
|
+
"""
|
|
320
|
+
task_table = {}
|
|
321
|
+
connectivity_table = {}
|
|
322
|
+
for graph in graph_list:
|
|
323
|
+
task_table.update(graph.task_table)
|
|
324
|
+
for edge, connection in graph.connectivity_table.items():
|
|
325
|
+
local_connection = connectivity_table.setdefault(edge, Connection())
|
|
326
|
+
local_connection.previous |= connection.previous
|
|
327
|
+
local_connection.next |= connection.next
|
|
328
|
+
|
|
329
|
+
return Graph(task_table, connectivity_table)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class Task:
|
|
333
|
+
"""
|
|
334
|
+
Class which holds the description of a task
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
python_program : Union[str, Path]
|
|
339
|
+
Python program code
|
|
340
|
+
image : str
|
|
341
|
+
Image name of the container in which the program will be executed
|
|
342
|
+
method : str
|
|
343
|
+
Currently, only :code:`"any"` is available
|
|
344
|
+
fixed : bool
|
|
345
|
+
If :code:`True`, the chosen nodes must remain the same over the execution of the :code:`Swarm`
|
|
346
|
+
excepted_ids : Optional[list]
|
|
347
|
+
List of ids that must not be chosen for this module
|
|
348
|
+
specified_ids : Optional[list]
|
|
349
|
+
List of ids that must be chosen for this module
|
|
350
|
+
maximum : Optional[Union[int, float]]
|
|
351
|
+
Maximum of ids that can be chosen for this module.
|
|
352
|
+
If it is a float, it is a percentage between :code:`0.0` and :code:`1.0`
|
|
353
|
+
network : Optional[str]
|
|
354
|
+
It indicates in which network the task will be executed.
|
|
355
|
+
Network name must exist in :code:`Swarm.networks`.
|
|
356
|
+
gpu : bool
|
|
357
|
+
If :code:`True`, the module will be executed on GPU
|
|
358
|
+
|
|
359
|
+
Attributes
|
|
360
|
+
----------
|
|
361
|
+
module : Module
|
|
362
|
+
Description of a task
|
|
363
|
+
graph : Graph
|
|
364
|
+
Hold the connectivity with previous tasks
|
|
365
|
+
uuid : UUID
|
|
366
|
+
ID of the task
|
|
367
|
+
|
|
368
|
+
Examples
|
|
369
|
+
--------
|
|
370
|
+
|
|
371
|
+
>>> aggregator = Task(
|
|
372
|
+
... module=Module("modules/aggregator.py", "manta-demo:latest"),
|
|
373
|
+
... method="any",
|
|
374
|
+
... fixed=False,
|
|
375
|
+
... maximum=1,
|
|
376
|
+
... alias="aggregator",
|
|
377
|
+
... )
|
|
378
|
+
>>> worker = Task(module="worker_module_id")
|
|
379
|
+
"""
|
|
380
|
+
|
|
381
|
+
def __init__(
|
|
382
|
+
self,
|
|
383
|
+
module: Module,
|
|
384
|
+
method: str = "all",
|
|
385
|
+
fixed: bool = False,
|
|
386
|
+
excepted_ids: Optional[list] = None,
|
|
387
|
+
specified_ids: Optional[list] = None,
|
|
388
|
+
maximum: Optional[Union[int, float]] = -1,
|
|
389
|
+
network: Optional[str] = None,
|
|
390
|
+
gpu: bool = False,
|
|
391
|
+
graph: Optional[Graph] = None,
|
|
392
|
+
alias: Optional[str] = None,
|
|
393
|
+
):
|
|
394
|
+
self.module = module
|
|
395
|
+
self.scheduling = Scheduling(
|
|
396
|
+
method=method,
|
|
397
|
+
fixed=fixed,
|
|
398
|
+
excepted_ids=excepted_ids,
|
|
399
|
+
specified_ids=specified_ids,
|
|
400
|
+
maximum=maximum,
|
|
401
|
+
gpu=gpu,
|
|
402
|
+
)
|
|
403
|
+
self.network = network
|
|
404
|
+
self.alias = alias or self.module.name
|
|
405
|
+
|
|
406
|
+
self.graph = Graph() if graph is None else graph
|
|
407
|
+
self.uuid = uuid.uuid4()
|
|
408
|
+
|
|
409
|
+
# If this task has been initialized with module data,
|
|
410
|
+
# immediately register it in the graph
|
|
411
|
+
self.take_in(self.module)
|
|
412
|
+
|
|
413
|
+
def take_in(self, module: Module):
|
|
414
|
+
"""
|
|
415
|
+
Add the module definition of the task to its graph
|
|
416
|
+
|
|
417
|
+
Parameters
|
|
418
|
+
----------
|
|
419
|
+
module : Module
|
|
420
|
+
Module of a task
|
|
421
|
+
"""
|
|
422
|
+
if module.name is not None:
|
|
423
|
+
self.uuid = uuid.UUID(hex=u64x(x2u64(module.name)))
|
|
424
|
+
self.graph.add_to_task_table(self.uuid, self)
|
|
425
|
+
|
|
426
|
+
def add_edge(self, uuid: uuid.UUID, condition: Condition):
|
|
427
|
+
"""
|
|
428
|
+
Add an edge to its graph where it is executed by the Manager
|
|
429
|
+
given the :code:`Condition`
|
|
430
|
+
|
|
431
|
+
Parameters
|
|
432
|
+
----------
|
|
433
|
+
uuid : uuid.UUID
|
|
434
|
+
ID of the task
|
|
435
|
+
condition : Condition
|
|
436
|
+
Condition which tells to the Manager when next task should be executed
|
|
437
|
+
"""
|
|
438
|
+
self.graph.add_to_connectivity_table(Edge(uuid, self.uuid, condition))
|
|
439
|
+
|
|
440
|
+
def __call__(
|
|
441
|
+
self,
|
|
442
|
+
task: Optional[Union[List["Task"], "Task"]] = None,
|
|
443
|
+
condition: Condition = Condition.FINISHED,
|
|
444
|
+
) -> "Task":
|
|
445
|
+
"""
|
|
446
|
+
Update its own graph with connections to other modules
|
|
447
|
+
|
|
448
|
+
Parameters
|
|
449
|
+
----------
|
|
450
|
+
task : Optional[Union[List[Task], Task]]
|
|
451
|
+
One or multiple tasks to connect with itself
|
|
452
|
+
condition : Condition
|
|
453
|
+
Condition which tells to the Manager when next task should be executed
|
|
454
|
+
|
|
455
|
+
Returns
|
|
456
|
+
-------
|
|
457
|
+
Task
|
|
458
|
+
Return itself with updated graph
|
|
459
|
+
|
|
460
|
+
Examples
|
|
461
|
+
--------
|
|
462
|
+
|
|
463
|
+
>>> aggregator = Task(
|
|
464
|
+
... Module(
|
|
465
|
+
... "modules/aggregator.py",
|
|
466
|
+
... "manta-demo:latest",
|
|
467
|
+
... ),
|
|
468
|
+
... method="any",
|
|
469
|
+
... fixed=False,
|
|
470
|
+
... maximum=1,
|
|
471
|
+
... alias="aggregator",
|
|
472
|
+
... )
|
|
473
|
+
>>> worker = Task(
|
|
474
|
+
... Module(
|
|
475
|
+
... "modules/worker",
|
|
476
|
+
... "manta-demo:latest",
|
|
477
|
+
... ),
|
|
478
|
+
... method="all",
|
|
479
|
+
... fixed=False,
|
|
480
|
+
... maximum=-1,
|
|
481
|
+
... alias="worker",
|
|
482
|
+
... )
|
|
483
|
+
>>> m = aggregator(worker) # start worker and follow by aggregator
|
|
484
|
+
"""
|
|
485
|
+
if task is None:
|
|
486
|
+
return self
|
|
487
|
+
elif isinstance(task, Task):
|
|
488
|
+
self.graph = merge([self.graph, task.graph])
|
|
489
|
+
self.add_edge(task.uuid, condition)
|
|
490
|
+
else:
|
|
491
|
+
# Handle list of tasks
|
|
492
|
+
self.graph = merge([self.graph] + [t.graph for t in task])
|
|
493
|
+
for t in task:
|
|
494
|
+
self.add_edge(t.uuid, condition)
|
|
495
|
+
return self
|
|
496
|
+
|
|
497
|
+
def __str__(self): # pragma: no cover
|
|
498
|
+
return f"Task({self.uuid})"
|