dv-flow-mgr 0.0.1.12992722023a1__py3-none-any.whl → 0.0.1.13468776985a1__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.
@@ -0,0 +1,50 @@
1
+
2
+ import dataclasses as dc
3
+ from typing import Any, Callable, Dict, List
4
+ from .expr_parser import ExprVisitor, Expr, ExprBin, ExprBinOp, ExprCall, ExprId, ExprString, ExprInt
5
+
6
+ @dc.dataclass
7
+ class ExprEval(ExprVisitor):
8
+ methods : Dict[str, Callable] = dc.field(default_factory=dict)
9
+ variables : Dict[str, object] = dc.field(default_factory=dict)
10
+ value : Any = None
11
+
12
+ def eval(self, e : Expr):
13
+ self.value = None
14
+ e.accept(self)
15
+ return self.value
16
+
17
+ def visitExprId(self, e : ExprId):
18
+ if e.id in self.variables:
19
+ self.value = self.variables[e.id]
20
+ else:
21
+ raise Exception("Variable %s not found" % e.id)
22
+
23
+ def visitExprString(self, e : ExprString):
24
+ self.value = e.value
25
+
26
+ def visitExprBin(self, e):
27
+ e.lhs.accept(self)
28
+
29
+ if e.op == ExprBinOp.Pipe:
30
+ # Value just goes over to the rhs
31
+ e.rhs.accept(self)
32
+ elif e.op == ExprBinOp.Plus:
33
+ pass
34
+
35
+ def visitExprCall(self, e : ExprCall):
36
+ if e.id in self.methods:
37
+ # Need to gather up argument values
38
+ in_value = self.value
39
+ args = []
40
+ for arg in e.args:
41
+ self.value = None
42
+ arg.accept(self)
43
+ args.append(self.value)
44
+
45
+ self.value = self.methods[e.id](in_value, args)
46
+ else:
47
+ raise Exception("Method %s not found" % e.id)
48
+
49
+ def visitExprInt(self, e : ExprInt):
50
+ self.value = e.value
@@ -0,0 +1,233 @@
1
+ import dataclasses as dc
2
+ import enum
3
+ import ply.lex as lex
4
+ import ply.yacc as yacc
5
+ from typing import ClassVar, List
6
+
7
+ @dc.dataclass
8
+ class Expr(object):
9
+ def accept(self, v):
10
+ raise NotImplementedError("Expr.accept for %s" % str(type(sepf)))
11
+
12
+ @dc.dataclass
13
+ class ExprId(Expr):
14
+ id : str
15
+
16
+ def accept(self, v):
17
+ v.visitExprId(self)
18
+
19
+ class ExprBinOp(enum.Enum):
20
+ Pipe = enum.auto()
21
+ Plus = enum.auto()
22
+ Minus = enum.auto()
23
+ Times = enum.auto()
24
+ Divide = enum.auto()
25
+
26
+ @dc.dataclass
27
+ class ExprBin(Expr):
28
+ op : ExprBinOp
29
+ lhs : Expr
30
+ rhs : Expr
31
+
32
+ def accept(self, v):
33
+ v.visitExprBin(self)
34
+
35
+ @dc.dataclass
36
+ class ExprCall(Expr):
37
+ id : str
38
+ args : List[Expr]
39
+
40
+ def accept(self, v):
41
+ v.visitExprCall(self)
42
+
43
+ @dc.dataclass
44
+ class ExprString(Expr):
45
+ value : str
46
+
47
+ def accept(self, v):
48
+ v.visitExprString(self)
49
+
50
+ @dc.dataclass
51
+ class ExprInt(Expr):
52
+ value : int
53
+
54
+ def accept(self, v):
55
+ v.visitExprInt(self)
56
+
57
+ class ExprVisitor(object):
58
+ def visitExprId(self, e : ExprId):
59
+ pass
60
+
61
+ def visitExprBin(self, e : ExprBin):
62
+ e.lhs.accept(self)
63
+ e.rhs.accept(self)
64
+
65
+ def visitExprCall(self, e : ExprCall):
66
+ for arg in e.args:
67
+ arg.accept(self)
68
+
69
+ def visitExprString(self, e : ExprString):
70
+ pass
71
+
72
+ def visitExprInt(self, e : ExprInt):
73
+ pass
74
+
75
+ @dc.dataclass
76
+ class ExprVisitor2String(ExprVisitor):
77
+ _ret : str = ""
78
+ _idx : int = 0
79
+
80
+ @staticmethod
81
+ def toString(e : Expr):
82
+ v = ExprVisitor2String()
83
+ e.accept(v)
84
+ return v._ret
85
+
86
+ def visitExprId(self, e : ExprId):
87
+ self._ret += e.id
88
+
89
+ def visitExprBin(self, e):
90
+ e.lhs.accept(self)
91
+ self._ret += " "
92
+ self._ret += "op%d" % self._idx
93
+ self._idx += 1
94
+ self._ret += " "
95
+ e.rhs.accept(self)
96
+
97
+ def visitExprCall(self, e):
98
+ self._ret += e.id
99
+ self._ret += "("
100
+ for i, arg in enumerate(e.args):
101
+ if i > 0:
102
+ self._ret += ", "
103
+ arg.accept(self)
104
+ self._ret += ")"
105
+
106
+ def visitExprString(self, e):
107
+ self._ret += e.value
108
+
109
+ def visitExprInt(self, e):
110
+ self._ret += str(e.value)
111
+
112
+
113
+ class ExprParser(object):
114
+
115
+ _inst : ClassVar['ExprParser'] = None
116
+
117
+ def __init__(self):
118
+
119
+ # Build the lexer
120
+ self.lexer = lex.lex(module=self)
121
+ self.parser = yacc.yacc(module=self)
122
+
123
+ @classmethod
124
+ def inst(cls):
125
+ if cls._inst is None:
126
+ cls._inst = ExprParser()
127
+ return cls._inst
128
+
129
+ tokens = (
130
+ 'ID','NUMBER','COMMA',
131
+ 'PLUS','MINUS','TIMES','DIVIDE',
132
+ 'LPAREN','RPAREN','PIPE','STRING1','STRING2'
133
+ )
134
+
135
+ # Tokens
136
+
137
+ t_COMMA = r','
138
+ t_PLUS = r'\+'
139
+ t_MINUS = r'-'
140
+ t_TIMES = r'\*'
141
+ t_DIVIDE = r'/'
142
+ t_LPAREN = r'\('
143
+ t_RPAREN = r'\)'
144
+ t_ID = r'[a-zA-Z_][a-zA-Z0-9_]*'
145
+ t_PIPE = r'\|'
146
+ t_STRING2 = r'\'.*\''
147
+
148
+ def t_NUMBER(self, t):
149
+ r'\d+'
150
+ try:
151
+ t.value = ExprInt(int(t.value))
152
+ except ValueError:
153
+ print("Integer value too large %d", t.value)
154
+ t.value = ExprInt(0)
155
+ return t
156
+
157
+ def t_STRING1(self, t):
158
+ r'(\'|\")([^\\\n]|(\\.))*?(\'|\")'
159
+ t.value = t.value[1:-1].replace('\\"', '"').replace("\\'", "'").replace('\\n', '\n').replace('\\t', '\t').replace('\\\\', '\\')
160
+ return t
161
+
162
+ # Ignored characters
163
+ t_ignore = " \t"
164
+
165
+ def t_newline(self, t):
166
+ r'\n+'
167
+ t.lexer.lineno += t.value.count("\n")
168
+
169
+ def t_error(self, t):
170
+ print("Illegal character '%s'" % t.value[0])
171
+ t.lexer.skip(1)
172
+
173
+ precedence = (
174
+ ('left','PLUS','MINUS','PIPE'),
175
+ ('left','TIMES','DIVIDE'),
176
+ # ('right','UMINUS'),
177
+ )
178
+
179
+ def p_call(self, t):
180
+ """expression : ID LPAREN RPAREN
181
+ | ID LPAREN args RPAREN"""
182
+ t[0] = ExprCall(t[1], t[3] if len(t) == 5 else [])
183
+
184
+ def p_args(self, t):
185
+ """args : expression
186
+ | args COMMA expression"""
187
+ if len(t) == 2:
188
+ t[0] = [t[1]]
189
+ else:
190
+ t[0] = t[1]
191
+ t[0].append(t[3])
192
+
193
+ def p_expression_binop(self, t):
194
+ '''expression : expression PLUS expression
195
+ | expression MINUS expression
196
+ | expression TIMES expression
197
+ | expression PIPE expression
198
+ | expression DIVIDE expression'''
199
+ op_m = {
200
+ '+' : ExprBinOp.Plus,
201
+ '-' : ExprBinOp.Minus,
202
+ '*' : ExprBinOp.Times,
203
+ '|' : ExprBinOp.Pipe,
204
+ '/' : ExprBinOp.Divide
205
+ }
206
+ t[0] = ExprBin(op_m[t[2]], t[1], t[3])
207
+
208
+ def p_expression_group(self, t):
209
+ 'expression : LPAREN expression RPAREN'
210
+ t[0] = t[2]
211
+
212
+ def p_expression_number(self, t):
213
+ 'expression : NUMBER'
214
+ t[0] = t[1]
215
+
216
+ def p_expression_name(self, t):
217
+ 'expression : ID'
218
+ t[0] = ExprId(t[1])
219
+
220
+ def p_expression_string1(self, t):
221
+ 'expression : STRING1'
222
+ t[0] = ExprString(t[1])
223
+
224
+ def p_expression_string2(self, t):
225
+ 'expression : STRING2'
226
+ t[0] = ExprString(t[1])
227
+
228
+ def p_error(self, t):
229
+ print("Syntax error at '%s'" % t.value)
230
+
231
+ def parse(self, input):
232
+ return self.parser.parse(input, lexer=self.lexer)
233
+
@@ -26,11 +26,13 @@ from typing import Any, Dict, List, Union
26
26
  from .package import Package
