dv-flow-mgr 0.0.1.12672327205a1__py3-none-any.whl → 0.0.1.12750690879a1__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/fragment_def.py +4 -6
- dv_flow_mgr/package_def.py +27 -26
- dv_flow_mgr/package_import_spec.py +31 -0
- dv_flow_mgr/session.py +56 -13
- dv_flow_mgr/share/flow.json +8 -7
- dv_flow_mgr/task.py +24 -1
- dv_flow_mgr/task_data.py +21 -4
- dv_flow_mgr/task_def.py +3 -3
- dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_image.py +3 -3
- dv_flow_mgr/tasklib/hdl/sim/vcs_pkg.py +14 -0
- dv_flow_mgr/tasklib/hdl/sim/vcs_task_sim_image.py +49 -0
- dv_flow_mgr/tasklib/hdl/sim/vcs_task_sim_run.py +45 -0
- dv_flow_mgr/tasklib/hdl/sim/vl_task_sim_image.py +29 -5
- dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_run.py +1 -1
- dv_flow_mgr/tasklib/std/task_fileset.py +2 -1
- {dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/METADATA +2 -2
- dv_flow_mgr-0.0.1.12750690879a1.dist-info/RECORD +39 -0
- {dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/WHEEL +1 -1
- dv_flow_mgr-0.0.1.12672327205a1.dist-info/RECORD +0 -35
- {dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/LICENSE +0 -0
- {dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/entry_points.txt +0 -0
- {dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/top_level.txt +0 -0
dv_flow_mgr/fragment_def.py
CHANGED
@@ -22,16 +22,14 @@
|
|
22
22
|
import pydantic.dataclasses as dc
|
23
23
|
import json
|
24
24
|
from pydantic import BaseModel
|
25
|
-
from typing import Any, Dict, List
|
26
|
-
from .flow import Flow
|
25
|
+
from typing import Any, Dict, List, Union
|
27
26
|
from .package import Package
|
28
|
-
from .
|
29
|
-
from .
|
30
|
-
from .task_def import TaskDef, TaskSpec
|
27
|
+
from .package_import_spec import PackageImportSpec
|
28
|
+
from .task_def import TaskDef
|
31
29
|
|
32
30
|
class FragmentDef(BaseModel):
|
33
31
|
tasks : List[TaskDef] = dc.Field(default_factory=list)
|
34
|
-
imports : List[
|
32
|
+
imports : List[Union[str,PackageImportSpec]] = dc.Field(default_factory=list, alias="imports")
|
35
33
|
fragments: List[str] = dc.Field(default_factory=list)
|
36
34
|
|
37
35
|
basedir : str = None
|
dv_flow_mgr/package_def.py
CHANGED
@@ -24,36 +24,12 @@ import json
|
|
24
24
|
from pydantic import BaseModel
|
25
25
|
from typing import Any, Dict, List
|
26
26
|
from .flow import Flow
|
27
|
+
from .fragment_def import FragmentDef
|
27
28
|
from .package import Package
|
29
|
+
from .package_import_spec import PackageImportSpec, PackageSpec
|
28
30
|
from .task import TaskParamCtor
|
29
31
|
from .task_def import TaskDef, TaskSpec
|
30
32
|
|
31
|
-
@dc.dataclass
|
32
|
-
class PackageSpec(object):
|
33
|
-
name : str
|
34
|
-
params : Dict[str,Any] = dc.Field(default_factory=dict)
|
35
|
-
_fullname : str = None
|
36
|
-
|
37
|
-
def get_fullname(self) -> str:
|
38
|
-
if self._fullname is None:
|
39
|
-
if len(self.params) != 0:
|
40
|
-
self._fullname = "%s%s}" % (
|
41
|
-
self.name,
|
42
|
-
json.dumps(self.params, separators=(',', ':')))
|
43
|
-
else:
|
44
|
-
self._fullname = self.name
|
45
|
-
return self._fullname
|
46
|
-
|
47
|
-
def __hash__(self):
|
48
|
-
return hash(self.get_fullname())
|
49
|
-
|
50
|
-
def __eq__(self, value):
|
51
|
-
return isinstance(value, PackageSpec) and value.get_fullname() == self.get_fullname()
|
52
|
-
|
53
|
-
@dc.dataclass
|
54
|
-
class PackageImportSpec(PackageSpec):
|
55
|
-
path : str = dc.Field(default=None, alias="from")
|
56
|
-
alias : str = dc.Field(default=None, alias="as")
|
57
33
|
|
58
34
|
class PackageDef(BaseModel):
|
59
35
|
name : str
|
@@ -63,6 +39,8 @@ class PackageDef(BaseModel):
|
|
63
39
|
imports : List[PackageImportSpec] = dc.Field(default_factory=list)
|
64
40
|
fragments: List[str] = dc.Field(default_factory=list)
|
65
41
|
|
42
|
+
fragment_l : List['FragmentDef'] = dc.Field(default_factory=list, exclude=True)
|
43
|
+
|
66
44
|
# import_m : Dict['PackageSpec','Package'] = dc.Field(default_factory=dict)
|
67
45
|
|
68
46
|
basedir : str = None
|
@@ -90,8 +68,31 @@ class PackageDef(BaseModel):
|
|
90
68
|
basedir=self.basedir,
|
91
69
|
depend_refs=task.depends)
|
92
70
|
else:
|
71
|
+
# We use the Null task from the std package
|
93
72
|
raise Exception("")
|
94
73
|
ret.tasks[task.name] = ctor_t
|
95
74
|
|
75
|
+
for frag in self.fragment_l:
|
76
|
+
for task in frag.tasks:
|
77
|
+
if task.type is not None:
|
78
|
+
# Find package (not package_def) that implements this task
|
79
|
+
# Insert an indirect reference to that tasks's constructor
|
80
|
+
|
81
|
+
# Only call getTaskCtor if the task is in a different package
|
82
|
+
task_t = task.type if isinstance(task.type, TaskSpec) else TaskSpec(task.type)
|
83
|
+
ctor_t = session.getTaskCtor(task_t, self)
|
84
|
+
|
85
|
+
ctor_t = TaskParamCtor(
|
86
|
+
base=ctor_t,
|
87
|
+
params=task.params,
|
88
|
+
basedir=frag.basedir,
|
89
|
+
depend_refs=task.depends)
|
90
|
+
else:
|
91
|
+
# We use the Null task from the std package
|
92
|
+
raise Exception("")
|
93
|
+
if task.name in ret.tasks:
|
94
|
+
raise Exception("Task %s already defined" % task.name)
|
95
|
+
ret.tasks[task.name] = ctor_t
|
96
|
+
|
96
97
|
return ret
|
97
98
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
import pydantic.dataclasses as dc
|
3
|
+
import json
|
4
|
+
from typing import Dict, Any
|
5
|
+
|
6
|
+
@dc.dataclass
|
7
|
+
class PackageSpec(object):
|
8
|
+
name : str
|
9
|
+
params : Dict[str,Any] = dc.Field(default_factory=dict)
|
10
|
+
_fullname : str = None
|
11
|
+
|
12
|
+
def get_fullname(self) -> str:
|
13
|
+
if self._fullname is None:
|
14
|
+
if len(self.params) != 0:
|
15
|
+
self._fullname = "%s%s}" % (
|
16
|
+
self.name,
|
17
|
+
json.dumps(self.params, separators=(',', ':')))
|
18
|
+
else:
|
19
|
+
self._fullname = self.name
|
20
|
+
return self._fullname
|
21
|
+
|
22
|
+
def __hash__(self):
|
23
|
+
return hash(self.get_fullname())
|
24
|
+
|
25
|
+
def __eq__(self, value):
|
26
|
+
return isinstance(value, PackageSpec) and value.get_fullname() == self.get_fullname()
|
27
|
+
|
28
|
+
@dc.dataclass
|
29
|
+
class PackageImportSpec(PackageSpec):
|
30
|
+
path : str = dc.Field(default=None, alias="from")
|
31
|
+
alias : str = dc.Field(default=None, alias="as")
|
dv_flow_mgr/session.py
CHANGED
@@ -24,6 +24,7 @@ import os
|
|
24
24
|
import yaml
|
25
25
|
import dataclasses as dc
|
26
26
|
from typing import Any, Callable, Dict, List
|
27
|
+
from .fragment_def import FragmentDef
|
27
28
|
from .package import Package
|
28
29
|
from .package_def import PackageDef, PackageSpec
|
29
30
|
from .task import Task,TaskSpec
|
@@ -47,14 +48,15 @@ class Session(object):
|
|
47
48
|
_task_list : List[Task] = dc.field(default_factory=list)
|
48
49
|
_task_m : Dict[TaskSpec,Task] = dc.field(default_factory=dict)
|
49
50
|
_task_id : int = 0
|
50
|
-
_rundir_s : List[str] = dc.field(default_factory=list)
|
51
51
|
|
52
52
|
def __post_init__(self):
|
53
53
|
from .tasklib.std.pkg_std import PackageStd
|
54
|
+
from .tasklib.hdl.sim.vcs_pkg import VcsPackage
|
54
55
|
from .tasklib.hdl.sim.vlt_pkg import VltPackage
|
55
56
|
from .tasklib.hdl.sim.mti_pkg import MtiPackage
|
56
57
|
self._pkg_m[PackageSpec("std")] = PackageStd("std")
|
57
58
|
self._pkg_m[PackageSpec("hdl.sim.mti")] = MtiPackage("hdl.sim.mti")
|
59
|
+
self._pkg_m[PackageSpec("hdl.sim.vcs")] = VcsPackage("hdl.sim.vcs")
|
58
60
|
self._pkg_m[PackageSpec("hdl.sim.vlt")] = VltPackage("hdl.sim.vlt")
|
59
61
|
|
60
62
|
def load(self, root : str):
|
@@ -73,27 +75,25 @@ class Session(object):
|
|
73
75
|
self._pkg_s.clear()
|
74
76
|
self._task_m.clear()
|
75
77
|
|
76
|
-
self.
|
77
|
-
self._rundir_s.append(self.rundir)
|
78
|
-
|
79
|
-
return self._mkTaskGraph(task)
|
78
|
+
return self._mkTaskGraph(task, self.rundir)
|
80
79
|
|
81
|
-
def _mkTaskGraph(self, task : str, params : dict = None) -> Task:
|
80
|
+
def _mkTaskGraph(self, task : str, parent_rundir : str, params : dict = None) -> Task:
|
82
81
|
|
83
82
|
elems = task.split(".")
|
84
83
|
|
85
84
|
pkg_name = ".".join(elems[0:-1])
|
86
85
|
task_name = elems[-1]
|
87
86
|
|
88
|
-
self._rundir_s.append(os.path.join(self._rundir_s[-1], pkg_name, task_name))
|
89
|
-
|
90
87
|
if pkg_name == "":
|
91
88
|
if len(self._pkg_spec_s) == 0:
|
92
89
|
raise Exception("No package context for %s" % task)
|
93
90
|
pkg_spec = self._pkg_spec_s[-1]
|
91
|
+
pkg_name = pkg_spec.name
|
94
92
|
else:
|
95
93
|
pkg_spec = PackageSpec(pkg_name)
|
96
94
|
|
95
|
+
rundir = os.path.join(parent_rundir, pkg_name, task_name)
|
96
|
+
|
97
97
|
self._pkg_spec_s.append(pkg_spec)
|
98
98
|
pkg = self.getPackage(pkg_spec)
|
99
99
|
|
@@ -115,20 +115,19 @@ class Session(object):
|
|
115
115
|
self,
|
116
116
|
params,
|
117
117
|
depends)
|
118
|
-
task.rundir =
|
118
|
+
task.rundir = rundir
|
119
119
|
|
120
120
|
for i,d in enumerate(task.depend_refs):
|
121
121
|
if d in self._task_m.keys():
|
122
122
|
task.depends.append(self._task_m[d])
|
123
123
|
else:
|
124
124
|
print("mkTaskGraph: %s" % d)
|
125
|
-
task.depends.append(self._mkTaskGraph(d))
|
125
|
+
task.depends.append(self._mkTaskGraph(d, parent_rundir))
|
126
126
|
|
127
127
|
self._task_m[task.name] = task
|
128
128
|
|
129
129
|
self._pkg_s.pop()
|
130
130
|
self._pkg_spec_s.pop()
|
131
|
-
self._rundir_s.pop()
|
132
131
|
|
133
132
|
return task
|
134
133
|
|
@@ -147,6 +146,7 @@ class Session(object):
|
|
147
146
|
file_s.append(root)
|
148
147
|
ret = None
|
149
148
|
with open(root, "r") as fp:
|
149
|
+
print("open %s" % root)
|
150
150
|
doc = yaml.load(fp, Loader=yaml.FullLoader)
|
151
151
|
if "package" not in doc.keys():
|
152
152
|
raise Exception("Missing 'package' key in %s" % root)
|
@@ -167,13 +167,56 @@ class Session(object):
|
|
167
167
|
self._pkg_spec_s.append(PackageSpec(pkg.name))
|
168
168
|
|
169
169
|
print("pkg: %s" % str(pkg))
|
170
|
-
|
171
|
-
|
170
|
+
|
171
|
+
print("fragments: %s" % str(pkg.fragments))
|
172
|
+
for spec in pkg.fragments:
|
173
|
+
self._load_fragment_spec(pkg, spec, file_s)
|
172
174
|
|
173
175
|
self._pkg_spec_s.pop()
|
174
176
|
file_s.pop()
|
175
177
|
|
176
178
|
return pkg
|
179
|
+
|
180
|
+
def _load_fragment_spec(self, pkg : PackageDef, spec : str, file_s : List[str]):
|
181
|
+
|
182
|
+
# We're either going to have:
|
183
|
+
# - File path
|
184
|
+
# - Directory path
|
185
|
+
|
186
|
+
if os.path.isfile(os.path.join(pkg.basedir, spec)):
|
187
|
+
self._load_fragment_file(pkg, spec, file_s)
|
188
|
+
elif os.path.isdir(os.path.join(pkg.basedir, spec)):
|
189
|
+
self._load_fragment_dir(pkg, os.path.join(pkg.basedir, spec), file_s)
|
190
|
+
else:
|
191
|
+
raise Exception("Fragment spec %s not found" % spec)
|
192
|
+
|
193
|
+
|
194
|
+
def _load_fragment_dir(self, pkg : PackageDef, dir : str, file_s : List[str]):
|
195
|
+
|
196
|
+
for file in os.listdir(dir):
|
197
|
+
if os.path.isdir(os.path.join(dir, file)):
|
198
|
+
self._load_fragment_dir(pkg, os.path.join(dir, file), file_s)
|
199
|
+
elif os.path.isfile(os.path.join(dir, file)) and file == "flow.yaml":
|
200
|
+
self._load_fragment_file(pkg, os.path.join(dir, file), file_s)
|
201
|
+
|
202
|
+
def _load_fragment_file(self, pkg : PackageDef, file : str, file_s : List[str]):
|
203
|
+
|
204
|
+
if file in file_s:
|
205
|
+
raise Exception("Recursive file processing @ %s: %s" % (file, ",".join(self._file_s)))
|
206
|
+
file_s.append(file)
|
207
|
+
|
208
|
+
with open(file, "r") as fp:
|
209
|
+
doc = yaml.load(fp, Loader=yaml.FullLoader)
|
210
|
+
print("doc: %s" % str(doc), flush=True)
|
211
|
+
if "fragment" in doc.keys():
|
212
|
+
# Merge the package definition
|
213
|
+
frag = FragmentDef(**(doc["fragment"]))
|
214
|
+
frag.basedir = os.path.dirname(file)
|
215
|
+
pkg.fragment_l.append(frag)
|
216
|
+
else:
|
217
|
+
print("Warning: file %s is not a fragment" % file)
|
218
|
+
|
219
|
+
|
177
220
|
|
178
221
|
def getPackage(self, spec : PackageSpec) -> Package:
|
179
222
|
pkg_spec = self._pkg_spec_s[-1]
|
dv_flow_mgr/share/flow.json
CHANGED
@@ -23,7 +23,6 @@
|
|
23
23
|
}
|
24
24
|
],
|
25
25
|
"defs": {
|
26
|
-
|
27
26
|
"package-def": {
|
28
27
|
"title": "Package Definition",
|
29
28
|
"$$target": "#/defs/package-def",
|
@@ -156,21 +155,23 @@
|
|
156
155
|
"$ref": "#/defs/param"
|
157
156
|
}
|
158
157
|
},
|
159
|
-
"
|
160
|
-
|
161
|
-
{
|
158
|
+
"oneOf": [
|
159
|
+
{
|
160
|
+
"needs": {
|
162
161
|
"type": "array",
|
163
162
|
"items": {
|
164
163
|
"$ref": "#/defs/task-dep"
|
165
164
|
}
|
166
|
-
}
|
165
|
+
}
|
166
|
+
}, {
|
167
|
+
"needs": {
|
167
168
|
"type": "array",
|
168
169
|
"items": {
|
169
170
|
"type": "string"
|
170
171
|
}
|
171
172
|
}
|
172
|
-
|
173
|
-
|
173
|
+
}
|
174
|
+
]
|
174
175
|
}
|
175
176
|
}
|
176
177
|
}
|
dv_flow_mgr/task.py
CHANGED
@@ -143,21 +143,44 @@ class Task(object):
|
|
143
143
|
def setMemento(self, memento : TaskMemento):
|
144
144
|
self.memento = memento
|
145
145
|
|
146
|
+
async def isUpToDate(self, memento) -> bool:
|
147
|
+
return False
|
148
|
+
|
146
149
|
async def do_run(self) -> TaskData:
|
147
150
|
print("do_run: %s - %d depends" % (self.name, len(self.depends)))
|
148
151
|
if len(self.depends) > 0:
|
149
152
|
awaitables = [dep.waitOutput() for dep in self.depends]
|
150
153
|
deps_o = await asyncio.gather(*awaitables)
|
151
154
|
|
155
|
+
# Merge filesets. A fileset with the same
|
152
156
|
print("deps_o: %s" % str(deps_o))
|
153
157
|
|
158
|
+
# First, merge the dep maps of all the inputs
|
159
|
+
deps_m = self.depends[0].output.deps.copy()
|
160
|
+
for deps in map(lambda d: d.deps, self.depends[1:]):
|
161
|
+
for k,v in deps.items():
|
162
|
+
if k in deps_m:
|
163
|
+
deps_m[k].add(v)
|
164
|
+
else:
|
165
|
+
deps_m[k] = set(v)
|
166
|
+
|
167
|
+
print("deps_m: %s" % str(deps_m))
|
168
|
+
|
154
169
|
# Merge the output of the dependencies into a single input data
|
155
170
|
# if len(self.depends) > 1:
|
156
171
|
# raise Exception("TODO: handle >1 inputs")
|
157
172
|
|
173
|
+
# Now that we have a clean input object, we need
|
174
|
+
# to build the dep map
|
175
|
+
|
158
176
|
input = self.depends[0].output.copy()
|
159
177
|
else:
|
160
178
|
input = TaskData()
|
179
|
+
|
180
|
+
|
181
|
+
|
182
|
+
# Mark the source of this data as being this task
|
183
|
+
input.src = self.name
|
161
184
|
|
162
185
|
if not os.path.isdir(self.rundir):
|
163
186
|
os.makedirs(self.rundir)
|
@@ -193,7 +216,7 @@ class Task(object):
|
|
193
216
|
|
194
217
|
def setOutput(self, output : TaskData):
|
195
218
|
self.output_set = True
|
196
|
-
output.
|
219
|
+
output.src = self.name
|
197
220
|
self.output = output
|
198
221
|
self.output_ev.set()
|
199
222
|
|
dv_flow_mgr/task_data.py
CHANGED
@@ -19,15 +19,31 @@
|
|
19
19
|
#* Author:
|
20
20
|
#*
|
21
21
|
#****************************************************************************
|
22
|
+
import enum
|
22
23
|
import pydantic.dataclasses as dc
|
23
24
|
from pydantic import BaseModel
|
24
25
|
from typing import Any, Dict, Set, List, Tuple
|
25
26
|
from .fileset import FileSet
|
26
27
|
|
28
|
+
class TaskDataParamOpE(enum.Enum):
|
29
|
+
Set = enum.auto()
|
30
|
+
Append = enum.auto()
|
31
|
+
Prepend = enum.auto()
|
32
|
+
PathAppend = enum.auto()
|
33
|
+
PathPrepend = enum.auto()
|
34
|
+
|
35
|
+
class TaskDataParamOp(BaseModel):
|
36
|
+
op : TaskDataParamOpE
|
37
|
+
value : Any
|
38
|
+
|
39
|
+
class TaskDataParam(BaseModel):
|
40
|
+
value : Any
|
41
|
+
ops : List[TaskDataParamOp] = dc.Field(default_factory=list)
|
42
|
+
|
27
43
|
class TaskData(BaseModel):
|
28
|
-
|
44
|
+
src : str = None
|
29
45
|
params : Dict[str,Any] = dc.Field(default_factory=dict)
|
30
|
-
deps :
|
46
|
+
deps : Dict[str,Set[str]] = dc.Field(default_factory=dict)
|
31
47
|
changed : bool = False
|
32
48
|
|
33
49
|
def hasParam(self, name: str) -> bool:
|
@@ -40,11 +56,12 @@ class TaskData(BaseModel):
|
|
40
56
|
self.params[name] = value
|
41
57
|
|
42
58
|
def addFileSet(self, fs : FileSet):
|
59
|
+
fs.src = self.src
|
43
60
|
if "filesets" not in self.params:
|
44
61
|
self.params["filesets"] = []
|
45
62
|
self.params["filesets"].append(fs)
|
46
63
|
|
47
|
-
def getFileSets(self, type
|
64
|
+
def getFileSets(self, type=None) -> List[FileSet]:
|
48
65
|
ret = []
|
49
66
|
|
50
67
|
if "filesets" in self.params:
|
@@ -56,7 +73,7 @@ class TaskData(BaseModel):
|
|
56
73
|
|
57
74
|
def copy(self) -> 'TaskData':
|
58
75
|
ret = TaskData()
|
59
|
-
ret.
|
76
|
+
ret.src = self.src
|
60
77
|
ret.params = self.params.copy()
|
61
78
|
for d in self.deps:
|
62
79
|
ret.deps.append(d.clone())
|
dv_flow_mgr/task_def.py
CHANGED
@@ -21,7 +21,7 @@
|
|
21
21
|
#****************************************************************************
|
22
22
|
import pydantic.dataclasses as dc
|
23
23
|
from pydantic import BaseModel
|
24
|
-
from typing import Any, Dict, List, Tuple
|
24
|
+
from typing import Any, Dict, List, Union, Tuple
|
25
25
|
from .task import Task
|
26
26
|
|
27
27
|
@dc.dataclass
|
@@ -32,8 +32,8 @@ class TaskSpec(object):
|
|
32
32
|
class TaskDef(BaseModel):
|
33
33
|
"""Holds definition information (ie the YAML view) for a task"""
|
34
34
|
name : str
|
35
|
-
type :
|
36
|
-
depends : List[
|
35
|
+
type : Union[str,TaskSpec] = dc.Field(default_factory=list)
|
36
|
+
depends : List[Union[str,TaskSpec]] = dc.Field(default_factory=list, alias="needs")
|
37
37
|
params: Dict[str,Any] = dc.Field(default_factory=dict, alias="with")
|
38
38
|
|
39
39
|
def copy(self) -> 'TaskDef':
|
@@ -15,10 +15,10 @@ from svdep import FileCollection, TaskCheckUpToDate, TaskBuildFileCollection
|
|
15
15
|
class TaskMtiSimImage(VlTaskSimImage):
|
16
16
|
|
17
17
|
def getRefTime(self):
|
18
|
-
if os.path.
|
18
|
+
if os.path.isfile(os.path.join(self.rundir, 'work.d')):
|
19
19
|
return os.path.getmtime(os.path.join(self.rundir, 'work.d'))
|
20
20
|
else:
|
21
|
-
raise Exception("work.d not found")
|
21
|
+
raise Exception("work.d not found (%s)")
|
22
22
|
|
23
23
|
async def build(self, files : List[str], incdirs : List[str]):
|
24
24
|
if not os.path.isdir(os.path.join(self.rundir, 'work')):
|
@@ -53,7 +53,7 @@ class TaskMtiSimImage(VlTaskSimImage):
|
|
53
53
|
await proc.wait()
|
54
54
|
|
55
55
|
with open(os.path.join(self.rundir, 'work.d'), "w") as fp:
|
56
|
-
|
56
|
+
fp.write("\n")
|
57
57
|
|
58
58
|
if proc.returncode != 0:
|
59
59
|
raise Exception("Questa opt failed")
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
from .pkg_hdl_sim import PackageHdlSim
|
3
|
+
from .vcs_task_sim_image import TaskVcsSimImageCtor
|
4
|
+
from .vcs_task_sim_run import TaskVcsSimRunCtor
|
5
|
+
|
6
|
+
@dc.dataclass
|
7
|
+
class VcsPackage(PackageHdlSim):
|
8
|
+
|
9
|
+
def __post_init__(self):
|
10
|
+
print("PackageVcs::__post_init__", flush=True)
|
11
|
+
self.tasks["SimImage"] = TaskVcsSimImageCtor()
|
12
|
+
self.tasks["SimRun"] = TaskVcsSimRunCtor()
|
13
|
+
pass
|
14
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
import os
|
2
|
+
import fnmatch
|
3
|
+
import dataclasses as dc
|
4
|
+
from ....fileset import FileSet
|
5
|
+
from ....package import TaskCtor
|
6
|
+
from ....task import Task, TaskParams, TaskCtorT
|
7
|
+
from ....task_data import TaskData
|
8
|
+
from ....task_memento import TaskMemento
|
9
|
+
from .vl_task_sim_image import VlTaskSimImage, VlTaskSimImageParams, VlTaskSimImageMemento
|
10
|
+
from typing import List, Tuple
|
11
|
+
|
12
|
+
from svdep import FileCollection, TaskCheckUpToDate, TaskBuildFileCollection
|
13
|
+
|
14
|
+
@dc.dataclass
|
15
|
+
class TaskVcsSimImage(VlTaskSimImage):
|
16
|
+
|
17
|
+
def getRefTime(self):
|
18
|
+
if os.path.isfile(os.path.join(self.rundir, 'simv')):
|
19
|
+
return os.path.getmtime(os.path.join(self.rundir, 'simv'))
|
20
|
+
else:
|
21
|
+
raise Exception
|
22
|
+
|
23
|
+
async def build(self, files : List[str], incdirs : List[str]):
|
24
|
+
cmd = ['vcs', '-sverilog']
|
25
|
+
|
26
|
+
for incdir in incdirs:
|
27
|
+
cmd.append('+incdir+%s' % incdir)
|
28
|
+
|
29
|
+
cmd.extend(files)
|
30
|
+
|
31
|
+
if len(self.params.top):
|
32
|
+
cmd.extend(['-top', "+".join(self.params.top)])
|
33
|
+
|
34
|
+
proc = await self.session.create_subprocess(*cmd,
|
35
|
+
cwd=self.rundir)
|
36
|
+
await proc.wait()
|
37
|
+
|
38
|
+
if proc.returncode != 0:
|
39
|
+
raise Exception("VCS simv failed")
|
40
|
+
|
41
|
+
class TaskVcsSimImageParams(VlTaskSimImageParams):
|
42
|
+
pass
|
43
|
+
|
44
|
+
class TaskVcsSimImageMemento(VlTaskSimImageMemento):
|
45
|
+
pass
|
46
|
+
|
47
|
+
class TaskVcsSimImageCtor(TaskCtorT):
|
48
|
+
def __init__(self):
|
49
|
+
super().__init__(TaskVcsSimImageParams, TaskVcsSimImage)
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import os
|
2
|
+
import fnmatch
|
3
|
+
import pydantic.dataclasses as dc
|
4
|
+
from ....fileset import FileSet
|
5
|
+
from ....package import TaskCtor
|
6
|
+
from ....task import Task, TaskParams, TaskCtorT
|
7
|
+
from ....task_data import TaskData
|
8
|
+
from ....task_memento import TaskMemento
|
9
|
+
from typing import List, Tuple
|
10
|
+
|
11
|
+
class TaskVcsSimRun(Task):
|
12
|
+
|
13
|
+
async def run(self, input : TaskData) -> TaskData:
|
14
|
+
vl_fileset = input.getFileSets("simDir")
|
15
|
+
|
16
|
+
build_dir = vl_fileset[0].basedir
|
17
|
+
|
18
|
+
cmd = [
|
19
|
+
os.path.join(build_dir, 'simv'),
|
20
|
+
]
|
21
|
+
|
22
|
+
fp = open(os.path.join(self.rundir, 'sim.log'), "w")
|
23
|
+
proc = await self.session.create_subprocess(*cmd,
|
24
|
+
cwd=self.rundir,
|
25
|
+
stdout=fp)
|
26
|
+
|
27
|
+
await proc.wait()
|
28
|
+
|
29
|
+
fp.close()
|
30
|
+
|
31
|
+
output = TaskData()
|
32
|
+
output.addFileSet(FileSet(src=self.name, type="simRunDir", basedir=self.rundir))
|
33
|
+
|
34
|
+
return output
|
35
|
+
|
36
|
+
class TaskVcsSimRunParams(TaskParams):
|
37
|
+
pass
|
38
|
+
|
39
|
+
class TaskVcsSimRunMemento(TaskMemento):
|
40
|
+
pass
|
41
|
+
|
42
|
+
class TaskVcsSimRunCtor(TaskCtorT):
|
43
|
+
def __init__(self):
|
44
|
+
super().__init__(TaskVcsSimRunParams, TaskVcsSimRun)
|
45
|
+
|
@@ -3,6 +3,7 @@ import fnmatch
|
|
3
3
|
import dataclasses
|
4
4
|
import shutil
|
5
5
|
import pydantic.dataclasses as dc
|
6
|
+
from toposort import toposort
|
6
7
|
from ....fileset import FileSet
|
7
8
|
from ....package import TaskCtor
|
8
9
|
from ....task import Task, TaskParams, TaskCtorT
|
@@ -31,9 +32,8 @@ class VlTaskSimImage(Task):
|
|
31
32
|
incdirs = []
|
32
33
|
memento = ex_memento
|
33
34
|
|
34
|
-
|
35
|
-
|
36
|
-
files.append(os.path.join(vl_filesets[0].basedir, file))
|
35
|
+
|
36
|
+
self._gatherSvSources(files, incdirs, input)
|
37
37
|
|
38
38
|
if not in_changed:
|
39
39
|
try:
|
@@ -41,7 +41,7 @@ class VlTaskSimImage(Task):
|
|
41
41
|
info = FileCollection.from_dict(ex_memento.svdeps)
|
42
42
|
in_changed = not TaskCheckUpToDate(files, incdirs).check(info, ref_mtime)
|
43
43
|
except Exception as e:
|
44
|
-
print("Unexpected output-directory format. Rebuilding")
|
44
|
+
print("Unexpected output-directory format (%s). Rebuilding" % str(e))
|
45
45
|
shutil.rmtree(self.rundir)
|
46
46
|
os.makedirs(self.rundir)
|
47
47
|
in_changed = True
|
@@ -56,11 +56,35 @@ class VlTaskSimImage(Task):
|
|
56
56
|
await self.build(files, incdirs)
|
57
57
|
|
58
58
|
output = TaskData()
|
59
|
-
output.addFileSet(FileSet(src=self.name, type="
|
59
|
+
output.addFileSet(FileSet(src=self.name, type="simDir", basedir=self.rundir))
|
60
60
|
output.changed = in_changed
|
61
61
|
|
62
62
|
self.setMemento(memento)
|
63
63
|
return output
|
64
|
+
|
65
|
+
def _gatherSvSources(self, files, incdirs, input):
|
66
|
+
# input must represent dependencies for all tasks related to filesets
|
67
|
+
# references must support transitivity
|
68
|
+
|
69
|
+
vl_filesets = input.getFileSets(("verilogSource", "systemVerilogSource"))
|
70
|
+
fs_tasks = [fs.src for fs in vl_filesets]
|
71
|
+
|
72
|
+
# Want dependencies just for the filesets
|
73
|
+
# - key is the task associated with a filelist
|
74
|
+
# - deps is the dep-set of the on the incoming
|
75
|
+
#
|
76
|
+
# -> Send output set of dependencies
|
77
|
+
# - Task -> deps map
|
78
|
+
# "task" : ["dep1", "dep2", ...],
|
79
|
+
# "task2" :
|
80
|
+
# - All tasks are represented in the map
|
81
|
+
# -> Assume projects will often flatten before exporting
|
82
|
+
|
83
|
+
# Sort the deps
|
84
|
+
order = list(toposort(input.deps))
|
85
|
+
|
86
|
+
print("order: %s" % str(order))
|
87
|
+
|
64
88
|
|
65
89
|
|
66
90
|
class VlTaskSimImageParams(TaskParams):
|
@@ -12,8 +12,9 @@ from typing import List, Tuple
|
|
12
12
|
class TaskFileSet(Task):
|
13
13
|
|
14
14
|
async def run(self, input : TaskData) -> TaskData:
|
15
|
-
print("run: %s: base=%s type=%s include=%s" % (
|
15
|
+
print("TaskFileSet run: %s: basedir=%s, base=%s type=%s include=%s" % (
|
16
16
|
self.name,
|
17
|
+
self.basedir,
|
17
18
|
self.params.base, self.params.type, str(self.params.include)
|
18
19
|
))
|
19
20
|
|
{dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/METADATA
RENAMED
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.2
|
2
2
|
Name: dv-flow-mgr
|
3
|
-
Version: 0.0.1.
|
3
|
+
Version: 0.0.1.12750690879a1
|
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,39 @@
|
|
1
|
+
dv_flow_mgr/__init__.py,sha256=GLfYxZONxJNNUplfmlsXrcycJ2VhTc8gvXN6qdlH7kg,97
|
2
|
+
dv_flow_mgr/__main__.py,sha256=4xXA4XCqLELlIak6bs-H6rRHp2URucipHPvCiVdR01c,513
|
3
|
+
dv_flow_mgr/fileset.py,sha256=89knoTNsDF85QJwrctLiM6ryqHS1oxW25Gd5jgpX-IQ,1123
|
4
|
+
dv_flow_mgr/flow.py,sha256=UdgJOIqBS2wTRpO-sNWCCqO9oQFxDfGPGVD0r42aTrA,1562
|
5
|
+
dv_flow_mgr/fragment_def.py,sha256=p5i6ONtBWlDHTBFsduu3Z36_76Bn8PCIylp_xoZ7jfQ,1552
|
6
|
+
dv_flow_mgr/package.py,sha256=jFhXgKDEYSRfs_VRUjKY4C7KScQfmrNLEXQgtWKaBfI,2767
|
7
|
+
dv_flow_mgr/package_def.py,sha256=Js8bZj8bSmJQ6Wk9xAhIBJScNGJOHNbXNhw_zkDVU5w,3834
|
8
|
+
dv_flow_mgr/package_import_spec.py,sha256=bStPa727wAKMcixydVY1Ht6ylzXsSMy2K31HWPXhc9k,921
|
9
|
+
dv_flow_mgr/parameters.py,sha256=kUjRss5VtMMz5eL3-Z_M6BS-wFs7MhQu3ANXO54UPo0,896
|
10
|
+
dv_flow_mgr/session.py,sha256=sYRyTojsfPFZOGu4mz9yNTX6ESNye0i5szgj5QVE-Pk,10802
|
11
|
+
dv_flow_mgr/task.py,sha256=ZTuSulc6lBLcTByD6gQjmbaJqqL1c1mlVtP84iLrLbE,7973
|
12
|
+
dv_flow_mgr/task_data.py,sha256=32rgwPxSthIjNbzbXK2sZoPo6Jedio_L54Qibu65fYk,2962
|
13
|
+
dv_flow_mgr/task_def.py,sha256=Yjw1Q-bnbi7Ct5X1PriMMNJ6i4TBVFWrO8BTnipz9hg,1532
|
14
|
+
dv_flow_mgr/task_memento.py,sha256=C7VTQpBhDEoYuDmE6YTM-6TLMLnqHp6Y0Vat1aTgtCs,1096
|
15
|
+
dv_flow_mgr/cmds/cmd_run.py,sha256=ii48_jdxCxh4MOJCeKKX66Cui4IvQQy_RrJEIixsph8,733
|
16
|
+
dv_flow_mgr/share/flow.json,sha256=lNmZex9NXkYbyb2aZseQfUOkV9CMyfH0iLODEI7EPBw,5096
|
17
|
+
dv_flow_mgr/tasklib/hdl/sim/mti_pkg.py,sha256=l_jerOEQrVSmxT6qJx0PlsorZsK037Y-arQvWzdm9No,348
|
18
|
+
dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_image.py,sha256=U1XADvEGaH412n_JujS1Maz08GJ07UL6mRT4B4qihZQ,2229
|
19
|
+
dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_run.py,sha256=QkKYOs0OhQ42F5bUbfCsezE4L50TfiIm7lVflVY4On8,1290
|
20
|
+
dv_flow_mgr/tasklib/hdl/sim/pkg_hdl_sim.py,sha256=hPk5w7dN3Uq3mLRBNCEtE7jkLavi2MAczJlle_xGoQ8,166
|
21
|
+
dv_flow_mgr/tasklib/hdl/sim/task_sim_image.py,sha256=DOSxzH-0EZQZlm-EwSq1q7_nz_yru6al36Ji1Q6z5F4,375
|
22
|
+
dv_flow_mgr/tasklib/hdl/sim/vcs_pkg.py,sha256=65W8NP54_EdtHo6lsmCejT8diPvizT9e3AjjTXJC_u0,413
|
23
|
+
dv_flow_mgr/tasklib/hdl/sim/vcs_task_sim_image.py,sha256=SAZYYCZ_ZO80Vfxx7sGcGeKBz00XsoaAjsUwRnCd7eo,1493
|
24
|
+
dv_flow_mgr/tasklib/hdl/sim/vcs_task_sim_run.py,sha256=LYjf--RZH2Jh4-c_4hZOo2uLO3Tu_waGQRXmlDggmZs,1191
|
25
|
+
dv_flow_mgr/tasklib/hdl/sim/vl_task_sim_image.py,sha256=QJP1gjclUSYfq-B9NIA46C1E1zTfOiqsmGjXtsu4BY8,3017
|
26
|
+
dv_flow_mgr/tasklib/hdl/sim/vlt_pkg.py,sha256=Pu9mWAR93kiTNT8GZJrX-VDjMOfr9P5ddcSPt1BElQQ,413
|
27
|
+
dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_image.py,sha256=9RDJ3r37C4tA4PIa7tDUYYgRpIh19up-Y9HTOwKxr0I,1564
|
28
|
+
dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_run.py,sha256=RxPaE1RSRi2QdadrZp2J3lZqTt6EnLjCnk__uPAV6_o,1199
|
29
|
+
dv_flow_mgr/tasklib/std/fileset.py,sha256=u88qjKQpIip_eETk0k6J1AGxk9blKlqAqYinHGKwco8,61
|
30
|
+
dv_flow_mgr/tasklib/std/pkg_std.py,sha256=ERDd515qtetQaldk9opUH19MyNwo8nP4-GLz-ke-5gE,370
|
31
|
+
dv_flow_mgr/tasklib/std/std.dfs,sha256=An2NUvvWaR9xI4U-kRQ4NN6U-GhX6GQmd3mNyRkW4NQ,68
|
32
|
+
dv_flow_mgr/tasklib/std/task_fileset.py,sha256=ZBG4e2gsTsRMsr_FhhzIoE3J7YwYQZ9HigpxpGePd74,3145
|
33
|
+
dv_flow_mgr/tasklib/std/task_null.py,sha256=bQH1HN4r-TtdUaJxfnmvoqKZSY4MWO48eK7z_yngdNU,599
|
34
|
+
dv_flow_mgr-0.0.1.12750690879a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
35
|
+
dv_flow_mgr-0.0.1.12750690879a1.dist-info/METADATA,sha256=UUW3UD8jLxZaP3Ou2R5gJXdH5muYOCaJMch8gYCnWgk,13252
|
36
|
+
dv_flow_mgr-0.0.1.12750690879a1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
37
|
+
dv_flow_mgr-0.0.1.12750690879a1.dist-info/entry_points.txt,sha256=VHxIon5AeHCtK73fYb1veDImAGwv76hrtBiuZePmzhI,51
|
38
|
+
dv_flow_mgr-0.0.1.12750690879a1.dist-info/top_level.txt,sha256=FGuhGIxN1FgD_YBkPcDq05fTxZcwaX9G_O8FFBvrTk4,12
|
39
|
+
dv_flow_mgr-0.0.1.12750690879a1.dist-info/RECORD,,
|
@@ -1,35 +0,0 @@
|
|
1
|
-
dv_flow_mgr/__init__.py,sha256=GLfYxZONxJNNUplfmlsXrcycJ2VhTc8gvXN6qdlH7kg,97
|
2
|
-
dv_flow_mgr/__main__.py,sha256=4xXA4XCqLELlIak6bs-H6rRHp2URucipHPvCiVdR01c,513
|
3
|
-
dv_flow_mgr/fileset.py,sha256=89knoTNsDF85QJwrctLiM6ryqHS1oxW25Gd5jgpX-IQ,1123
|
4
|
-
dv_flow_mgr/flow.py,sha256=UdgJOIqBS2wTRpO-sNWCCqO9oQFxDfGPGVD0r42aTrA,1562
|
5
|
-
dv_flow_mgr/fragment_def.py,sha256=s6RLDTUDc2ktzaz8VtExkjgHqhe70GeH9zWgJLTyTcg,1597
|
6
|
-
dv_flow_mgr/package.py,sha256=jFhXgKDEYSRfs_VRUjKY4C7KScQfmrNLEXQgtWKaBfI,2767
|
7
|
-
dv_flow_mgr/package_def.py,sha256=1Oz3uiPXEQ6XXqcimpYcO3VNBmTMwgvKil4f2bRtAgY,3399
|
8
|
-
dv_flow_mgr/parameters.py,sha256=kUjRss5VtMMz5eL3-Z_M6BS-wFs7MhQu3ANXO54UPo0,896
|
9
|
-
dv_flow_mgr/session.py,sha256=KMCXW_fDhH5G1iBjD89cyk_FVEBTa5s1lWNX5ndjy6c,8939
|
10
|
-
dv_flow_mgr/task.py,sha256=C3GRK2wvypq5b4xfk164irsN8pY3-OJ3lWMsHmncBY4,7245
|
11
|
-
dv_flow_mgr/task_data.py,sha256=tIerZoe8yt1ig1m6IPQ6N64SI2rQlUoVY5oOjFYICws,2590
|
12
|
-
dv_flow_mgr/task_def.py,sha256=Dn5EN9tu0e1R_GsbkrZHY0idRG1omOs-XI60uGhH62I,1500
|
13
|
-
dv_flow_mgr/task_memento.py,sha256=C7VTQpBhDEoYuDmE6YTM-6TLMLnqHp6Y0Vat1aTgtCs,1096
|
14
|
-
dv_flow_mgr/cmds/cmd_run.py,sha256=ii48_jdxCxh4MOJCeKKX66Cui4IvQQy_RrJEIixsph8,733
|
15
|
-
dv_flow_mgr/share/flow.json,sha256=h2Jeh2lfGJUe6xE_o5nMO8zkcrGL_GVS2taEqFzKr5g,5042
|
16
|
-
dv_flow_mgr/tasklib/hdl/sim/mti_pkg.py,sha256=l_jerOEQrVSmxT6qJx0PlsorZsK037Y-arQvWzdm9No,348
|
17
|
-
dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_image.py,sha256=tp0AlxIp-zu6YuNk9eleveDlPls0m56eToSvoTjVFio,2213
|
18
|
-
dv_flow_mgr/tasklib/hdl/sim/mti_task_sim_run.py,sha256=QkKYOs0OhQ42F5bUbfCsezE4L50TfiIm7lVflVY4On8,1290
|
19
|
-
dv_flow_mgr/tasklib/hdl/sim/pkg_hdl_sim.py,sha256=hPk5w7dN3Uq3mLRBNCEtE7jkLavi2MAczJlle_xGoQ8,166
|
20
|
-
dv_flow_mgr/tasklib/hdl/sim/task_sim_image.py,sha256=DOSxzH-0EZQZlm-EwSq1q7_nz_yru6al36Ji1Q6z5F4,375
|
21
|
-
dv_flow_mgr/tasklib/hdl/sim/vl_task_sim_image.py,sha256=pjdkZtei1eGAm_P5HXNNinZ-x8WBAE3warpj_YR8N4o,2263
|
22
|
-
dv_flow_mgr/tasklib/hdl/sim/vlt_pkg.py,sha256=Pu9mWAR93kiTNT8GZJrX-VDjMOfr9P5ddcSPt1BElQQ,413
|
23
|
-
dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_image.py,sha256=9RDJ3r37C4tA4PIa7tDUYYgRpIh19up-Y9HTOwKxr0I,1564
|
24
|
-
dv_flow_mgr/tasklib/hdl/sim/vlt_task_sim_run.py,sha256=kUuiwNdvyYY8HUNSCgC8UWf5gL7sIK0eNp5TrPAs2sc,1208
|
25
|
-
dv_flow_mgr/tasklib/std/fileset.py,sha256=u88qjKQpIip_eETk0k6J1AGxk9blKlqAqYinHGKwco8,61
|
26
|
-
dv_flow_mgr/tasklib/std/pkg_std.py,sha256=ERDd515qtetQaldk9opUH19MyNwo8nP4-GLz-ke-5gE,370
|
27
|
-
dv_flow_mgr/tasklib/std/std.dfs,sha256=An2NUvvWaR9xI4U-kRQ4NN6U-GhX6GQmd3mNyRkW4NQ,68
|
28
|
-
dv_flow_mgr/tasklib/std/task_fileset.py,sha256=ISsI-g8v8bKYYQiGd1Ju2VlyEOxEziNgXtssEEmnu6s,3095
|
29
|
-
dv_flow_mgr/tasklib/std/task_null.py,sha256=bQH1HN4r-TtdUaJxfnmvoqKZSY4MWO48eK7z_yngdNU,599
|
30
|
-
dv_flow_mgr-0.0.1.12672327205a1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
31
|
-
dv_flow_mgr-0.0.1.12672327205a1.dist-info/METADATA,sha256=IFGISfbNIMqisxzkYNavsm92ORxBaVEyxOAYYh8ZKJI,13252
|
32
|
-
dv_flow_mgr-0.0.1.12672327205a1.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
33
|
-
dv_flow_mgr-0.0.1.12672327205a1.dist-info/entry_points.txt,sha256=VHxIon5AeHCtK73fYb1veDImAGwv76hrtBiuZePmzhI,51
|
34
|
-
dv_flow_mgr-0.0.1.12672327205a1.dist-info/top_level.txt,sha256=FGuhGIxN1FgD_YBkPcDq05fTxZcwaX9G_O8FFBvrTk4,12
|
35
|
-
dv_flow_mgr-0.0.1.12672327205a1.dist-info/RECORD,,
|
{dv_flow_mgr-0.0.1.12672327205a1.dist-info → dv_flow_mgr-0.0.1.12750690879a1.dist-info}/LICENSE
RENAMED
File without changes
|
File without changes
|
File without changes
|