dv-flow-mgr 0.0.1.13931887892a1__py3-none-any.whl → 0.0.1.13959047687a1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
dv_flow/mgr/__init__.py CHANGED
@@ -21,7 +21,6 @@
21
21
  #****************************************************************************
22
22
  from .package_def import *
23
23
  from .pkg_rgy import PkgRgy
24
- from .task_graph_runner import *
25
24
  from .task import *
26
25
  from .task_data import *
27
26
  from .task_graph_builder import TaskGraphBuilder
@@ -23,10 +23,8 @@ import asyncio
23
23
  import os
24
24
  import logging
25
25
  from typing import ClassVar
26
- from ..task_graph_runner import TaskGraphRunner
27
26
  from ..util import loadProjPkgDef
28
27
  from ..task_graph_builder import TaskGraphBuilder
29
- from ..task_graph_runner_local import TaskGraphRunnerLocal
30
28
  from ..task_runner import TaskSetRunner
31
29
  from ..task_listener_log import TaskListenerLog
32
30
  from ..pkg_rgy import PkgRgy
@@ -33,6 +33,7 @@ from typing import Any, Dict, List, Callable, Tuple, ClassVar, Union
33
33
  from .fragment_def import FragmentDef
34
34
  from .package import Package
35
35
  from .package_import_spec import PackageImportSpec, PackageSpec
36
+ from .param_def import ParamDef
36
37
  from .task_node import TaskNodeCtor, TaskNodeCtorProxy, TaskNodeCtorTask
37
38
  from .task_ctor import TaskCtor
38
39
  from .task_def import TaskDef, TaskSpec
@@ -41,13 +42,26 @@ from .type_def import TypeDef
41
42
 
42
43
 
43
44
  class PackageDef(BaseModel):
44
- name : str
45
+ name : str = dc.Field(
46
+ description="Name of the package")
45
47
  params : Dict[str,Any] = dc.Field(default_factory=dict)
46
48
  type : List[PackageSpec] = dc.Field(default_factory=list)
47
- tasks : List[TaskDef] = dc.Field(default_factory=list)
48
- imports : List[Union[str,PackageImportSpec]] = dc.Field(default_factory=list)
49
- fragments: List[str] = dc.Field(default_factory=list)
49
+ tasks : List[TaskDef] = dc.Field(
50
+ default_factory=list,
51
+ description="List of tasks defined in the package")
52
+ imports : List[Union[str,PackageImportSpec]] = dc.Field(
53
+ default_factory=list,
54
+ description="List of packages to import")
55
+ fragments: List[str] = dc.Field(
56
+ default_factory=list,
57
+ description="List of fragments to include")
50
58
  types : List[TypeDef] = dc.Field(default_factory=list)
59
+ uses : str = dc.Field(
60
+ default=None,
61
+ description="Name of the package to use as a base")
62
+ params : List[ParamDef] = dc.Field(
63
+ default_factory=list, alias="with",
64
+ description="List of package parameters to set")
51
65
 
52
66
  fragment_l : List['FragmentDef'] = dc.Field(default_factory=list, exclude=True)
53
67
  subpkg_m : Dict[str,'PackageDef'] = dc.Field(default_factory=dict, exclude=True)
dv_flow/mgr/param_def.py CHANGED
@@ -36,6 +36,7 @@ class ComplexType(BaseModel):
36
36
  class ParamDef(BaseModel):
37
37
  doc : str = None
38
38
  type : Union[str, 'ComplexType'] = None
39
+ derived : bool = Field(default=False)
39
40
  value : Union[Any, None] = None
40
41
  append : Union[Any, None] = None
41
42
  prepend : Union[Any, None] = None
dv_flow/mgr/std/exec.py CHANGED
@@ -20,23 +20,100 @@
20
20
  #*
21
21
  #****************************************************************************
22
22
  import asyncio
23
+ import os
23
24
  import logging
24
- from dv_flow.mgr import TaskDataResult
25
+ from pydantic import BaseModel
26
+ from dv_flow.mgr import TaskDataResult, TaskMarker
25
27
 
26
28
  _log = logging.getLogger("Exec")
27
29
 
28
- class Memento()
30
+ class Memento(BaseModel):
31
+ timestamp_file : str
32
+ timestamp : float
29
33
 
30
34
  async def Exec(runner, input) -> TaskDataResult:
31
35
  _log.debug("TaskExec run: %s: cmd=%s" % (input.name, input.params.command))
32
36
 