27
27
  from .package_import_spec import PackageImportSpec
28
28
  from .task_def import TaskDef
29
+ from .type_def import TypeDef
29
30
 
30
31
  class FragmentDef(BaseModel):
31
32
  tasks : List[TaskDef] = dc.Field(default_factory=list)
32
33
  imports : List[Union[str,PackageImportSpec]] = dc.Field(default_factory=list, alias="imports")
33
34
  fragments: List[str] = dc.Field(default_factory=list)
35
+ types : List[TypeDef] = dc.Field(default_factory=list)
34
36
 
35
37
  basedir : str = None
36
38
 
dv_flow/mgr/out ADDED
@@ -0,0 +1,12 @@
1
+ __main__.py
2
+ flow.py
3
+ package.py
4
+ package_def.py
5
+ package_import_spec.py
6
+ parameters.py
7
+ pkg_rgy.py
8
+ task.py
9
+ task_graph_builder.py
10
+ task_graph_runner.py
11
+ util.py
12
+
dv_flow/mgr/package.py CHANGED
@@ -31,6 +31,7 @@ class Package(object):
31
31
  # Package holds constructors for tasks
32
32
  # - Dict holds the default parameters for the task
33
33
  tasks : Dict[str,TaskCtor] = dc.field(default_factory=dict)
