dv-flow-mgr 0.0.1.12761553329a1__py3-none-any.whl → 0.0.1.12849118090a1__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/package.py +0 -20
- dv_flow_mgr/package_def.py +151 -39
- dv_flow_mgr/session.py +81 -47
- dv_flow_mgr/task.py +33 -81
- dv_flow_mgr/task_data.py +194 -19
- dv_flow_mgr/task_def.py +4 -2
- dv_flow_mgr/tasklib/builtin_pkg.py +62 -0
- dv_flow_mgr/tasklib/std/fileset.py +64 -1
- dv_flow_mgr/tasklib/std/flow.dv +26 -0
- dv_flow_mgr/tasklib/std/message.py +7 -0
- {dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/METADATA +1 -1
- {dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/RECORD +17 -14
- {dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/LICENSE +0 -0
- {dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/WHEEL +0 -0
- {dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/entry_points.txt +0 -0
- {dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.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/package.py
CHANGED
@@ -54,26 +54,6 @@ class Package(object):
|
|
54
54
|
def getTaskCtor(self, name : str) -> TaskCtor:
|
55
55
|
return self.tasks[name]
|
56
56
|
|
57
|
-
def mkTaskParams(self, name : str) -> TaskParams:
|
58
|
-
if name not in self.tasks:
|
59
|
-
raise Exception("Task " + name + " not found")
|
60
|
-
return self.tasks[name].mkTaskParams()
|
61
|
-
|
62
|
-
def setTaskParams(self, name : str, params : TaskParams, pvals : Dict[str,Any]):
|
63
|
-
if name not in self.tasks:
|
64
|
-
raise Exception("Task " + name + " not found")
|
65
|
-
self.tasks[name].setTaskParams(params, pvals)
|
66
|
-
|
67
|
-
def mkTask(self,
|
68
|
-
name : str,
|
69
|
-
task_id : int,
|
70
|
-
session : 'Session',
|
71
|
-
params : TaskParams,
|
72
|
-
depends : List['Task']) -> 'Task':
|
73
|
-
# TODO: combine parameters to create the full taskname
|
74
|
-
task = self.tasks[name].mkTask(name, task_id, session, params, depends)
|
75
|
-
return task
|
76
|
-
|
77
57
|
def __hash__(self):
|
78
58
|
return hash(self.fullname())
|
79
59
|
|
dv_flow_mgr/package_def.py
CHANGED
@@ -19,16 +19,20 @@
|
|
19
19
|
#* Author:
|
20
20
|
#*
|
21
21
|
#****************************************************************************
|
22
|
-
import pydantic.dataclasses as dc
|
23
22
|
import json
|
23
|
+
import importlib
|
24
|
+
import sys
|
25
|
+
import pydantic
|
26
|
+
import pydantic.dataclasses as dc
|
24
27
|
from pydantic import BaseModel
|
25
|
-
from typing import Any, Dict, List
|
28
|
+
from typing import Any, Dict, List, Callable, Tuple
|
26
29
|
from .flow import Flow
|
27
30
|
from .fragment_def import FragmentDef
|
28
31
|
from .package import Package
|
29
32
|
from .package_import_spec import PackageImportSpec, PackageSpec
|
30
|
-
from .task import
|
33
|
+
from .task import TaskCtor, TaskParams
|
31
34
|
from .task_def import TaskDef, TaskSpec
|
35
|
+
from .tasklib.builtin_pkg import TaskNull
|
32
36
|
|
33
37
|
|
34
38
|
class PackageDef(BaseModel):
|
@@ -53,46 +57,154 @@ class PackageDef(BaseModel):
|
|
53
57
|
def mkPackage(self, session, params : Dict[str,Any] = None) -> 'Package':
|
54
58
|
ret = Package(self.name)
|
55
59
|
|
60
|
+
session.push_package(ret)
|
61
|
+
|
62
|
+
tasks_m : Dict[str,str,TaskCtor]= {}
|
63
|
+
|
56
64
|
for task in self.tasks:
|
57
|
-
if task.
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
# Only call getTaskCtor if the task is in a different package
|
62
|
-
task_t = task.type if isinstance(task.type, TaskSpec) else TaskSpec(task.type)
|
63
|
-
ctor_t = session.getTaskCtor(task_t, self)
|
64
|
-
|
65
|
-
ctor_t = TaskParamCtor(
|
66
|
-
base=ctor_t,
|
67
|
-
params=task.params,
|
68
|
-
basedir=self.basedir,
|
69
|
-
depend_refs=task.depends)
|
70
|
-
else:
|
71
|
-
# We use the Null task from the std package
|
72
|
-
raise Exception("")
|
73
|
-
ret.tasks[task.name] = ctor_t
|
65
|
+
if task.name in tasks_m.keys():
|
66
|
+
raise Exception("Duplicate task %s" % task.name)
|
67
|
+
tasks_m[task.name] = (task, self.basedir, ) # We'll add a TaskCtor later
|
74
68
|
|
75
69
|
for frag in self.fragment_l:
|
76
70
|
for task in frag.tasks:
|
77
|
-
if task.
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# We use the Null task from the std package
|
92
|
-
raise Exception("")
|
93
|
-
if task.name in ret.tasks:
|
94
|
-
raise Exception("Task %s already defined" % task.name)
|
95
|
-
ret.tasks[task.name] = ctor_t
|
71
|
+
if task.name in tasks_m.keys():
|
72
|
+
raise Exception("Duplicate task %s" % task.name)
|
73
|
+
tasks_m[task.name] = (task, frag.basedir, ) # We'll add a TaskCtor later
|
74
|
+
|
75
|
+
# Now we have a unified map of the tasks declared in this package
|
76
|
+
for name in list(tasks_m.keys()):
|
77
|
+
task_i = tasks_m[name]
|
78
|
+
if len(task_i) < 3:
|
79
|
+
# Need to create the task ctor
|
80
|
+
ctor_t = self.mkTaskCtor(session, task_i[0], task_i[1], tasks_m)
|
81
|
+
tasks_m[name] = (task_i[0], task_i[1], ctor_t)
|
82
|
+
ret.tasks[name] = tasks_m[name][2]
|
83
|
+
|
84
|
+
session.pop_package(ret)
|
96
85
|
|
97
86
|
return ret
|
87
|
+
|
88
|
+
def mkTaskCtor(self, session, task, srcdir, tasks_m) -> TaskCtor:
|
89
|
+
ctor_t : TaskCtor = None
|
90
|
+
|
91
|
+
if task.uses is not None:
|
92
|
+
# Find package (not package_def) that implements this task
|
93
|
+
# Insert an indirect reference to that tasks's constructor
|
94
|
+
last_dot = task.uses.rfind('.')
|
95
|
+
|
96
|
+
if last_dot != -1:
|
97
|
+
pkg_name = task.uses[:last_dot]
|
98
|
+
task_name = task.uses[last_dot+1:]
|
99
|
+
else:
|
100
|
+
pkg_name = None
|
101
|
+
task_name = task.uses
|
102
|
+
|
103
|
+
if pkg_name is not None:
|
104
|
+
pkg = session.getPackage(PackageSpec(pkg_name))
|
105
|
+
if pkg is None:
|
106
|
+
raise Exception("Failed to find package %s" % pkg_name)
|
107
|
+
ctor_t = pkg.getTaskCtor(task_name)
|
108
|
+
ctor_t = ctor_t.copy()
|
109
|
+
ctor_t.srcdir = srcdir
|
110
|
+
else:
|
111
|
+
if task_name not in tasks_m.keys():
|
112
|
+
raise Exception("Failed to find task %s" % task_name)
|
113
|
+
if len(tasks_m[task_name]) == 3:
|
114
|
+
ctor_t = tasks_m[task_name][2].copy()
|
115
|
+
ctor_t.srcdir = srcdir
|
116
|
+
else:
|
117
|
+
task_i = tasks_m[task_name]
|
118
|
+
ctor_t = self.mkTaskCtor(
|
119
|
+
session,
|
120
|
+
task=task_i[0],
|
121
|
+
srcdir=srcdir,
|
122
|
+
tasks_m=tasks_m)
|
123
|
+
tasks_m[task_name] = ctor_t
|
124
|
+
|
125
|
+
if ctor_t is None:
|
126
|
+
# Provide a default implementation
|
127
|
+
ctor_t = TaskCtor(
|
128
|
+
task_ctor=TaskNull,
|
129
|
+
param_ctor=TaskParams,
|
130
|
+
srcdir=srcdir)
|
131
|
+
|
132
|
+
if task.pyclass is not None:
|
133
|
+
# Built-in impl
|
134
|
+
# Now, lookup the class
|
135
|
+
last_dot = task.pyclass.rfind('.')
|
136
|
+
clsname = task.pyclass[last_dot+1:]
|
137
|
+
modname = task.pyclass[:last_dot]
|
138
|
+
|
139
|
+
try:
|
140
|
+
if modname not in sys.modules:
|
141
|
+
if self.basedir not in sys.path:
|
142
|
+
sys.path.append(self.basedir)
|
143
|
+
mod = importlib.import_module(modname)
|
144
|
+
else:
|
145
|
+
mod = sys.modules[modname]
|
146
|
+
except ModuleNotFoundError as e:
|
147
|
+
raise Exception("Failed to import module %s" % modname)
|
148
|
+
|
149
|
+
if not hasattr(mod, clsname):
|
150
|
+
raise Exception("Class %s not found in module %s" % (clsname, modname))
|
151
|
+
ctor_t.task_ctor = getattr(mod, clsname)
|
152
|
+
|
153
|
+
if task.uses is None:
|
154
|
+
ctor_t.param_ctor = TaskParams
|
155
|
+
|
156
|
+
decl_params = False
|
157
|
+
for value in task.params.values():
|
158
|
+
if "type" in value:
|
159
|
+
decl_params = True
|
160
|
+
break
|
161
|
+
|
162
|
+
if decl_params:
|
163
|
+
# We need to combine base parameters with new parameters
|
164
|
+
field_m = {}
|
165
|
+
# First, add parameters from the base class
|
166
|
+
for fname,info in ctor_t.param_ctor.model_fields.items():
|
167
|
+
print("Field: %s (%s)" % (fname, info.default))
|
168
|
+
field_m[fname] = (info.annotation, info.default)
|
169
|
+
ptype_m = {
|
170
|
+
"str" : str,
|
171
|
+
"int" : int,
|
172
|
+
"float" : float,
|
173
|
+
"bool" : bool
|
174
|
+
}
|
175
|
+
for p in task.params.keys():
|
176
|
+
param = task.params[p]
|
177
|
+
if type(param) == dict and "type" in param.keys():
|
178
|
+
ptype_s = param["type"]
|
179
|
+
if ptype_s not in ptype_m.keys():
|
180
|
+
raise Exception("Unknown type %s" % ptype_s)
|
181
|
+
ptype = ptype_m[ptype_s]
|
182
|
+
|
183
|
+
if p in field_m.keys():
|
184
|
+
raise Exception("Duplicate field %s" % p)
|
185
|
+
if "value" in param.keys():
|
186
|
+
field_m[p] = (ptype, param["value"])
|
187
|
+
else:
|
188
|
+
field_m[p] = (ptype, )
|
189
|
+
else:
|
190
|
+
if p not in field_m.keys():
|
191
|
+
raise Exception("Field %s not found" % p)
|
192
|
+
if type(param) != dict:
|
193
|
+
value = param
|
194
|
+
elif "value" in param.keys():
|
195
|
+
value = param["value"]
|
196
|
+
else:
|
197
|
+
raise Exception("No value specified for param %s: %s" % (
|
198
|
+
p, str(param)))
|
199
|
+
field_m[p] = (field_m[p][0], value)
|
200
|
+
print("field_m: %s" % str(field_m))
|
201
|
+
ctor_t.param_ctor = pydantic.create_model(
|
202
|
+
"Task%sParams" % task.name, **field_m)
|
203
|
+
else:
|
204
|
+
if len(task.params) > 0:
|
205
|
+
ctor_t.params = task.params
|
206
|
+
if len(task.depends) > 0:
|
207
|
+
ctor_t.depends.extends(task.depends)
|
208
|
+
|
209
|
+
return ctor_t
|
98
210
|
|
dv_flow_mgr/session.py
CHANGED
@@ -27,7 +27,7 @@ from typing import Any, Callable, Dict, List
|
|
27
27
|
from .fragment_def import FragmentDef
|
28
28
|
from .package import Package
|
29
29
|
from .package_def import PackageDef, PackageSpec
|
30
|
-
from .task import Task,TaskSpec
|
30
|
+
from .task import Task, TaskSpec, TaskCtor
|
31
31
|
|
32
32
|
@dc.dataclass
|
33
33
|
class Session(object):
|
@@ -45,29 +45,36 @@ class Session(object):
|
|
45
45
|
_pkg_m : Dict[PackageSpec,Package] = dc.field(default_factory=dict)
|
46
46
|
_pkg_spec_s : List[PackageDef] = dc.field(default_factory=list)
|
47
47
|
_pkg_def_m : Dict[str,PackageDef] = dc.field(default_factory=dict)
|
48
|
+
_pkg_file_m : Dict[str,str] = dc.field(default_factory=dict)
|
49
|
+
_pkg_path : List[str] = dc.field(default_factory=list)
|
48
50
|
_task_list : List[Task] = dc.field(default_factory=list)
|
49
51
|
_task_m : Dict[TaskSpec,Task] = dc.field(default_factory=dict)
|
50
52
|
_task_id : int = 0
|
51
53
|
|
52
54
|
def __post_init__(self):
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
55
|
+
# Add a reference to the built-in 'std' package
|
56
|
+
this_dir = os.path.dirname(os.path.abspath(__file__))
|
57
|
+
self._pkg_file_m["std"] = os.path.join(this_dir, "tasklib/std/flow.dv")
|
58
|
+
|
59
|
+
# from .tasklib.std.pkg_std import PackageStd
|
60
|
+
# from .tasklib.hdl.sim.vcs_pkg import VcsPackage
|
61
|
+
# from .tasklib.hdl.sim.vlt_pkg import VltPackage
|
62
|
+
# from .tasklib.hdl.sim.mti_pkg import MtiPackage
|
63
|
+
# self._pkg_m[PackageSpec("std")] = PackageStd("std")
|
64
|
+
# self._pkg_m[PackageSpec("hdl.sim.mti")] = MtiPackage("hdl.sim.mti")
|
65
|
+
# self._pkg_m[PackageSpec("hdl.sim.vcs")] = VcsPackage("hdl.sim.vcs")
|
66
|
+
# self._pkg_m[PackageSpec("hdl.sim.vlt")] = VltPackage("hdl.sim.vlt")
|
67
|
+
pass
|
68
|
+
|
69
|
+
def load(self):
|
70
|
+
if not os.path.isdir(self.srcdir):
|
71
|
+
raise Exception("Root directory %s does not exist" % self.srcdir)
|
72
|
+
|
73
|
+
if not os.path.isfile(os.path.join(self.srcdir, "flow.dv")):
|
67
74
|
raise Exception("No root flow file")
|
68
75
|
|
69
|
-
self._root_dir = os.path.dirname(
|
70
|
-
self.package = self._load_package(os.path.join(
|
76
|
+
self._root_dir = os.path.dirname(self.srcdir)
|
77
|
+
self.package = self._load_package(os.path.join(self.srcdir, "flow.dv"), [])
|
71
78
|
|
72
79
|
return self.package
|
73
80
|
|
@@ -77,7 +84,7 @@ class Session(object):
|
|
77
84
|
|
78
85
|
return self._mkTaskGraph(task, self.rundir)
|
79
86
|
|
80
|
-
def _mkTaskGraph(self, task : str, parent_rundir : str
|
87
|
+
def _mkTaskGraph(self, task : str, parent_rundir : str) -> Task:
|
81
88
|
|
82
89
|
elems = task.split(".")
|
83
90
|
|
@@ -99,23 +106,19 @@ class Session(object):
|
|
99
106
|
|
100
107
|
self._pkg_s.append(pkg)
|
101
108
|
|
102
|
-
|
109
|
+
ctor_t : TaskCtor = pkg.getTaskCtor(task_name)
|
103
110
|
|
104
111
|
depends = []
|
105
112
|
|
106
|
-
params = pkg.mkTaskParams(task_name)
|
107
|
-
|
108
|
-
task_id = self.mkTaskId(None)
|
109
|
-
# task_name = "%s.%s" % (pkg.name, task_def.name)
|
110
|
-
|
111
113
|
# The returned task should have all param references resolved
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
self,
|
116
|
-
params,
|
117
|
-
depends
|
118
|
-
|
114
|
+
print("task_ctor=%s" % str(ctor_t.task_ctor), flush=True)
|
115
|
+
task = ctor_t.task_ctor(
|
116
|
+
name=task_name,
|
117
|
+
session=self,
|
118
|
+
params=ctor_t.mkParams(),
|
119
|
+
depends=depends,
|
120
|
+
rundir=rundir,
|
121
|
+
srcdir=ctor_t.srcdir)
|
119
122
|
|
120
123
|
for i,d in enumerate(task.depend_refs):
|
121
124
|
if d in self._task_m.keys():
|
@@ -130,6 +133,15 @@ class Session(object):
|
|
130
133
|
self._pkg_spec_s.pop()
|
131
134
|
|
132
135
|
return task
|
136
|
+
|
137
|
+
def push_package(self, pkg : Package):
|
138
|
+
self._pkg_s.append(pkg)
|
139
|
+
|
140
|
+
def pop_package(self, pkg : Package):
|
141
|
+
self._pkg_s.pop()
|
142
|
+
|
143
|
+
def package(self):
|
144
|
+
return self._pkg_s[-1]
|
133
145
|
|
134
146
|
def mkTaskId(self, task : 'Task') -> int:
|
135
147
|
self._task_id += 1
|
@@ -158,13 +170,13 @@ class Session(object):
|
|
158
170
|
|
159
171
|
if not len(self._pkg_spec_s):
|
160
172
|
self._pkg_spec_s.append(PackageSpec(pkg.name))
|
161
|
-
self._pkg_def_m[PackageSpec(pkg.name)] = pkg
|
162
173
|
else:
|
163
|
-
if self._pkg_spec_s[
|
164
|
-
raise Exception("Package name mismatch: %s != %s" % (self.
|
174
|
+
if self._pkg_spec_s[-1].name != pkg.name:
|
175
|
+
raise Exception("Package name mismatch: %s != %s" % (self._pkg_spec_s[-1].name, pkg.name))
|
165
176
|
else:
|
166
177
|
# TODO: merge content
|
167
178
|
self._pkg_spec_s.append(PackageSpec(pkg.name))
|
179
|
+
self._pkg_def_m[PackageSpec(pkg.name)] = pkg
|
168
180
|
|
169
181
|
print("pkg: %s" % str(pkg))
|
170
182
|
|
@@ -219,9 +231,12 @@ class Session(object):
|
|
219
231
|
|
220
232
|
|
221
233
|
def getPackage(self, spec : PackageSpec) -> Package:
|
234
|
+
# Obtain the active package definition
|
222
235
|
pkg_spec = self._pkg_spec_s[-1]
|
223
236
|
pkg_def = self._pkg_def_m[pkg_spec]
|
224
237
|
|
238
|
+
print("spec: %s ; _pkg_def_m: %s" % (str(spec), str(self._pkg_def_m.keys())))
|
239
|
+
|
225
240
|
# Need a stack to track which package we are currently in
|
226
241
|
# Need a map to get a concrete package from a name with parameterization
|
227
242
|
|
@@ -261,30 +276,49 @@ class Session(object):
|
|
261
276
|
pkg = base.mkPackage(self, spec.params)
|
262
277
|
self._pkg_m[spec] = pkg
|
263
278
|
break
|
279
|
+
|
280
|
+
if pkg is None:
|
281
|
+
# Look in the set of registered packages
|
282
|
+
if spec.name in self._pkg_file_m.keys():
|
283
|
+
# Load the package
|
284
|
+
self._pkg_spec_s.append(spec)
|
285
|
+
pkg_def = self._load_package(
|
286
|
+
self._pkg_file_m[spec.name],
|
287
|
+
[])
|
288
|
+
|
289
|
+
self._pkg_spec_s.pop()
|
290
|
+
|
291
|
+
# The definition is now in the map, so recurse to create it
|
292
|
+
pkg = self.getPackage(spec)
|
293
|
+
else:
|
294
|
+
# Go search the package path
|
295
|
+
pass
|
296
|
+
|
297
|
+
|
264
298
|
|
265
299
|
if pkg is None:
|
266
300
|
raise Exception("Failed to find package %s from package %s" % (
|
267
301
|
spec.name, pkg_def.name))
|
268
302
|
|
269
|
-
# base_spec = PackageSpec(spec.name)
|
270
|
-
# if not base_spec in self._pkg_def_m.keys():
|
271
|
-
# # Template is not present. Go find it...
|
272
|
-
#
|
273
|
-
# # If not found...
|
274
|
-
# raise Exception("Package %s not found" % spec.name)
|
275
|
-
|
276
303
|
return pkg
|
277
304
|
|
278
305
|
def getTaskCtor(self, spec : TaskSpec, pkg : PackageDef) -> 'TaskCtor':
|
279
306
|
spec_e = spec.name.split(".")
|
280
307
|
task_name = spec_e[-1]
|
281
|
-
pkg_name = ".".join(spec_e[0:-1])
|
282
308
|
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
309
|
+
if len(spec_e) == 1:
|
310
|
+
# Just have a task name. Use the current package
|
311
|
+
if len(self._pkg_s) == 0:
|
312
|
+
raise Exception("No package context for task %s" % spec.name)
|
313
|
+
pkg = self._pkg_s[-1]
|
314
|
+
else:
|
315
|
+
pkg_name = ".".join(spec_e[0:-1])
|
316
|
+
|
317
|
+
try:
|
318
|
+
pkg = self.getPackage(PackageSpec(pkg_name))
|
319
|
+
except Exception as e:
|
320
|
+
print("Failed to find package %s while looking for task %s" % (pkg_name, spec.name))
|
321
|
+
raise e
|
288
322
|
|
289
323
|
return pkg.getTaskCtor(task_name)
|
290
324
|
|
dv_flow_mgr/task.py
CHANGED
@@ -24,7 +24,7 @@ import json
|
|
24
24
|
import asyncio
|
25
25
|
import dataclasses as dc
|
26
26
|
from pydantic import BaseModel
|
27
|
-
from typing import Any, Dict, List, Tuple
|
27
|
+
from typing import Any, Callable, Dict, List, Tuple
|
28
28
|
from .task_data import TaskData
|
29
29
|
from .task_memento import TaskMemento
|
30
30
|
|
@@ -37,78 +37,32 @@ class TaskParams(BaseModel):
|
|
37
37
|
|
38
38
|
@dc.dataclass
|
39
39
|
class TaskCtor(object):
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
def mkTask(self, name : str, task_id : int, session : 'Session', params : TaskParams, depends : List['Task']) -> 'Task':
|
62
|
-
task = self.TaskT(
|
63
|
-
name=name,
|
64
|
-
task_id=task_id,
|
65
|
-
session=session,
|
66
|
-
params=params,
|
67
|
-
depends=depends)
|
68
|
-
task.depends.extend(depends)
|
69
|
-
return task
|
70
|
-
|
71
|
-
@dc.dataclass
|
72
|
-
class TaskParamCtor(object):
|
73
|
-
base : TaskCtor
|
74
|
-
params : Dict[str,Any]
|
75
|
-
basedir : str
|
76
|
-
depend_refs : List['TaskSpec']
|
77
|
-
|
78
|
-
def mkTaskParams(self) -> TaskParams:
|
79
|
-
params = self.base.mkTaskParams()
|
80
|
-
self.base.setTaskParams(params, self.params)
|
81
|
-
return params
|
82
|
-
|
83
|
-
def setTaskParams(self, params : Dict, pvals : Dict[str,Any]):
|
84
|
-
pass
|
85
|
-
|
86
|
-
def mkTask(self, name : str, task_id : int, session : 'Session', params : Dict, depends : List['Task']) -> 'Task':
|
87
|
-
task = self.base.mkTask(
|
88
|
-
name=name,
|
89
|
-
task_id=task_id,
|
90
|
-
session=session,
|
91
|
-
params=params,
|
92
|
-
depends=depends)
|
93
|
-
task.basedir = self.basedir
|
94
|
-
task.depend_refs.extend(self.depend_refs)
|
95
|
-
return task
|
96
|
-
|
97
|
-
@dc.dataclass
|
98
|
-
class PackageTaskCtor(TaskCtor):
|
99
|
-
name : str
|
100
|
-
pkg : 'Package'
|
101
|
-
|
102
|
-
def mkTaskParams(self, params : Dict) -> Dict:
|
103
|
-
return self.pkg.mkTaskParams(self.name, params)
|
104
|
-
def mkTask(self, name : str, task_id : int, session : 'Session', params : Dict, depends : List['Task']) -> 'Task':
|
105
|
-
return self.pkg.mkTask(self.name, task_id, session, params, depends)
|
40
|
+
task_ctor : Callable
|
41
|
+
param_ctor : Callable
|
42
|
+
params : Dict[str,Any] = None
|
43
|
+
srcdir : str = None
|
44
|
+
depends : List[TaskSpec] = dc.field(default_factory=list)
|
45
|
+
|
46
|
+
def copy(self):
|
47
|
+
return TaskCtor(
|
48
|
+
task_ctor=self.task_ctor,
|
49
|
+
param_ctor=self.param_ctor,
|
50
|
+
params=self.params,
|
51
|
+
srcdir=self.srcdir,
|
52
|
+
depends=self.depends.copy())
|
53
|
+
|
54
|
+
def mkParams(self):
|
55
|
+
print("mkParams: %s" % str(self.params))
|
56
|
+
ret = self.param_ctor()
|
57
|
+
if self.params is not None:
|
58
|
+
for k,v in self.params.items():
|
59
|
+
setattr(ret, k, v)
|
60
|
+
return ret
|
106
61
|
|
107
62
|
@dc.dataclass
|
108
63
|
class Task(object):
|
109
64
|
"""Executable view of a task"""
|
110
65
|
name : str
|
111
|
-
task_id : int
|
112
66
|
session : 'Session'
|
113
67
|
params : TaskParams
|
114
68
|
basedir : str
|
@@ -155,14 +109,6 @@ class Task(object):
|
|
155
109
|
# Merge filesets. A fileset with the same
|
156
110
|
print("deps_o: %s" % str(deps_o))
|
157
111
|
|
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
112
|
|
167
113
|
print("deps_m: %s" % str(deps_m))
|
168
114
|
|
@@ -182,8 +128,7 @@ class Task(object):
|
|
182
128
|
# Mark the source of this data as being this task
|
183
129
|
input.src = self.name
|
184
130
|
|
185
|
-
|
186
|
-
os.makedirs(self.rundir)
|
131
|
+
self.init_rundir()
|
187
132
|
|
188
133
|
result = await self.run(input)
|
189
134
|
|
@@ -202,9 +147,7 @@ class Task(object):
|
|
202
147
|
result = self.getOutput()
|
203
148
|
|
204
149
|
# 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))
|
150
|
+
self.save_memento()
|
208
151
|
|
209
152
|
self.running = False
|
210
153
|
|
@@ -214,6 +157,15 @@ class Task(object):
|
|
214
157
|
async def run(self, input : TaskData) -> TaskData:
|
215
158
|
raise NotImplementedError("TaskImpl.run() not implemented")
|
216
159
|
|
160
|
+
def init_rundir(self):
|
161
|
+
if not os.path.isdir(self.rundir):
|
162
|
+
os.makedirs(self.rundir)
|
163
|
+
|
164
|
+
def save_memento(self):
|
165
|
+
if self.memento is not None:
|
166
|
+
with open(os.path.join(self.rundir, "memento.json"), "w") as fp:
|
167
|
+
fp.write(self.memento.model_dump_json(indent=2))
|
168
|
+
|
217
169
|
def setOutput(self, output : TaskData):
|
218
170
|
self.output_set = True
|
219
171
|
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
|
dv_flow_mgr/task_def.py
CHANGED
@@ -28,11 +28,13 @@ from .task import Task
|
|
28
28
|
class TaskSpec(object):
|
29
29
|
name : str
|
30
30
|
|
31
|
-
|
32
31
|
class TaskDef(BaseModel):
|
33
32
|
"""Holds definition information (ie the YAML view) for a task"""
|
34
33
|
name : str
|
35
|
-
type : Union[str,TaskSpec] = dc.Field(default_factory=list)
|
34
|
+
# type : Union[str,TaskSpec] = dc.Field(default_factory=list)
|
35
|
+
uses : str = dc.Field(default=None)
|
36
|
+
pyclass : str = dc.Field(default=None)
|
37
|
+
doc : str = dc.Field(default=None)
|
36
38
|
depends : List[Union[str,TaskSpec]] = dc.Field(default_factory=list, alias="needs")
|
37
39
|
params: Dict[str,Any] = dc.Field(default_factory=dict, alias="with")
|
38
40
|
|
@@ -0,0 +1,62 @@
|
|
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
|
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
|
+
# pyclass : str = None
|
17
|
+
|
18
|
+
# async def run(self, input : TaskData) -> TaskData:
|
19
|
+
|
20
|
+
# if self.srcdir not in sys.path:
|
21
|
+
# sys.path.insert(0, self.srcdir)
|
22
|
+
|
23
|
+
# print("sys.path: %s" % str(sys.path), flush=True)
|
24
|
+
# idx = self.params.pyclass.rfind('.')
|
25
|
+
# modname = self.params.pyclass[:idx]
|
26
|
+
# clsname = self.params.pyclass[idx+1:]
|
27
|
+
|
28
|
+
# if os.path.isfile(os.path.join(self.basedir, "my_module.py")):
|
29
|
+
# print("my_module.py exists", flush=True)
|
30
|
+
# else:
|
31
|
+
# print("my_module.py does not exist", flush=True)
|
32
|
+
|
33
|
+
# if modname in sys.modules.keys():
|
34
|
+
# module = sys.modules[modname]
|
35
|
+
# else:
|
36
|
+
# try:
|
37
|
+
# print("modname=%s" % modname, flush=True)
|
38
|
+
# module = importlib.import_module(modname)
|
39
|
+
# except ModuleNotFoundError as e:
|
40
|
+
# print("Module not found: %s syspath=%s" % (str(e), str(sys.path)), flush=True)
|
41
|
+
# raise e
|
42
|
+
|
43
|
+
# cls = getattr(module, clsname)
|
44
|
+
|
45
|
+
# obj = cls(self.name, self.task_id, self.session, self.basedir, srcdir=self.srcdir)
|
46
|
+
|
47
|
+
# return await obj.run(input)
|
48
|
+
|
49
|
+
|
50
|
+
# class TaskPyClassMemento(TaskMemento):
|
51
|
+
# pass
|
52
|
+
|
53
|
+
class TaskNull(Task):
|
54
|
+
async def run(self, input : TaskData) -> TaskData:
|
55
|
+
return input
|
56
|
+
|
57
|
+
# @dc.dataclass
|
58
|
+
# class PackageBuiltin(Package):
|
59
|
+
|
60
|
+
# def __post_init__(self):
|
61
|
+
# print("PackageBuiltin::__post_init__", flush=True)
|
62
|
+
# self.tasks["PyClass"] = TaskPyClass()
|
@@ -1,5 +1,68 @@
|
|
1
1
|
|
2
|
-
|
2
|
+
import os
|
3
|
+
import fnmatch
|
4
|
+
import glob
|
5
|
+
import pydantic.dataclasses as dc
|
6
|
+
from typing import List, Tuple
|
7
|
+
from dv_flow_mgr import Task, TaskData, TaskMemento
|
8
|
+
from dv_flow_mgr import FileSet as _FileSet
|
9
|
+
|
10
|
+
class TaskFileSetMemento(TaskMemento):
|
11
|
+
files : List[Tuple[str,float]] = dc.Field(default_factory=list)
|
3
12
|
|
4
13
|
class FileSet(Task):
|
14
|
+
|
15
|
+
async def run(self, input : TaskData) -> TaskData:
|
16
|
+
print("TaskFileSet run: %s: basedir=%s, base=%s type=%s include=%s" % (
|
17
|
+
self.name,
|
18
|
+
self.srcdir,
|
19
|
+
self.params.base, self.params.type, str(self.params.include)
|
20
|
+
))
|
21
|
+
|
22
|
+
|
23
|
+
ex_memento = self.getMemento(TaskFileSetMemento)
|
24
|
+
memento = TaskFileSetMemento()
|
25
|
+
|
26
|
+
if self.params is not None:
|
27
|
+
glob_root = os.path.join(self.srcdir, self.params.base)
|
28
|
+
|
29
|
+
print("glob_root: %s" % glob_root)
|
30
|
+
|
31
|
+
fs = _FileSet(
|
32
|
+
src=self.name,
|
33
|
+
type=self.params.type,
|
34
|
+
basedir=glob_root)
|
35
|
+
print("glob_root: %s" % glob_root)
|
36
|
+
|
37
|
+
if not isinstance(self.params.include, list):
|
38
|
+
self.params.include = [self.params.include]
|
39
|
+
|
40
|
+
included_files = []
|
41
|
+
for pattern in self.params.include:
|
42
|
+
print("pattern: %s" % pattern)
|
43
|
+
included_files.extend(glob.glob(os.path.join(glob_root, pattern), recursive=False))
|
44
|
+
|
45
|
+
for file in included_files:
|
46
|
+
if not any(glob.fnmatch.fnmatch(file, os.path.join(glob_root, pattern)) for pattern in self.params.exclude):
|
47
|
+
memento.files.append((file, os.path.getmtime(os.path.join(glob_root, file))))
|
48
|
+
fs.files.append(file[len(glob_root):])
|
49
|
+
|
50
|
+
# Check to see if the filelist or fileset have changed
|
51
|
+
# Only bother doing this if the upstream task data has not changed
|
52
|
+
if ex_memento is not None and not input.changed:
|
53
|
+
ex_memento.files.sort(key=lambda x: x[0])
|
54
|
+
memento.files.sort(key=lambda x: x[0])
|
55
|
+
print("ex_memento.files: %s" % str(ex_memento.files))
|
56
|
+
print("memento.files: %s" % str(memento.files))
|
57
|
+
input.changed = ex_memento != memento
|
58
|
+
else:
|
59
|
+
input.changed = True
|
60
|
+
|
61
|
+
self.setMemento(memento)
|
62
|
+
|
63
|
+
if fs is not None:
|
64
|
+
input.addFileSet(fs)
|
65
|
+
|
66
|
+
return input
|
67
|
+
|
5
68
|
pass
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
package:
|
3
|
+
name: std
|
4
|
+
|
5
|
+
tasks:
|
6
|
+
- name: Message
|
7
|
+
pyclass: message.Message
|
8
|
+
with:
|
9
|
+
msg:
|
10
|
+
type: str
|
11
|
+
value: ""
|
12
|
+
- name: FileSet
|
13
|
+
pyclass: fileset.FileSet
|
14
|
+
with:
|
15
|
+
base:
|
16
|
+
type: str
|
17
|
+
value: ""
|
18
|
+
type:
|
19
|
+
type: str
|
20
|
+
value: ""
|
21
|
+
include:
|
22
|
+
type: str
|
23
|
+
value: ""
|
24
|
+
exclude:
|
25
|
+
type: str
|
26
|
+
value: ""
|
{dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/RECORD
RENAMED
@@ -1,19 +1,20 @@
|
|
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
|
-
dv_flow_mgr/package.py,sha256=
|
7
|
-
dv_flow_mgr/package_def.py,sha256=
|
6
|
+
dv_flow_mgr/package.py,sha256=k6gaDun9mJeGwGsFP5YOYOaFLmKb3KyPZy5wGRgJd_E,1965
|
7
|
+
dv_flow_mgr/package_def.py,sha256=YZkXk6alkP6hjGT61EAglAHPEE-Rax8VCybIYbQ9NJs,8040
|
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
|
-
dv_flow_mgr/session.py,sha256=
|
11
|
-
dv_flow_mgr/task.py,sha256=
|
12
|
-
dv_flow_mgr/task_data.py,sha256=
|
13
|
-
dv_flow_mgr/task_def.py,sha256=
|
10
|
+
dv_flow_mgr/session.py,sha256=oj75khugWLdBe7ouAmQX9sVAMRZi6O4CdLquokIkXDY,12163
|
11
|
+
dv_flow_mgr/task.py,sha256=AIz9YI-K3riv1EQ-hArL6eYsfbWjHMoN07Ao4mRdiW8,6146
|
12
|
+
dv_flow_mgr/task_data.py,sha256=8AcFCxVmv9agzUDXnwUNJImpfp0N4jB1IHodIECf-0k,9735
|
13
|
+
dv_flow_mgr/task_def.py,sha256=w0V5FSHi8D6PFyq_3j_smO3fmJp-cAMpigWT0yU4-GY,1654
|
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=ps5SkO7s29xVzyeEw96qbMAg9Dk6UPErH2Lc87foIcs,1883
|
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
|
@@ -26,14 +27,16 @@ dv_flow_mgr/tasklib/hdl/sim/vl_task_sim_image.py,sha256=QJP1gjclUSYfq-B9NIA46C1E
|
|
26
27
|
dv_flow_mgr/tasklib/hdl/sim/vlt_pkg.py,sha256=Pu9mWAR93kiTNT8GZJrX-VDjMOfr9P5ddcSPt1BElQQ,413
|
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
|
-
dv_flow_mgr/tasklib/std/fileset.py,sha256=
|
30
|
+
dv_flow_mgr/tasklib/std/fileset.py,sha256=m7b85A81pNkkq_HM7XdDO5zdkoGvbbOCaTckEH666jg,2350
|
31
|
+
dv_flow_mgr/tasklib/std/flow.dv,sha256=d3jFrZnTqdI2IZB-lSOs5tjA_beLtuLHgjusytf2_nA,391
|
32
|
+
dv_flow_mgr/tasklib/std/message.py,sha256=O61dY00bQPCd7Ak5o-KGXh3C7a9wfZcbU_D2fiBudd8,193
|
30
33
|
dv_flow_mgr/tasklib/std/pkg_std.py,sha256=ERDd515qtetQaldk9opUH19MyNwo8nP4-GLz-ke-5gE,370
|
31
34
|
dv_flow_mgr/tasklib/std/std.dfs,sha256=An2NUvvWaR9xI4U-kRQ4NN6U-GhX6GQmd3mNyRkW4NQ,68
|
32
35
|
dv_flow_mgr/tasklib/std/task_fileset.py,sha256=ZBG4e2gsTsRMsr_FhhzIoE3J7YwYQZ9HigpxpGePd74,3145
|
33
36
|
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.
|
37
|
+
dv_flow_mgr-0.0.1.12849118090a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
38
|
+
dv_flow_mgr-0.0.1.12849118090a1.dist-info/METADATA,sha256=Si9x7uqsXSWlCl6c6eQUJ8CpIi3duJ_4rBM2QkPTJ_Q,13252
|
39
|
+
dv_flow_mgr-0.0.1.12849118090a1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
40
|
+
dv_flow_mgr-0.0.1.12849118090a1.dist-info/entry_points.txt,sha256=VHxIon5AeHCtK73fYb1veDImAGwv76hrtBiuZePmzhI,51
|
41
|
+
dv_flow_mgr-0.0.1.12849118090a1.dist-info/top_level.txt,sha256=FGuhGIxN1FgD_YBkPcDq05fTxZcwaX9G_O8FFBvrTk4,12
|
42
|
+
dv_flow_mgr-0.0.1.12849118090a1.dist-info/RECORD,,
|
{dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/LICENSE
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12761553329a1.dist-info → dv_flow_mgr-0.0.1.12849118090a1.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|
File without changes
|