37
+ # Running the command is gated by inputs to the task
38
+ need_to_run = input.params.when == "always" or input.changed
39
+
40
+ status = 0
41
+ markers = []
42
+
43
+ if need_to_run:
44
+ fp = open(os.path.join(input.rundir, "run.log"), "w")
45
+ fp.write("Command: %s\n" % input.params.command)
46
+ proc = await asyncio.create_subprocess_shell(
47
+ input.params.command,
48
+ stdout=fp,
49
+ stderr=asyncio.subprocess.STDOUT)
50
+
51
+ result = await proc.wait()
52
+
53
+ status = proc.returncode
54
+
55
+ if status != 0:
56
+ markers.append(TaskMarker(
57
+ message="Command \"%s\" failed with status %d" % (
58
+ input.params.command, status), severity="error"))
59
+
60
+ changed = False
61
+ ex_memento = input.memento
62
+ memento = None
63
+
64
+ if ex_memento is not None and status == 0:
65
+ ex_memento_o = None
66
+ try:
67
+ ex_memento_o = Memento(**ex_memento)
68
+ except Exception as e:
69
+ _log.debug("Failed to deserialize memento: %s" % str(e))
70
+
71
+ if ex_memento_o is not None:
72
+ if input.params.timestamp is not None and input.params.timestamp != "":
73
+ # Have a file to use
74
+ if os.path.isfile(os.path.join(input.rundir, input.params.timestamp)):
75
+ ts_file = os.path.join(input.rundir, input.params.timestamp)
76
+ ts = os.path.getmtime(ts_file)
77
+
78
+ if ts_file != ex_memento_o.timestamp_file or ts != ex_memento_o.timestamp:
79
+ changed = True
80
+
81
+ memento = Memento(timestamp_file=ts_file, timestamp=ts)
82
+ else:
83
+ markers.append(TaskMarker(
84
+ message="Timestamp file %s not found" % (
85
+ os.path.join(input.rundir, input.params.timestamp)),
86
+ severity="error"))
87
+ status = 1
88
+ else:
89
+ memento = Memento()
90
+ else:
91
+ changed = True
92
+ memento = ex_memento
93
+ else:
94
+ # No existing memento, or the task failed
95
+ changed = (status == 0)
96
+
97
+ if input.params.when == "changed":
98
+ changed = input.changed
99
+
100
+ if input.params.timestamp is not None and input.params.timestamp != "":
101
+ # Check the timestamp file
102
+ try:
103
+ with open(input.params.timestamp_file, "r") as f:
104
+ timestamp = float(f.read())
105
+ except FileNotFoundError:
106
+ timestamp = 0.0
107
+
108
+ if timestamp < input.params.timestamp:
109
+ changed = True
33
110
 
34
- proc = await asyncio.create_subprocess_shell(
35
- input.params.command,
36
- stdout=asyncio.subprocess.PIPE,
37
- stderr=asyncio.subprocess.PIPE)
38
111
 
39
- await proc.wait()
40
112
 
41
- return TaskDataResult()
113
+ return TaskDataResult(
114
+ status=status,
115
+ changed=changed,
116
+ markers=markers,
117
+ memento=memento)
118
+
42
119
 
dv_flow/mgr/std/flow.dv CHANGED
@@ -1,5 +1,27 @@
1
1
 
2
- # yaml-language-server: $schema=https://dv-flow.github.io/dv-flow.schema.json
2
+ # yaml-language-server: $schema=https://dv-flow.github.io/flow.dv.schema.json
3
+
4
+ #****************************************************************************
5
+ #* flow.dv
6
+ #*
7
+ #* Copyright 2023-2025 Matthew Ballance and Contributors
8
+ #*
9
+ #* Licensed under the Apache License, Version 2.0 (the "License"); you may
10
+ #* not use this file except in compliance with the License.
11
+ #* You may obtain a copy of the License at:
12
+ #*
13
+ #* http://www.apache.org/licenses/LICENSE-2.0
14
+ #*
15
+ #* Unless required by applicable law or agreed to in writing, software
16
+ #* distributed under the License is distributed on an "AS IS" BASIS,
17
+ #* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18
+ #* See the License for the specific language governing permissions and
19
+ #* limitations under the License.
20
+ #*
21
+ #* Created on:
22
+ #* Author:
23
+ #*
24
+ #****************************************************************************
3
25
 
4
26
  package:
5
27
  name: std
@@ -12,18 +34,26 @@ package:
12
34
  type: str
13
35
  value: ""
14
36
  - name: FileSet
37
+ doc: |
38
+ Creates a fileset from a list of files or glob patterns
15
39
  pytask: dv_flow.mgr.std.fileset.FileSet
16
40
  passthrough: true
17
41
  with:
18
42
  base:
43
+ doc: |
44
+ Specifies the base directory for the fileset.
19
45
  type: str
20
46
  value: ""
21
47
  type:
48
+ doc: |
49
+ Specifies the file type (eg verilogSource) for the fileset.
22
50
  type: str
23
51
  value: ""
24
52
  incdirs:
25
53
  type: list
26
54
  include:
55
+ doc: |
56
+ Specifies a list of files or a glob pattern for the files to include
27
57
  type: str
28
58
  value: ""
29
59
  exclude:
dv_flow/mgr/task.py CHANGED
@@ -26,7 +26,6 @@ import logging
26
26
  from pydantic import BaseModel
27
27
  from typing import Any, Callable, ClassVar, Dict, List, Tuple
28
28
  from .task_data import TaskData, TaskDataInput, TaskDataOutput, TaskDataResult
29
- from .task_memento import TaskMemento
30
29
  from .task_ctor import TaskParamsCtor
31
30
  from .task_params_ctor import TaskParamsCtor
32
31
  from .task_runner import TaskRunner
dv_flow/mgr/task_ctor.py CHANGED
@@ -38,7 +38,7 @@ class TaskCtor(object):
38
38
 
39
39
  _log : ClassVar = logging.getLogger("TaskCtor")
40
40
 
41
- def mkTask(self, name : str, srcdir=None) -> 'Task':
41
+ def mkTask(self, name : str, srcdir=None) -> 'TaskNode':
42
42
  """Creates a task object"""
