dv-flow-mgr 0.0.1.12750690879a1__py3-none-any.whl → 0.0.1.12822558956a1__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.
- dv_flow_mgr/fileset.py +2 -1
- dv_flow_mgr/task.py +11 -13
- dv_flow_mgr/task_data.py +194 -19
- dv_flow_mgr/tasklib/builtin_pkg.py +61 -0
- dv_flow_mgr/tasklib/std/flow.dv +12 -0
- {dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/METADATA +1 -1
- {dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/RECORD +11 -9
- {dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/LICENSE +0 -0
- {dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/WHEEL +0 -0
- {dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/entry_points.txt +0 -0
- {dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/top_level.txt +0 -0
dv_flow_mgr/fileset.py
CHANGED
@@ -24,8 +24,9 @@ from pydantic import BaseModel
|
|
24
24
|
from typing import Any, Dict, List, Tuple
|
25
25
|
|
26
26
|
class FileSet(BaseModel):
|
27
|
-
src : str
|
28
27
|
type : str
|
29
28
|
basedir : str
|
29
|
+
name : str = ""
|
30
|
+
src : str = None
|
30
31
|
files : List[str] = dc.Field(default_factory=list)
|
31
32
|
params : Dict[str,str] = dc.Field(default_factory=dict)
|
dv_flow_mgr/task.py
CHANGED
@@ -155,14 +155,6 @@ class Task(object):
|
|
155
155
|
# Merge filesets. A fileset with the same
|
156
156
|
print("deps_o: %s" % str(deps_o))
|
157
157
|
|
158
|
-
# First, merge the dep maps of all the inputs
|
159
|
-
deps_m = self.depends[0].output.deps.copy()
|
160
|
-
for deps in map(lambda d: d.deps, self.depends[1:]):
|
161
|
-
for k,v in deps.items():
|
162
|
-
if k in deps_m:
|
163
|
-
deps_m[k].add(v)
|
164
|
-
else:
|
165
|
-
deps_m[k] = set(v)
|
166
158
|
|
167
159
|
print("deps_m: %s" % str(deps_m))
|
168
160
|
|
@@ -182,8 +174,7 @@ class Task(object):
|
|
182
174
|
# Mark the source of this data as being this task
|
183
175
|
input.src = self.name
|
184
176
|
|
185
|
-
|
186
|
-
os.makedirs(self.rundir)
|
177
|
+
self.init_rundir()
|
187
178
|
|
188
179
|
result = await self.run(input)
|
189
180
|
|
@@ -202,9 +193,7 @@ class Task(object):
|
|
202
193
|
result = self.getOutput()
|
203
194
|
|
204
195
|
# Write-back the memento, if specified
|
205
|
-
|
206
|
-
with open(os.path.join(self.rundir, "memento.json"), "w") as fp:
|
207
|
-
fp.write(self.memento.model_dump_json(indent=2))
|
196
|
+
self.save_memento()
|
208
197
|
|
209
198
|
self.running = False
|
210
199
|
|
@@ -214,6 +203,15 @@ class Task(object):
|
|
214
203
|
async def run(self, input : TaskData) -> TaskData:
|
215
204
|
raise NotImplementedError("TaskImpl.run() not implemented")
|
216
205
|
|
206
|
+
def init_rundir(self):
|
207
|
+
if not os.path.isdir(self.rundir):
|
208
|
+
os.makedirs(self.rundir)
|
209
|
+
|
210
|
+
def save_memento(self):
|
211
|
+
if self.memento is not None:
|
212
|
+
with open(os.path.join(self.rundir, "memento.json"), "w") as fp:
|
213
|
+
fp.write(self.memento.model_dump_json(indent=2))
|
214
|
+
|
217
215
|
def setOutput(self, output : TaskData):
|
218
216
|
self.output_set = True
|
219
217
|
output.src = self.name
|
dv_flow_mgr/task_data.py
CHANGED
@@ -24,6 +24,7 @@ import pydantic.dataclasses as dc
|
|
24
24
|
from pydantic import BaseModel
|
25
25
|
from typing import Any, Dict, Set, List, Tuple
|
26
26
|
from .fileset import FileSet
|
27
|
+
from toposort import toposort
|
27
28
|
|
28
29
|
class TaskDataParamOpE(enum.Enum):
|
29
30
|
Set = enum.auto()
|
@@ -32,18 +33,25 @@ class TaskDataParamOpE(enum.Enum):
|
|
32
33
|
PathAppend = enum.auto()
|
33
34
|
PathPrepend = enum.auto()
|
34
35
|
|
36
|
+
class TaskDataParamKindE(enum.Enum):
|
37
|
+
String = enum.auto()
|
38
|
+
FilePath = enum.auto()
|
39
|
+
SearchPath = enum.auto()
|
40
|
+
List = enum.auto()
|
41
|
+
|
35
42
|
class TaskDataParamOp(BaseModel):
|
36
43
|
op : TaskDataParamOpE
|
37
44
|
value : Any
|
38
45
|
|
39
46
|
class TaskDataParam(BaseModel):
|
40
|
-
|
47
|
+
kind : TaskDataParamKindE
|
41
48
|
ops : List[TaskDataParamOp] = dc.Field(default_factory=list)
|
42
49
|
|
43
50
|
class TaskData(BaseModel):
|
44
51
|
src : str = None
|
45
|
-
params : Dict[str,
|
52
|
+
params : Dict[str,TaskDataParam] = dc.Field(default_factory=dict)
|
46
53
|
deps : Dict[str,Set[str]] = dc.Field(default_factory=dict)
|
54
|
+
filesets : List[FileSet] = dc.Field(default_factory=list)
|
47
55
|
changed : bool = False
|
48
56
|
|
49
57
|
def hasParam(self, name: str) -> bool:
|
@@ -56,16 +64,27 @@ class TaskData(BaseModel):
|
|
56
64
|
self.params[name] = value
|
57
65
|
|
58
66
|
def addFileSet(self, fs : FileSet):
|
59
|
-
|
60
|
-
if "filesets" not in self.params:
|
61
|
-
self.params["filesets"] = []
|
62
|
-
self.params["filesets"].append(fs)
|
67
|
+
self.filesets.append(fs)
|
63
68
|
|
64
|
-
def getFileSets(self, type=None) -> List[FileSet]:
|
69
|
+
def getFileSets(self, type=None, order=True) -> List[FileSet]:
|
65
70
|
ret = []
|
66
71
|
|
67
|
-
if
|
68
|
-
|
72
|
+
if order:
|
73
|
+
# The deps map specifies task dependencies
|
74
|
+
|
75
|
+
candidate_fs = []
|
76
|
+
for fs in self.filesets:
|
77
|
+
if type is None or fs.type in type:
|
78
|
+
candidate_fs.append(fs)
|
79
|
+
|
80
|
+
order = toposort(self.deps)
|
81
|
+
|
82
|
+
for order_s in order:
|
83
|
+
for fs in candidate_fs:
|
84
|
+
if fs.src in order_s:
|
85
|
+
ret.append(fs)
|
86
|
+
else:
|
87
|
+
for fs in self.filesets:
|
69
88
|
if type is None or fs.type in type:
|
70
89
|
ret.append(fs)
|
71
90
|
|
@@ -80,15 +99,171 @@ class TaskData(BaseModel):
|
|
80
99
|
ret.changed = self.changed
|
81
100
|
return ret
|
82
101
|
|
83
|
-
def
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
102
|
+
def setParamVal(self, name: str, kind : TaskDataParamKindE, value: Any):
|
103
|
+
if name not in self.params:
|
104
|
+
self.params[name] = TaskDataParam(kind=kind)
|
105
|
+
self.params[name].ops.append(TaskDataParamOp(op=TaskDataParamOpE.Set, value=value))
|
106
|
+
|
107
|
+
def getParamVal(self, name: str) -> Any:
|
108
|
+
if name not in self.params.keys():
|
109
|
+
raise Exception("No such parameter: %s" % name)
|
110
|
+
param = self.params[name]
|
111
|
+
value = param.ops[0].value
|
112
|
+
|
113
|
+
if len(param.ops) > 1:
|
114
|
+
for op in param.ops[1:]:
|
115
|
+
if op.op == TaskDataParamOpE.Append:
|
116
|
+
if isinstance(value, list):
|
117
|
+
value.extend(op.value)
|
118
|
+
else:
|
119
|
+
value += op.value
|
120
|
+
elif op.op == TaskDataParamOpE.Prepend:
|
121
|
+
if isinstance(value, list):
|
122
|
+
for nv in op.value:
|
123
|
+
value.insert(0, nv)
|
124
|
+
else:
|
125
|
+
value = op.value + value
|
126
|
+
elif op.op == TaskDataParamOpE.PathAppend:
|
127
|
+
if isinstance(value, list):
|
128
|
+
value = ":".join(value)
|
129
|
+
value = value + ":" + op.value
|
130
|
+
elif op.op == TaskDataParamOpE.PathPrepend:
|
131
|
+
if isinstance(value, list):
|
132
|
+
value = ":".join(value)
|
133
|
+
value = op.value + ":" + value
|
134
|
+
|
135
|
+
return value
|
136
|
+
|
137
|
+
@staticmethod
|
138
|
+
def merge(incoming : List['TaskData'], local : 'TaskData' = None) -> 'TaskData':
|
139
|
+
"""Merges incoming data with local settings and produces an output"""
|
140
|
+
|
141
|
+
# Deal with the dependency trees first
|
142
|
+
output = TaskData()
|
143
|
+
|
144
|
+
# First, merge the dep maps of all the inputs
|
145
|
+
output.deps = incoming[0].deps.copy()
|
146
|
+
for deps in map(lambda i: i.deps, incoming[1:]):
|
147
|
+
for k,v in deps.items():
|
148
|
+
if k not in output.deps:
|
149
|
+
output.deps[k] = []
|
150
|
+
for vi in v:
|
151
|
+
if vi not in output.deps[k]:
|
152
|
+
output.deps[k].append(v)
|
153
|
+
|
154
|
+
# Process filesets
|
155
|
+
for inp in incoming:
|
156
|
+
for fs in inp.filesets:
|
157
|
+
exists = False
|
158
|
+
for fs_o in output.filesets:
|
159
|
+
if fs_o.name == fs.name and fs_o.src == fs.src:
|
160
|
+
exists = True
|
161
|
+
break
|
162
|
+
if not exists:
|
163
|
+
output.addFileSet(fs.model_copy())
|
164
|
+
|
165
|
+
# Now, deal with parameters
|
166
|
+
# Find collisions first
|
167
|
+
colliding_keys = set()
|
168
|
+
passthrough_keys = set()
|
169
|
+
|
170
|
+
for i in incoming:
|
171
|
+
for k in i.params.keys():
|
172
|
+
if k in passthrough_keys:
|
173
|
+
colliding_keys.add(k)
|
174
|
+
else:
|
175
|
+
passthrough_keys.add(k)
|
176
|
+
|
177
|
+
# Now, removes those that are locally set
|
178
|
+
local_set_params = set()
|
179
|
+
if local is not None:
|
180
|
+
for k,v in local.params.items():
|
181
|
+
if len(v.ops) == 1 and v.ops[0].op == TaskDataParamOpE.Set:
|
182
|
+
local_set_params.add(k)
|
183
|
+
# If are setting locally, it's not passthrough
|
184
|
+
passthrough_keys.remove(k)
|
185
|
+
if k in colliding_keys:
|
186
|
+
colliding_keys.remove(k)
|
187
|
+
|
188
|
+
# Construct the passthrough set by removing
|
189
|
+
# colliding entries and those that we will set locally
|
190
|
+
for k in colliding_keys:
|
191
|
+
if k in passthrough_keys:
|
192
|
+
passthrough_keys.remove(k)
|
193
|
+
|
194
|
+
# For the remaining keys, check for conflicts by
|
195
|
+
# confirming that the last 'set' in each incoming parameter
|
196
|
+
# are equal
|
197
|
+
for k in colliding_keys:
|
198
|
+
value = None
|
199
|
+
for i,inp in enumerate(incoming):
|
200
|
+
value_i = None
|
201
|
+
param = inp.params[k]
|
202
|
+
if len(param.ops) == 1:
|
203
|
+
value_i = param.ops[0].value
|
204
|
+
else:
|
205
|
+
# Iterate in reverse over the operations
|
206
|
+
for op in param.ops[::-1]:
|
207
|
+
if op.op == TaskDataParamOpE.Set:
|
208
|
+
value_i = op.value
|
209
|
+
break
|
210
|
+
if not i:
|
211
|
+
value = value_i
|
212
|
+
else:
|
213
|
+
if value != value_i:
|
214
|
+
raise Exception("Parameter %s has conflicting values (%s %s)" % (
|
215
|
+
k,
|
216
|
+
str(value),
|
217
|
+
value(value_i)))
|
218
|
+
|
219
|
+
|
220
|
+
# Now, we need to construct the result
|
221
|
+
# - copy over passthrough parameters
|
222
|
+
# - add locally-set parameters
|
223
|
+
# - for others
|
224
|
+
# - Apply full list for first input
|
225
|
+
# - Apply all beyond the last 'set' operation for others
|
226
|
+
for k in passthrough_keys:
|
227
|
+
# Find an input that has the parameter
|
228
|
+
for inp in incoming:
|
229
|
+
if k in inp.params:
|
230
|
+
break
|
231
|
+
# Find the value of the param
|
232
|
+
param = inp.params[k]
|
233
|
+
|
234
|
+
if len(param.ops) == 1:
|
235
|
+
output.params[k] = TaskDataParam(kind=param.kind)
|
236
|
+
output.params[k].ops.append(param.ops[0])
|
237
|
+
else:
|
238
|
+
for op in param.ops[::-1]:
|
239
|
+
if op.op == TaskDataParamOpE.Set:
|
240
|
+
output.params[k] = TaskDataParam(kind=param.kind)
|
241
|
+
output.params[k].ops.append(op)
|
242
|
+
break
|
243
|
+
for k in local_set_params:
|
244
|
+
output.params[k] = local.params[k].model_copy()
|
245
|
+
|
246
|
+
for k in colliding_keys:
|
247
|
+
value = None
|
248
|
+
for i,inp in enumerate(incoming):
|
249
|
+
# Find the last location that performs a 'set'
|
250
|
+
last_set_i = -1
|
251
|
+
param = inp.params[k]
|
252
|
+
if len(param.ops) == 1:
|
253
|
+
last_set_i = 0
|
254
|
+
else:
|
255
|
+
# Iterate in reverse over the operations
|
256
|
+
for j,op in enumerate(param.ops[::-1]):
|
257
|
+
if op.op == TaskDataParamOpE.Set:
|
258
|
+
last_set_i = j
|
259
|
+
break
|
260
|
+
|
261
|
+
if not i:
|
262
|
+
# Copy the full list, including the last 'set'
|
263
|
+
output.params[k].ops = param.param[last_set_i:].copy()
|
88
264
|
else:
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
elif self.params[k] != v:
|
93
|
-
raise Exception("Parameter %s has conflicting values" % k)
|
265
|
+
# append any additional directives
|
266
|
+
if last_set_i+1 < len(param.ops):
|
267
|
+
output.params[k].extend(param.ops[last_set_i+1:])
|
94
268
|
|
269
|
+
return output
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import glob
|
4
|
+
import fnmatch
|
5
|
+
import importlib
|
6
|
+
import pydantic.dataclasses as dc
|
7
|
+
from ..package import TaskCtor
|
8
|
+
from ..task import Task, TaskParams, TaskCtorT
|
9
|
+
from ..task_data import TaskData
|
10
|
+
from ..task_memento import TaskMemento
|
11
|
+
from typing import List, Tuple
|
12
|
+
import dataclasses as dc
|
13
|
+
from ..package_def import Package
|
14
|
+
|
15
|
+
class TaskPyClass(Task):
|
16
|
+
|
17
|
+
async def run(self, input : TaskData) -> TaskData:
|
18
|
+
|
19
|
+
if self.srcdir not in sys.path:
|
20
|
+
sys.path.insert(0, self.srcdir)
|
21
|
+
|
22
|
+
print("sys.path: %s" % str(sys.path), flush=True)
|
23
|
+
idx = self.params.pyclass.rfind('.')
|
24
|
+
modname = self.params.pyclass[:idx]
|
25
|
+
clsname = self.params.pyclass[idx+1:]
|
26
|
+
|
27
|
+
if os.path.isfile(os.path.join(self.basedir, "my_module.py")):
|
28
|
+
print("my_module.py exists", flush=True)
|
29
|
+
else:
|
30
|
+
print("my_module.py does not exist", flush=True)
|
31
|
+
|
32
|
+
try:
|
33
|
+
print("modname=%s" % modname, flush=True)
|
34
|
+
module = importlib.import_module(modname)
|
35
|
+
except ModuleNotFoundError as e:
|
36
|
+
print("Module not found: %s syspath=%s" % (str(e), str(sys.path)), flush=True)
|
37
|
+
raise e
|
38
|
+
|
39
|
+
cls = getattr(module, clsname)
|
40
|
+
|
41
|
+
obj = cls(self.name, self.task_id, self.session, self.basedir, srcdir=self.srcdir)
|
42
|
+
|
43
|
+
return await obj.run(input)
|
44
|
+
|
45
|
+
|
46
|
+
class TaskPyClassParams(TaskParams):
|
47
|
+
pyclass : str
|
48
|
+
|
49
|
+
class TaskPyClassMemento(TaskMemento):
|
50
|
+
pass
|
51
|
+
|
52
|
+
class TaskPyClassCtor(TaskCtorT):
|
53
|
+
def __init__(self):
|
54
|
+
super().__init__(TaskPyClassParams, TaskPyClass)
|
55
|
+
|
56
|
+
@dc.dataclass
|
57
|
+
class PackageBuiltin(Package):
|
58
|
+
|
59
|
+
def __post_init__(self):
|
60
|
+
print("PackageBuiltin::__post_init__", flush=True)
|
61
|
+
self.tasks["PyClass"] = TaskPyClass()
|
{dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/RECORD
RENAMED
@@ -1,6 +1,6 @@
|
|
1
1
|
dv_flow_mgr/__init__.py,sha256=GLfYxZONxJNNUplfmlsXrcycJ2VhTc8gvXN6qdlH7kg,97
|
2
2
|
dv_flow_mgr/__main__.py,sha256=4xXA4XCqLELlIak6bs-H6rRHp2URucipHPvCiVdR01c,513
|
3
|
-
dv_flow_mgr/fileset.py,sha256=
|
3
|
+
dv_flow_mgr/fileset.py,sha256=FNvC5sU2ArxJ0OO3v8dXTv8zX-bZ5t0a0ljne0fQQ1o,1150
|
4
4
|
dv_flow_mgr/flow.py,sha256=UdgJOIqBS2wTRpO-sNWCCqO9oQFxDfGPGVD0r42aTrA,1562
|
5
5
|
dv_flow_mgr/fragment_def.py,sha256=p5i6ONtBWlDHTBFsduu3Z36_76Bn8PCIylp_xoZ7jfQ,1552
|
6
6
|
dv_flow_mgr/package.py,sha256=jFhXgKDEYSRfs_VRUjKY4C7KScQfmrNLEXQgtWKaBfI,2767
|
@@ -8,12 +8,13 @@ dv_flow_mgr/package_def.py,sha256=Js8bZj8bSmJQ6Wk9xAhIBJScNGJOHNbXNhw_zkDVU5w,38
|
|
8
8
|
dv_flow_mgr/package_import_spec.py,sha256=bStPa727wAKMcixydVY1Ht6ylzXsSMy2K31HWPXhc9k,921
|
9
9
|
dv_flow_mgr/parameters.py,sha256=kUjRss5VtMMz5eL3-Z_M6BS-wFs7MhQu3ANXO54UPo0,896
|
10
10
|
dv_flow_mgr/session.py,sha256=sYRyTojsfPFZOGu4mz9yNTX6ESNye0i5szgj5QVE-Pk,10802
|
11
|
-
dv_flow_mgr/task.py,sha256=
|
12
|
-
dv_flow_mgr/task_data.py,sha256=
|
11
|
+
dv_flow_mgr/task.py,sha256=976-6lsx0qarXDgzOHvg8szS1dIjsp1VoQTrcOWUiQE,7723
|
12
|
+
dv_flow_mgr/task_data.py,sha256=8AcFCxVmv9agzUDXnwUNJImpfp0N4jB1IHodIECf-0k,9735
|
13
13
|
dv_flow_mgr/task_def.py,sha256=Yjw1Q-bnbi7Ct5X1PriMMNJ6i4TBVFWrO8BTnipz9hg,1532
|
14
14
|
dv_flow_mgr/task_memento.py,sha256=C7VTQpBhDEoYuDmE6YTM-6TLMLnqHp6Y0Vat1aTgtCs,1096
|
15
15
|
dv_flow_mgr/cmds/cmd_run.py,sha256=ii48_jdxCxh4MOJCeKKX66Cui4IvQQy_RrJEIixsph8,733
|
16
16
|
dv_flow_mgr/share/flow.json,sha256=lNmZex9NXkYbyb2aZseQfUOkV9CMyfH0iLODEI7EPBw,5096
|
17
|
+
dv_flow_mgr/tasklib/builtin_pkg.py,sha256=qdLUrhF7ZGPpT4EQmtSeOiB4q_tbdLmY6JLxhAYevEA,1746
|
17
18
|
dv_flow_mgr/tasklib/hdl/sim/mti_pkg.py,sha256=l_jerOEQrVSmxT6qJx0PlsorZsK037Y-arQvWzdm9No,348
|
18
19
|
dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_image.py,sha256=U1XADvEGaH412n_JujS1Maz08GJ07UL6mRT4B4qihZQ,2229
|
19
20
|
dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_run.py,sha256=QkKYOs0OhQ42F5bUbfCsezE4L50TfiIm7lVflVY4On8,1290
|
@@ -27,13 +28,14 @@ dv_flow_mgr/tasklib/hdl/sim/vlt_pkg.py,sha256=Pu9mWAR93kiTNT8GZJrX-VDjMOfr9P5ddc
|
|
27
28
|
dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_image.py,sha256=9RDJ3r37C4tA4PIa7tDUYYgRpIh19up-Y9HTOwKxr0I,1564
|
28
29
|
dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_run.py,sha256=RxPaE1RSRi2QdadrZp2J3lZqTt6EnLjCnk__uPAV6_o,1199
|
29
30
|
dv_flow_mgr/tasklib/std/fileset.py,sha256=u88qjKQpIip_eETk0k6J1AGxk9blKlqAqYinHGKwco8,61
|
31
|
+
dv_flow_mgr/tasklib/std/flow.dv,sha256=onqRPp-71uAvLlQdXivvnrIs-OANZC5WYJQMn427TrE,158
|
30
32
|
dv_flow_mgr/tasklib/std/pkg_std.py,sha256=ERDd515qtetQaldk9opUH19MyNwo8nP4-GLz-ke-5gE,370
|
31
33
|
dv_flow_mgr/tasklib/std/std.dfs,sha256=An2NUvvWaR9xI4U-kRQ4NN6U-GhX6GQmd3mNyRkW4NQ,68
|
32
34
|
dv_flow_mgr/tasklib/std/task_fileset.py,sha256=ZBG4e2gsTsRMsr_FhhzIoE3J7YwYQZ9HigpxpGePd74,3145
|
33
35
|
dv_flow_mgr/tasklib/std/task_null.py,sha256=bQH1HN4r-TtdUaJxfnmvoqKZSY4MWO48eK7z_yngdNU,599
|
34
|
-
dv_flow_mgr-0.0.1.
|
35
|
-
dv_flow_mgr-0.0.1.
|
36
|
-
dv_flow_mgr-0.0.1.
|
37
|
-
dv_flow_mgr-0.0.1.
|
38
|
-
dv_flow_mgr-0.0.1.
|
39
|
-
dv_flow_mgr-0.0.1.
|
36
|
+
dv_flow_mgr-0.0.1.12822558956a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
37
|
+
dv_flow_mgr-0.0.1.12822558956a1.dist-info/METADATA,sha256=sN9jrnKJpUhpO6NILL6OZBr1jC38YhnbyDtlbt8nESk,13252
|
38
|
+
dv_flow_mgr-0.0.1.12822558956a1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
39
|
+
dv_flow_mgr-0.0.1.12822558956a1.dist-info/entry_points.txt,sha256=VHxIon5AeHCtK73fYb1veDImAGwv76hrtBiuZePmzhI,51
|
40
|
+
dv_flow_mgr-0.0.1.12822558956a1.dist-info/top_level.txt,sha256=FGuhGIxN1FgD_YBkPcDq05fTxZcwaX9G_O8FFBvrTk4,12
|
41
|
+
dv_flow_mgr-0.0.1.12822558956a1.dist-info/RECORD,,
|
{dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/LICENSE
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12750690879a1.dist-info → dv_flow_mgr-0.0.1.12822558956a1.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|