34
+ types : Dict[str,Any] = dc.field(default_factory=dict)
34
35
  _log : ClassVar = logging.getLogger("Package")
35
36
 
36
37
  def getTaskCtor(self, name : str) -> TaskCtor:
@@ -19,6 +19,7 @@
19
19
  #* Author:
20
20
  #*
21
21
  #****************************************************************************
22
+ import io
22
23
  import os
23
24
  import json
24
25
  import yaml
@@ -35,6 +36,7 @@ from .package_import_spec import PackageImportSpec, PackageSpec
35
36
  from .task import TaskCtor, TaskCtorProxy, TaskCtorCls, TaskCtorParam, TaskCtorParamCls
36
37
  from .task_def import TaskDef, TaskSpec
37
38
  from .std.task_null import TaskNull
39
+ from .type_def import TypeDef
38
40
 
39
41
 
40
42
  class PackageDef(BaseModel):
@@ -44,6 +46,7 @@ class PackageDef(BaseModel):
44
46
  tasks : List[TaskDef] = dc.Field(default_factory=list)
45
47
  imports : List[PackageImportSpec] = dc.Field(default_factory=list)
46
48
  fragments: List[str] = dc.Field(default_factory=list)
49
+ types : List[TypeDef] = dc.Field(default_factory=list)
47
50
 
48
51
  fragment_l : List['FragmentDef'] = dc.Field(default_factory=list, exclude=True)
49
52
 
@@ -314,6 +317,32 @@ class PackageDef(BaseModel):
314
317
  file_s.pop()
315
318
 
316
319
  return pkg
320
+
321
+ @staticmethod
322
+ def loads(data, exp_pkg_name=None):
323
+ return PackageDef._loadPkgDefS(data, exp_pkg_name)
324
+ pass
325
+
326
+ @staticmethod
327
+ def _loadPkgDefS(data, exp_pkg_name):
328
+ ret = None
329
+ doc = yaml.load(io.StringIO(data), Loader=yaml.FullLoader)
330
+ if "package" not in doc.keys():
331
+ raise Exception("Missing 'package' key in %s" % root)
332
+ pkg = PackageDef(**(doc["package"]))
333
+ pkg.basedir = None
334
+
335
+ # for t in pkg.tasks:
336
+ # t.basedir = os.path.dirname(root)
337
+
338
+ if exp_pkg_name is not None:
339
+ if exp_pkg_name != pkg.name:
340
+ raise Exception("Package name mismatch: %s != %s" % (exp_pkg_name, pkg.name))
341
+
342
+ if len(pkg.fragments) > 0:
343
+ raise Exception("Cannot load a package-def with fragments from a string")
344
+
345
+ return pkg
317
346
 
318
347
  @staticmethod
319
348
  def _loadFragmentSpec(pkg, spec, file_s):
