dv-flow-mgr 0.0.1.13577785562a1__tar.gz → 0.0.1.13644197178a1__tar.gz

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 (98) hide show
  1. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/PKG-INFO +1 -1
  2. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Steps.md +27 -0
  3. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/pyproject.toml +1 -1
  4. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/__init__.py +1 -0
  5. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/package_def.py +99 -38
  6. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/param_def.py +0 -1
  7. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/param_ref_eval.py +2 -2
  8. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_def.py +3 -3
  9. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_graph_builder.py +16 -10
  10. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_node.py +101 -15
  11. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow_mgr.egg-info/PKG-INFO +1 -1
  12. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_pyclass.py +22 -25
  13. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_pytask_smoke.py +34 -38
  14. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/.github/workflows/ci.yml +0 -0
  15. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/.gitignore +0 -0
  16. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/.vscode/settings.json +0 -0
  17. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/LICENSE +0 -0
  18. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/README.md +0 -0
  19. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/KeyArchitecture.md +0 -0
  20. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Makefile +0 -0
  21. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Notes.md +0 -0
  22. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Roadmap.md +0 -0
  23. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/RundirLayout.md +0 -0
  24. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Stages.md +0 -0
  25. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Tasks.md +0 -0
  26. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/TypesAndDefs.md +0 -0
  27. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/Usecases.md +0 -0
  28. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/conf.py +0 -0
  29. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/index.rst +0 -0
  30. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/intro.rst +0 -0
  31. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/quickstart.rst +0 -0
  32. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/docs/reference.rst +0 -0
  33. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/fwperiph_dma.pss +0 -0
  34. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/ivpm.yaml +0 -0
  35. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/setup.cfg +0 -0
  36. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/__main__.py +0 -0
  37. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/cmds/cmd_run.py +0 -0
  38. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/eval_jq.py +0 -0
  39. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/expr_eval.py +0 -0
  40. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/expr_parser.py +0 -0
  41. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/fileset.py +0 -0
  42. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/fragment_def.py +0 -0
  43. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/out +0 -0
  44. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/package.py +0 -0
  45. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/package_import_spec.py +0 -0
  46. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/param.py +0 -0
  47. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/parsetab.py +0 -0
  48. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/pkg_rgy.py +0 -0
  49. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/share/flow.json +0 -0
  50. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/std/fileset.py +0 -0
  51. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/std/flow.dv +0 -0
  52. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/std/message.py +0 -0
  53. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/std/task_null.py +0 -0
  54. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task.py +0 -0
  55. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_ctor.py +0 -0
  56. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_data.py +0 -0
  57. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_exec_data.py +0 -0
  58. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_graph_runner.py +0 -0
  59. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_graph_runner_local.py +0 -0
  60. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_impl_data.py +0 -0
  61. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_memento.py +0 -0
  62. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_output.py +0 -0
  63. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_params_ctor.py +0 -0
  64. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/task_runner.py +0 -0
  65. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/type.py +0 -0
  66. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/type_def.py +0 -0
  67. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow/mgr/util.py +0 -0
  68. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow_mgr.egg-info/SOURCES.txt +0 -0
  69. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow_mgr.egg-info/dependency_links.txt +0 -0
  70. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow_mgr.egg-info/entry_points.txt +0 -0
  71. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow_mgr.egg-info/requires.txt +0 -0
  72. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/src/dv_flow_mgr.egg-info/top_level.txt +0 -0
  73. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/examples/example1/example1.flow +0 -0
  74. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/system/test_depends.py +0 -0
  75. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/system/test_pkg_discovery.py +0 -0
  76. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/system/test_stdlib.py +0 -0
  77. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/__init__.py +0 -0
  78. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1/files1/file1_1.sv +0 -0
  79. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1/files1/file1_2.sv +0 -0
  80. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1/files2/file2_1.sv +0 -0
  81. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1/files2/file2_2.sv +0 -0
  82. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1/flow.dv +0 -0
  83. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1 copy/files1/file1_1.sv +0 -0
  84. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1 copy/files1/file1_2.sv +0 -0
  85. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1 copy/files2/file2_1.sv +0 -0
  86. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1 copy/files2/file2_2.sv +0 -0
  87. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/fileset/test1 copy/test1.dfs +0 -0
  88. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/proj1/proj1.dfs +0 -0
  89. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/proj2/proj2.dfs +0 -0
  90. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/data/proj3/proj3.dfs +0 -0
  91. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_data_merge.py +0 -0
  92. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_expr_eval.py +0 -0
  93. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_expr_parser.py +0 -0
  94. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_fileset.py +0 -0
  95. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_parse.py +0 -0
  96. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_smoke copy.sav +0 -0
  97. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_smoke.py +0 -0
  98. {dv_flow_mgr-0.0.1.13577785562a1 → dv_flow_mgr-0.0.1.13644197178a1}/tests/unit/test_stdlib.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: dv-flow-mgr