43
43
  if srcdir is None:
44
44
  srcdir = self.srcdir
dv_flow/mgr/task_data.py CHANGED
@@ -27,14 +27,25 @@ 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 SeverityE(enum.Enum):
31
+ Info = "info"
32
+ Warning = "warning"
33
+ Error = "error"
34
+
30
35
  class TaskMarkerLoc(BaseModel):
36
+ """
37
+ Captures the source location of a marker
38
+ """
31
39
  path : str
32
40
  line : int = dc.Field(default=-1)
33
41
  pos : int = dc.Field(default=-1)
34
42
 
35
43
  class TaskMarker(BaseModel):
44
+ """
45
+ Captures marker data produced by a task.
46
+ """
36
47
  msg : str
37
- severity : str
48
+ severity : SeverityE
38
49
  loc : TaskMarkerLoc = dc.Field(default=None)
39
50
 
40
51
  class TaskParameterSet(BaseModel):
@@ -43,6 +54,15 @@ class TaskParameterSet(BaseModel):
43
54
  seq : int = -1 # Order in which the param-set must appear
44
55
 
45
56
  class TaskDataInput(BaseModel):
57
+ """
58
+ Input data to a task
59
+ - name - name of the task
60
+ - changed - indicates whether any of this task's dependencies have changed
61
+ - rundir - directory in which the task is to be run
62
+ - params - parameters to the task
63
+ - inputs - list of parameter sets 'consumed' by this task
64
+ - memento - memento data previously returned by this task. None if no memento is available
65
+ """
46
66
  name : str
47
67
  changed : bool
48
68
  srcdir : str
@@ -52,6 +72,14 @@ class TaskDataInput(BaseModel):
52
72
  memento : Any
53
73
 
54
74
  class TaskDataResult(BaseModel):
75
+ """
76
+ Result data from a task
77
+ - changed - indicates whether the task modified its result data
78
+ - output - list of output parameter sets
79
+ - memento - memento data to be passed to the next invocation of the task
80
+ - markers - list of markers produced by the task
81
+ - status - status code (0=success, non-zero=failure)
82
+ """
55
83
  changed : bool = dc.Field(default=True)
56
84
  output : List[Any] = dc.Field(default_factory=list)
57
85
  memento : Any = dc.Field(default=None)
dv_flow/mgr/task_def.py CHANGED
@@ -20,6 +20,7 @@
20
20
  #*
21
21
  #****************************************************************************
22
22
  import pydantic.dataclasses as dc
23
+ import enum
23
24
  from pydantic import BaseModel
24
25
  from typing import Any, Dict, List, Union, Tuple
25
26
  from .param_def import ParamDef
@@ -35,20 +36,60 @@ class NeedSpec(object):
35
36
  name : str
36
37
  block : bool = False
37
38
 
39
+ class RundirE(enum.Enum):
40
+ Unique = "unique"
41
+ Inherit = "inherit"
42
+
43
+ class StrategyDef(BaseModel):
44
+ matrix : Dict[str,List[Any]] = dc.Field(
45
+ default_factory=dict,
46
+ description="Matrix of parameter values to explore")
47
+
38
48
  class TaskDef(BaseModel):
39
49
  """Holds definition information (ie the YAML view) for a task"""
40
- name : str
50
+ name : str = dc.Field(
51
+ title="Task Name",
52
+ description="The name of the task")
41
53
  fullname : str = dc.Field(default=None)
42
54
  # type : Union[str,TaskSpec] = dc.Field(default_factory=list)
43
- uses : str = dc.Field(default=None)
44
- pytask : str = dc.Field(default=None)
45
- desc : str = dc.Field(default="")
46
- doc : str = dc.Field(default="")
47
- needs : List[Union[str,NeedSpec,TaskSpec]] = dc.Field(default_factory=list, alias="needs")
48
- params: Dict[str,Union[str,list,ParamDef]] = dc.Field(default_factory=dict, alias="with")
49
- passthrough: bool = dc.Field(default=False)
50
- consumes : List[Any] = dc.Field(default_factory=list)
51
- tasks: List['TaskDef'] = dc.Field(default_factory=list)
55
+ uses : str = dc.Field(
56
+ default=None,
57
+ title="Base type",
58
+ description="Task from which this task is derived")
59
+ pytask : str = dc.Field(
60
+ default=None,
61
+ title="Python method name",
62
+ description="Python method to execute to implement this task")
63
+ strategy : StrategyDef = dc.Field(
64
+ default=None)
65
+ tasks: List['TaskDef'] = dc.Field(
66
+ default_factory=list,
67
+ description="Sub-tasks")
68
+ desc : str = dc.Field(
69
+ default="",
70
+ title="Task description",
71
+ description="Short description of the task's purpose")
72
+ doc : str = dc.Field(
73
+ default="",
74
+ title="Task documentation",
75
+ description="Full documentation of the task")
76
+ # needs : List[Union[str,NeedSpec,TaskSpec]] = dc.Field(
77
+ needs : List[Union[str]] = dc.Field(
78
+ default_factory=list,
79
+ description="List of tasks that this task depends on")
80
+ params: Dict[str,Union[str,list,ParamDef]] = dc.Field(
81
+ default_factory=dict,
82
+ alias="with",
83
+ description="Parameters for the task")
84
+ rundir : RundirE = dc.Field(
85
+ default=RundirE.Unique,
86
+ description="Specifies handling of this tasks's run directory")
87
+ passthrough: bool = dc.Field(
88
+ default=False,
89
+ description="Specifies whether this task should pass its inputs to its output")
90
+ consumes : List[Any] = dc.Field(
91
+ default_factory=list,
92
+ description="Specifies matching patterns for parameter sets that this task consumes")
52
93
 
