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.
Files changed (37) hide show
  1. dv_flow/mgr/__init__.py +4 -0
  2. dv_flow/mgr/cmds/cmd_run.py +6 -1
  3. dv_flow/mgr/cmds/cmd_show.py +3 -3
  4. dv_flow/mgr/config_def.py +1 -1
  5. dv_flow/mgr/expr_eval.py +24 -1
  6. dv_flow/mgr/expr_parser.py +26 -1
  7. dv_flow/mgr/package.py +13 -6
  8. dv_flow/mgr/package_def.py +3 -4
  9. dv_flow/mgr/package_loader.py +252 -120
  10. dv_flow/mgr/param_def.py +7 -2
  11. dv_flow/mgr/param_ref_eval.py +3 -0
  12. dv_flow/mgr/parser.out +258 -138
  13. dv_flow/mgr/parsetab.py +20 -17
  14. dv_flow/mgr/std/flow.dv +31 -53
  15. dv_flow/mgr/std/incdirs.py +18 -0
  16. dv_flow/mgr/task.py +1 -0
  17. dv_flow/mgr/task_def.py +5 -1
  18. dv_flow/mgr/task_graph_builder.py +265 -24
  19. dv_flow/mgr/task_graph_dot_writer.py +32 -3
  20. dv_flow/mgr/task_listener_log.py +46 -31
  21. dv_flow/mgr/task_node.py +3 -0
  22. dv_flow/mgr/task_node_compound.py +1 -0
  23. dv_flow/mgr/task_node_ctor_wrapper.py +3 -1
  24. dv_flow/mgr/task_node_ctxt.py +7 -0
  25. dv_flow/mgr/task_node_leaf.py +77 -54
  26. dv_flow/mgr/task_run_ctxt.py +18 -0
  27. dv_flow/mgr/task_runner.py +8 -5
  28. dv_flow/mgr/type.py +33 -0
  29. dv_flow/mgr/type_def.py +4 -2
  30. dv_flow/mgr/util/util.py +9 -0
  31. dv_flow/mgr/yaml_srcinfo_loader.py +1 -0
  32. {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/METADATA +1 -1
  33. {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/RECORD +37 -35
  34. {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/WHEEL +1 -1
  35. {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/entry_points.txt +0 -0
  36. {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/licenses/LICENSE +0 -0
  37. {dv_flow_mgr-1.0.0.14528489065a1.dist-info → dv_flow_mgr-1.5.0.dist-info}/top_level.txt +0 -0
@@ -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 find(self, name) -> Task:
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) -> Task:
35
- pass
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 find(self, name) -> Task:
50
- return self.findType(name)
62
+ def findTask(self, name) -> Task:
63
+ self._log.debug("--> findTask: %s" % name)
51
64
 
52
- def findType(self, name) -> Task:
53
- last_dot = name.rfind('.')
65
+ ret = None
54
66
  pkg = None
55
- if last_dot != -1:
56
- pkg_name = name[:last_dot]
57
- task_name = name[last_dot+1:]
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 and name in pkg.task_m.keys():
68
- return pkg.task_m[name]
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
- return None
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 find(self, name) -> Task:
92
- self._log.debug("--> %s::find %s" % (self.pkg.name, name))
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.find(name)
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().find(name)
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.findType(name)
176
+ ret = self.loader.findTask(name)
116
177
 
117
- self._log.debug("<-- %s::find %s (%s)" % (self.pkg.name, name, ("found" if ret is not None else "not found")))
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) -> Task:
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.task_m.keys():
137
- ret = self.pkg.task_m[name]
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 = obj[el]
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
- frag = FragmentDef(**(doc["fragment"]))
410
- basedir = os.path.dirname(file)
411
- pkg.fragment_def_l.append(frag)
412
-
413
- self._loadPackageImports(pkg, frag.imports, basedir)
414
- self._loadFragments(pkg, frag.fragments, basedir, taskdefs)
415
- taskdefs.extend(frag.tasks)
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._findTaskType(taskdef.uses)
565
+ task.uses = self._findTask(taskdef.uses)
453
566
 
454
567
  if task.uses is None:
455
- raise Exception("Failed to link task %s" % taskdef.uses)
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._findTaskType(td.uses)
669
+ st.uses = self._findTask(td.uses)
526
670
  if st.uses is None:
527
- raise Exception("Failed to find task %s" % td.uses)
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
- st.needs.append(self._findTask(need))
683
+ nn = self._findTask(need)
538
684
  elif isinstance(need, TaskDef):
539
- st.needs.append(self._findTask(need.name))
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 _findTaskType(self, name):
718
+ def _findType(self, name):
567
719
  if len(self._pkg_s):
568
- return self._pkg_s[-1].find(name)
720
+ return self._pkg_s[-1].findType(name)
569
721
  else:
570
- return self._loader_scope.find(name)
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].find(name)
726
+ return self._pkg_s[-1].findTask(name)
575
727
  else:
576
- return self._loader_scope.find(name)
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
- ptype_s = param.type
690
- if ptype_s not in ptype_m.keys():
691
- raise Exception("Unknown type %s" % ptype_s)
692
- ptype = ptype_m[ptype_s]
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, pdflt_m[ptype_s])
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 not in field_m.keys():
703
- raise Exception("Field %s not found" % p)
704
- if type(param) != dict:
705
- value = param
706
- elif "value" in param.keys():
707
- value = param["value"]
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
- raise Exception("No value specified for param %s: %s" % (
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
- params_t = pydantic.create_model("Task%sParams" % taskdef.name, **field_m)
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
- item : Union[str, Any]
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
@@ -34,6 +34,9 @@ class ParamRefEval(object):
34
34
  def __post_init__(self):
35
35
  self.expr_eval.methods["jq"] = eval_jq
36
36
 
37
+ def set(self, name : str, value : object):
38
+ self.expr_eval.set(name, value)
39
+
37
40
  def eval(self, val : str) -> str:
38
41
  idx = 0
39
42