dv-flow-mgr 1.9.0__py3-none-any.whl → 1.9.14960981876rc0__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
@@ -32,6 +32,6 @@ from .task_runner import TaskSetRunner
32
32
  from .task_listener_log import TaskListenerLog
33
33
 
34
34
  VERSION="1.9.0"
35
- SUFFIX=""
35
+ SUFFIX="14960981876rc0"
36
36
  __version__="%s%s" % (VERSION, SUFFIX)
37
37
 
@@ -0,0 +1,85 @@
1
+ import dataclasses as dc
2
+ import importlib
3
+ import importlib.util
4
+ import logging
5
+ import os
6
+ import sys
7
+ from typing import ClassVar, List
8
+ from .task_data import TaskDataResult
9
+
10
+ @dc.dataclass
11
+ class ExecGenCallable(object):
12
+ body : str
13
+ _log : ClassVar = logging.getLogger("ExecGenCallable")
14
+
15
+ def __call__(self, ctxt, input):
16
+ self._log.debug("--> ExecCallable")
17
+ self._log.debug("Body:\n%s" % self.body)
18
+
19
+ # If it is a single line, then we have a spec to load
20
+ # Otherwise, we have an inline task
21
+
22
+ if self.body.find("\n") == -1:
23
+ # Two forms:
24
+ # <path>::method
25
+ # <method-path>
26
+
27
+ ci = self.body.find("::")
28
+ if ci != -1:
29
+ # have a file to load
30
+ file = self.body[:ci]
31
+ method = self.body[ci+2:]
32
+ spec = importlib.util.spec_from_file_location(input.name, file)
33
+ module = importlib.util.module_from_spec(spec)
34
+ sys.modules[input.name] = module
35
+ spec.loader.exec_module(module)
36
+
37
+ callable = getattr(module, method)
38
+ pass
39
+ else:
40
+ # self._log.debug("Use PyTask implementation")
41
+ last_dot = self.body.rfind('.')
42
+ clsname = self.body[last_dot+1:]
43
+ modname = self.body[:last_dot]
44
+
45
+ try:
46
+ if modname not in sys.modules:
47
+ if input.srcdir not in sys.path:
48
+ sys.path.append(input.srcdir)
49
+ mod = importlib.import_module(modname)
50
+ else:
51
+ mod = sys.modules[modname]
52
+ except ModuleNotFoundError as e:
53
+ raise Exception("Failed to import module %s: %s" % (modname, str(e)))
54
+
55
+ if not hasattr(mod, clsname):
56
+ raise Exception("Method %s not found in module %s" % (clsname, modname))
57
+ callable = getattr(mod, clsname)
58
+ else:
59
+ text_lines = self.body.splitlines()
60
+
61
+ least_whitespace = 2^32
62
+ have_content = False
63
+ for line in text_lines:
64
+ line_no_leading_ws = line.lstrip()
65
+ if line_no_leading_ws != "":
66
+ have_content = True
67
+ leading_ws = len(line) - len(line_no_leading_ws)
68
+ if leading_ws < least_whitespace:
69
+ least_whitespace = leading_ws
70
+ # Remove leading whitespace
71
+ if have_content:
72
+ for i,line in enumerate(text_lines):
73
+ if len(line) >= least_whitespace:
74
+ text_lines[i] = line[least_whitespace:]
75
+
76
+ method = "def pytask(ctxt, input):\n" + "\n".join([" %s" % l for l in text_lines])
77
+
78
+ exec(method)
79
+
80
+ callable = locals()['pytask']
81
+
82
+ result = callable(ctxt, input)
83
+
84
+ self._log.debug("<-- ExecCallable")
85
+ return result
@@ -13,7 +13,7 @@ from .package import Package
13
13
  from .param_def import ComplexType
14
14
  from .ext_rgy import ExtRgy
15
15
  from .srcinfo import SrcInfo
16
- from .task import Task
16
+ from .task import Task, Strategy, StrategyGenerate
17
17
  from .task_def import TaskDef, PassthroughE, ConsumesE, RundirE
18
18
  from .task_data import TaskMarker, TaskMarkerLoc, SeverityE
19
19
  from .type import Type