53
94
  # out: List[TaskOutput] = dc.Field(default_factory=list)
54
95
 
@@ -56,8 +56,15 @@ class TaskListenerLog(object):
56
56
  "error": "[red]E[/red]",
57
57
  }
58
58
  for m in task.result.markers:
59
+ severity_s = str(m.severity)
60
+
61
+ if severity_s in sev_pref_m.keys():
62
+ sev_pref = sev_pref_m[severity_s]
63
+ else:
64
+ sev_pref = ""
65
+
59
66
  msg = " %s %s: %s" % (
60
- sev_pref_m[m.severity],
67
+ sev_pref,
61
68
  task.name,
62
69
  m.msg)
63
70
 
dv_flow/mgr/task_node.py CHANGED
@@ -128,8 +128,8 @@ class TaskNode(object):
128
128
 
129
129
  # Set variables from the inputs
130
130
  for need in self.needs:
131
- for name,value in {"rundir" : need.rundir}.items():
132
- eval.setVar("%s.%s" % (need.name, name), value)
131
+ for name,value in {"rundir" : need[0].rundir}.items():
132
+ eval.setVar("%s.%s" % (need[0].name, name), value)
133
133
 
134
134
  # Default inputs is the list of parameter sets that match 'consumes'
135
135
  inputs = []
@@ -1,5 +1,5 @@
1
1
  #****************************************************************************
2
- #* task_impl_data.py
2
+ #* task_node_compound.py
3
3
  #*
4
4
  #* Copyright 2023-2025 Matthew Ballance and Contributors
5
5
  #*
@@ -19,19 +19,19 @@
19
19
  #* Author:
20
20
  #*
21
21
  #****************************************************************************
22
- from pydantic import BaseModel
23
- from typing import Any, ClassVar, Dict, Set, List, Tuple
22
+ import dataclasses as dc
23
+ from .task_node import TaskNode
24
+ from .task_data import TaskDataResult, TaskDataInput, TaskDataOutput
25
+ from .task_runner import TaskRunner
26
+ from typing import Any, List
24
27
 
25
- class TaskImplParams(BaseModel):
26
- pass
27
-
28
- class TaskImplSourceData(BaseModel):
29
- params : Any
30
- changed : bool
31
- memento : Any
32
-
33
- class TaskImplResultData(BaseModel):
34
- data : List[Any]
35
- changed : bool
36
- memento : Any
28
+ @dc.dataclass
29
+ class TaskNodeCompound(TaskNode):
30
+ tasks : List[TaskNode] = dc.field(default_factory=list)
37
31
 
32
+ async def do_run(self,
33
+ runner : TaskRunner,
34
+ rundir,
35
+ memento : Any=None) -> TaskDataResult:
36
+ pass
37
+ pass
@@ -29,7 +29,7 @@ from datetime import datetime
29
29
  from toposort import toposort
30
30
  from typing import Any, Callable, ClassVar, List, Tuple, Union
31
31
  from .task_data import TaskDataInput, TaskDataOutput, TaskDataResult
32
- from .task_node import TaskNode
32
+ from .task_node import TaskNode, RundirE
33
33
 
34
34
  @dc.dataclass
35
35
  class TaskRunner(object):
@@ -140,10 +140,14 @@ class TaskSetRunner(TaskRunner):
140
140
  memento = src_memento.get(t.name, None)
141
141
  dirname = t.name
142
142
  invalid_chars_pattern = r'[\/:*?"<>|#%&{}\$\\!\'`;=@+]'
143
- # Replace invalid characters with the replacement string.
144
- dirname = re.sub(invalid_chars_pattern, '_', dirname)
145
143
 
146
- rundir = os.path.join(self.rundir, dirname)
144
+ if t.rundir_t == RundirE.Unique:
145
+ # Replace invalid characters with the replacement string.
146
+ dirname = re.sub(invalid_chars_pattern, '_', dirname)
147
+
148
+ rundir = os.path.join(self.rundir, dirname)
149
+ else:
150
+ rundir = self.rundir
147
151
 
148
152
  if not os.path.isdir(rundir):
149
153
  os.makedirs(rundir, exist_ok=True)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: dv-flow-mgr
3
- Version: 0.0.1.13931887892a1
3
+ Version: 0.0.1.13959047687a1
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
@@ -212,3 +212,4 @@ Requires-Dist: pyyaml
212
212
  Requires-Dist: rich
213
213
  Requires-Dist: toposort
214
214
  Requires-Dist: svdep
215
+ Dynamic: license-file
@@ -1,4 +1,4 @@
1
- dv_flow/mgr/__init__.py,sha256=63pCyRCpFj4Rdc3Lz-HKaVmFAI4BAma1OEy6dDRQeXM,1134
1
+ dv_flow/mgr/__init__.py,sha256=XWO0B0wXUyhqGzu7Pt2f-r-_k7CHPZOOxAaEPUgjaAs,1101
2
2
  dv_flow/mgr/__main__.py,sha256=yH_LoWlqPc5y9fKATUyDLNVobUnjWtvcqgqcP2kc628,2213