3
- Version: 0.0.1.13577785562a1
3
+ Version: 0.0.1.13644197178a1
4
4
  Summary: DV Flow Manager is a build system for silicon design
5
5
  Author-email: Matthew Ballance <matt.ballance@gmail.com>
6
6
  License: Apache License
@@ -115,4 +115,31 @@ with:
115
115
  # List-of
116
116
  - append-list:
117
117
 
118
+ # Why PSS?
119
+ - Key usecases
120
+
121
+ # Open Source and PSS
122
+
123
+ # YAML basics
124
+ - Load packages and create TaskNodeCtor objects from a YAML file
125
+ - Define types in YAML
126
+ - Implement a 'task factory'
127
+ - Support package overrides (config setting?)
128
+ -
129
+
130
+ # TaskNode, TaskNodeCtor
131
+ - TaskNodeCtor exists for each node type
132
+ - Every node declaration in a YAML file
133
+ - Node types accessed via the Python API
134
+ - A new node -- likely with different parameter values -- can be created via the API
135
+ - A node created via the YAML spec has a dedicated node ctor
136
+
137
+ When created via the
138
+
139
+ # Early Differentiators
140
+ - Library of tools with aggressive work avoidance (faster turnaround)
141
+ - Cross-tool support (strategy for category support)
142
+ - Extract and display markers (easier identification of failures)
143
+
144
+
118
145
 
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "dv-flow-mgr"
8
- version = "0.0.1.13577785562a1"
8
+ version = "0.0.1.13644197178a1"
9
9
  dependencies = [
10
10
  'pydantic',
11
11
  'pyyaml',
@@ -7,4 +7,5 @@ from .task_data import *
7
7
  from .task_graph_runner import TaskGraphRunner
8
8
  from .task_graph_runner_local import TaskGraphRunnerLocal
9
9
  from .task_graph_builder import TaskGraphBuilder
10
+ from .task_node import task
10
11
 
@@ -33,7 +33,7 @@ from typing import Any, Dict, List, Callable, Tuple, ClassVar
33
33
  from .fragment_def import FragmentDef
34
34
  from .package import Package
35
35
  from .package_import_spec import PackageImportSpec, PackageSpec
36
- #from .task import TaskCtorCls, TaskCtorParam, TaskCtorParamCls
36
+ from .task_node import TaskNodeCtor, TaskNodeCtorProxy, TaskNodeCtorTask
37
37
  from .task_ctor import TaskCtor
38
38
  from .task_def import TaskDef, TaskSpec
39
39
  from .std.task_null import TaskNull
@@ -151,20 +151,7 @@ class PackageDef(BaseModel):
151
151
  if decl_params:
152
152
  self._log.debug("Type declares new parameters")
153
153
  # We need to combine base parameters with new parameters
154
- ptype_m = {
155
- "str" : str,
156
- "int" : int,
157
- "float" : float,
158
- "bool" : bool,
159
- "list" : List
160
- }
161
- pdflt_m = {
162
- "str" : "",
163
- "int" : 0,
164
- "float" : 0.0,
165
- "bool" : False,
166
- "list" : []
167
- }
154
+
168
155
  for p in task.params.keys():
169
156
  param = task.params[p]
170
157
  self._log.debug("param: %s" % str(param))
@@ -221,16 +208,24 @@ class PackageDef(BaseModel):
221
208
 
222
209
  def mkTaskCtor(self, session, task, srcdir, tasks_m) -> TaskCtor:
223
210
  self._log.debug("--> %s::mkTaskCtor %s (srcdir: %s)" % (self.name, task.name, srcdir))
211
+ base_ctor_t : TaskCtor = None
224
212
  ctor_t : TaskCtor = None
213
+ base_params : BaseModel = None
214
+ callable = None
215
+ needs = [] if task.needs is None else task.needs.copy()
216
+
217
+ if task.uses is not None:
218
+ base_ctor_t = self.getTaskCtor(session, task.uses, tasks_m)
219
+ base_params = base_ctor_t.mkTaskParams()
225
220
 
226
221
  # Determine the implementation constructor first
227
- if task.pyclass is not None:
222
+ if task.pytask is not None:
228
223
  # Built-in impl
229
224
  # Now, lookup the class
230
- self._log.debug("Use PyClass implementation")
231
- last_dot = task.pyclass.rfind('.')
232
- clsname = task.pyclass[last_dot+1:]
233
- modname = task.pyclass[:last_dot]
225
+ self._log.debug("Use PyTask implementation")
226
+ last_dot = task.pytask.rfind('.')
227
+ clsname = task.pytask[last_dot+1:]
228
+ modname = task.pytask[:last_dot]
234
229
 
235
230
  try:
236
231
  if modname not in sys.modules:
@@ -245,26 +240,26 @@ class PackageDef(BaseModel):
245
240
 
246
241
  if not hasattr(mod, clsname):
247
242
  raise Exception("Class %s not found in module %s" % (clsname, modname))
248
- task_ctor = getattr(mod, clsname)
249
-
250
- # Determine if we need to use a new
251
-
252
- if task.uses is not None:
253
- uses = self.getTaskCtor(session, task.uses, tasks_m)
254
- else:
255
- uses = None
243
+ callable = getattr(mod, clsname)
256
244
 
257
- ctor_t = TaskCtorCls(
245
+ # Determine if we need to use a new
246
+ paramT = self._getParamT(task, base_params)
247
+
248
+ if callable is not None:
249
+ ctor_t = TaskNodeCtorTask(
258
250
  name=task.name,
259
- uses=uses,
260
- task_ctor=task_ctor,
261
- srcdir=srcdir)
262
- elif task.uses is not None:
251
+ srcdir=srcdir,
252
+ paramT=paramT, # TODO: need to determine the parameter type
253
+ needs=needs, # TODO: need to determine the needs
254
+ task=callable)
255
+ elif base_ctor_t is not None:
263
256
  # Use the existing (base) to create the implementation
264
- ctor_t = TaskCtor(
257
+ ctor_t = TaskNodeCtorProxy(
265
258
  name=task.name,
266
- uses=self.getTaskCtor(session, task.uses, tasks_m),
267
- srcdir=srcdir)
259
+ srcdir=srcdir,
260
+ paramT=paramT, # TODO: need to determine the parameter type
261
+ needs=needs,
262
+ uses=base_ctor_t)
268
263
  else:
269
264
  self._log.debug("Use 'Null' as the class implementation")
270
265
  ctor_t = TaskCtorCls(
@@ -272,11 +267,77 @@ class PackageDef(BaseModel):
272
267
  task_ctor=TaskNull,
273
268
  srcdir=srcdir)
274
269
 
275
- ctor_t = self.handleParams(task, ctor_t)
276
- ctor_t.depends.extend(task.depends)
270
+ # TODO:
271
+ # ctor_t = self.handleParams(task, ctor_t)
272
+ # ctor_t.depends.extend(task.depends)
277
273
 
278
274
  self._log.debug("<-- %s::mkTaskCtor %s" % (self.name, task.name))
279
275
  return ctor_t
276
+
277
+ def _getParamT(self, task, base_t : BaseModel):
278
+ # Get the base parameter type (if available)
279
+ # We will build a new type with updated fields
280
+
281
+ ptype_m = {
282
+ "str" : str,
283
+ "int" : int,
284
+ "float" : float,
285
+ "bool" : bool,
286
+ "list" : List
287
+ }
288
+ pdflt_m = {
289
+ "str" : "",
290
+ "int" : 0,
291
+ "float" : 0.0,
292
+ "bool" : False,
293
+ "list" : []
294
+ }
295
+
296
+ fields = []
297
+ field_m : Dict[str,int] = {}
298
+
299
+ # First, pull out existing fields (if there's a base type)
300
+ if base_t is not None:
301
+ self._log.debug("Base type: %s" % str(base_t))
302
+ for name,f in base_t.model_fields.items():
303
+ ff : dc.Field = f
304
+ fields.append(f)
305
+ field_m[name] = (f.annotation, getattr(base_t, name))
306
+ else:
307
+ self._log.debug("No base type")
308
+
309
+ for p in task.params.keys():
310
+ param = task.params[p]
311
+ self._log.debug("param: %s %s (%s)" % (p, str(param), str(type(param))))
312
+ if hasattr(param, "type") and param.type is not None:
313
+ ptype_s = param.type
314
+ if ptype_s not in ptype_m.keys():
315
+ raise Exception("Unknown type %s" % ptype_s)
316
+ ptype = ptype_m[ptype_s]
317
+
318
+ if p in field_m.keys():
319
+ raise Exception("Duplicate field %s" % p)
320
+ if param.value is not None:
321
+ field_m[p] = (ptype, param.value)
322
+ else:
323
+ field_m[p] = (ptype, pdflt_m[ptype_s])
324
+ self._log.debug("Set param=%s to %s" % (p, str(field_m[p][1])))
325
+ else:
326
+ if p not in field_m.keys():
327
+ raise Exception("Field %s not found" % p)
328
+ if type(param) != dict:
329
+ value = param
330
+ elif "value" in param.keys():
331
+ value = param["value"]
332
+ else:
333
+ raise Exception("No value specified for param %s: %s" % (
334
+ p, str(param)))
335
+ field_m[p] = (field_m[p][0], value)
336
+ self._log.debug("Set param=%s to %s" % (p, str(field_m[p][1])))
337
+
338
+ params_t = pydantic.create_model("Task%sParams" % task.name, **field_m)
339
+
340
+ return params_t
280
341
 
281
342
  @staticmethod
282
343
  def load(path, exp_pkg_name=None):
@@ -14,7 +14,6 @@ class ComplexType(BaseModel):
14
14
  map : Union[MapType, None] = None
15
15
 
16
16
  class ParamDef(BaseModel):
17
- name : str
18
17
  doc : str = None
19
18
  type : Union[str, 'ComplexType'] = None
20
19
  value : Union[Any, None] = None
@@ -7,8 +7,8 @@ from .eval_jq import eval_jq
7
7
  @dc.dataclass
8
8
  class ParamRefEval(object):
9
9
 
10
- parser : ExprParser = ExprParser()
11
- expr_eval : ExprEval = ExprEval()
10
+ parser : ExprParser = dc.field(default_factory=ExprParser)
11
+ expr_eval : ExprEval = dc.field(default_factory=ExprEval)
12
12
 
13
13
  def __post_init__(self):
14
14
  self.expr_eval.methods["jq"] = eval_jq
@@ -35,11 +35,11 @@ class TaskDef(BaseModel):
35
35
  name : str
36
36
  # type : Union[str,TaskSpec] = dc.Field(default_factory=list)
37
37
  uses : str = dc.Field(default=None)
38
- pyclass : str = dc.Field(default=None)
38
+ pytask : str = dc.Field(default=None)
39
39
  desc : str = dc.Field(default="")
40
40
  doc : str = dc.Field(default="")
41
- depends : List[Union[str,TaskSpec]] = dc.Field(default_factory=list, alias="needs")
42
- params: List[ParamDef] = dc.Field(default_factory=list, alias="with")
41
+ needs : List[Union[str,TaskSpec]] = dc.Field(default_factory=list, alias="needs")
42
+ params: Dict[str,Union[str,ParamDef]] = dc.Field(default_factory=dict, alias="with")
43
43
  # out: List[TaskOutput] = dc.Field(default_factory=list)
44
44
 
45
45
  def copy(self) -> 'TaskDef':
@@ -96,20 +96,26 @@ class TaskGraphBuilder(object):
96
96
 
97
97
  self._logger.debug("ctor_t: %s" % ctor_t.name)
98
98
 
99
- depends = []
99
+ needs = []
100
100
 
101
- for dep in ctor_t.depends:
102
- if not dep in self._task_m.keys():
103
- task = self._mkTaskGraph(dep, rundir)
104
- self._task_m[dep] = task
105
- pass
106
- depends.append(self._task_m[dep])
101
+ # for dep in ctor_t.depends:
102
+ # if not dep in self._task_m.keys():
103
+ # task = self._mkTaskGraph(dep, rundir)
104
+ # self._task_m[dep] = task
105
+ # pass
106
+ # depends.append(self._task_m[dep])
107
107
 
108
108
  # The returned task should have all param references resolved
109
- task = ctor_t.mkTask(
109
+ params = ctor_t.mkTaskParams()
110
+
111
+ if params is None:
112
+ raise Exception("ctor %s returned None for params" % str(ctor_t))
113
+
114
+ task = ctor_t.mkTaskNode(
115
+ params=params,
110
116
  name=task_name,
111
- depends=depends,
112
- rundir=rundir)
117
+ needs=needs)
118
+ task.rundir = rundir
113
119
 
114
120
  self._task_m[task.name] = task
115
121
 
@@ -1,4 +1,5 @@
1
-
1
+ import os
2
+ import sys
2
3
  import dataclasses as dc
3
4
  import pydantic.dataclasses as pdc
4
5
  import logging
@@ -27,6 +28,10 @@ class TaskNode(object):
27
28
 
28
29
  _log : ClassVar = logging.getLogger("TaskNode")
29
30
 
31
+ def __post_init__(self):
32
+ if self.needs is None:
33
+ self.needs = []
34
+
30
35
  async def do_run(self,
31
36
  runner,
32
37
  rundir,
@@ -96,38 +101,110 @@ class TaskNodeCtor(object):
96
101
  - Produces a TaskNode
97
102
  """
98
103
  name : str
104
+ srcdir : str
105
+ paramT : Any
99
106
 
100
- def mkTaskNode(self, srcdir, params, name=None) -> TaskNode:
107
+ def getNeeds(self) -> List[str]:
108
+ return []
109
+
110
+ def mkTaskNode(self,
111
+ params,
112
+ srcdir=None,
113
+ name=None,
114
+ needs=None) -> TaskNode:
101
115
  raise NotImplementedError("mkTaskNode in type %s" % str(type(self)))
102
116
 
103
- def mkTaskParams(self, params : Dict) -> Any:
104
- raise NotImplementedError("mkTaskParams in type %s" % str(type(self)))
117
+ def mkTaskParams(self, params : Dict = None) -> Any:
118
+ obj = self.paramT()
119
+
120
+ # Apply user-specified params
121
+ if params is not None:
122
+ for key,value in params.items():
123
+ if not hasattr(obj, key):
124
+ raise Exception("Parameters class %s does not contain field %s" % (
125
+ str(type(obj)),
126
+ key))
127
+ else:
128
+ if isinstance(value, Param):
129
+ if value.append is not None:
130
+ ex_value = getattr(obj, key, [])
131
+ ex_value.extend(value.append)
132
+ setattr(obj, key, ex_value)
133
+ elif value.prepend is not None:
134
+ ex_value = getattr(obj, key, [])
135
+ value = value.copy()
136
+ value.extend(ex_value)
137
+ setattr(obj, key, value)
138
+ pass
139
+ else:
140
+ raise Exception("Unhandled value spec: %s" % str(value))
141
+ else:
142
+ setattr(obj, key, value)
143
+ return obj
144
+
145
+ @dc.dataclass
146
+ class TaskNodeCtorDefBase(TaskNodeCtor):
147
+ """Task defines its own needs, that will need to be filled in"""
148
+ needs : List['str']
149
+
150
+ def __post_init__(self):
151
+ if self.needs is None:
152
+ self.needs = []
153
+
154
+ def getNeeds(self) -> List[str]:
155
+ return self.needs
156
+
157
+ @dc.dataclass
158
+ class TaskNodeCtorProxy(TaskNodeCtorDefBase):
159
+ """Task has a 'uses' clause, so we delegate creation of the node"""
160
+ uses : TaskNodeCtor
161
+
162
+ def mkTaskNode(self, params, srcdir=None, name=None, needs=None) -> TaskNode:
163
+ if srcdir is None:
164
+ srcdir = self.srcdir
165
+ node = self.uses.mkTaskNode(params=params, srcdir=srcdir, name=name, needs=needs)
166
+ return node
167
+
168
+ @dc.dataclass
169
+ class TaskNodeCtorTask(TaskNodeCtorDefBase):
170
+ task : Callable[['TaskRunner','TaskDataInput'],'TaskDataResult']
171
+
172
+ def mkTaskNode(self, params, srcdir=None, name=None, needs=None) -> TaskNode:
173
+ if srcdir is None:
174
+ srcdir = self.srcdir
175
+
176
+ node = TaskNode(name, srcdir, params, self.task, needs=needs)
177
+ node.task = self.task
178
+
179
+ return node
105
180
 
106
181
  @dc.dataclass
107
182
  class TaskNodeCtorWrapper(TaskNodeCtor):
108
183
  T : Any
109
- paramT : Any
110
184
 
111
185
  def __call__(self,
112
- srcdir,
113
- name=None,
114
- params=None,
186
+ name=None,
187
+ srcdir=None,
188
+ params=None,
115
189
  needs=None,
116
190
  **kwargs):
117
191
  """Convenience method for direct creation of tasks"""
118
192
  if params is None:
119
193
  params = self.mkTaskParams(kwargs)
120
194
 
121
- node = self.mkTaskNode(srcdir, params, name)
122
- if needs is not None:
123
- node.needs.extend(needs)
195
+ node = self.mkTaskNode(
196
+ srcdir=srcdir,
197
+ params=params,
198
+ name=name,
199
+ needs=needs)
200
+
124
201
  return node
125
202
 
126
- def mkTaskNode(self, srcdir, params, name=None) -> TaskNode:
127
- node = TaskNode(name, srcdir, params, self.T)
203
+ def mkTaskNode(self, params, srcdir=None, name=None, needs=None) -> TaskNode:
204
+ node = TaskNode(name, srcdir, params, self.T, needs=needs)
128
205
  return node
129
206
 
130
- def mkTaskParams(self, params : Dict) -> Any:
207
+ def mkTaskParams(self, params : Dict = None) -> Any:
131
208
  obj = self.paramT()
132
209
 
133
210
  # Apply user-specified params
@@ -155,7 +232,16 @@ class TaskNodeCtorWrapper(TaskNodeCtor):
155
232
  return obj
156
233
 
157
234
  def task(paramT):
235
+ """Decorator to wrap a task method as a TaskNodeCtor"""
158
236
  def wrapper(T):
159
- ctor = TaskNodeCtorWrapper(T.__name__, T, paramT)
237
+ task_mname = T.__module__
238
+ task_module = sys.modules[task_mname]
239
+ ctor = TaskNodeCtorWrapper(
240
+ T.__name__,
241
+ os.path.dirname(os.path.abspath(task_module.__file__)),
242
+ paramT,
243
+ T)
160
244
  return ctor
161
245
  return wrapper
246
+
247
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: dv-flow-mgr
3
- Version: 0.0.1.13577785562a1
3
+ Version: 0.0.1.13644197178a1
4
4
  Summary: DV Flow Manager is a build system for silicon design
5
5
  Author-email: Matthew Ballance <matt.ballance@gmail.com>
6
6
  License: Apache License
@@ -3,6 +3,7 @@ import os
3
3
  import asyncio
4
4
  import pytest
5
5
  from dv_flow.mgr import TaskGraphBuilder, TaskGraphRunnerLocal, PackageDef
6
+ from dv_flow.mgr.task_runner import TaskSetRunner
6
7
  #from dv_flow_mgr.tasklib.builtin_pkg import TaskPyClass, TaskPyClassParams
7
8
 
8
9
  # def test_smoke(tmpdir):
@@ -36,20 +37,18 @@ package:
36
37
  name: pkg1
37
38
  tasks:
38
39
  - name: foo
39
- pyclass: my_module.foo
40
+ pytask: my_module.foo
40
41
  with:
41
42
  param1:
42
43
  type: str
43
44
  value: "1"
44
45
  """
45
46
  module = """
46
- from dv_flow.mgr import Task, TaskData
47
-
48
- class foo(Task):
49
- async def run(self, input : TaskData) -> TaskData:
50
- print("foo::run", flush=True)
51
- print("params: %s" % str(self.params), flush=True)
52
- return input
47
+ from dv_flow.mgr import TaskDataResult
48
+ async def foo(runner, input):
49
+ print("foo::run", flush=True)
50
+ print("params: %s" % str(input.params), flush=True)
51
+ return TaskDataResult()
53
52
  """
54
53
 
55
54
  with open(os.path.join(tmpdir, "my_module.py"), "w") as f:
@@ -62,7 +61,7 @@ class foo(Task):
62
61
  builder = TaskGraphBuilder(
63
62
  root_pkg=pkg_def,
64
63
  rundir=os.path.join(tmpdir, "rundir"))
65
- runner = TaskGraphRunnerLocal(rundir=os.path.join(tmpdir, "rundir"))
64
+ runner = TaskSetRunner(os.path.join(tmpdir, "rundir"))
66
65
 
67
66
  task = builder.mkTaskGraph("pkg1.foo")
68
67
  output = asyncio.run(runner.run(task))
@@ -75,7 +74,7 @@ package:
75
74
  name: pkg1
76
75
  tasks:
77
76
  - name: foo
78
- pyclass: my_module.foo
77
+ pytask: my_module.foo
79
78
  with:
80
79
  param1:
81
80
  type: str
@@ -84,13 +83,12 @@ package:
84
83
  uses: foo
85
84
  """
86
85
  module = """
87
- from dv_flow.mgr import Task, TaskData
86
+ from dv_flow.mgr import TaskDataResult
88
87
 
89
- class foo(Task):
90
- async def run(self, input : TaskData) -> TaskData:
91
- print("foo::run", flush=True)
92
- print("params: %s" % str(self.params), flush=True)
93
- return input
88
+ async def foo(runner, input) -> TaskDataResult:
89
+ print("foo::run", flush=True)
90
+ print("params: %s" % str(input.params), flush=True)
91
+ return TaskDataResult()
94
92
  """
95
93
 
96
94
  with open(os.path.join(tmpdir, "my_module.py"), "w") as f:
@@ -102,7 +100,7 @@ class foo(Task):
102
100
  builder = TaskGraphBuilder(
103
101
  root_pkg=pkg_def,
104
102
  rundir=os.path.join(tmpdir, "rundir"))
105
- runner = TaskGraphRunnerLocal(rundir=os.path.join(tmpdir, "rundir"))
103
+ runner = TaskSetRunner(rundir=os.path.join(tmpdir, "rundir"))
106
104
 
107
105
  task = builder.mkTaskGraph("pkg1.foo2")
108
106
  output = asyncio.run(runner.run(task))
@@ -114,7 +112,7 @@ package:
114
112
  name: pkg1
115
113
  tasks:
116
114
  - name: foo
117
- pyclass: my_module.foo
115
+ pytask: my_module.foo
118
116
  with:
119
117
  param1:
120
118
  type: str
@@ -126,13 +124,12 @@ package:
126
124
 
127
125
  """
128
126
  module = """
129
- from dv_flow.mgr import Task, TaskData
127
+ from dv_flow.mgr import TaskDataResult
130
128
 
131
- class foo(Task):
132
- async def run(self, input : TaskData) -> TaskData:
129
+ async def foo(runner, input) -> TaskDataResult:
133
130
  print("foo::run", flush=True)
134
- print("params: %s" % str(self.params), flush=True)
135
- return input
131
+ print("params: %s" % str(input.params), flush=True)
132
+ return TaskDataResult()
136
133
  """
137
134
 
138
135
  with open(os.path.join(tmpdir, "my_module.py"), "w") as f:
@@ -144,9 +141,9 @@ class foo(Task):
144
141
  builder = TaskGraphBuilder(
145
142
  root_pkg=pkg_def,
146
143
  rundir=os.path.join(tmpdir, "rundir"))
147
- runner = TaskGraphRunnerLocal(rundir=os.path.join(tmpdir, "rundir"))
144
+ runner = TaskSetRunner(rundir=os.path.join(tmpdir, "rundir"))
148
145
 
149
- task = builder.mkTaskGraph("pkg1.foo")
146
+ task = builder.mkTaskGraph("pkg1.foo2")
150
147
  output = asyncio.run(runner.run(task))
151
148
 
152
149
  def test_class_use_with_new_param(tmpdir):
@@ -20,17 +20,17 @@ def test_smoke_1(tmpdir):
20
20
 
21
21
  called = False
22
22
 
23
- @t_decorator(Params)
23
+ @task(Params)
24
24
  async def MyTask(runner, input):
25
25
  nonlocal called
26
26
  called = True
27
27
  print("Hello from run")
28
28
  return TaskDataResult()
29
29
 
30
- task = MyTask("srcdir", p1="p1")
30
+ task1 = MyTask(srcdir="srcdir", p1="p1")
31
31
  runner = SingleTaskRunner("rundir")
32
32
 
33
- result = asyncio.run(runner.run(task))
33
+ result = asyncio.run(runner.run(task1))
34
34
 
35
35
  assert called
36
36
 
@@ -41,22 +41,19 @@ def test_smoke_2(tmpdir):
41
41
  p1 : str = None
42
42
 
43
43
  called = False
44
- @Task.ctor(Params)
45
- class MyTask(Task):
46
- async def run(self, runner, input):
47
- nonlocal called
48
- called = True
49
- print("Hello from run")
50
- return TaskDataResult(
51
- markers=[TaskMarker(msg="testing", severity="info")]
52
- )
53
-
54
- task = MyTask.mkTask("task1", "srcdir", MyTask.mkParams(
55
- p1="p1"
56
- ))
44
+ @task(Params)
45
+ async def MyTask(runner, input):
46
+ nonlocal called
47
+ called = True
48
+ print("Hello from run")
49
+ return TaskDataResult(
50
+ markers=[TaskMarker(msg="testing", severity="info")]
51
+ )
52
+
53
+ task1 = MyTask(name="task1", srcdir="srcdir", p1="p1")
57
54
  runner = SingleTaskRunner("rundir")
58
55
 
59
- result = asyncio.run(runner.run(task))
56
+ result = asyncio.run(runner.run(task1))
60
57
 
61
58
  assert called
62
59
  assert result is not None
@@ -64,33 +61,32 @@ def test_smoke_2(tmpdir):
64
61
 
65
62
  def test_smoke_3(tmpdir):
66
63
 
67
- @dc.dataclass
68
- class Params(object):
64
+ class Params(BaseModel):
69
65
  p1 : str = None
70
66
 
71
67
  called = []
72
68
 
73
- @t_decorator(Params)
69
+ @task(Params)
74
70
  async def MyTask1(runner, input):
75
71
  nonlocal called
76
72
  called.append(("MyTask1", input.params.p1))
77
73
  return TaskDataResult()
78
74
 
79
- @t_decorator(Params)
75
+ @task(Params)
80
76
  async def MyTask2(runner, input):
81
77
  nonlocal called
82
78
  called.append(("MyTask2", input.params.p1))
83
79
  return TaskDataResult()
84
80
 
85
- @t_decorator(Params)
81
+ @task(Params)
86
82
  async def MyTask3(runner, input):
87
83
  nonlocal called
88
84
  called.append(("MyTask3", input.params.p1))
89
85
  return TaskDataResult()
90
86
 
91
- task1 = MyTask1("srcdir", p1="1")
92
- task2 = MyTask2("srcdir", p1="2")
93
- task3 = MyTask3("srcdir", p1="3", needs=[task1, task2])
87
+ task1 = MyTask1(srcdir="srcdir", p1="1")
88
+ task2 = MyTask2(srcdir="srcdir", p1="2")
89
+ task3 = MyTask3(srcdir="srcdir", p1="3", needs=[task1, task2])
94
90
  runner = TaskSetRunner("rundir")
95
91
 
96
92
  result = asyncio.run(runner.run(task3))
@@ -109,7 +105,7 @@ def test_smoke_4(tmpdir):
109
105
 
110
106
  called = []
111
107
 
112
- @t_decorator(Params)
108
+ @task(Params)
113
109
  async def MyTask1(runner, input):
114
110
  nonlocal called
115
111
  called.append(("MyTask1", input.params.p1))
@@ -117,7 +113,7 @@ def test_smoke_4(tmpdir):
117
113
  output=[TaskData(val=1)]
118
114
  )
119
115
 
120
- @t_decorator(Params)
116
+ @task(Params)
121
117
  async def MyTask2(runner, input):
122
118
  nonlocal called
123
119
  called.append(("MyTask2", input.params.p1))
@@ -125,16 +121,16 @@ def test_smoke_4(tmpdir):
125
121
  output=[TaskData(val=2)]
126
122
  )