@@ -0,0 +1,25 @@
1
+
2
+ from typing import Any, List, Union
3
+ from pydantic import BaseModel, Field
4
+
5
+ class ListType(BaseModel):
6
+ item : Union[str, 'ComplexType']
7
+
8
+ class MapType(BaseModel):
9
+ key : Union[str, 'ComplexType']
10
+ item : Union[str, 'ComplexType']
11
+
12
+ class ComplexType(BaseModel):
13
+ list : Union[ListType, None] = None
14
+ map : Union[MapType, None] = None
15
+
16
+ class ParamDef(BaseModel):
17
+ name : str
18
+ doc : str = None
19
+ type : Union[str, 'ComplexType'] = None
20
+ value : Union[Any, None] = None
21
+ append : Union[Any, None] = None
22
+ prepend : Union[Any, None] = None
23
+ path_append : Union[Any, None] = Field(alias="path-append", default=None)
24
+ path_prepend : Union[Any, None] = Field(alias="path-prepend", default=None)
25
+
@@ -0,0 +1,44 @@
1
+
2
+ # parsetab.py
3
+ # This file is automatically generated. Do not edit.
4
+ # pylint: disable=W,C,R
5
+ _tabversion = '3.10'
6
+
7
+ _lr_method = 'LALR'
8
+
9
+ _lr_signature = 'leftPLUSMINUSPIPEleftTIMESDIVIDECOMMA DIVIDE ID LPAREN MINUS NUMBER PIPE PLUS RPAREN STRING1 STRING2 TIMESexpression : ID LPAREN RPAREN \n | ID LPAREN args RPARENargs : expression \n | args COMMA expressionexpression : expression PLUS expression\n | expression MINUS expression\n | expression TIMES expression\n | expression PIPE expression\n | expression DIVIDE expressionexpression : LPAREN expression RPARENexpression : NUMBERexpression : IDexpression : STRING1expression : STRING2'
10
+
11
+ _lr_action_items = {'ID':([0,3,7,8,9,10,11,12,24,],[2,2,2,2,2,2,2,2,2,]),'LPAREN':([0,2,3,7,8,9,10,11,12,24,],[3,12,3,3,3,3,3,3,3,3,]),'NUMBER':([0,3,7,8,9,10,11,12,24,],[4,4,4,4,4,4,4,4,4,]),'STRING1':([0,3,7,8,9,10,11,12,24,],[5,5,5,5,5,5,5,5,5,]),'STRING2':([0,3,7,8,9,10,11,12,24,],[6,6,6,6,6,6,6,6,6,]),'$end':([1,2,4,5,6,14,15,16,17,18,19,22,23,],[0,-12,-11,-13,-14,-5,-6,-7,-8,-9,-1,-10,-2,]),'PLUS':([1,2,4,5,6,13,14,15,16,17,18,19,21,22,23,25,],[7,-12,-11,-13,-14,7,-5,-6,-7,-8,-9,-1,7,-10,-2,7,]),'MINUS':([1,2,4,5,6,13,14,15,16,17,18,19,21,22,23,25,],[8,-12,-11,-13,-14,8,-5,-6,-7,-8,-9,-1,8,-10,-2,8,]),'TIMES':([1,2,4,5,6,13,14,15,16,17,18,19,21,22,23,25,],[9,-12,-11,-13,-14,9,9,9,-7,9,-9,-1,9,-10,-2,9,]),'PIPE':([1,2,4,5,6,13,14,15,16,17,18,19,21,22,23,25,],[10,-12,-11,-13,-14,10,-5,-6,-7,-8,-9,-1,10,-10,-2,10,]),'DIVIDE':([1,2,4,5,6,13,14,15,16,17,18,19,21,22,23,25,],[11,-12,-11,-13,-14,11,11,11,-7,11,-9,-1,11,-10,-2,11,]),'RPAREN':([2,4,5,6,12,13,14,15,16,17,18,19,20,21,22,23,25,],[-12,-11,-13,-14,19,22,-5,-6,-7,-8,-9,-1,23,-3,-10,-2,-4,]),'COMMA':([2,4,5,6,14,15,16,17,18,19,20,21,22,23,25,],[-12,-11,-13,-14,-5,-6,-7,-8,-9,-1,24,-3,-10,-2,-4,]),}
12
+
13
+ _lr_action = {}
14
+ for _k, _v in _lr_action_items.items():
15
+ for _x,_y in zip(_v[0],_v[1]):
16
+ if not _x in _lr_action: _lr_action[_x] = {}
17
+ _lr_action[_x][_k] = _y
18
+ del _lr_action_items
19
+
20
+ _lr_goto_items = {'expression':([0,3,7,8,9,10,11,12,24,],[1,13,14,15,16,17,18,21,25,]),'args':([12,],[20,]),}
21
+
22
+ _lr_goto = {}
23
+ for _k, _v in _lr_goto_items.items():
24
+ for _x, _y in zip(_v[0], _v[1]):
25
+ if not _x in _lr_goto: _lr_goto[_x] = {}
26
+ _lr_goto[_x][_k] = _y
27
+ del _lr_goto_items
28
+ _lr_productions = [
29
+ ("S' -> expression","S'",1,None,None,None),
30
+ ('expression -> ID LPAREN RPAREN','expression',3,'p_call','expr_parser.py',160),
31
+ ('expression -> ID LPAREN args RPAREN','expression',4,'p_call','expr_parser.py',161),
32
+ ('args -> expression','args',1,'p_args','expr_parser.py',165),
33
+ ('args -> args COMMA expression','args',3,'p_args','expr_parser.py',166),
34
+ ('expression -> expression PLUS expression','expression',3,'p_expression_binop','expr_parser.py',174),
35
+ ('expression -> expression MINUS expression','expression',3,'p_expression_binop','expr_parser.py',175),
36
+ ('expression -> expression TIMES expression','expression',3,'p_expression_binop','expr_parser.py',176),
37
+ ('expression -> expression PIPE expression','expression',3,'p_expression_binop','expr_parser.py',177),
38
+ ('expression -> expression DIVIDE expression','expression',3,'p_expression_binop','expr_parser.py',178),
39
+ ('expression -> LPAREN expression RPAREN','expression',3,'p_expression_group','expr_parser.py',189),
40
+ ('expression -> NUMBER','expression',1,'p_expression_number','expr_parser.py',193),
41
+ ('expression -> ID','expression',1,'p_expression_name','expr_parser.py',197),
42
+ ('expression -> STRING1','expression',1,'p_expression_string1','expr_parser.py',201),
43
+ ('expression -> STRING2','expression',1,'p_expression_string2','expr_parser.py',205),
44
+ ]
dv_flow/mgr/std/flow.dv CHANGED
@@ -27,4 +27,52 @@ package:
27
27
  # - name: Exec
28
28
  # pyclass: dv_flow.mgr.std.exec.Exec
29
29
  # with: {}
30
-
30
+ types:
31
+ # - name: TaskDataItem
32
+ # doc: |
33
+ # Base type for a data element produced by a task.
34
+ # TaskDataItem is never used directly
35
+ # with:
36
+ # - name: kind
37
+ # type: str
38
+ # kind: metadata
39
+ # doc: |
40
+ # Kind of data item
41
+ # - name: src
42
+ # type: str
43
+ # kind: metadata
44
+ # doc: |
45
+ # Name of the task that produced this item
46
+ # - name: id
47
+ # type: str
48
+ # kind: metadata
49
+ # doc: |
50
+ # Unique identiifer
51
+
52
+ - name: Env
53
+ doc: |
54
+ Environment variables
55
+ with:
56
+ - name: doc
57
+
58
+ - name: FileSet
59
+ uses: TaskDataItem
60
+ with:
61
+ - name: kind
62
+ value: "FileSet"
63
+ - name: base
64
+ type: str
65
+ - name: fileType
66
+ type: str
67
+ - name: files
68
+ type:
69
+ list:
70
+ item:
71
+ type: str
72
+
73
+ # type:
74
+ # list: (str,int)
75
+ # - complex type
76
+ # type:
77
+ # object:
78
+ #
dv_flow/mgr/task.py CHANGED
@@ -25,7 +25,7 @@ import dataclasses as dc
25
25
  import logging