3
3
  dv_flow/mgr/eval_jq.py,sha256=bRsHtaN51qIOiZK1VJV52W0-vj5VH0nQ7XIFebZi5kI,1129
4
4
  dv_flow/mgr/expr_eval.py,sha256=N_8hRIgzJK9JVqhRt8F9rc4S7AAdKHMMltafqk6KhJs,3113
@@ -7,42 +7,38 @@ dv_flow/mgr/fileset.py,sha256=cfKem8w5Xw4AUQkC0gyCXof2OlnoJ1t06Iw7IvMyihs,1245
7
7
  dv_flow/mgr/fragment_def.py,sha256=nwxx3TW7UMa6uFMp0QEKgJdmOsO2iX89cwyD2beaGoU,1646
8
8
  dv_flow/mgr/out,sha256=d8GGBi3J43fhdLBlnsUbzBfRe0TD0QTP3nOTz54l2bI,200
9
9
  dv_flow/mgr/package.py,sha256=D-jH3jqoiQG3xZIYgteFLZ4vQ0ZfkbhnW1u6wlyAJMc,1684
10
- dv_flow/mgr/package_def.py,sha256=7WUStRgJcUY0FEKx3NYOs7hyLel0YI1lfRMutTgcblM,17193
10
+ dv_flow/mgr/package_def.py,sha256=ZGanENWXRqYDKL8qiY4JzsGYLm2iXU85XfSAsq_7rIg,17719
11
11
  dv_flow/mgr/package_import_spec.py,sha256=aZMpnS9a5NFY76_pYXEuO3-Mkc_xFzy73fdrUe_54Dc,1760
12
12
  dv_flow/mgr/param.py,sha256=kkxMRGf6mPjSZJsjgLKH2vJL62Sn0ZESvjBLkEYOp20,1386
13
- dv_flow/mgr/param_def.py,sha256=ObRf289sI1xzOudjO9MzyTVuKsz3AS949XA4Deyz-kE,1549
13
+ dv_flow/mgr/param_def.py,sha256=snLHgafVqqWcDthJUOm9zvKocFsb7-wx2WTc5ltAlhg,1591
14
14
  dv_flow/mgr/param_ref_eval.py,sha256=5yH37oIX6f2qmk7GfRgNT5qZx0jm3CJFgB9lLDZZ1yQ,1981
15
15
  dv_flow/mgr/parsetab.py,sha256=I-p3nC60t9jiNtPhKyl_sE92SiP96zJLnNdydcLy33g,3780
16
16
  dv_flow/mgr/pkg_rgy.py,sha256=d1nIjRm3ymMNJT-yiMDxCS6bFisTPvLMqh5VrfsHVKM,5404
17
- dv_flow/mgr/task.py,sha256=BmS0wd51l4tpTrsit3-ugCB5VGnwpMJNl0dfJfHS4DQ,5981
18
- dv_flow/mgr/task_ctor.py,sha256=YDYb5uW9Js7MnA8GqbYJljNCbeJFKGveZ2v-IJRgIa8,2221
19
- dv_flow/mgr/task_data.py,sha256=ysawiUcbQu-ImNSgU5LsfOWlBKdfBt_8juwSacnAqAQ,11437
20
- dv_flow/mgr/task_def.py,sha256=0rVlDjNF39PQ_0uzkSuOgvE2sZjFwpTAR8HIu_Arbog,2140
21
- dv_flow/mgr/task_exec_data.py,sha256=-mh9G2-iq6ioB7v7QrHiQAOEwd_hDKhnVf2Mb_IHRtg,1483
17
+ dv_flow/mgr/task.py,sha256=464P7RAiHHiUcDzzoc1XSQj2ihwT6Lcuxr1U2qGfgLA,5943
18
+ dv_flow/mgr/task_ctor.py,sha256=sPbDqRBMlbMAUddgtT2c7xWzbrYnZwcXf16wj-q7_5Y,2225
19
+ dv_flow/mgr/task_data.py,sha256=IBkxdqpWDMqD1S06u4ohG9pOTdiQPCePT4ZJknPAAw0,12401
20
+ dv_flow/mgr/task_def.py,sha256=295FqKPcZKlgJENRdPdk_io_2lvVN2c3T3CezLEt1UU,3497
22
21
  dv_flow/mgr/task_graph_builder.py,sha256=EYFsMZCDDHMEFWZOVSpPb7KBVE6N6XyL4KFzJVrPSPE,10106