127
123
 
128
- @t_decorator(Params)
124
+ @task(Params)
129
125
  async def MyTask3(runner, input):
130
126
  nonlocal called
131
127
  called.append(("MyTask3", input.params.p1))
132
128
  return TaskDataResult()
133
129
 
134
- task1 = MyTask1("srcdir", p1="1")
135
- task2 = MyTask2("srcdir", p1="2")
136
- task3 = MyTask3("srcdir",
137
- p1="${{ in | jq('.[] .val') }}",
130
+ task1 = MyTask1(srcdir="srcdir", p1="1")
131
+ task2 = MyTask2(srcdir="srcdir", p1="2")
132
+ task3 = MyTask3(srcdir="srcdir",
133
+ p1="${{ in | jq('[.[] .val]') }}",
138
134
  needs=[task1, task2])
139
135
  runner = TaskSetRunner("rundir")
140
136
 
@@ -176,9 +172,9 @@ def test_smoke_5(tmpdir):
176
172
  called.append(("MyTask3", input.params.p1))
177
173
  return TaskDataResult()
178
174
 
179
- task1 = MyTask1("srcdir", p1="1")
180
- task2 = MyTask2("srcdir", p1="2")
181
- task3 = MyTask3("srcdir",
175
+ task1 = MyTask1(srcdir="srcdir", p1="1")
176
+ task2 = MyTask2(srcdir="srcdir", p1="2")
177
+ task3 = MyTask3(srcdir="srcdir",
182
178
  p1="${{ in | jq('[.[] .files]') | jq('flatten') }}",
183
179
  # p1="${{ in | jq('.[] .files') }}",
184
180
  needs=[task1, task2])
@@ -222,9 +218,9 @@ def test_smoke_6(tmpdir):
222
218
  called.append(("MyTask3", input.params.p1))
223
219
  return TaskDataResult()
224
220
 
225
- task1 = MyTask1("srcdir", p1="3")
226
- task2 = MyTask2("srcdir", p1=Param(append=["4"]))
227
- task3 = MyTask3("srcdir",
221
+ task1 = MyTask1(srcdir="srcdir", p1="3")
222
+ task2 = MyTask2(srcdir="srcdir", p1=Param(append=["4"]))
223
+ task3 = MyTask3(srcdir="srcdir",
228
224
  p1="${{ in | jq('[.[] .files]') | jq('flatten') }}",
229
225
  # p1="${{ in | jq('.[] .files') }}",
230
226
  needs=[task1, task2])