26
26
  from pydantic import BaseModel
27
27
  from typing import Any, Callable, ClassVar, Dict, List, Tuple
28
- from .task_data import TaskData
28
+ from .task_data import TaskData, TaskDataInput, TaskDataOutput, TaskDataResult
29
29
  from .task_memento import TaskMemento
30
30
 
31
31
  @dc.dataclass
@@ -180,112 +180,21 @@ class TaskCtorProxy(TaskCtor):
180
180
  class Task(object):
181
181
  """Executable view of a task"""
182
182
  name : str
183
- params : TaskParams
184
- srcdir : str = None
185
- session : 'TaskGraphRunner' = None
186
- basedir : str = None
187
- memento : TaskMemento = None
188
- depends : List['Task'] = dc.field(default_factory=list)
189
- output : Any = None
190
-
191
- # Implementation data below
192
- basedir : str = dc.field(default=None)
193
- rundir : str = dc.field(default=None)
194
- impl : str = None
195
- body: Dict[str,Any] = dc.field(default_factory=dict)
196
- impl_t : Any = None
197
-
198
- _log : ClassVar = logging.getLogger("Task")
199
-
200
- def init(self, runner, basedir):
201
- self.session = runner
202
- self.basedir = basedir
203
-
204
- def getMemento(self, T) -> TaskMemento:
205
- if os.path.isfile(os.path.join(self.rundir, "memento.json")):
206
- with open(os.path.join(self.rundir, "memento.json"), "r") as fp:
207
- try:
208
- data = json.load(fp)
209
- self.memento = T(**data)
210
- except Exception as e:
211
- self._log.critical("Failed to load memento %s: %s" % (
212
- os.path.join(self.rundir, "memento.json"), str(e)))
213
- os.unlink(os.path.join(self.rundir, "memento.json"))
214
- return self.memento
215
-
216
- def setMemento(self, memento : TaskMemento):
217
- self.memento = memento
218
-
219
- async def isUpToDate(self, memento) -> bool:
220
- return False
221
-
222
- async def do_run(self, session) -> TaskData:
223
- self._log.info("--> %s (%s) do_run - %d depends" % (
224
- self.name,
225
- str(type(self)),
226
- len(self.depends)))
227
-
228
- self.session = session
229
-
230
- if len(self.depends) > 0:
231
- deps_o = []
232
- for d in self.depends:
233
- dep_o = d.getOutput()
234
- if dep_o is None:
235
- raise Exception("Null output for %s" % d.name)
236
- deps_o.append(dep_o)
237
-
238
- input = TaskData.merge(deps_o)
239
- input.src = self.name
240
- input.deps[self.name] = list(inp.name for inp in self.depends)
241
- else:
242
- input = TaskData()
243
-
244
-
245
- # Mark the source of this data as being this task
246
- input.src = self.name
247
-
248
- self.init_rundir()
249
183
 
250
- self.output = await self.run(input)
184
+ # Need TaskDef
251
185
 
252
- if self.output is None:
253
- raise Exception("No output produced by %s" % self.name)
254
- result = TaskData()
255
-
256
- # Write-back the memento, if specified
257
- self.save_memento()
186
+ params : TaskParams # Might need to be set of instructions for building...
187
+ # This needs to be 'inside out' -- listed bottom to top
188
+ srcdir : str = dc.field(default=None)
189
+ rundir : str = dc.field(default=None)
190
+ depends : List['Task'] = dc.field(default_factory=list)
191
+ dependents : List['Task'] = dc.field(default_factory=list)
192
+ output : TaskDataOutput = dc.field(default=None)
258
193
 
259
- # Combine data from the deps to produce a result
260
- self._log.info("<-- %s (%s) do_run - %d depends" % (
261
- self.name,
262
- str(type(self)),
263
- len(self.depends)))
264
- return self.output
194
+ _log : ClassVar = logging.getLogger("Task")
265
195
 
266
- async def run(self, input : TaskData) -> TaskData:
196
+ async def run(self,
197
+ input : TaskDataInput,
198
+ runner : 'TaskGraphRunner') -> TaskDataResult:
267
199
  raise NotImplementedError("TaskImpl.run() not implemented")
268
-
269
- def init_rundir(self):
270
- if not os.path.isdir(self.rundir):
271
- os.makedirs(self.rundir)
272
-
273
- def save_memento(self):
274
- if self.memento is not None:
275
- with open(os.path.join(self.rundir, "memento.json"), "w") as fp:
276
- fp.write(self.memento.model_dump_json(indent=2))
277
-
278
- def getOutput(self) -> TaskData:
279
- return self.output
280
-
281
- def getField(self, name : str) -> Any:
282
- if name in self.__dict__.keys():
283
- return self.__dict__[name]
284
- elif name in self.__pydantic_extra__.keys():
285
- return self.__pydantic_extra__[name]
286
- else:
287
- raise Exception("No such field %s" % name)
288
-
289
-
290
-
291
200
 
dv_flow/mgr/task_data.py CHANGED
@@ -27,6 +27,24 @@ from typing import Any, ClassVar, Dict, Set, List, Tuple
27
27
  from .fileset import FileSet