@@ -626,6 +626,20 @@ class PackageLoader(object):
626
626
  raise Exception("Failed to find task %s" % need)
627
627
  task.needs.append(nt)
628
628
 
629
+ if taskdef.strategy is not None:
630
+ self._log.debug("Task %s strategy: %s" % (task.name, str(taskdef.strategy)))
631
+ if taskdef.strategy.generate is not None:
632
+ shell = taskdef.strategy.generate.shell
633
+ if shell is None:
634
+ shell = "pytask"
635
+ task.strategy = Strategy(
636
+ generate=StrategyGenerate(
637
+ shell=shell,
638
+ run=taskdef.strategy.generate.run))
639
+
640
+ # task.strategy = taskdef.strategy
641
+
642
+
629
643
  # Determine how to implement this task
630
644
  if taskdef.body is not None and len(taskdef.body) > 0:
631
645
  self._mkTaskBody(task, taskdef)
dv_flow/mgr/task.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import dataclasses as dc
2
- from typing import Any, Dict, List, Tuple, Union
2
+ from typing import Any, Callable, Dict, List, Tuple, Union
3
3
  from .srcinfo import SrcInfo
4
4
  from .task_def import TaskDef, RundirE, PassthroughE, ConsumesE
5
5
  from .task_node_ctor import TaskNodeCtor
@@ -9,6 +9,16 @@ class Need(object):
9
9
  task : 'Task'
10
10
  cond : str = None
11
11
 
12
+ @dc.dataclass
13
+ class StrategyGenerate(object):
14
+ shell : str = "pytask"
15
+ run : str = None
16
+
17
+ @dc.dataclass
18
+ class Strategy(object):
19
+ generate : StrategyGenerate = None
20
+ matrix : Dict[str, List[Any]] = dc.field(default_factory=dict)
21
+
12
22
  @dc.dataclass
13
23
  class Task(object):
