dv-flow-mgr 0.0.1.12992722023a1__tar.gz → 0.0.1.13335470340a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/PKG-INFO +1 -1
- dv_flow_mgr-0.0.1.13335470340a1/docs/KeyArchitecture.md +65 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/Roadmap.md +6 -1
- dv_flow_mgr-0.0.1.13335470340a1/docs/Steps.md +50 -0
- dv_flow_mgr-0.0.1.13335470340a1/docs/Usecases.md +49 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/ivpm.yaml +2 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/pyproject.toml +1 -1
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/expr_parser.py +38 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/fragment_def.py +2 -0
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/out +12 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/package.py +1 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/package_def.py +29 -0
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/param_def.py +25 -0
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/std/flow.dv +78 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_data.py +12 -14
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_def.py +4 -1
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/task_impl_data.py +17 -0
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/task_output.py +6 -0
- dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/type_def.py +10 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow_mgr.egg-info/PKG-INFO +1 -1
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow_mgr.egg-info/SOURCES.txt +11 -0
- dv_flow_mgr-0.0.1.13335470340a1/tests/unit/data/fileset/test1/files2/file2_2.sv +0 -0
- dv_flow_mgr-0.0.1.13335470340a1/tests/unit/test_parse.py +38 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_smoke.py +55 -1
- dv_flow_mgr-0.0.1.12992722023a1/src/dv_flow/mgr/std/flow.dv +0 -30
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/.github/workflows/ci.yml +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/.gitignore +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/.vscode/settings.json +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/LICENSE +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/README.md +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/Makefile +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/Notes.md +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/Stages.md +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/TypesAndDefs.md +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/conf.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/index.rst +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/intro.rst +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/quickstart.rst +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/docs/reference.rst +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/setup.cfg +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/__init__.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/__main__.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/cmds/cmd_run.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/fileset.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/package_import_spec.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/pkg_rgy.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/share/flow.json +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/std/fileset.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/std/message.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/std/task_null.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_graph_builder.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_graph_runner.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_graph_runner_local.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_memento.py +0 -0
- /dv_flow_mgr-0.0.1.12992722023a1/tests/unit/data/fileset/test1 copy/files1/file1_1.sv → /dv_flow_mgr-0.0.1.13335470340a1/src/dv_flow/mgr/type.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/util.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow_mgr.egg-info/dependency_links.txt +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow_mgr.egg-info/entry_points.txt +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow_mgr.egg-info/requires.txt +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow_mgr.egg-info/top_level.txt +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/examples/example1/example1.flow +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/system/test_depends.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/system/test_pkg_discovery.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/system/test_stdlib.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/__init__.py +0 -0
- /dv_flow_mgr-0.0.1.12992722023a1/tests/unit/data/fileset/test1/files1/file1_2.sv → /dv_flow_mgr-0.0.1.13335470340a1/tests/unit/data/fileset/test1/files1/file1_1.sv +0 -0
- /dv_flow_mgr-0.0.1.12992722023a1/tests/unit/data/fileset/test1/files2/file2_1.sv → /dv_flow_mgr-0.0.1.13335470340a1/tests/unit/data/fileset/test1/files1/file1_2.sv +0 -0
- /dv_flow_mgr-0.0.1.12992722023a1/tests/unit/data/fileset/test1/files2/file2_2.sv → /dv_flow_mgr-0.0.1.13335470340a1/tests/unit/data/fileset/test1/files2/file2_1.sv +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/fileset/test1/flow.dv +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1/tests/unit/data/fileset/test1 → dv_flow_mgr-0.0.1.13335470340a1/tests/unit/data/fileset/test1 copy}/files1/file1_1.sv +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/fileset/test1 copy/files1/file1_2.sv +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/fileset/test1 copy/files2/file2_1.sv +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/fileset/test1 copy/files2/file2_2.sv +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/fileset/test1 copy/test1.dfs +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/proj1/proj1.dfs +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/proj2/proj2.dfs +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/proj3/proj3.dfs +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_data_merge.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_fileset.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_pyclass.py +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_smoke copy.sav +0 -0
- {dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_stdlib.py +0 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
# Tasks
|
3
|
+
- A task has 0..N dependencies (references to tasks whose output
|
4
|
+
data must be available prior to execution of the task)
|
5
|
+
- The input data available to a task includes
|
6
|
+
- Output data from its dependencies
|
7
|
+
- Memento data from its prior execution (a memento is a record of task execution)
|
8
|
+
- Makes sense to include markers here
|
9
|
+
- Locally-specified data (ie task parameters)
|
10
|
+
- The core implementation of a task is invoked with a
|
11
|
+
consolidated set of data that is specified in the task definition.
|
12
|
+
- Example: select all FileSet that have kind systemVerilog, verilog, or VHDL
|
13
|
+
- The output of a task is comprised of (think of this as a filter?)
|
14
|
+
- Output data from its dependencies
|
15
|
+
- Memento data from the implementation, including marker information
|
16
|
+
|
17
|
+
# Types
|
18
|
+
- Types are named structures
|
19
|
+
|
20
|
+
# Task Parameters
|
21
|
+
- A task may have parameters. Parameters are singletons, and are
|
22
|
+
not extensible from outside.
|
23
|
+
- If a task needs to accept outside input, it must select that
|
24
|
+
by type from input parameter sets
|
25
|
+
- Direct parameters
|
26
|
+
- Task parameters are exposed to task implementation via a type with the task name
|
27
|
+
- Do we really need this?
|
28
|
+
- Using explicit types results in one extra layer of indirection
|
29
|
+
- Still may have to deal with ambiguity...
|
30
|
+
|
31
|
+
- name: RunSim
|
32
|
+
uses: SimRun
|
33
|
+
with:
|
34
|
+
- name: simargs
|
35
|
+
type:
|
36
|
+
list:
|
37
|
+
item: SimArgs
|
38
|
+
value: ${{ jq in.[]}}
|
39
|
+
- uses: SimArgs
|
40
|
+
with:
|
41
|
+
- append-list
|
42
|
+
|
43
|
+
So... Tasks do not have parameters.
|
44
|
+
- Tasks can inject parameter sets into the input set
|
45
|
+
- Tasks can control what emerges from the task
|
46
|
+
|
47
|
+
plusargs: .[] select(uses==SimArgs) |
|
48
|
+
|
49
|
+
# Cross-Task Dataflow
|
50
|
+
- Cross-task dataflow is comprised of a collection of typed objects
|
51
|
+
containing typed fields.
|
52
|
+
- Augmenting data is done by injecting new object instances into
|
53
|
+
the dataset. For example:
|
54
|
+
- The dataset contains an object for specifying simulation runtime
|
55
|
+
arguments. It contains a directive to append "+UVM_TEST=my_test"
|
56
|
+
to the arguments
|
57
|
+
- I add a new runtime-arguments object that contains a directive
|
58
|
+
to append "+debug" to the arguments
|
59
|
+
- The consumer will see [+UVM_TEST=my_test +debug]
|
60
|
+
|
61
|
+
|
62
|
+
# Data-Combination Rules
|
63
|
+
- In most cases, data must be flattened in order to use it. For example,
|
64
|
+
|
65
|
+
-
|
@@ -123,4 +123,9 @@ are evaluated.
|
|
123
123
|
- Dependency strategy for Exec/Make
|
124
124
|
- Specify dependency file created by task
|
125
125
|
- When the timestamp is updated, task is known to have been rebuilt
|
126
|
-
-
|
126
|
+
-
|
127
|
+
|
128
|
+
- Allow each task to emit a series of markers as part of the result
|
129
|
+
- Enables users to easily click on first N warnings/errors in each step
|
130
|
+
without needing to find and open a logfile
|
131
|
+
- Allow files to be attached as part of the result
|
@@ -0,0 +1,50 @@
|
|
1
|
+
|
2
|
+
# Tasks and Types
|
3
|
+
- Load type definitions from YAML
|
4
|
+
- Load task definitions from YAML
|
5
|
+
|
6
|
+
# Data Selection and Extraction
|
7
|
+
- Sort and select data
|
8
|
+
- Need to support expressions
|
9
|
+
-
|
10
|
+
|
11
|
+
# Task Implementation Source/Result Data
|
12
|
+
|
13
|
+
Source Data
|
14
|
+
- Task parameters
|
15
|
+
- Upstream-change indication
|
16
|
+
- Memento
|
17
|
+
|
18
|
+
Result Data
|
19
|
+
- List of output parameter sets
|
20
|
+
- Change indication
|
21
|
+
- Memento
|
22
|
+
|
23
|
+
# Data Combination
|
24
|
+
-
|
25
|
+
|
26
|
+
# Day in the Life
|
27
|
+
- Task Runner receives outputs from dependent tasks
|
28
|
+
- ORs input changed' input flags to determine 'changed' flag to pass to task
|
29
|
+
- Task Runner orders parameters using dependency information
|
30
|
+
- Task Runner evaluates task-parameter creation code. Uses input data in this process
|
31
|
+
- Creates object of appropriate type
|
32
|
+
- Evalutes base-up to assign and augment parameter values
|
33
|
+
- Retrieves memento (if available)
|
34
|
+
- Passes accumulated data to task
|
35
|
+
- changed
|
36
|
+
- parameters
|
37
|
+
-
|
38
|
+
- Receives output from task
|
39
|
+
- list of parameter sets
|
40
|
+
- changed
|
41
|
+
- memento
|
42
|
+
- list of markers
|
43
|
+
- Saves memento and markers for later inspection (central dir?)
|
44
|
+
- Sets 'self' as source of parameter sets
|
45
|
+
- Forms output data from
|
46
|
+
- changed
|
47
|
+
- list of parameter sets
|
48
|
+
|
49
|
+
# Creating Task Parameters
|
50
|
+
-
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
# Simple Initial Project Setup
|
3
|
+
|
4
|
+
|
5
|
+
# Reconfigure Project Build
|
6
|
+
|
7
|
+
# Global Configuration Data
|
8
|
+
Some configuration data is global in nature -- in other words,
|
9
|
+
it is relevant to multiple tools. Debug is one example. Enabling
|
10
|
+
a debug flow impacts multiple simulation tools, and may impact
|
11
|
+
how user-specified input behaves as well (eg adding +UVM_VERBOSITY)
|
12
|
+
|
13
|
+
# Configure Package Usage
|
14
|
+
I have a package that depends on UVM, as well as other packages (UVCs)
|
15
|
+
that depend on UVM. By default, the UVM library is provided as a
|
16
|
+
pre-compiled library (n simulators that support it). For "reasons",
|
17
|
+
I want to switch to using the pure-source version. My choice must
|
18
|
+
apply to all packages within my orbit -- in other words, having
|
19
|
+
my package depend on source UVM while the UVC depends on pre-compiled
|
20
|
+
will result in a conflict.
|
21
|
+
|
22
|
+
# Configure Project Toolchain
|
23
|
+
My package has external dependencies that may specify processing
|
24
|
+
in addition to sources (eg the UVM library specifies how to
|
25
|
+
precompile it). I need a way to configure the toolchain that the
|
26
|
+
external packages use the toolchain defined by my package.
|
27
|
+
|
28
|
+
# Inline Specification of Inputs
|
29
|
+
The simulation tool receives its inputs and controls via task data.
|
30
|
+
This provides flexibility, by allowing multiple tasks to contribute
|
31
|
+
command-line arguments. While I could create a new task to output
|
32
|
+
data that would add a command-line argument, I'd prefer to have
|
33
|
+
a more-direct way to do so -- a sort of inline injection of task
|
34
|
+
data that is combined with the task data of dependencies prior to
|
35
|
+
being presented to the implementation.
|
36
|
+
|
37
|
+
|
38
|
+
# Static Composition of Task Graphs (Introspection?)
|
39
|
+
I have a collection of test definitions. I want to take a selection
|
40
|
+
of them, connect my preferred simulation image, and run them.
|
41
|
+
|
42
|
+
|
43
|
+
# Static Composition of Task Graphs (Introspection)
|
44
|
+
I have collections of test definitions. I want to select tests that
|
45
|
+
have a specific attribute / tag value, connect my preferred
|
46
|
+
simulation image, and run them.
|
47
|
+
|
48
|
+
|
49
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import dataclasses as dc
|
2
|
+
import enum
|
3
|
+
|
4
|
+
class TokenKind(enum.Enum):
|
5
|
+
ID = enum.auto()
|
6
|
+
|
7
|
+
@dc.dataclass
|
8
|
+
class Expr(object):
|
9
|
+
kind : TokenKind = TokenKind.ID
|
10
|
+
|
11
|
+
class ExprId(Expr):
|
12
|
+
id : str
|
13
|
+
|
14
|
+
def __post_init__(self):
|
15
|
+
self.kind = TokenKind.ID
|
16
|
+
|
17
|
+
class ExprPipe(Expr):
|
18
|
+
lhs : Expr
|
19
|
+
rhs : Expr
|
20
|
+
|
21
|
+
def __post_init__(self):
|
22
|
+
self.kind = TokenKind.ID
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
class ExprParser(object):
|
27
|
+
|
28
|
+
def __init__(self, input):
|
29
|
+
self.input = input
|
30
|
+
|
31
|
+
def __iter__(self):
|
32
|
+
return self
|
33
|
+
|
34
|
+
def __next__(self):
|
35
|
+
|
36
|
+
self.expr = expr
|
37
|
+
self.tokens = []
|
38
|
+
self.pos = 0
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/fragment_def.py
RENAMED
@@ -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-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/package.py
RENAMED
@@ -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:
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/package_def.py
RENAMED
@@ -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,78 @@
|
|
1
|
+
|
2
|
+
package:
|
3
|
+
name: std
|
4
|
+
|
5
|
+
tasks:
|
6
|
+
- name: Message
|
7
|
+
pyclass: dv_flow.mgr.std.message.Message
|
8
|
+
with:
|
9
|
+
msg:
|
10
|
+
type: str
|
11
|
+
value: ""
|
12
|
+
- name: FileSet
|
13
|
+
pyclass: dv_flow.mgr.std.fileset.FileSet
|
14
|
+
with:
|
15
|
+
base:
|
16
|
+
type: str
|
17
|
+
value: ""
|
18
|
+
type:
|
19
|
+
type: str
|
20
|
+
value: ""
|
21
|
+
include:
|
22
|
+
type: str
|
23
|
+
value: ""
|
24
|
+
exclude:
|
25
|
+
type: str
|
26
|
+
value: ""
|
27
|
+
# - name: Exec
|
28
|
+
# pyclass: dv_flow.mgr.std.exec.Exec
|
29
|
+
# with: {}
|
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-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_data.py
RENAMED
@@ -48,26 +48,22 @@ class TaskDataParam(BaseModel):
|
|
48
48
|
kind : TaskDataParamKindE
|
49
49
|
ops : List[TaskDataParamOp] = dc.Field(default_factory=list)
|
50
50
|
|
51
|
+
class TaskDataItem(BaseModel):
|
52
|
+
type : str
|
53
|
+
src : str
|
54
|
+
id : str
|
55
|
+
|
51
56
|
class TaskData(BaseModel):
|
52
57
|
src : str = None
|
53
|
-
params : Dict[str,TaskDataParam] = dc.Field(default_factory=dict)
|
54
58
|
deps : Dict[str,Set[str]] = dc.Field(default_factory=dict)
|
55
|
-
filesets : List[FileSet] = dc.Field(default_factory=list)
|
56
59
|
changed : bool = False
|
60
|
+
data : List[TaskDataItem] = dc.Field(default_factory=list)
|
57
61
|
|
58
62
|
_log : ClassVar = logging.getLogger("TaskData")
|
59
63
|
|
60
|
-
def
|
61
|
-
|
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)
|
64
|
+
def addData(self, item : TaskDataItem):
|
65
|
+
item.src = self.src
|
66
|
+
self.data.append(item)
|
71
67
|
|
72
68
|
def getFileSets(self, type=None, order=True) -> List[FileSet]:
|
73
69
|
ret = []
|
@@ -77,8 +73,10 @@ class TaskData(BaseModel):
|
|
77
73
|
if order:
|
78
74
|
# The deps map specifies task dependencies
|
79
75
|
|
76
|
+
filesets = filter(lambda x: x.type == "std.FileSet", self.data)
|
77
|
+
|
80
78
|
candidate_fs = []
|
81
|
-
for fs in
|
79
|
+
for fs in filesets:
|
82
80
|
self._log.debug("fs: %s" % str(fs))
|
83
81
|
if type is None or fs.type in type:
|
84
82
|
candidate_fs.append(fs)
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_def.py
RENAMED
@@ -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:
|
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,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
|
+
|
@@ -5,11 +5,14 @@ ivpm.yaml
|
|
5
5
|
pyproject.toml
|
6
6
|
.github/workflows/ci.yml
|
7
7
|
.vscode/settings.json
|
8
|
+
docs/KeyArchitecture.md
|
8
9
|
docs/Makefile
|
9
10
|
docs/Notes.md
|
10
11
|
docs/Roadmap.md
|
11
12
|
docs/Stages.md
|
13
|
+
docs/Steps.md
|
12
14
|
docs/TypesAndDefs.md
|
15
|
+
docs/Usecases.md
|
13
16
|
docs/conf.py
|
14
17
|
docs/index.rst
|
15
18
|
docs/intro.rst
|
@@ -17,11 +20,14 @@ docs/quickstart.rst
|
|
17
20
|
docs/reference.rst
|
18
21
|
src/dv_flow/mgr/__init__.py
|
19
22
|
src/dv_flow/mgr/__main__.py
|
23
|
+
src/dv_flow/mgr/expr_parser.py
|
20
24
|
src/dv_flow/mgr/fileset.py
|
21
25
|
src/dv_flow/mgr/fragment_def.py
|
26
|
+
src/dv_flow/mgr/out
|
22
27
|
src/dv_flow/mgr/package.py
|
23
28
|
src/dv_flow/mgr/package_def.py
|
24
29
|
src/dv_flow/mgr/package_import_spec.py
|
30
|
+
src/dv_flow/mgr/param_def.py
|
25
31
|
src/dv_flow/mgr/pkg_rgy.py
|
26
32
|
src/dv_flow/mgr/task.py
|
27
33
|
src/dv_flow/mgr/task_data.py
|
@@ -29,7 +35,11 @@ src/dv_flow/mgr/task_def.py
|
|
29
35
|
src/dv_flow/mgr/task_graph_builder.py
|
30
36
|
src/dv_flow/mgr/task_graph_runner.py
|
31
37
|
src/dv_flow/mgr/task_graph_runner_local.py
|
38
|
+
src/dv_flow/mgr/task_impl_data.py
|
32
39
|
src/dv_flow/mgr/task_memento.py
|
40
|
+
src/dv_flow/mgr/task_output.py
|
41
|
+
src/dv_flow/mgr/type.py
|
42
|
+
src/dv_flow/mgr/type_def.py
|
33
43
|
src/dv_flow/mgr/util.py
|
34
44
|
src/dv_flow/mgr/cmds/cmd_run.py
|
35
45
|
src/dv_flow/mgr/share/flow.json
|
@@ -50,6 +60,7 @@ tests/system/test_stdlib.py
|
|
50
60
|
tests/unit/__init__.py
|
51
61
|
tests/unit/test_data_merge.py
|
52
62
|
tests/unit/test_fileset.py
|
63
|
+
tests/unit/test_parse.py
|
53
64
|
tests/unit/test_pyclass.py
|
54
65
|
tests/unit/test_smoke copy.sav
|
55
66
|
tests/unit/test_smoke.py
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import io
|
2
|
+
import pytest
|
3
|
+
import yaml
|
4
|
+
|
5
|
+
from dv_flow.mgr.type_def import TypeDef
|
6
|
+
|
7
|
+
def test_typedef_1():
|
8
|
+
flow_dv = """
|
9
|
+
package:
|
10
|
+
name: abc
|
11
|
+
types:
|
12
|
+
- name: T1
|
13
|
+
with:
|
14
|
+
- name: F1
|
15
|
+
doc: "Field 1"
|
16
|
+
type: str
|
17
|
+
- name: F2
|
18
|
+
type:
|
19
|
+
list:
|
20
|
+
item: str
|
21
|
+
- name: F3
|
22
|
+
type:
|
23
|
+
map:
|
24
|
+
key: str
|
25
|
+
item:
|
26
|
+
list:
|
27
|
+
item: str
|
28
|
+
"""
|
29
|
+
|
30
|
+
data = yaml.load(io.StringIO(flow_dv), yaml.FullLoader)
|
31
|
+
|
32
|
+
typedef = data["package"]["types"][0]
|
33
|
+
td = TypeDef(**typedef)
|
34
|
+
|
35
|
+
print("td=" + str(td))
|
36
|
+
|
37
|
+
|
38
|
+
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_smoke.py
RENAMED
@@ -3,12 +3,66 @@ import io
|
|
3
3
|
import os
|
4
4
|
import dataclasses as dc
|
5
5
|
import pytest
|
6
|
+
import jq
|
6
7
|
from typing import List
|
7
8
|
import yaml
|
8
|
-
from dv_flow.mgr import FileSet, PackageDef, TaskData
|
9
|
+
from dv_flow.mgr import FileSet, PackageDef, TaskData, TaskGraphBuilder
|
9
10
|
from pydantic import BaseModel
|
10
11
|
from shutil import copytree
|
11
12
|
|
13
|
+
def test_smoke_1():
|
14
|
+
flowdv = """
|
15
|
+
package:
|
16
|
+
name: my_pkg
|
17
|
+
|
18
|
+
tasks:
|
19
|
+
- name: entry
|
20
|
+
with:
|
21
|
+
- name: p1
|
22
|
+
type: int
|
23
|
+
- name: p2
|
24
|
+
type: int
|
25
|
+
"""
|
26
|
+
|
27
|
+
pkg_def = PackageDef.loads(flowdv)
|
28
|
+
builder = TaskGraphBuilder(pkg_def, os.getcwd())
|
29
|
+
task = builder.mkTaskGraph("my_pkg.entry")
|
30
|
+
|
31
|
+
def test_jq():
|
32
|
+
data = [
|
33
|
+
{
|
34
|
+
"type": "FileSet",
|
35
|
+
"kind": "systemVerilogSource"
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"type": "FileSet",
|
39
|
+
"kind": "vhdlSource"
|
40
|
+
},
|
41
|
+
{
|
42
|
+
"type": "FileSet",
|
43
|
+
"kind": "verilogSource"
|
44
|
+
}
|
45
|
+
]
|
46
|
+
|
47
|
+
result = jq.compile(""".[] |
|
48
|
+
select(
|
49
|
+
.kind == "systemVerilogSource"
|
50
|
+
or .kind == "verilogSource")
|
51
|
+
""").input(data).all()
|
52
|
+
value = """
|
53
|
+
with:
|
54
|
+
- name: files
|
55
|
+
list-append: |
|
56
|
+
${{
|
57
|
+
in | jq('.[] | select(
|
58
|
+
.kind == "systemVerilogSource"
|
59
|
+
or .kind == "verilogSource")')
|
60
|
+
}}
|
61
|
+
"""
|
62
|
+
print("result: %s" % str(result))
|
63
|
+
|
64
|
+
|
65
|
+
|
12
66
|
# def test_smoke():
|
13
67
|
# file = """
|
14
68
|
# package:
|
@@ -1,30 +0,0 @@
|
|
1
|
-
|
2
|
-
package:
|
3
|
-
name: std
|
4
|
-
|
5
|
-
tasks:
|
6
|
-
- name: Message
|
7
|
-
pyclass: dv_flow.mgr.std.message.Message
|
8
|
-
with:
|
9
|
-
msg:
|
10
|
-
type: str
|
11
|
-
value: ""
|
12
|
-
- name: FileSet
|
13
|
-
pyclass: dv_flow.mgr.std.fileset.FileSet
|
14
|
-
with:
|
15
|
-
base:
|
16
|
-
type: str
|
17
|
-
value: ""
|
18
|
-
type:
|
19
|
-
type: str
|
20
|
-
value: ""
|
21
|
-
include:
|
22
|
-
type: str
|
23
|
-
value: ""
|
24
|
-
exclude:
|
25
|
-
type: str
|
26
|
-
value: ""
|
27
|
-
# - name: Exec
|
28
|
-
# pyclass: dv_flow.mgr.std.exec.Exec
|
29
|
-
# with: {}
|
30
|
-
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/.github/workflows/ci.yml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/__init__.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/__main__.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/cmds/cmd_run.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/fileset.py
RENAMED
File without changes
|
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/pkg_rgy.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/share/flow.json
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/std/fileset.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/std/message.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/std/task_null.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/src/dv_flow/mgr/task_memento.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/system/test_depends.py
RENAMED
File without changes
|
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/system/test_stdlib.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/proj1/proj1.dfs
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/proj2/proj2.dfs
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/data/proj3/proj3.dfs
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_data_merge.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_fileset.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_pyclass.py
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_smoke copy.sav
RENAMED
File without changes
|
{dv_flow_mgr-0.0.1.12992722023a1 → dv_flow_mgr-0.0.1.13335470340a1}/tests/unit/test_stdlib.py
RENAMED
File without changes
|