28
28
  from toposort import toposort
29
29
 
30
+ class TaskDataInput(BaseModel):
31
+ changed : bool
32
+ srcdir : str
33
+ rundir : str
34
+ params : Any
35
+ memento : Any
36
+
37
+ class TaskDataResult(BaseModel):
38
+ changed : bool
39
+ output : List[Any]
40
+ memento : Any
41
+ markers : List[Any]
42
+ status : int
43
+
44
+ class TaskDataOutput(BaseModel):
45
+ changed : bool
46
+ output : List[Any]
47
+
30
48
  class TaskDataParamOpE(enum.Enum):
31
49
  Set = enum.auto()
32
50
  Append = enum.auto()
@@ -48,26 +66,22 @@ class TaskDataParam(BaseModel):
48
66
  kind : TaskDataParamKindE
49
67
  ops : List[TaskDataParamOp] = dc.Field(default_factory=list)
50
68
 
69
+ class TaskDataItem(BaseModel):
70
+ type : str
71
+ src : str
72
+ id : str
73
+
51
74
  class TaskData(BaseModel):
52
75
  src : str = None
53
- params : Dict[str,TaskDataParam] = dc.Field(default_factory=dict)
54
76
  deps : Dict[str,Set[str]] = dc.Field(default_factory=dict)
55
- filesets : List[FileSet] = dc.Field(default_factory=list)
56
77
  changed : bool = False
78
+ data : List[TaskDataItem] = dc.Field(default_factory=list)
57
79
 
58
80
  _log : ClassVar = logging.getLogger("TaskData")
59
81
 
60
- def hasParam(self, name: str) -> bool:
61
- return name in self.params
62
-
63
- def getParam(self, name: str) -> Any:
64
- return self.params[name]
65
-
66
- def setParam(self, name: str, value: Any):
67
- self.params[name] = value
68
-
69
- def addFileSet(self, fs : FileSet):
70
- self.filesets.append(fs)
82
+ def addData(self, item : TaskDataItem):
83
+ item.src = self.src
84
+ self.data.append(item)
71
85
 
72
86
  def getFileSets(self, type=None, order=True) -> List[FileSet]:
73
87
  ret = []
@@ -77,8 +91,10 @@ class TaskData(BaseModel):
77
91
  if order:
78
92
  # The deps map specifies task dependencies
79
93
 
94
+ filesets = filter(lambda x: x.type == "std.FileSet", self.data)
95
+
80
96
  candidate_fs = []
81
- for fs in self.filesets:
97
+ for fs in filesets:
82
98
  self._log.debug("fs: %s" % str(fs))
83
99
  if type is None or fs.type in type:
84
100
  candidate_fs.append(fs)
dv_flow/mgr/task_def.py CHANGED
@@ -22,7 +22,9 @@
22
22
  import pydantic.dataclasses as dc
23
23
  from pydantic import BaseModel
24
24
  from typing import Any, Dict, List, Union, Tuple
25
+ from .param_def import ParamDef
25
26
  from .task import Task
27
+ from .task_output import TaskOutput
26
28
 
27
29
  @dc.dataclass
28
30
  class TaskSpec(object):
@@ -37,7 +39,8 @@ class TaskDef(BaseModel):
37
39
  desc : str = dc.Field(default="")
38
40
  doc : str = dc.Field(default="")
39
41
  depends : List[Union[str,TaskSpec]] = dc.Field(default_factory=list, alias="needs")
40
- params: Dict[str,Any] = dc.Field(default_factory=dict, alias="with")
42
+ params: List[ParamDef] = dc.Field(default_factory=list, alias="with")
43
+ out: List[TaskOutput] = dc.Field(default_factory=list)
41
44
 
42
45
  def copy(self) -> 'TaskDef':