23
- dv_flow/mgr/task_graph_runner.py,sha256=LZ5cTXLQlcK348AxTYKqfpsFFmxA3aseGfholvQW39s,2187
24
- dv_flow/mgr/task_graph_runner_local.py,sha256=quAxmF1go2iVhBDieksg3brAZukIvpvF-8oJ_YXiauE,4692
25
- dv_flow/mgr/task_impl_data.py,sha256=jpO7kQ6AjYcOOfpgFIPCEYA1pQbVwFcIY_SY3Q53eGk,1163
26
- dv_flow/mgr/task_listener_log.py,sha256=b7caUHERGkN6eT8IinBJTdZpwASUs8xAqDmtEymMKzQ,3529
27
- dv_flow/mgr/task_memento.py,sha256=CV3d1J4ADhMpqvYPfWvUI7duSFCbLEzY41y2GZBHIhM,1101
28
- dv_flow/mgr/task_node.py,sha256=DL7gI79uu0yoaz2J7PJhr91isL42agATbLDO0ngGqi4,15215
22
+ dv_flow/mgr/task_listener_log.py,sha256=vhyLegEown54RY3sRqFTgqhxrRAHqp_YhomObdnZ0vs,3743
23
+ dv_flow/mgr/task_node.py,sha256=H0OuBrridAhYutDUap-V09T-2xZNaJKkfayeqi1UrTw,15221
24
+ dv_flow/mgr/task_node_compound.py,sha256=1NZvPh0EkyJ_1Vj4H9RNmFQKcmGavybZWubNIOyl5AA,1330
29
25
  dv_flow/mgr/task_output.py,sha256=ZwyvwnYj_gHOEFAEOH3m24Xfc4Cn77hb1j7LkX8_3C4,1086
30
26
  dv_flow/mgr/task_params_ctor.py,sha256=BPkbnoCtzhCxc1g8CJ6VimCcm5UAu92PXeDMhQ4lYsQ,1957
31
- dv_flow/mgr/task_runner.py,sha256=TB4feCEItxufUyyBSwNNY3OkQ0yjSO0fUfjga0u7rsg,8790
27
+ dv_flow/mgr/task_runner.py,sha256=6yoNzAGb79vgYG95ku_4Kr90cgztdisSICFfV5Ykf9c,8936
32
28
  dv_flow/mgr/type.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
29
  dv_flow/mgr/type_def.py,sha256=NDeyplKrPnWwEv4yHkhXEMK9d9j39b5MOeLB-1Mchqo,1095
34
30
  dv_flow/mgr/util.py,sha256=BLp-25Ph9roqo1O3VHI5sKhwxQ0wUU7znFwcSKt0hpA,1442
35
- dv_flow/mgr/cmds/cmd_run.py,sha256=lNMvpiyKf-Ehs0GUkzcOIoJxaXgeLKv6UFNakcm9_hw,3303
31
+ dv_flow/mgr/cmds/cmd_run.py,sha256=J6uCzzhtGHD9MYkvE0PpX4dkk5KlY3iW7yZ29iBO3js,3196
36
32
  dv_flow/mgr/share/flow.json,sha256=lNmZex9NXkYbyb2aZseQfUOkV9CMyfH0iLODEI7EPBw,5096
37
33
  dv_flow/mgr/std/create_file.py,sha256=wmn5N_mObx_wr2LPdKOVbNmdM71hhs3UXOv6Ap9l3Ts,2726
38
- dv_flow/mgr/std/exec.py,sha256=kU9S8mIBDvZFqcWGGe9RQIfeldDw2g2eGBBh-po0ePQ,1302
34
+ dv_flow/mgr/std/exec.py,sha256=UChqa_tAjvdB1NjqTsvlPgFomP8hMsX2rAOPyUonNpk,3896
39
35
  dv_flow/mgr/std/fileset.py,sha256=5IxS6T-x0wzA6fdEQcfHZ9kNP8IpH9hfJ3UMhL4A6Iw,3911
40
- dv_flow/mgr/std/flow.dv,sha256=Ehw0rrFcHoXt3WudeJ5PyPXpVtUcvvWGm43ikUWl-lE,2602
36
+ dv_flow/mgr/std/flow.dv,sha256=rl0VZt_H-TyIJq0iERai07aDDZHI86mNozs4gUxidDA,3759
41
37
  dv_flow/mgr/std/message.py,sha256=_Gox9oBzL9ZYG1JfJ-WYPXojVLqGNaKxZ9tpLVT0LO0,1035
42
38
  dv_flow/mgr/std/task_null.py,sha256=dw6LXBXVwth6gLPeduDvlz5znAhcVpDH8r1DticD-0w,1041
