dv-flow-mgr 1.0.0.14528489065a1__py3-none-any.whl → 1.5.0__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/__init__.py +4 -0
- dv_flow/mgr/cmds/cmd_run.py +6 -1
- dv_flow/mgr/cmds/cmd_show.py +3 -3
- dv_flow/mgr/config_def.py +1 -1
- dv_flow/mgr/expr_eval.py +24 -1
- dv_flow/mgr/expr_parser.py +26 -1
- dv_flow/mgr/package.py +13 -6
- dv_flow/mgr/package_def.py +3 -4
- dv_flow/mgr/package_loader.py +252 -120
- dv_flow/mgr/param_def.py +7 -2
- dv_flow/mgr/param_ref_eval.py +3 -0
- dv_flow/mgr/parser.out +258 -138
- dv_flow/mgr/parsetab.py +20 -17
- dv_flow/mgr/std/flow.dv +31 -53
- dv_flow/mgr/std/incdirs.py +18 -0
- dv_flow/mgr/task.py +1 -0
- dv_flow/mgr/task_def.py +5 -1
- dv_flow/mgr/task_graph_builder.py +265 -24
- dv_flow/mgr/task_graph_dot_writer.py +32 -3
- dv_flow/mgr/task_listener_log.py +46 -31
- dv_flow/mgr/task_node.py +3 -0
- dv_flow/mgr/task_node_compound.py +1 -0
- dv_flow/mgr/task_node_ctor_wrapper.py +3 -1
- dv_flow/mgr/task_node_ctxt.py +7 -0
- dv_flow/mgr/task_node_leaf.py +77 -54
- dv_flow/mgr/task_run_ctxt.py +18 -0
- dv_flow/mgr/task_runner.py +8 -5
- dv_flow/mgr/type.py +33 -0
- dv_flow/mgr/type_def.py +4 -2
- dv_flow/mgr/util/util.py +9 -0
- dv_flow/mgr/yaml_srcinfo_loader.py +1 -0
- {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/METADATA +1 -1
- {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/RECORD +37 -35
- {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/WHEEL +1 -1
- {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/entry_points.txt +0 -0
- {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/licenses/LICENSE +0 -0
- {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/top_level.txt +0 -0
dv_flow/mgr/package_loader.py
CHANGED
@@ -10,29 +10,38 @@ from typing import Any, Callable, ClassVar, Dict, List, Tuple
|
|
10
10
|
from .fragment_def import FragmentDef
|
11
11
|
from .package_def import PackageDef
|
12
12
|
from .package import Package
|
13
|
+
from .param_def import ComplexType
|
13
14
|
from .ext_rgy import ExtRgy
|
14
15
|
from .srcinfo import SrcInfo
|
15
16
|
from .task import Task
|
16
17
|
from .task_def import TaskDef, PassthroughE, ConsumesE, RundirE
|
17
18
|
from .task_data import TaskMarker, TaskMarkerLoc, SeverityE
|
19
|
+
from .type import Type
|
18
20
|
from .yaml_srcinfo_loader import YamlSrcInfoLoader
|
19
21
|
|
20
22
|
@dc.dataclass
|
21
23
|
class SymbolScope(object):
|
22
24
|
name : str
|
23
25
|
task_m : Dict[str,Task] = dc.field(default_factory=dict)
|
26
|
+
type_m : Dict[str,Type] = dc.field(default_factory=dict)
|
24
27
|
|
25
28
|
def add(self, task, name):
|
26
29
|
self.task_m[name] = task
|
27
30
|
|
28
|
-
def
|
31
|
+
def addType(self, type, name):
|
32
|
+
self.type_m[name] = type
|
33
|
+
|
34
|
+
def findTask(self, name) -> Task:
|
29
35
|
if name in self.task_m.keys():
|
30
36
|
return self.task_m[name]
|
31
37
|
else:
|
32
38
|
return None
|
33
39
|
|
34
|
-
def findType(self, name) ->
|
35
|
-
|
40
|
+
def findType(self, name) -> Type:
|
41
|
+
if name in self.type_m.keys():
|
42
|
+
return self.type_m[name]
|
43
|
+
else:
|
44
|
+
return None
|
36
45
|
|
37
46
|
|
38
47
|
@dc.dataclass
|
@@ -42,19 +51,25 @@ class TaskScope(SymbolScope):
|
|
42
51
|
@dc.dataclass
|
43
52
|
class LoaderScope(SymbolScope):
|
44
53
|
loader : 'PackageLoader' = None
|
54
|
+
_log : ClassVar = logging.getLogger("LoaderScope")
|
45
55
|
|
46
56
|
def add(self, task, name):
|
47
57
|
raise NotImplementedError("LoaderScope.add() not implemented")
|
58
|
+
|
59
|
+
def addType(self, task, name):
|
60
|
+
raise NotImplementedError("LoaderScope.addType() not implemented")
|
48
61
|
|
49
|
-
def
|
50
|
-
|
62
|
+
def findTask(self, name) -> Task:
|
63
|
+
self._log.debug("--> findTask: %s" % name)
|
51
64
|
|
52
|
-
|
53
|
-
last_dot = name.rfind('.')
|
65
|
+
ret = None
|
54
66
|
pkg = None
|
55
|
-
|
56
|
-
|
57
|
-
|
67
|
+
|
68
|
+
# Split the name into elements
|
69
|
+
name_elems = name.split('.')
|
70
|
+
|
71
|
+
def find_pkg(pkg_name):
|
72
|
+
pkg = None
|
58
73
|
|
59
74
|
if pkg_name in self.loader._pkg_m.keys():
|
60
75
|
pkg = self.loader._pkg_m[pkg_name]
|
@@ -64,10 +79,50 @@ class LoaderScope(SymbolScope):
|
|
64
79
|
path = os.path.normpath(path)
|
65
80
|
pkg = self.loader._loadPackage(path)
|
66
81
|
self.loader._pkg_m[pkg_name] = pkg
|
67
|
-
if pkg is not None
|
68
|
-
|
82
|
+
if pkg is not None:
|
83
|
+
self._log.debug("Found pkg %s (%s)" % (pkg_name, str(pkg.task_m.keys())))
|
84
|
+
else:
|
85
|
+
self._log.debug("Failed to find pkg %s" % pkg_name)
|
86
|
+
|
87
|
+
return pkg
|
88
|
+
|
89
|
+
if len(name_elems) > 1:
|
90
|
+
for i in range(len(name_elems)-1, -1, -1):
|
91
|
+
pkg_name = ".".join(name_elems[:i+1])
|
92
|
+
|
93
|
+
pkg = find_pkg(pkg_name)
|
94
|
+
if pkg is not None:
|
95
|
+
break;
|
96
|
+
else:
|
97
|
+
raise Exception("Task name %s is not fully qualified" % name)
|
98
|
+
|
99
|
+
if pkg is not None and name in pkg.task_m.keys():
|
100
|
+
ret = pkg.task_m[name]
|
101
|
+
|
102
|
+
self._log.debug("<-- findTask: %s (%s)" % (name, str(ret)))
|
103
|
+
|
104
|
+
return ret
|
105
|
+
|
106
|
+
def findType(self, name) -> Type:
|
107
|
+
self._log.debug("--> findType: %s" % name)
|
108
|
+
ret = None
|
109
|
+
last_dot = name.rfind('.')
|
110
|
+
if last_dot != -1:
|
111
|
+
pkg_name = name[:last_dot]
|
112
|
+
|
113
|
+
if pkg_name in self.loader._pkg_m.keys():
|
114
|
+
pkg = self.loader._pkg_m[pkg_name]
|
69
115
|
else:
|
70
|
-
|
116
|
+
path = self.loader.pkg_rgy.findPackagePath(pkg_name)
|
117
|
+
if path is not None:
|
118
|
+
pkg = self.loader._loadPackage(path)
|
119
|
+
self.loader._pkg_m[pkg_name] = pkg
|
120
|
+
if pkg is not None and name in pkg.type_m.keys():
|
121
|
+
ret = pkg.type_m[name]
|
122
|
+
|
123
|
+
self._log.debug("<-- findType: %s (%s)" % (name, str(ret)))
|
124
|
+
|
125
|
+
return ret
|
71
126
|
|
72
127
|
@dc.dataclass
|
73
128
|
class PackageScope(SymbolScope):
|
@@ -81,6 +136,12 @@ class PackageScope(SymbolScope):
|
|
81
136
|
self._scope_s[-1].add(task, name)
|
82
137
|
else:
|
83
138
|
super().add(task, name)
|
139
|
+
|
140
|
+
def addType(self, type, name):
|
141
|
+
if len(self._scope_s):
|
142
|
+
self._scope_s[-1].addType(type, name)
|
143
|
+
else:
|
144
|
+
super().addType(type, name)
|
84
145
|
|
85
146
|
def push_scope(self, scope):
|
86
147
|
self._scope_s.append(scope)
|
@@ -88,17 +149,17 @@ class PackageScope(SymbolScope):
|
|
88
149
|
def pop_scope(self):
|
89
150
|
self._scope_s.pop()
|
90
151
|
|
91
|
-
def
|
92
|
-
self._log.debug("--> %s::
|
152
|
+
def findTask(self, name) -> Task:
|
153
|
+
self._log.debug("--> %s::findTask %s" % (self.pkg.name, name))
|
93
154
|
ret = None
|
94
155
|
for i in range(len(self._scope_s)-1, -1, -1):
|
95
156
|
scope = self._scope_s[i]
|
96
|
-
ret = scope.
|
157
|
+
ret = scope.findTask(name)
|
97
158
|
if ret is not None:
|
98
159
|
break
|
99
160
|
|
100
161
|
if ret is None:
|
101
|
-
ret = super().
|
162
|
+
ret = super().findTask(name)
|
102
163
|
|
103
164
|
if ret is None and name in self.pkg.task_m.keys():
|
104
165
|
ret = self.pkg.task_m[name]
|
@@ -112,33 +173,38 @@ class PackageScope(SymbolScope):
|
|
112
173
|
|
113
174
|
if ret is None:
|
114
175
|
self._log.debug("Searching loader for %s" % name)
|
115
|
-
ret = self.loader.
|
176
|
+
ret = self.loader.findTask(name)
|
116
177
|
|
117
|
-
self._log.debug("<-- %s::
|
178
|
+
self._log.debug("<-- %s::findTask %s (%s)" % (self.pkg.name, name, ("found" if ret is not None else "not found")))
|
118
179
|
return ret
|
119
180
|
|
120
|
-
def findType(self, name) ->
|
181
|
+
def findType(self, name) -> Type:
|
182
|
+
self._log.debug("--> %s::findType %s" % (self.pkg.name, name))
|
121
183
|
ret = None
|
184
|
+
for i in range(len(self._scope_s)-1, -1, -1):
|
185
|
+
scope = self._scope_s[i]
|
186
|
+
ret = scope.findType(name)
|
187
|
+
if ret is not None:
|
188
|
+
break
|
122
189
|
|
123
|
-
if name in self.task_m.keys():
|
124
|
-
ret = self.task_m[name]
|
125
|
-
|
126
|
-
if ret is None:
|
127
|
-
for i in range(len(self._scope_s)-1, -1, -1):
|
128
|
-
scope = self._scope_s[i]
|
129
|
-
ret = scope.findType(name)
|
130
|
-
if ret is not None:
|
131
|
-
break
|
132
|
-
|
133
190
|
if ret is None:
|
134
191
|
ret = super().findType(name)
|
135
192
|
|
136
|
-
if ret is None and name in self.pkg.
|
137
|
-
ret = self.pkg.
|
193
|
+
if ret is None and name in self.pkg.type_m.keys():
|
194
|
+
ret = self.pkg.type_m[name]
|
195
|
+
|
196
|
+
if ret is None:
|
197
|
+
for pkg in self.pkg.pkg_m.values():
|
198
|
+
self._log.debug("Searching pkg %s for %s" % (pkg.name, name))
|
199
|
+
if name in pkg.type_m.keys():
|
200
|
+
ret = pkg.type_m[name]
|
201
|
+
break
|
138
202
|
|
139
203
|
if ret is None:
|
204
|
+
self._log.debug("Searching loader for %s" % name)
|
140
205
|
ret = self.loader.findType(name)
|
141
|
-
|
206
|
+
|
207
|
+
self._log.debug("<-- %s::findType %s (%s)" % (self.pkg.name, name, ("found" if ret is not None else "not found")))
|
142
208
|
return ret
|
143
209
|
|
144
210
|
def getScopeFullname(self, leaf=None) -> str:
|
@@ -246,7 +312,8 @@ class PackageLoader(object):
|
|
246
312
|
loc_s += "." + str(el)
|
247
313
|
else:
|
248
314
|
loc_s = str(el)
|
249
|
-
obj
|
315
|
+
if hasattr(obj, "__getitem__"):
|
316
|
+
obj = obj[el]
|
250
317
|
if type(obj) == dict and 'srcinfo' in obj.keys():
|
251
318
|
loc = obj['srcinfo']
|
252
319
|
if loc is not None:
|
@@ -284,6 +351,14 @@ class PackageLoader(object):
|
|
284
351
|
os.path.dirname(root),
|
285
352
|
srcinfo=SrcInfo(file=root))
|
286
353
|
|
354
|
+
# TODO: handle 'uses' for packages
|
355
|
+
pkg.paramT = self._getParamT(pkg_def, None)
|
356
|
+
|
357
|
+
pkg_scope = self.package_scope()
|
358
|
+
if pkg_scope is not None:
|
359
|
+
self._log.debug("Add self (%s) as a subpkg of %s" % (pkg.name, pkg_scope.pkg.name))
|
360
|
+
pkg_scope.pkg.pkg_m[pkg.name] = pkg
|
361
|
+
|
287
362
|
if pkg.name in self._pkg_m.keys():
|
288
363
|
epkg = self._pkg_m[pkg.name]
|
289
364
|
if epkg.srcinfo.file != pkg.srcinfo.file:
|
@@ -301,9 +376,11 @@ class PackageLoader(object):
|
|
301
376
|
self._loadPackageImports(pkg, pkg_def.imports, pkg.basedir)
|
302
377
|
|
303
378
|
taskdefs = pkg_def.tasks.copy()
|
379
|
+
typedefs = pkg_def.types.copy()
|
304
380
|
|
305
|
-
self._loadFragments(pkg, pkg_def.fragments, pkg.basedir, taskdefs)
|
381
|
+
self._loadFragments(pkg, pkg_def.fragments, pkg.basedir, taskdefs, typedefs)
|
306
382
|
|
383
|
+
self._loadTypes(pkg, typedefs)
|
307
384
|
self._loadTasks(pkg, taskdefs, pkg.basedir)
|
308
385
|
|
309
386
|
self._pkg_s.pop()
|
@@ -335,7 +412,7 @@ class PackageLoader(object):
|
|
335
412
|
if not os.path.isabs(imp_path):
|
336
413
|
self._log.debug("_basedir: %s ; imp_path: %s" % (basedir, imp_path))
|
337
414
|
imp_path = os.path.join(basedir, imp_path)
|
338
|
-
|
415
|
+
|
339
416
|
# Search down the tree looking for a flow.dv file
|
340
417
|
if os.path.isdir(imp_path):
|
341
418
|
path = imp_path
|
@@ -371,11 +448,11 @@ class PackageLoader(object):
|
|
371
448
|
self._log.debug("<-- _loadPackageImport %s" % str(imp))
|
372
449
|
pass
|
373
450
|
|
374
|
-
def _loadFragments(self, pkg, fragments, basedir, taskdefs):
|
451
|
+
def _loadFragments(self, pkg, fragments, basedir, taskdefs, typedefs):
|
375
452
|
for spec in fragments:
|
376
|
-
self._loadFragmentSpec(pkg, spec, basedir, taskdefs)
|
453
|
+
self._loadFragmentSpec(pkg, spec, basedir, taskdefs, typedefs)
|
377
454
|
|
378
|
-
def _loadFragmentSpec(self, pkg, spec, basedir, taskdefs):
|
455
|
+
def _loadFragmentSpec(self, pkg, spec, basedir, taskdefs, typedefs):
|
379
456
|
# We're either going to have:
|
380
457
|
# - File path
|
381
458
|
# - Directory path
|
@@ -384,20 +461,20 @@ class PackageLoader(object):
|
|
384
461
|
self._loadFragmentFile(
|
385
462
|
pkg,
|
386
463
|
os.path.join(basedir, spec),
|
387
|
-
taskdefs)
|
464
|
+
taskdefs, typedefs)
|
388
465
|
elif os.path.isdir(os.path.join(basedir, spec)):
|
389
|
-
self._loadFragmentDir(pkg, os.path.join(basedir, spec), taskdefs)
|
466
|
+
self._loadFragmentDir(pkg, os.path.join(basedir, spec), taskdefs, typedefs)
|
390
467
|
else:
|
391
468
|
raise Exception("Fragment spec %s not found" % spec)
|
392
469
|
|
393
|
-
def _loadFragmentDir(self, pkg, dir, taskdefs):
|
470
|
+
def _loadFragmentDir(self, pkg, dir, taskdefs, typedefs):
|
394
471
|
for file in os.listdir(dir):
|
395
472
|
if os.path.isdir(os.path.join(dir, file)):
|
396
|
-
self._loadFragmentDir(pkg, os.path.join(dir, file), taskdefs)
|
473
|
+
self._loadFragmentDir(pkg, os.path.join(dir, file), taskdefs, typedefs)
|
397
474
|
elif os.path.isfile(os.path.join(dir, file)) and file == "flow.dv":
|
398
|
-
self._loadFragmentFile(pkg, os.path.join(dir, file), taskdefs)
|
475
|
+
self._loadFragmentFile(pkg, os.path.join(dir, file), taskdefs, typedefs)
|
399
476
|
|
400
|
-
def _loadFragmentFile(self, pkg, file, taskdefs):
|
477
|
+
def _loadFragmentFile(self, pkg, file, taskdefs, typedefs):
|
401
478
|
if file in self._file_s:
|
402
479
|
raise Exception("Recursive file processing @ %s: %s" % (file, ", ".join(self._file_s)))
|
403
480
|
self._file_s.append(file)
|
@@ -406,13 +483,45 @@ class PackageLoader(object):
|
|
406
483
|
doc = yaml.load(fp, Loader=YamlSrcInfoLoader(file))
|
407
484
|
self._log.debug("doc: %s" % str(doc))
|
408
485
|
if doc is not None and "fragment" in doc.keys():
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
486
|
+
try:
|
487
|
+
frag = FragmentDef(**(doc["fragment"]))
|
488
|
+
basedir = os.path.dirname(file)
|
489
|
+
pkg.fragment_def_l.append(frag)
|
490
|
+
|
491
|
+
self._loadPackageImports(pkg, frag.imports, basedir)
|
492
|
+
self._loadFragments(pkg, frag.fragments, basedir, taskdefs, typedefs)
|
493
|
+
taskdefs.extend(frag.tasks)
|
494
|
+
typedefs.extend(frag.types)
|
495
|
+
except pydantic.ValidationError as e:
|
496
|
+
print("Errors: %s" % file)
|
497
|
+
error_paths = []
|
498
|
+
loc = None
|
499
|
+
for ee in e.errors():
|
500
|
+
# print(" Error: %s" % str(ee))
|
501
|
+
obj = doc["fragment"]
|
502
|
+
loc = None
|
503
|
+
for el in ee['loc']:
|
504
|
+
print("el: %s" % str(el))
|
505
|
+
obj = obj[el]
|
506
|
+
if type(obj) == dict and 'srcinfo' in obj.keys():
|
507
|
+
loc = obj['srcinfo']
|
508
|
+
if loc is not None:
|
509
|
+
marker_loc = TaskMarkerLoc(path=loc['file'])
|
510
|
+
if 'lineno' in loc.keys():
|
511
|
+
marker_loc.line = loc['lineno']
|
512
|
+
if 'linepos' in loc.keys():
|
513
|
+
marker_loc.pos = loc['linepos']
|
514
|
+
|
515
|
+
marker = TaskMarker(
|
516
|
+
msg=("%s (in %s)" % (ee['msg'], str(ee['loc'][-1]))),
|
517
|
+
severity=SeverityE.Error,
|
518
|
+
loc=marker_loc)
|
519
|
+
else:
|
520
|
+
marker = TaskMarker(
|
521
|
+
msg=ee['msg'],
|
522
|
+
severity=SeverityE.Error,
|
523
|
+
loc=TaskMarkerLoc(path=file))
|
524
|
+
self.marker(marker)
|
416
525
|
else:
|
417
526
|
print("Warning: file %s is not a fragment" % file)
|
418
527
|
|
@@ -441,6 +550,10 @@ class PackageLoader(object):
|
|
441
550
|
desc=desc,
|
442
551
|
doc=doc,
|
443
552
|
srcinfo=taskdef.srcinfo)
|
553
|
+
|
554
|
+
if taskdef.iff is not None:
|
555
|
+
task.iff = taskdef.iff
|
556
|
+
|
444
557
|
tasks.append((taskdef, task))
|
445
558
|
pkg.task_m[task.name] = task
|
446
559
|
self._pkg_s[-1].add(task, taskdef.name)
|
@@ -449,10 +562,11 @@ class PackageLoader(object):
|
|
449
562
|
for taskdef, task in tasks:
|
450
563
|
|
451
564
|
if taskdef.uses is not None:
|
452
|
-
task.uses = self.
|
565
|
+
task.uses = self._findTask(taskdef.uses)
|
453
566
|
|
454
567
|
if task.uses is None:
|
455
|
-
|
568
|
+
self.error("failed to resolve task-uses %s" % taskdef.uses, taskdef.srcinfo)
|
569
|
+
continue
|
456
570
|
|
457
571
|
passthrough, consumes, rundir = self._getPTConsumesRundir(taskdef, task.uses)
|
458
572
|
|
@@ -474,6 +588,7 @@ class PackageLoader(object):
|
|
474
588
|
raise Exception("Unknown need type %s" % str(type(need)))
|
475
589
|
|
476
590
|
if nt is None:
|
591
|
+
self.error("failed to find task %s" % need, taskdef.srcinfo)
|
477
592
|
raise Exception("Failed to find task %s" % need)
|
478
593
|
task.needs.append(nt)
|
479
594
|
|
@@ -492,6 +607,31 @@ class PackageLoader(object):
|
|
492
607
|
|
493
608
|
self._log.debug("<-- _loadTasks %s" % pkg.name)
|
494
609
|
|
610
|
+
def _loadTypes(self, pkg, typedefs):
|
611
|
+
self._log.debug("--> _loadTypes")
|
612
|
+
types = []
|
613
|
+
for td in typedefs:
|
614
|
+
tt = Type(
|
615
|
+
name=self._getScopeFullname(td.name),
|
616
|
+
doc=td.doc,
|
617
|
+
srcinfo=td.srcinfo)
|
618
|
+
pkg.type_m[tt.name] = tt
|
619
|
+
self._pkg_s[-1].addType(tt, td.name)
|
620
|
+
types.append((td, tt))
|
621
|
+
|
622
|
+
# Now, resolve 'uses' and build out
|
623
|
+
for td,tt in types:
|
624
|
+
if td.uses is not None:
|
625
|
+
tt.uses = self._findType(td.uses)
|
626
|
+
if tt.uses is None:
|
627
|
+
raise Exception("Failed to find type %s" % td.uses)
|
628
|
+
tt.paramT = self._getParamT(
|
629
|
+
td,
|
630
|
+
tt.uses.paramT if tt.uses is not None else None,
|
631
|
+
typename=tt.name)
|
632
|
+
self._log.debug("<-- _loadTypes")
|
633
|
+
pass
|
634
|
+
|
495
635
|
def _mkTaskBody(self, task, taskdef):
|
496
636
|
self._pkg_s[-1].push_scope(TaskScope(name=taskdef.name))
|
497
637
|
|
@@ -514,6 +654,10 @@ class PackageLoader(object):
|
|
514
654
|
desc=desc,
|
515
655
|
doc=doc,
|
516
656
|
srcinfo=td.srcinfo)
|
657
|
+
|
658
|
+
if td.iff is not None:
|
659
|
+
st.iff = td.iff
|
660
|
+
|
517
661
|
subtasks.append((td, st))
|
518
662
|
task.subtasks.append(st)
|
519
663
|
self._pkg_s[-1].add(st, td.name)
|
@@ -522,9 +666,10 @@ class PackageLoader(object):
|
|
522
666
|
for td, st in subtasks:
|
523
667
|
if td.uses is not None:
|
524
668
|
if st.uses is None:
|
525
|
-
st.uses = self.
|
669
|
+
st.uses = self._findTask(td.uses)
|
526
670
|
if st.uses is None:
|
527
|
-
|
671
|
+
self.error("failed to find task %s" % td.uses, td.srcinfo)
|
672
|
+
# raise Exception("Failed to find task %s" % td.uses)
|
528
673
|
|
529
674
|
passthrough, consumes, rundir = self._getPTConsumesRundir(td, st.uses)
|
530
675
|
|
@@ -533,12 +678,19 @@ class PackageLoader(object):
|
|
533
678
|
st.rundir = rundir
|
534
679
|
|
535
680
|
for need in td.needs:
|
681
|
+
nn = None
|
536
682
|
if isinstance(need, str):
|
537
|
-
|
683
|
+
nn = self._findTask(need)
|
538
684
|
elif isinstance(need, TaskDef):
|
539
|
-
|
685
|
+
nn = self._findTask(need.name)
|
540
686
|
else:
|
541
687
|
raise Exception("Unknown need type %s" % str(type(need)))
|
688
|
+
|
689
|
+
if nn is None:
|
690
|
+
self.error("failed to find task %s" % need, td.srcinfo)
|
691
|
+
# raise Exception("failed to find task %s" % need)
|
692
|
+
|
693
|
+
st.needs.append(nn)
|
542
694
|
|
543
695
|
if td.body is not None and len(td.body) > 0:
|
544
696
|
self._mkTaskBody(st, td)
|
@@ -563,17 +715,17 @@ class PackageLoader(object):
|
|
563
715
|
|
564
716
|
self._pkg_s[-1].pop_scope()
|
565
717
|
|
566
|
-
def
|
718
|
+
def _findType(self, name):
|
567
719
|
if len(self._pkg_s):
|
568
|
-
return self._pkg_s[-1].
|
720
|
+
return self._pkg_s[-1].findType(name)
|
569
721
|
else:
|
570
|
-
return self._loader_scope.
|
722
|
+
return self._loader_scope.findType(name)
|
571
723
|
|
572
724
|
def _findTask(self, name):
|
573
725
|
if len(self._pkg_s):
|
574
|
-
return self._pkg_s[-1].
|
726
|
+
return self._pkg_s[-1].findTask(name)
|
575
727
|
else:
|
576
|
-
return self._loader_scope.
|
728
|
+
return self._loader_scope.findTask(name)
|
577
729
|
|
578
730
|
|
579
731
|
def _getScopeFullname(self, leaf=None):
|
@@ -583,44 +735,6 @@ class PackageLoader(object):
|
|
583
735
|
# Determine
|
584
736
|
pass
|
585
737
|
|
586
|
-
# def _mkPackage(self, pkg : PackageDef, params : Dict[str,Any] = None) -> 'Package':
|
587
|
-
# self._log.debug("--> mkPackage %s" % pkg.name)
|
588
|
-
# ret = Package(pkg.name)
|
589
|
-
|
590
|
-
# self.push_package(ret, add=True)
|
591
|
-
|
592
|
-
# tasks_m : Dict[str,str,TaskNodeCtor]= {}
|
593
|
-
|
594
|
-
# for task in ret.tasks:
|
595
|
-
# if task.name in tasks_m.keys():
|
596
|
-
# raise Exception("Duplicate task %s" % task.name)
|
597
|
-
# tasks_m[task.name] = (task, self._basedir, ) # We'll add a TaskNodeCtor later
|
598
|
-
|
599
|
-
# for frag in pkg._fragment_l:
|
600
|
-
# for task in frag.tasks:
|
601
|
-
# if task.name in tasks_m.keys():
|
602
|
-
# raise Exception("Duplicate task %s" % task.name)
|
603
|
-
# tasks_m[task.name] = (task, frag._basedir, ) # We'll add a TaskNodeCtor later
|
604
|
-
|
605
|
-
# # Now we have a unified map of the tasks declared in this package
|
606
|
-
# for name in list(tasks_m.keys()):
|
607
|
-
# task_i = tasks_m[name]
|
608
|
-
# fullname = pkg.name + "." + name
|
609
|
-
# if len(task_i) < 3:
|
610
|
-
# # Need to create the task ctor
|
611
|
-
# # TODO:
|
612
|
-
# ctor_t = self.mkTaskCtor(task_i[0], task_i[1], tasks_m)
|
613
|
-
# tasks_m[name] = (task_i[0], task_i[1], ctor_t)
|
614
|
-
# ret.tasks[name] = tasks_m[name][2]
|
615
|
-
# ret.tasks[fullname] = tasks_m[name][2]
|
616
|
-
|
617
|
-
# self.pop_package(ret)
|
618
|
-
|
619
|
-
# self._log.debug("<-- mkPackage %s" % pkg.name)
|
620
|
-
# return ret
|
621
|
-
|
622
|
-
|
623
|
-
|
624
738
|
def _getPTConsumesRundir(self, taskdef : TaskDef, base_t : Task):
|
625
739
|
self._log.debug("_getPTConsumesRundir %s" % taskdef.name)
|
626
740
|
passthrough = taskdef.passthrough
|
@@ -644,7 +758,7 @@ class PackageLoader(object):
|
|
644
758
|
|
645
759
|
return (passthrough, consumes, rundir)
|
646
760
|
|
647
|
-
def _getParamT(self, taskdef, base_t : BaseModel):
|
761
|
+
def _getParamT(self, taskdef, base_t : BaseModel, typename=None):
|
648
762
|
self._log.debug("--> _getParamT %s" % taskdef.name)
|
649
763
|
# Get the base parameter type (if available)
|
650
764
|
# We will build a new type with updated fields
|
@@ -686,32 +800,49 @@ class PackageLoader(object):
|
|
686
800
|
param = taskdef.params[p]
|
687
801
|
self._log.debug("param: %s %s (%s)" % (p, str(param), str(type(param))))
|
688
802
|
if hasattr(param, "type") and param.type is not None:
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
803
|
+
if isinstance(param.type, ComplexType):
|
804
|
+
if param.type.list is not None:
|
805
|
+
ptype = List
|
806
|
+
pdflt = []
|
807
|
+
elif param.type.map is not None:
|
808
|
+
ptype = Dict
|
809
|
+
pdflt = {}
|
810
|
+
else:
|
811
|
+
raise Exception("Complex type %s not supported" % str(param.type))
|
812
|
+
pass
|
813
|
+
else:
|
814
|
+
ptype_s = param.type
|
815
|
+
if ptype_s not in ptype_m.keys():
|
816
|
+
raise Exception("Unknown type %s" % ptype_s)
|
817
|
+
ptype = ptype_m[ptype_s]
|
818
|
+
pdflt = pdflt_m[ptype_s]
|
693
819
|
|
694
820
|
if p in field_m.keys():
|
695
821
|
raise Exception("Duplicate field %s" % p)
|
696
822
|
if param.value is not None:
|
697
823
|
field_m[p] = (ptype, param.value)
|
698
824
|
else:
|
699
|
-
field_m[p] = (ptype,
|
825
|
+
field_m[p] = (ptype, pdflt)
|
700
826
|
self._log.debug("Set param=%s to %s" % (p, str(field_m[p][1])))
|
701
827
|
else:
|
702
|
-
if p
|
703
|
-
|
704
|
-
|
705
|
-
value
|
706
|
-
|
707
|
-
|
828
|
+
if p in field_m.keys():
|
829
|
+
if type(param) != dict:
|
830
|
+
value = param
|
831
|
+
elif "value" in param.keys():
|
832
|
+
value = param["value"]
|
833
|
+
else:
|
834
|
+
raise Exception("No value specified for param %s: %s" % (
|
835
|
+
p, str(param)))
|
836
|
+
field_m[p] = (field_m[p][0], value)
|
837
|
+
self._log.debug("Set param=%s to %s" % (p, str(field_m[p][1])))
|
708
838
|
else:
|
709
|
-
|
710
|
-
p, str(param)))
|
711
|
-
field_m[p] = (field_m[p][0], value)
|
712
|
-
self._log.debug("Set param=%s to %s" % (p, str(field_m[p][1])))
|
839
|
+
self.error("Field %s not found in task %s" % (p, taskdef.name), taskdef.srcinfo)
|
713
840
|
|
714
|
-
|
841
|
+
if typename is not None:
|
842
|
+
field_m["type"] = (str, typename)
|
843
|
+
params_t = pydantic.create_model(typename, **field_m)
|
844
|
+
else:
|
845
|
+
params_t = pydantic.create_model("Task%sParams" % taskdef.name, **field_m)
|
715
846
|
|
716
847
|
self._log.debug("== Params")
|
717
848
|
for name,info in params_t.model_fields.items():
|
@@ -720,14 +851,15 @@ class PackageLoader(object):
|
|
720
851
|
self._log.debug("<-- _getParamT %s" % taskdef.name)
|
721
852
|
return params_t
|
722
853
|
|
723
|
-
def error(self, msg, loc=None):
|
854
|
+
def error(self, msg, loc : SrcInfo =None):
|
724
855
|
if loc is not None:
|
725
856
|
marker = TaskMarker(msg=msg, severity=SeverityE.Error,
|
726
|
-
loc=loc)
|
857
|
+
loc=TaskMarkerLoc(path=loc.file, line=loc.lineno, pos=loc.linepos))
|
727
858
|
else:
|
728
859
|
marker = TaskMarker(msg=msg, severity=SeverityE.Error)
|
729
860
|
self.marker(marker)
|
730
861
|
|
731
862
|
def marker(self, marker):
|
863
|
+
print("listeners: %d" % len(self.marker_listeners))
|
732
864
|
for l in self.marker_listeners:
|
733
865
|
l(marker)
|
dv_flow/mgr/param_def.py
CHANGED
@@ -19,6 +19,7 @@
|
|
19
19
|
#* Author:
|
20
20
|
#*
|
21
21
|
#****************************************************************************
|
22
|
+
import enum
|
22
23
|
from typing import Any, List, Union
|
23
24
|
from pydantic import BaseModel, Field, model_validator
|
24
25
|
|
@@ -30,7 +31,7 @@ class MapType(BaseModel):
|
|
30
31
|
# key : Union[str, 'ComplexType']
|
31
32
|
# item : Union[str, 'ComplexType']
|
32
33
|
key : Union[str, Any]
|
33
|
-
|
34
|
+
val : Union[str, Any]
|
34
35
|
|
35
36
|
class ComplexType(BaseModel):
|
36
37
|
list : Union[ListType, None] = None
|
@@ -38,10 +39,14 @@ class ComplexType(BaseModel):
|
|
38
39
|
# list : Union[Any, None] = None
|
39
40
|
# map : Union[Any, None] = None
|
40
41
|
|
42
|
+
class VisibilityE(enum.Enum):
|
43
|
+
LOCAL = "local"
|
44
|
+
EXPORT = "export"
|
45
|
+
|
41
46
|
class ParamDef(BaseModel):
|
42
47
|
doc : str = None
|
43
48
|
type : Union[str, 'ComplexType'] = None
|
44
|
-
derived : bool = Field(default=False)
|
49
|
+
# derived : bool = Field(default=False)
|
45
50
|
value : Union[Any, None] = None
|
46
51
|
append : Union[Any, None] = None
|
47
52
|
prepend : Union[Any, None] = None
|
dv_flow/mgr/param_ref_eval.py
CHANGED