43
46
  ret = TaskDef(
@@ -0,0 +1,22 @@
1
+ import pydantic.dataclasses as dc
2
+ from pydantic import BaseModel
3
+ from typing import Any, Dict, List
4
+
5
+
6
+ class TaskExecData(BaseModel):
7
+ """Data from a single exection of a task"""
8
+ name : str
9
+ start : str
10
+ finish : str
11
+ status : int
12
+ memento : Any
13
+ markers : List[Any]
14
+
15
+ class FlowExecData(BaseModel):
16
+ """
17
+ Data from multiple tasks executions. 'info' holds information
18
+ across multiple flow invocations. 'tasks' holds the names of
19
+ tasks executed in the most-recent invocation.
20
+ """
21
+ info : Dict[str, TaskExecData] = dc.Field(default_factory=dict)
22
+ tasks : List[str] = dc.Field(default_factory=list)
@@ -0,0 +1,17 @@
1
+
2
+ from pydantic import BaseModel
3
+ from typing import Any, ClassVar, Dict, Set, List, Tuple
4
+
5
+ class TaskImplParams(BaseModel):
6
+ pass
7
+
8
+ class TaskImplSourceData(BaseModel):
9
+ params : Any
10
+ changed : bool
11
+ memento : Any
12
+
13
+ class TaskImplResultData(BaseModel):
14
+ data : List[Any]
15
+ changed : bool
16
+ memento : Any
17
+
@@ -0,0 +1,6 @@
1
+ from pydantic import BaseModel, Field
2
+ from typing import Any, List
3
+
4
+ class TaskOutput(BaseModel):
5
+ type : str
6
+ params : List[Any] = Field(default_factory=list, alias="with")
dv_flow/mgr/type.py ADDED
File without changes
@@ -0,0 +1,10 @@
1
+
2
+ from typing import List, Union
3
+ from pydantic import BaseModel, Field
4
+ from .param_def import ParamDef
5
+
6
+ class TypeDef(BaseModel):
7
+ name : str
8
+ uses : str = None
9
+ doc : str = None
10
+ fields : List[ParamDef] = Field(alias="with", default_factory=list)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: dv-flow-mgr
3
- Version: 0.0.1.12992722023a1
3
+ Version: 0.0.1.13468776985a1
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
@@ -0,0 +1,38 @@
1
+ dv_flow/mgr/__init__.py,sha256=IZA7I1u7RH34DrJXSkETxWFpK5Jn_A2zXfnCAzJ8XxA,289
2
+ dv_flow/mgr/__main__.py,sha256=uik6gDAvtZNG0yyDKYc4FTl6R1QHAR543jNG2lCAa6E,1771
3
+ dv_flow/mgr/expr_eval.py,sha256=pfnTDurXPTURgpdzlno5XtXlkoPfnJmAAq45G9T2D3k,1517
4
+ dv_flow/mgr/expr_parser.py,sha256=aR8n6hgk5xmFknIaSVC02K-So-eU4pkkFtwb7zWsSPs,5474
5
+ dv_flow/mgr/fileset.py,sha256=FNvC5sU2ArxJ0OO3v8dXTv8zX-bZ5t0a0ljne0fQQ1o,1150
6
+ dv_flow/mgr/fragment_def.py,sha256=cyzp1XeWtNOaagScmeS-BPsoXj9j2LTBbKq5ZUioz8I,1641
7
+ dv_flow/mgr/out,sha256=d8GGBi3J43fhdLBlnsUbzBfRe0TD0QTP3nOTz54l2bI,200
8
+ dv_flow/mgr/package.py,sha256=MDnt9q4pD_Aex_hSK_EUQ38IiaxOihgxbMmk5dH1deQ,1674
9
+ dv_flow/mgr/package_def.py,sha256=Sv3KS5pDysUrtPBWElCvmWt2pnkTipZcZGYwKr5N7Mc,14967
10
+ dv_flow/mgr/package_import_spec.py,sha256=ah3r15v5Jdub2poc3sgi6Uar1L3oGoYsCPPNiOHV-a4,1760
11
+ dv_flow/mgr/param_def.py,sha256=e2WvRCMArbgcsKC4TKQqZTscZmCdo3WvVR6w3LN0VK8,727
12
+ dv_flow/mgr/parsetab.py,sha256=enSOnMQ-woIsMEzHyeYiefvhAl8enxfX9Ct_o8-jkqs,3780
13
+ dv_flow/mgr/pkg_rgy.py,sha256=2R_EaeBDJn5qUq9DzSnLc37wUP36MWSv-p0LgUjJRAg,4471
14
+ dv_flow/mgr/task.py,sha256=jZrxTevSulUQ56RdgD0TQXrQ05859FgmXahOdxhdyT8,6349
15
+ dv_flow/mgr/task_data.py,sha256=TCc5KYuKoQNYfemVOzIlNKkMKIw-cqVl5_EmDs03W7M,10718
16
+ dv_flow/mgr/task_def.py,sha256=6qDDgge5RXssL5TAZR01dGb_Vjvbj72tJirg66O-Yt4,1818
17
+ dv_flow/mgr/task_exec_data.py,sha256=aT__kmVmNxqnS_GbTRS1vrYgKiv8cH-HUSmRb6YYKsI,640
18
+ dv_flow/mgr/task_graph_builder.py,sha256=4dfy_T26MYI7ls2xiofr4V0ItZHDehU2iw6UBPt-SZQ,7074
19
+ dv_flow/mgr/task_graph_runner.py,sha256=NwNYcOJ952lPMLwIIlYE9CoDdedqvcw2fWHYUsKFXuU,2164
20
+ dv_flow/mgr/task_graph_runner_local.py,sha256=66JYJcu-W60LjfuT9UkbcKslNqDcD5q4UR7ZAWrSaGM,4707
21
+ dv_flow/mgr/task_impl_data.py,sha256=bFPijoKrh9x7fZN2DsvRJp0UHo-gGM0VjtDQISyfhFk,321
22
+ dv_flow/mgr/task_memento.py,sha256=C7VTQpBhDEoYuDmE6YTM-6TLMLnqHp6Y0Vat1aTgtCs,1096
23
+ dv_flow/mgr/task_output.py,sha256=l-W-FvVo6YDah1RQS-I9N0KUtB3vp-kl7lxIdmNz0l4,178
24
+ dv_flow/mgr/type.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
25
+ dv_flow/mgr/type_def.py,sha256=KdhuNlfw-NKU-4VZFCnMPyj775yEB7cpr5tz73a9yuQ,259
26
+ dv_flow/mgr/util.py,sha256=06eVyURF4ga-s8C9Sd3ZSDebwO4QS0XXaB8xADVbWRc,1437
27
+ dv_flow/mgr/cmds/cmd_run.py,sha256=eths8kT7mBmpZqwOuMtpKAaux4rg-f7hPBxxTHbpKT4,2903
28
+ dv_flow/mgr/share/flow.json,sha256=lNmZex9NXkYbyb2aZseQfUOkV9CMyfH0iLODEI7EPBw,5096
29
+ dv_flow/mgr/std/fileset.py,sha256=uP7bGntRq-Tn5_GEFnt0_J_OAmfvep3GlCwCuE8by4o,2710
30
+ dv_flow/mgr/std/flow.dv,sha256=j9wLrF3Ghh1ZLbJxmk7WiNiRYUYEer-8CCUA5hsgtfk,1409
31
+ dv_flow/mgr/std/message.py,sha256=BPTHnEMD4tBufQ9LvsS9Sa_0xjaJATbBpwqosWslvVA,193
32
+ dv_flow/mgr/std/task_null.py,sha256=KObmjG_4D08GJ1k6neqKIQrFY72Sj0jLnwXxEkq5HA0,321
33
+ dv_flow_mgr-0.0.1.13468776985a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
34
+ dv_flow_mgr-0.0.1.13468776985a1.dist-info/METADATA,sha256=C2BOmVhhEQfwS9QQ9reuEWFsP9uWupVItzxnL5lilJc,13276
35
+ dv_flow_mgr-0.0.1.13468776985a1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
36
+ dv_flow_mgr-0.0.1.13468776985a1.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
37
+ dv_flow_mgr-0.0.1.13468776985a1.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
38
+ dv_flow_mgr-0.0.1.13468776985a1.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- dv_flow/mgr/__init__.py,sha256=IZA7I1u7RH34DrJXSkETxWFpK5Jn_A2zXfnCAzJ8XxA,289
2
- dv_flow/mgr/__main__.py,sha256=uik6gDAvtZNG0yyDKYc4FTl6R1QHAR543jNG2lCAa6E,1771
3
- dv_flow/mgr/fileset.py,sha256=FNvC5sU2ArxJ0OO3v8dXTv8zX-bZ5t0a0ljne0fQQ1o,1150
4
- dv_flow/mgr/fragment_def.py,sha256=p5i6ONtBWlDHTBFsduu3Z36_76Bn8PCIylp_xoZ7jfQ,1552
5
- dv_flow/mgr/package.py,sha256=AOLEEotVQF9VNMMl13uNQ7Na2TuHPXxEvybBOX7XIps,1615
6
- dv_flow/mgr/package_def.py,sha256=iHBFV-CKyCypvrd31zm3Yjkcib9xZo1gFlFL7YMfJO8,14012
7
- dv_flow/mgr/package_import_spec.py,sha256=ah3r15v5Jdub2poc3sgi6Uar1L3oGoYsCPPNiOHV-a4,1760
8
- dv_flow/mgr/pkg_rgy.py,sha256=2R_EaeBDJn5qUq9DzSnLc37wUP36MWSv-p0LgUjJRAg,4471
9
- dv_flow/mgr/task.py,sha256=giy5elwIS_fab6wGnA8JCeZIEeX0nG5zpcq5ifGYSOs,9087
10
- dv_flow/mgr/task_data.py,sha256=XBPWwvuaQ3BZ94wknvv1bqLh98iTzAg5fskv7_kk6DQ,10524
11
- dv_flow/mgr/task_def.py,sha256=96hSwqJo0MazJ1VcLhovYRmNCplsNLt47AumtyjSddU,1690
12
- dv_flow/mgr/task_graph_builder.py,sha256=4dfy_T26MYI7ls2xiofr4V0ItZHDehU2iw6UBPt-SZQ,7074
13
- dv_flow/mgr/task_graph_runner.py,sha256=NwNYcOJ952lPMLwIIlYE9CoDdedqvcw2fWHYUsKFXuU,2164
14
- dv_flow/mgr/task_graph_runner_local.py,sha256=66JYJcu-W60LjfuT9UkbcKslNqDcD5q4UR7ZAWrSaGM,4707
15
- dv_flow/mgr/task_memento.py,sha256=C7VTQpBhDEoYuDmE6YTM-6TLMLnqHp6Y0Vat1aTgtCs,1096
16
- dv_flow/mgr/util.py,sha256=06eVyURF4ga-s8C9Sd3ZSDebwO4QS0XXaB8xADVbWRc,1437
17
- dv_flow/mgr/cmds/cmd_run.py,sha256=eths8kT7mBmpZqwOuMtpKAaux4rg-f7hPBxxTHbpKT4,2903
18
- dv_flow/mgr/share/flow.json,sha256=lNmZex9NXkYbyb2aZseQfUOkV9CMyfH0iLODEI7EPBw,5096
19
- dv_flow/mgr/std/fileset.py,sha256=uP7bGntRq-Tn5_GEFnt0_J_OAmfvep3GlCwCuE8by4o,2710
20
- dv_flow/mgr/std/flow.dv,sha256=pSpzrPPEu_L8DHccGfArxsKYgUfyQidShZc0ShgGtsY,500
21
- dv_flow/mgr/std/message.py,sha256=BPTHnEMD4tBufQ9LvsS9Sa_0xjaJATbBpwqosWslvVA,193
22
- dv_flow/mgr/std/task_null.py,sha256=KObmjG_4D08GJ1k6neqKIQrFY72Sj0jLnwXxEkq5HA0,321
23
- dv_flow_mgr-0.0.1.12992722023a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
24
- dv_flow_mgr-0.0.1.12992722023a1.dist-info/METADATA,sha256=kCTd3eqAjQmtiL2_rnfPvCERKOp4I3aRl3yusyz4xMw,13276
25
- dv_flow_mgr-0.0.1.12992722023a1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
26
- dv_flow_mgr-0.0.1.12992722023a1.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
27
- dv_flow_mgr-0.0.1.12992722023a1.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
28
- dv_flow_mgr-0.0.1.12992722023a1.dist-info/RECORD,,