43
- dv_flow_mgr-0.0.1.13931887892a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
44
- dv_flow_mgr-0.0.1.13931887892a1.dist-info/METADATA,sha256=D2JLp63FgCw_yZC_bdxrl76DDLMzyI4By_K7mhYYhmM,13314
45
- dv_flow_mgr-0.0.1.13931887892a1.dist-info/WHEEL,sha256=beeZ86-EfXScwlR_HKu4SllMC9wUEj_8Z_4FJ3egI2w,91
46
- dv_flow_mgr-0.0.1.13931887892a1.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
47
- dv_flow_mgr-0.0.1.13931887892a1.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
48
- dv_flow_mgr-0.0.1.13931887892a1.dist-info/RECORD,,
39
+ dv_flow_mgr-0.0.1.13959047687a1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
40
+ dv_flow_mgr-0.0.1.13959047687a1.dist-info/METADATA,sha256=BzJ7u3Dpcs3DIfCz-igUqT2LZi1tnsJNRuvOsOmk9Ws,13336
41
+ dv_flow_mgr-0.0.1.13959047687a1.dist-info/WHEEL,sha256=tTnHoFhvKQHCh4jz3yCn0WPTYIy7wXx3CJtJ7SJGV7c,91
42
+ dv_flow_mgr-0.0.1.13959047687a1.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
43
+ dv_flow_mgr-0.0.1.13959047687a1.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
44
+ dv_flow_mgr-0.0.1.13959047687a1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (76.1.0)
2
+ Generator: setuptools (77.0.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,43 +0,0 @@
1
- #****************************************************************************
2
- #* task_exec_data.py
3
- #*
4
- #* Copyright 2023-2025 Matthew Ballance and Contributors
5
- #*
6
- #* Licensed under the Apache License, Version 2.0 (the "License"); you may
7
- #* not use this file except in compliance with the License.
8
- #* You may obtain a copy of the License at:
9
- #*
10
- #* http://www.apache.org/licenses/LICENSE-2.0
11
- #*
12
- #* Unless required by applicable law or agreed to in writing, software
13
- #* distributed under the License is distributed on an "AS IS" BASIS,
14
- #* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- #* See the License for the specific language governing permissions and
16
- #* limitations under the License.
17
- #*
18
- #* Created on:
19
- #* Author:
20
- #*
21
- #****************************************************************************
22
- import pydantic.dataclasses as dc
23
- from pydantic import BaseModel
24
- from typing import Any, Dict, List
25
-
26
-
27
- class TaskExecData(BaseModel):
28
- """Data from a single exection of a task"""
29
- name : str
30
- start : str
31
- finish : str
32
- status : int
33
- memento : Any
34
- markers : List[Any]
35
-
36
- class FlowExecData(BaseModel):
37
- """
38
- Data from multiple tasks executions. 'info' holds information
39
- across multiple flow invocations. 'tasks' holds the names of
40
- tasks executed in the most-recent invocation.
41
- """
42
- info : Dict[str, TaskExecData] = dc.Field(default_factory=dict)
43
- tasks : List[str] = dc.Field(default_factory=list)
@@ -1,70 +0,0 @@
1
- #****************************************************************************
2
- #* task_graph_runner.py
3
- #*
4
- #* Copyright 2023-2025 Matthew Ballance and Contributors
5
- #*
6
- #* Licensed under the Apache License, Version 2.0 (the "License"); you may
7
- #* not use this file except in compliance with the License.
8
- #* You may obtain a copy of the License at:
9
- #*
10
- #* http://www.apache.org/licenses/LICENSE-2.0
11
- #*
12
- #* Unless required by applicable law or agreed to in writing, software
13
- #* distributed under the License is distributed on an "AS IS" BASIS,
14
- #* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- #* See the License for the specific language governing permissions and
16
- #* limitations under the License.
17
- #*
18
- #* Created on:
19
- #* Author:
20
- #*
21
- #****************************************************************************
22
- import asyncio
23
- import os
24
- import dataclasses as dc
25
- from typing import Any, Callable, ClassVar, Dict, List, Tuple
26
- from .task import Task
27
- from .task_data import TaskData
28
- from .task_runner import TaskRunner
29
-
30
- @dc.dataclass
31
- class TaskGraphRunner(TaskRunner):
32
- """Session manages execution of a task graph"""
33
-
34
- _inst : ClassVar['TaskGraphRunner'] = None
35
-
36
-
37
- # Search path for .dfs files
38
- create_subprocess : Callable = asyncio.create_subprocess_exec
39
- _root_dir : str = None
40
-
41
- async def exec(self, *args, **kwargs):
42
- return self.create_subprocess(*args, **kwargs)
43
-
44
- # def load(self):
45
- # if not os.path.isdir(self.srcdir):
46
- # raise Exception("Root directory %s does not exist" % self.srcdir)
47
-
48
- # if not os.path.isfile(os.path.join(self.srcdir, "flow.dv")):
49
- # raise Exception("No root flow file")
50
-
51
- # self._root_dir = os.path.dirname(self.srcdir)
52
- # self.package = PackageDef.load(os.path.join(self.srcdir, "flow.dv"), [])
53
-
54
- # return self.package
55
-
56
-
57
- async def run(self, task : str) -> 'TaskData':
58
- impl = self.mkTaskGraph(task)
59
- return await impl.do_run()
60
-
61
- async def runTask(self, task : Task) -> 'TaskData':
62
- return await task.do_run()
63
-
64
- def queueTask(self, task : Task):
65
- """Queue a task for execution"""
66
- pass
67
-
68
-
69
-
70
-
@@ -1,141 +0,0 @@
1
- #****************************************************************************
2
- #* task_graph_runner_local.py
3
- #*
4
- #* Copyright 2023-2025 Matthew Ballance and Contributors
5
- #*
6
- #* Licensed under the Apache License, Version 2.0 (the "License"); you may
7
- #* not use this file except in compliance with the License.
8
- #* You may obtain a copy of the License at:
9
- #*
10
- #* http://www.apache.org/licenses/LICENSE-2.0
11
- #*
12
- #* Unless required by applicable law or agreed to in writing, software
13
- #* distributed under the License is distributed on an "AS IS" BASIS,
14
- #* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- #* See the License for the specific language governing permissions and
16
- #* limitations under the License.
17
- #*
18
- #* Created on:
19
- #* Author:
20
- #*
21
- #****************************************************************************
22
- import asyncio
23
- import os
24
- import yaml
25
- import dataclasses as dc
26
- import logging
27
- from toposort import toposort
28
- from typing import Any, Callable, ClassVar, Coroutine, Dict, List, Tuple, Union
29
- from .fragment_def import FragmentDef
30
- from .package import Package
31
- from .pkg_rgy import PkgRgy
32
- from .package_def import PackageDef, PackageSpec
33
- from .task import Task
34
- from .task_data import TaskData
35
- from .task_graph_runner import TaskGraphRunner
36
-
37
- @dc.dataclass
38
- class TaskGraphRunnerLocal(TaskGraphRunner):
39
- """Session manages execution of a task graph"""
40
-
41
- rundir : str
42
- nproc : int = 4
43
- done_task_m : Dict = dc.field(default_factory=dict)
44
- _workers : List = dc.field(default_factory=list)
45
-
46
- _inst : ClassVar['TaskGraphRunner'] = None
47
-
48
- # Search path for .dfs files
49
- create_subprocess : Callable = asyncio.create_subprocess_exec
50
- _root_dir : str = None
51
- _log : ClassVar = logging.getLogger("TaskGraphRunnerLocal")
52
-
53
- def __post_init__(self):
54
- if self.nproc == -1:
55
- self.nproc = os.cpu_count()
56
- for _ in range(self.nproc):
57
- self._workers.append(LocalRunnerWorker(self))
58
-
59
-
60
- async def exec(self, *args, **kwargs):
61
- return await self.create_subprocess(*args, **kwargs)
62
-
63
- async def run(self, task : Union[Task,List[Task]]) -> List['TaskData']:
64
- if isinstance(task, Task):
65
- unwrap = True
66
- task = [task]
67
- else:
68
- unwrap = False
69
-
70
- dep_m = {}
71
- task_m = {}
72
-
73
- for t in task:
74
- self._mkDeps(dep_m, task_m, t)
75
-
76
- self._log.debug("dep_m: %s" % str(dep_m))
77
-
78
- order = list(toposort(dep_m))
79
-
80
- self._log.debug("order: %s" % str(order))
81
-
82
- active_task_l : List[Tuple[Task,Coroutine]]= []
83
- # Now, iterate over the concurrent sets
84
- for active_s in order:
85
-
86
- # Check to see if all tasks are complete
87
- done = True
88
- for t in active_s:
89
- while len(active_task_l) >= self.nproc and t not in self.done_task_m.keys():
90
- # Wait for at least one job to complete
91
- done, pending = await asyncio.wait(at[1] for at in active_task_l)
92
- for d in done:
93
- for i in range(len(active_task_l)):
94
- if active_task_l[i][1] == d:
95
- tt = active_task_l[i][0]
96
- self.done_task_m[tt.name] = tt
97
- active_task_l.pop(i)
98
- break
99
- if t not in self.done_task_m.keys():
100
- task_t = task_m[t]
101
- coro = asyncio.Task(task_t.do_run(self))
102
- active_task_l.append((task_t, coro))
103
-
104
- # Now, wait for tasks to complete
105
- if len(active_task_l):
106
- coros = list(at[1] for at in active_task_l)
107
- res = await asyncio.gather(*coros)
108
-
109
- # print("order: %s" % str(order))
110
- #
111
- # run_o = list(t.do_run() for t in task)
112
-
113
- # ret = await asyncio.gather(*run_o)
114
- ret = None
115
-
116
- if unwrap:
117
- return task[0].output
118
- else:
119
- return list(t.output for t in task)
120
-
121
- def _mkDeps(self, dep_m, task_m, task):
122
- if task.name not in dep_m.keys():
123
- task_m[task.name] = task
124
- dep_m[task.name] = set(t.name for t in task.depends)
125
- for d in task.depends:
126
- self._mkDeps(dep_m, task_m, d)
127
-
128
- async def runTask(self, task : Task) -> 'TaskData':
129
- return await task.do_run()
130
-
131
- def queueTask(self, task : Task):
132
- """Queue a task for execution"""
133
- pass
134
-
135
- @dc.dataclass
136
- class LocalRunnerWorker(object):
137
- runner : TaskGraphRunnerLocal
138
- task_s : List = dc.field(default_factory=list)
139
-
140
-
141
-
@@ -1,34 +0,0 @@
1
- #****************************************************************************
2
- #* task_memento.py
3
- #*
4
- #* Copyright 2023-2025 Matthew Ballance and Contributors
5
- #*
6
- #* Licensed under the Apache License, Version 2.0 (the "License"); you may
7
- #* not use this file except in compliance with the License.
8
- #* You may obtain a copy of the License at:
9
- #*
10
- #* http://www.apache.org/licenses/LICENSE-2.0
11
- #*
12
- #* Unless required by applicable law or agreed to in writing, software
13
- #* distributed under the License is distributed on an "AS IS" BASIS,
14
- #* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- #* See the License for the specific language governing permissions and
16
- #* limitations under the License.
17
- #*
18
- #* Created on:
19
- #* Author:
20
- #*
21
- #****************************************************************************
22
- import pydantic.dataclasses as dc
23
- from pydantic import BaseModel
24
- from typing import Any, Dict, List
25
-
26
- class TaskMemento(BaseModel):
27
- # dep_ids : List[int] = dc.Field(default_factory=list)
28
- # params : Dict[str,Any] = dc.Field(default_factory=dict)
29
-
30
- pass
31
-
32
-
33
-
34
-