14
24
  """
@@ -31,6 +41,7 @@ class Task(object):
31
41
  rundir : RundirE = None
32
42
  # TODO: strategy / matrix
33
43
  subtasks : List['Task'] = dc.field(default_factory=list)
44
+ strategy : Strategy = dc.field(default=None)
34
45
  run : str = None
35
46
  shell : str = "bash"
36
47
  srcinfo : SrcInfo = None
dv_flow/mgr/task_def.py CHANGED
@@ -50,8 +50,13 @@ class PassthroughE(enum.Enum):
50
50
  All = "all"
51
51
  Unused = "unused"
52
52
 
53
+ class GenerateSpec(BaseModel):
54
+ shell: Union[str, None] = dc.Field(default=None)
55
+ run: str
56
+
53
57
  class StrategyDef(BaseModel):
54
58
  chain: Union[bool, None] = dc.Field(default=None)
59
+ generate: Union[GenerateSpec, None] = dc.Field(default=None)
55
60
  matrix : Union[Dict[str,List[Any]],None] = dc.Field(
56
61
  default=None,
57
62
  description="Matrix of parameter values to explore")
@@ -0,0 +1,35 @@
1
+
2
+ import dataclasses as dc
3
+ from typing import Any, List
4
+ from .task_node import TaskNode
5
+
6
+ @dc.dataclass
7
+ class TaskGenInputData(object):
8
+ params : Any
9
+
10
+ @dc.dataclass
11
+ class TaskGenCtxt(object):
12
+ rundir : str
13
+ input : TaskNode
14
+ builder : 'TaskGraphBuilder'
15
+ body : List['Task'] = dc.field(default_factory=list)
16
+ tasks : List['TaskNode'] = dc.field(default_factory=list)
17
+
18
+ def mkTaskNode(self, type_t, name=None, srcdir=None, needs=None, **kwargs):
19
+ return self.builder.mkTaskNode(type_t, name, srcdir, needs, **kwargs)
20
+
21
+ def addTask(self, task : 'TaskNode'):
22
+ if task is None:
23
+ raise Exception("Task is None")
24
+ self.tasks.append(task)
25
+
26
+ def mkName(self, leaf):
27
+ # TODO: add on context
28
+ return leaf
29
+
30
+ def marker(self, m):
31
+ pass
32
+
33
+ def error(self, msg):
34
+ pass
35
+
@@ -29,10 +29,12 @@ from .package_def import PackageDef, PackageSpec
29
29
  from .package_loader import PackageLoader
30
30
  from .param_ref_eval import ParamRefEval
31
31
  from .name_resolution import NameResolutionContext, TaskNameResolutionScope
32
+ from .exec_gen_callable import ExecGenCallable
32
33
  from .ext_rgy import ExtRgy
33
34
  from .task import Task
34
35
  from .task_def import RundirE
35
36
  from .task_data import TaskMarker, TaskMarkerLoc, SeverityE
37
+ from .task_gen_ctxt import TaskGenCtxt, TaskGenInputData
36
38
  from .task_node import TaskNode
37
39
  from .task_node_ctor import TaskNodeCtor
38
40
  from .task_node_compound import TaskNodeCompound
@@ -480,22 +482,25 @@ class TaskGraphBuilder(object):
480
482
 
481
483
  # Determine how to build this node
482
484
  if iff:
483
- if self._isCompound(task):
484
- ret = self._mkTaskCompoundNode(
485
- task,
486
- name=name,
487
- srcdir=srcdir,
488
- params=params,
489
- hierarchical=hierarchical,
490
- eval=eval)
485
+ if task.strategy is not None:
486
+ ret = self._applyStrategy(task, name, srcdir, params, hierarchical, eval)
491
487
  else:
492
- ret = self._mkTaskLeafNode(
493
- task,
494
- name=name,
495
- srcdir=srcdir,
496
- params=params,
497
- hierarchical=hierarchical,
498
- eval=eval)
488
+ if self._isCompound(task):
489
+ ret = self._mkTaskCompoundNode(
490
+ task,
491
+ name=name,
492
+ srcdir=srcdir,
493
+ params=params,
494
+ hierarchical=hierarchical,
495
+ eval=eval)
496
+ else:
497
+ ret = self._mkTaskLeafNode(
498
+ task,
499
+ name=name,
500
+ srcdir=srcdir,
501
+ params=params,
502
+ hierarchical=hierarchical,
503
+ eval=eval)
499
504
  else:
500
505
  if name is None:
501
506
  name = task.name
@@ -524,6 +529,105 @@ class TaskGraphBuilder(object):
524
529
 
525
530
  return ret
526
531
 
532
+ def _applyStrategy(self, task, name, srcdir, params, hierarchical, eval):
533
+ self._log.debug("--> _applyStrategy %s" % task.name)
534
+
535
+ if name is None:
536
+ name = task.name
537
+
538
+ if srcdir is None:
539
+ srcdir = os.path.dirname(task.srcinfo.file)
540
+
541
+ if params is None:
542
+ params = task.paramT()
543
+
544
+ ret = TaskNodeCompound(
545
+ name=name,
546
+ srcdir=srcdir,
547
+ params=params,
548
+ ctxt=self._ctxt)
549
+
550
+ if ret.input is None:
551
+ raise Exception("Task %s does not have an input" % task.name)
552
+
553
+ self._gatherNeeds(task, ret)
554
+
555
+ ctxt = TaskGenCtxt(
556
+ rundir=self.get_rundir(),
557
+ input=ret.input,
558
+ builder=self
559
+ )
560
+
561
+ # In both cases, the result 'lives' inside a compound task
562
+
563
+ res = None
564
+ if task.strategy.generate is not None:
565
+ callable = ExecGenCallable(body=task.strategy.generate.run)
566
+ input = TaskGenInputData(params=params)
567
+
568
+ res = callable(ctxt, input)
569
+ elif len(task.strategy.matrix):
570
+ matrix = {}
571
+ matrix_items = []
572
+ for k in task.strategy.matrix.keys():
573
+ matrix[k] = None
574
+ matrix_items.append((k, task.strategy.matrix[k]))
575
+
576
+ res = self._applyStrategyMatrix(task.tasks, matrix_items, 0)
577
+
578
+ pass
579
+
580
+
581
+ # tasks = [ret.input]
582
+ tasks = []
583
+ tasks.extend(ret.tasks[1:])
584
+
585
+ tasks.extend(ctxt.tasks.copy())
586
+ if res is not None:
587
+ if isinstance(res, list):
588
+ tasks.extend(res)
589
+ else:
590
+ tasks.append(res)
591
+
592
+ # Finish hooking this up...
593
+ for tn in tasks:
594
+ if tn is None:
595
+ raise Exception("Generator yielded a null class")
596
+ referenced = None
597
+ for tt in tasks:
598
+ for tnn,_ in tt.needs:
599
+ if tn == tnn:
600
+ referenced = tnn
601
+ break
602
+
603
+ refs_internal = None
604
+ for nn,_ in tn.first.needs:
605
+ for tnn in tasks:
606
+ if nn == tnn:
607
+ refs_internal = tnn
608
+ break
609
+ if refs_internal is not None:
610
+ break
611
+
612
+ if not refs_internal:
613
+ if ret.input is None:
614
+ raise Exception("Adding None input")
615
+ if tn == ret.input:
616
+ raise Exception("Adding input to itself")
617
+ tn.needs.append((ret.input, False))
618
+
619
+ if referenced is None:
620
+ if tn is None:
621
+ raise Exception("Adding None input")
622
+ ret.needs.append((tn, False))
623
+
624
+ self._log.debug("<-- _applyStrategy %s" % task.name)
625
+ return ret
626
+
627
+ def _applyStrategyMatrix(self, tasks, matrix_items, idx):
628
+ raise Exception("_applyStrategyMatrix not implemented")
629
+
630
+
527
631
  def _isCompound(self, task):
528
632
  if isinstance(task, Task):
529
633
  if task.subtasks is not None and len(task.subtasks):
@@ -49,6 +49,10 @@ class TaskNodeLeaf(TaskNode):
49
49
  for i,(need,block) in enumerate(self.needs):
50
50
  self._log.debug("dep %s dep_m: %s" % (need.name, str(dep_m)))
51
51
  if not block:
52
+ if need.output is None:
53
+ raise Exception("Need %s has no output (in %s)" % (
54
+ need.name,
55
+ self.name))
52
56
  for subdep in need.output.dep_m.keys():
53
57
  if subdep not in dep_m.keys():
54
58
  dep_m[subdep] = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-flow-mgr
3
- Version: 1.9.0
3
+ Version: 1.9.14960981876rc0
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
@@ -1,4 +1,4 @@
1
- dv_flow/mgr/__init__.py,sha256=XEEeRw_ZtMVNVh1mpM2XZQWxTclTlRrlh9BLZp09RhE,1301
1
+ dv_flow/mgr/__init__.py,sha256=A_xkZr8PLXmBBnX9KfRO0LLgliSssvdgayAw39syRIU,1315
2
2
  dv_flow/mgr/__main__.py,sha256=BogNdBkXhgg05E8_IumNkVoag6WwvfbpiI8346oOtPo,3844
3
3
  dv_flow/mgr/cond_def.py,sha256=2ZkzPusqVkN1fFMTvkDl9O_OJLPdD_cK3xzX9J75RMw,343
4
4
  dv_flow/mgr/config.py,sha256=b2MVlVVNB0psk8x4bQRAYshkpNJrtyMtV1Ymhmx9AfM,137
@@ -6,6 +6,7 @@ dv_flow/mgr/config_def.py,sha256=N5nBc_2VPrx0pCDyIe-VPhQ7ItnbyJqrak3ZiPEAbtI,104
6
6
  dv_flow/mgr/data_callable.py,sha256=-GeMgBUdUEcdAkWsqvUYcpKqUd5BQsFgi6ARflnp2B8,687
7
7
  dv_flow/mgr/eval_jq.py,sha256=bRsHtaN51qIOiZK1VJV52W0-vj5VH0nQ7XIFebZi5kI,1129
8
8
  dv_flow/mgr/exec_callable.py,sha256=NbhTVqvrTd-vsTi3cJ3iGrpVe8tfAqxFsSopaNXApRE,3117
9
+ dv_flow/mgr/exec_gen_callable.py,sha256=KLAKgu0c6nrEzfy85qeogH64VOFDBa6anslSBajykOE,3039
9
10
  dv_flow/mgr/expr_eval.py,sha256=ojHo3U_QGqm0CWVSEGtFJRo3jrjiTKhy_B58yRNxN8g,4814
10
11
  dv_flow/mgr/expr_parser.py,sha256=LMLe4RTbgcQVIpuZIi1vowHsKRgRmzKzomGvlJL8kJI,7110
11
12
  dv_flow/mgr/ext_rgy.py,sha256=BeHbTjB6KFcI5xhbl_O00YQW7MQ8efCFTD_Y8xf7I44,5651
@@ -20,7 +21,7 @@ dv_flow/mgr/out,sha256=d8GGBi3J43fhdLBlnsUbzBfRe0TD0QTP3nOTz54l2bI,200
20
21
  dv_flow/mgr/package.py,sha256=L1ba5xguOZWuyg9s4MfafKgSoIka3SgAQzYAmcV7XgQ,4430
21
22
  dv_flow/mgr/package_def.py,sha256=1O1SBJATnw-zeYKRNENgw-RWxZK0hxNQhnncfE_NR-U,5674
22
23
  dv_flow/mgr/package_import_spec.py,sha256=aZMpnS9a5NFY76_pYXEuO3-Mkc_xFzy73fdrUe_54Dc,1760
23
- dv_flow/mgr/package_loader.py,sha256=DUNSolfB-9E0KgmCCEjz6ezWm4xlwgPRpWgxcugFEmM,34771
24
+ dv_flow/mgr/package_loader.py,sha256=jfZj1TuYWmuSEVT8Yon8bC0GWJtdynWwugbgZEJsQKY,35389
24
25
  dv_flow/mgr/package_node.py,sha256=CccD2ECiIXy9JBkRR3c7qDxeBiLiPbRT9CqR-Al_niI,214
25
26
  dv_flow/mgr/param.py,sha256=kkxMRGf6mPjSZJsjgLKH2vJL62Sn0ZESvjBLkEYOp20,1386
26
27
  dv_flow/mgr/param_def.py,sha256=9uO-7UI4OotYixQBo8Nwb2o8FQRFxxJylYCZm9rjt48,1917
@@ -31,10 +32,11 @@ dv_flow/mgr/pytask_callable.py,sha256=JiFN2vq6qanI6FXJBeidwiBSn6t0oC0izPJ01c5QJT
31
32
  dv_flow/mgr/root_package.py,sha256=nYLOpZVQEDbY0Ui5X5UNeUHXOvqRENew7B2zpC2V2gQ,136
32
33
  dv_flow/mgr/shell_callable.py,sha256=IWb0C4L-v_hfnvnhS3g2rhXqutURex_U-dBJgdNxP7I,302
33
34
  dv_flow/mgr/srcinfo.py,sha256=xrfp-relVr7hYNbxOjY5jqX4H0nNMm9HK5AAM6_Piyk,366
34
- dv_flow/mgr/task.py,sha256=n3v9A9HvgMWNeQhXVB_L2qRjgjounXMs9-bbxtyEau8,2088
35
+ dv_flow/mgr/task.py,sha256=XQ-mVyDGvpU4gB6GmnNeTQhxKqFXiblShh7qd_-SIbM,2387
35
36
  dv_flow/mgr/task_data.py,sha256=lN7Iq8YTitEMGG4rZqYQi6Ri2HuPgBQ5oGQbW-63T8c,12436
36
- dv_flow/mgr/task_def.py,sha256=8NPwtTROfWDkMqcO9mKXV4dw0sC4mCMmnsNuv8uTdTY,5094
37
- dv_flow/mgr/task_graph_builder.py,sha256=2u5iOa4vMZaAxbImVknMLQLV6TEVbxXzEfsE7d3YXKI,29380
37
+ dv_flow/mgr/task_def.py,sha256=lhiOL7E_TfW7Ytg5qipE6d2cqTkfVqAOs1MZgtCqeLg,5257
38
+ dv_flow/mgr/task_gen_ctxt.py,sha256=1QQqqgaCjJSlzTV0SASpTb69vINFrDq3aqjYCKUkx3s,846
39
+ dv_flow/mgr/task_graph_builder.py,sha256=pqzazJjA36g-ETuvxfEl6JV6035koJJPqSF_L-Egtgg,32716
38
40
  dv_flow/mgr/task_graph_dot_writer.py,sha256=qK4Imy9o2_F1aKoU1tJ-qoBHslq2BhSMbdjAUPfpN7I,6009
39
41
  dv_flow/mgr/task_listener_log.py,sha256=Ai-6X5BOoGsaNTgnlXEW0-czrjJm7__ShNK501CUmko,4337
40
42
  dv_flow/mgr/task_listener_trace.py,sha256=7B-V2YK8uXd_QSGBq_7USmbe5CleVvwumU0CpsmxZvg,6224
@@ -48,7 +50,7 @@ dv_flow/mgr/task_node_ctor_proxy.py,sha256=ViOFJ64JM4-CGFZNl89BghFuKSQ66kZVqSj4v
48
50
  dv_flow/mgr/task_node_ctor_task.py,sha256=d49g90TyPCMFR8BuWWqp4ym-MW5vGSdDR0V47Ru28JY,2232
49
51
  dv_flow/mgr/task_node_ctor_wrapper.py,sha256=KMSYd4ik2Si7UXhNMeXAPHBwwrFkuhpeTMeYRpWv0hw,3718
50
52
  dv_flow/mgr/task_node_ctxt.py,sha256=dQp68ppFENK0zGo7TKaFXHInPCCsFai1yZwoBKDwJ20,166
51
- dv_flow/mgr/task_node_leaf.py,sha256=od6INBSqMkKZTbCAGJFXzZ3_eD-g7_rt_v3HNa61cQ8,8926
53
+ dv_flow/mgr/task_node_leaf.py,sha256=nULlu-veyPC-PXdoQhahkLgqpdKNzaoD0XUlCw0EuZ4,9109
52
54
  dv_flow/mgr/task_output.py,sha256=ZwyvwnYj_gHOEFAEOH3m24Xfc4Cn77hb1j7LkX8_3C4,1086
53
55
  dv_flow/mgr/task_params_ctor.py,sha256=qlrzibGAFHmbqOu88jEoh1wOSFHu68Gwdgc259-50e8,1915
54
56
  dv_flow/mgr/task_run_ctxt.py,sha256=q88OsuKAHC_GipZ7jBSjbybARsJkgcJhvbKjjj2TweA,3801
@@ -74,9 +76,9 @@ dv_flow/mgr/util/util.py,sha256=BO7iqP_c9ttmXkojq7nKDN-g8wl1_Pco9k-KnrXxjwE,1889
74
76
  dv_flow/mgr/util/cmds/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
77
  dv_flow/mgr/util/cmds/cmd_schema.py,sha256=IJzZdxCSEgIQ79LpYiM7UqJ9RJ-7yraqmBN2XVgAgXA,1752
76
78
  dv_flow/mgr/util/cmds/cmd_workspace.py,sha256=egmaIXpe5L-TePwmcfisfrG6tdiTUWSjqa9Za5WChVs,890
77
- dv_flow_mgr-1.9.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
78
- dv_flow_mgr-1.9.0.dist-info/METADATA,sha256=1BuEuGg1VHbODzmAwS0AxdWZMJva1UWSsaqHiRSrjFk,13322
79
- dv_flow_mgr-1.9.0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
80
- dv_flow_mgr-1.9.0.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
81
- dv_flow_mgr-1.9.0.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
82
- dv_flow_mgr-1.9.0.dist-info/RECORD,,
79
+ dv_flow_mgr-1.9.14960981876rc0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
80
+ dv_flow_mgr-1.9.14960981876rc0.dist-info/METADATA,sha256=0O2YxHZdwX3mB_2MU1YJl_QweoVoTFWlMcem5I1hMec,13335
81
+ dv_flow_mgr-1.9.14960981876rc0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
82
+ dv_flow_mgr-1.9.14960981876rc0.dist-info/entry_points.txt,sha256=1roy8wAFM48LabOvr6jiOw0MUs-qE8X3Vf8YykPazxk,50
83
+ dv_flow_mgr-1.9.14960981876rc0.dist-info/top_level.txt,sha256=amfVTkggzYPtWwLqNmRukfz1Buu0pGS2SrYBBLhXm04,8
84
+ dv_flow_mgr-1.9.14960981876rc0.dist-info/RECORD,,