sierra-research 1.3.6__py3-none-any.whl → 1.5.0__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.
- sierra/__init__.py +3 -3
- sierra/core/__init__.py +3 -3
- sierra/core/batchroot.py +223 -0
- sierra/core/cmdline.py +681 -1057
- sierra/core/compare.py +11 -0
- sierra/core/config.py +96 -88
- sierra/core/engine.py +306 -0
- sierra/core/execenv.py +380 -0
- sierra/core/expdef.py +11 -0
- sierra/core/experiment/__init__.py +1 -0
- sierra/core/experiment/bindings.py +150 -101
- sierra/core/experiment/definition.py +414 -245
- sierra/core/experiment/spec.py +83 -85
- sierra/core/exproot.py +44 -0
- sierra/core/generators/__init__.py +10 -0
- sierra/core/generators/experiment.py +528 -0
- sierra/core/generators/generator_factory.py +138 -137
- sierra/core/graphs/__init__.py +23 -0
- sierra/core/graphs/bcbridge.py +94 -0
- sierra/core/graphs/heatmap.py +245 -324
- sierra/core/graphs/pathset.py +27 -0
- sierra/core/graphs/schema.py +77 -0
- sierra/core/graphs/stacked_line.py +341 -0
- sierra/core/graphs/summary_line.py +506 -0
- sierra/core/logging.py +3 -2
- sierra/core/models/__init__.py +3 -1
- sierra/core/models/info.py +19 -0
- sierra/core/models/interface.py +52 -122
- sierra/core/pipeline/__init__.py +2 -5
- sierra/core/pipeline/pipeline.py +228 -126
- sierra/core/pipeline/stage1/__init__.py +10 -0
- sierra/core/pipeline/stage1/pipeline_stage1.py +45 -31
- sierra/core/pipeline/stage2/__init__.py +10 -0
- sierra/core/pipeline/stage2/pipeline_stage2.py +8 -11
- sierra/core/pipeline/stage2/runner.py +401 -0
- sierra/core/pipeline/stage3/__init__.py +12 -0
- sierra/core/pipeline/stage3/gather.py +321 -0
- sierra/core/pipeline/stage3/pipeline_stage3.py +37 -84
- sierra/core/pipeline/stage4/__init__.py +12 -2
- sierra/core/pipeline/stage4/pipeline_stage4.py +36 -354
- sierra/core/pipeline/stage5/__init__.py +12 -0
- sierra/core/pipeline/stage5/pipeline_stage5.py +33 -208
- sierra/core/pipeline/yaml.py +48 -0
- sierra/core/plugin.py +529 -62
- sierra/core/proc.py +11 -0
- sierra/core/prod.py +11 -0
- sierra/core/ros1/__init__.py +5 -1
- sierra/core/ros1/callbacks.py +22 -21
- sierra/core/ros1/cmdline.py +59 -88
- sierra/core/ros1/generators.py +159 -175
- sierra/core/ros1/variables/__init__.py +3 -0
- sierra/core/ros1/variables/exp_setup.py +122 -116
- sierra/core/startup.py +106 -76
- sierra/core/stat_kernels.py +4 -5
- sierra/core/storage.py +13 -32
- sierra/core/trampoline.py +30 -0
- sierra/core/types.py +116 -71
- sierra/core/utils.py +103 -106
- sierra/core/variables/__init__.py +1 -1
- sierra/core/variables/base_variable.py +12 -17
- sierra/core/variables/batch_criteria.py +387 -481
- sierra/core/variables/builtin.py +135 -0
- sierra/core/variables/exp_setup.py +19 -39
- sierra/core/variables/population_size.py +72 -76
- sierra/core/variables/variable_density.py +44 -68
- sierra/core/vector.py +1 -1
- sierra/main.py +256 -88
- sierra/plugins/__init__.py +119 -0
- sierra/plugins/compare/__init__.py +14 -0
- sierra/plugins/compare/graphs/__init__.py +19 -0
- sierra/plugins/compare/graphs/cmdline.py +120 -0
- sierra/plugins/compare/graphs/comparator.py +291 -0
- sierra/plugins/compare/graphs/inter_controller.py +531 -0
- sierra/plugins/compare/graphs/inter_scenario.py +297 -0
- sierra/plugins/compare/graphs/namecalc.py +53 -0
- sierra/plugins/compare/graphs/outputroot.py +73 -0
- sierra/plugins/compare/graphs/plugin.py +147 -0
- sierra/plugins/compare/graphs/preprocess.py +172 -0
- sierra/plugins/compare/graphs/schema.py +37 -0
- sierra/plugins/engine/__init__.py +14 -0
- sierra/plugins/engine/argos/__init__.py +18 -0
- sierra/plugins/{platform → engine}/argos/cmdline.py +144 -151
- sierra/plugins/{platform/argos/variables → engine/argos/generators}/__init__.py +5 -0
- sierra/plugins/engine/argos/generators/engine.py +394 -0
- sierra/plugins/engine/argos/plugin.py +393 -0
- sierra/plugins/{platform/argos/generators → engine/argos/variables}/__init__.py +5 -0
- sierra/plugins/engine/argos/variables/arena_shape.py +183 -0
- sierra/plugins/engine/argos/variables/cameras.py +240 -0
- sierra/plugins/engine/argos/variables/constant_density.py +112 -0
- sierra/plugins/engine/argos/variables/exp_setup.py +82 -0
- sierra/plugins/{platform → engine}/argos/variables/physics_engines.py +83 -87
- sierra/plugins/engine/argos/variables/population_constant_density.py +178 -0
- sierra/plugins/engine/argos/variables/population_size.py +115 -0
- sierra/plugins/engine/argos/variables/population_variable_density.py +123 -0
- sierra/plugins/engine/argos/variables/rendering.py +108 -0
- sierra/plugins/engine/ros1gazebo/__init__.py +18 -0
- sierra/plugins/engine/ros1gazebo/cmdline.py +175 -0
- sierra/plugins/{platform/ros1robot → engine/ros1gazebo}/generators/__init__.py +5 -0
- sierra/plugins/engine/ros1gazebo/generators/engine.py +125 -0
- sierra/plugins/engine/ros1gazebo/plugin.py +404 -0
- sierra/plugins/engine/ros1gazebo/variables/__init__.py +15 -0
- sierra/plugins/engine/ros1gazebo/variables/population_size.py +214 -0
- sierra/plugins/engine/ros1robot/__init__.py +18 -0
- sierra/plugins/engine/ros1robot/cmdline.py +159 -0
- sierra/plugins/{platform/ros1gazebo → engine/ros1robot}/generators/__init__.py +4 -0
- sierra/plugins/engine/ros1robot/generators/engine.py +95 -0
- sierra/plugins/engine/ros1robot/plugin.py +410 -0
- sierra/plugins/{hpc/local → engine/ros1robot/variables}/__init__.py +5 -0
- sierra/plugins/engine/ros1robot/variables/population_size.py +146 -0
- sierra/plugins/execenv/__init__.py +11 -0
- sierra/plugins/execenv/hpc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/__init__.py +18 -0
- sierra/plugins/execenv/hpc/adhoc/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/adhoc/plugin.py +131 -0
- sierra/plugins/execenv/hpc/cmdline.py +137 -0
- sierra/plugins/execenv/hpc/local/__init__.py +18 -0
- sierra/plugins/execenv/hpc/local/cmdline.py +31 -0
- sierra/plugins/execenv/hpc/local/plugin.py +145 -0
- sierra/plugins/execenv/hpc/pbs/__init__.py +18 -0
- sierra/plugins/execenv/hpc/pbs/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/pbs/plugin.py +121 -0
- sierra/plugins/execenv/hpc/slurm/__init__.py +18 -0
- sierra/plugins/execenv/hpc/slurm/cmdline.py +30 -0
- sierra/plugins/execenv/hpc/slurm/plugin.py +133 -0
- sierra/plugins/execenv/prefectserver/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/dockerremote/cmdline.py +66 -0
- sierra/plugins/execenv/prefectserver/dockerremote/plugin.py +132 -0
- sierra/plugins/execenv/prefectserver/flow.py +66 -0
- sierra/plugins/execenv/prefectserver/local/__init__.py +18 -0
- sierra/plugins/execenv/prefectserver/local/cmdline.py +29 -0
- sierra/plugins/execenv/prefectserver/local/plugin.py +133 -0
- sierra/plugins/{hpc/adhoc → execenv/robot}/__init__.py +1 -0
- sierra/plugins/execenv/robot/turtlebot3/__init__.py +18 -0
- sierra/plugins/execenv/robot/turtlebot3/plugin.py +204 -0
- sierra/plugins/expdef/__init__.py +14 -0
- sierra/plugins/expdef/json/__init__.py +14 -0
- sierra/plugins/expdef/json/plugin.py +504 -0
- sierra/plugins/expdef/xml/__init__.py +14 -0
- sierra/plugins/expdef/xml/plugin.py +386 -0
- sierra/{core/hpc → plugins/proc}/__init__.py +1 -1
- sierra/plugins/proc/collate/__init__.py +15 -0
- sierra/plugins/proc/collate/cmdline.py +47 -0
- sierra/plugins/proc/collate/plugin.py +271 -0
- sierra/plugins/proc/compress/__init__.py +18 -0
- sierra/plugins/proc/compress/cmdline.py +47 -0
- sierra/plugins/proc/compress/plugin.py +123 -0
- sierra/plugins/proc/decompress/__init__.py +18 -0
- sierra/plugins/proc/decompress/plugin.py +96 -0
- sierra/plugins/proc/imagize/__init__.py +15 -0
- sierra/plugins/proc/imagize/cmdline.py +49 -0
- sierra/plugins/proc/imagize/plugin.py +270 -0
- sierra/plugins/proc/modelrunner/__init__.py +16 -0
- sierra/plugins/proc/modelrunner/plugin.py +250 -0
- sierra/plugins/proc/statistics/__init__.py +15 -0
- sierra/plugins/proc/statistics/cmdline.py +64 -0
- sierra/plugins/proc/statistics/plugin.py +390 -0
- sierra/plugins/{hpc → prod}/__init__.py +1 -0
- sierra/plugins/prod/graphs/__init__.py +18 -0
- sierra/plugins/prod/graphs/cmdline.py +269 -0
- sierra/plugins/prod/graphs/collate.py +279 -0
- sierra/plugins/prod/graphs/inter/__init__.py +13 -0
- sierra/plugins/prod/graphs/inter/generate.py +83 -0
- sierra/plugins/prod/graphs/inter/heatmap.py +86 -0
- sierra/plugins/prod/graphs/inter/line.py +134 -0
- sierra/plugins/prod/graphs/intra/__init__.py +15 -0
- sierra/plugins/prod/graphs/intra/generate.py +202 -0
- sierra/plugins/prod/graphs/intra/heatmap.py +74 -0
- sierra/plugins/prod/graphs/intra/line.py +114 -0
- sierra/plugins/prod/graphs/plugin.py +103 -0
- sierra/plugins/prod/graphs/targets.py +63 -0
- sierra/plugins/prod/render/__init__.py +18 -0
- sierra/plugins/prod/render/cmdline.py +72 -0
- sierra/plugins/prod/render/plugin.py +282 -0
- sierra/plugins/storage/__init__.py +5 -0
- sierra/plugins/storage/arrow/__init__.py +18 -0
- sierra/plugins/storage/arrow/plugin.py +38 -0
- sierra/plugins/storage/csv/__init__.py +9 -0
- sierra/plugins/storage/csv/plugin.py +12 -5
- sierra/version.py +3 -2
- sierra_research-1.5.0.dist-info/METADATA +238 -0
- sierra_research-1.5.0.dist-info/RECORD +186 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/WHEEL +1 -2
- sierra/core/experiment/xml.py +0 -454
- sierra/core/generators/controller_generator_parser.py +0 -34
- sierra/core/generators/exp_creator.py +0 -351
- sierra/core/generators/exp_generators.py +0 -142
- sierra/core/graphs/scatterplot2D.py +0 -109
- sierra/core/graphs/stacked_line_graph.py +0 -249
- sierra/core/graphs/stacked_surface_graph.py +0 -220
- sierra/core/graphs/summary_line_graph.py +0 -369
- sierra/core/hpc/cmdline.py +0 -142
- sierra/core/models/graphs.py +0 -87
- sierra/core/pipeline/stage2/exp_runner.py +0 -286
- sierra/core/pipeline/stage3/imagizer.py +0 -149
- sierra/core/pipeline/stage3/run_collator.py +0 -317
- sierra/core/pipeline/stage3/statistics_calculator.py +0 -478
- sierra/core/pipeline/stage4/graph_collator.py +0 -319
- sierra/core/pipeline/stage4/inter_exp_graph_generator.py +0 -240
- sierra/core/pipeline/stage4/intra_exp_graph_generator.py +0 -317
- sierra/core/pipeline/stage4/model_runner.py +0 -168
- sierra/core/pipeline/stage4/rendering.py +0 -283
- sierra/core/pipeline/stage4/yaml_config_loader.py +0 -103
- sierra/core/pipeline/stage5/inter_scenario_comparator.py +0 -328
- sierra/core/pipeline/stage5/intra_scenario_comparator.py +0 -989
- sierra/core/platform.py +0 -493
- sierra/core/plugin_manager.py +0 -369
- sierra/core/root_dirpath_generator.py +0 -241
- sierra/plugins/hpc/adhoc/plugin.py +0 -125
- sierra/plugins/hpc/local/plugin.py +0 -81
- sierra/plugins/hpc/pbs/__init__.py +0 -9
- sierra/plugins/hpc/pbs/plugin.py +0 -126
- sierra/plugins/hpc/slurm/__init__.py +0 -9
- sierra/plugins/hpc/slurm/plugin.py +0 -130
- sierra/plugins/platform/__init__.py +0 -9
- sierra/plugins/platform/argos/__init__.py +0 -9
- sierra/plugins/platform/argos/generators/platform_generators.py +0 -383
- sierra/plugins/platform/argos/plugin.py +0 -337
- sierra/plugins/platform/argos/variables/arena_shape.py +0 -145
- sierra/plugins/platform/argos/variables/cameras.py +0 -243
- sierra/plugins/platform/argos/variables/constant_density.py +0 -136
- sierra/plugins/platform/argos/variables/exp_setup.py +0 -113
- sierra/plugins/platform/argos/variables/population_constant_density.py +0 -175
- sierra/plugins/platform/argos/variables/population_size.py +0 -102
- sierra/plugins/platform/argos/variables/population_variable_density.py +0 -132
- sierra/plugins/platform/argos/variables/rendering.py +0 -104
- sierra/plugins/platform/ros1gazebo/__init__.py +0 -9
- sierra/plugins/platform/ros1gazebo/cmdline.py +0 -213
- sierra/plugins/platform/ros1gazebo/generators/platform_generators.py +0 -137
- sierra/plugins/platform/ros1gazebo/plugin.py +0 -335
- sierra/plugins/platform/ros1gazebo/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1gazebo/variables/population_size.py +0 -204
- sierra/plugins/platform/ros1robot/__init__.py +0 -9
- sierra/plugins/platform/ros1robot/cmdline.py +0 -175
- sierra/plugins/platform/ros1robot/generators/platform_generators.py +0 -112
- sierra/plugins/platform/ros1robot/plugin.py +0 -373
- sierra/plugins/platform/ros1robot/variables/__init__.py +0 -10
- sierra/plugins/platform/ros1robot/variables/population_size.py +0 -146
- sierra/plugins/robot/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/__init__.py +0 -9
- sierra/plugins/robot/turtlebot3/plugin.py +0 -194
- sierra_research-1.3.6.data/data/share/man/man1/sierra-cli.1 +0 -2349
- sierra_research-1.3.6.data/data/share/man/man7/sierra-examples.7 +0 -488
- sierra_research-1.3.6.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
- sierra_research-1.3.6.data/data/share/man/man7/sierra-glossary.7 +0 -285
- sierra_research-1.3.6.data/data/share/man/man7/sierra-platforms.7 +0 -358
- sierra_research-1.3.6.data/data/share/man/man7/sierra-usage.7 +0 -725
- sierra_research-1.3.6.data/data/share/man/man7/sierra.7 +0 -78
- sierra_research-1.3.6.dist-info/METADATA +0 -500
- sierra_research-1.3.6.dist-info/RECORD +0 -133
- sierra_research-1.3.6.dist-info/top_level.txt +0 -1
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
- {sierra_research-1.3.6.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
@@ -3,92 +3,137 @@
|
|
3
3
|
# SPDX-License-Identifier: MIT
|
4
4
|
|
5
5
|
"""
|
6
|
-
Functionality for reading, writing,
|
6
|
+
Functionality for reading, writing, etc., experiment definitions.
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
- XML
|
8
|
+
Format-specific bits handled at a lower level via plugin; this is generic
|
9
|
+
functionality for experiment definitions.
|
11
10
|
"""
|
12
11
|
|
13
12
|
# Core packages
|
13
|
+
import pathlib
|
14
14
|
import typing as tp
|
15
15
|
import logging
|
16
|
-
import
|
17
|
-
import sys
|
18
|
-
import pathlib
|
16
|
+
import pickle
|
19
17
|
|
20
18
|
# 3rd party packages
|
19
|
+
import implements
|
21
20
|
|
22
21
|
# Project packages
|
23
|
-
from sierra.core.experiment import xml
|
24
22
|
from sierra.core import types
|
25
23
|
|
26
24
|
|
27
|
-
class
|
28
|
-
"""
|
25
|
+
class WriterConfig:
|
26
|
+
"""Config for writing :class:`~sierra.core.experiment.definition.BaseExpDef`.
|
29
27
|
|
30
|
-
|
31
|
-
change/add/remove.
|
28
|
+
Different parts of the AST can be written to multiple files, as configured.
|
32
29
|
|
33
|
-
|
30
|
+
The order of operations for the applying the config should be:
|
34
31
|
|
35
|
-
|
32
|
+
- Extraction of subtree
|
36
33
|
|
37
|
-
|
38
|
-
"""
|
34
|
+
- Renaming subtree root
|
39
35
|
|
40
|
-
|
41
|
-
input_fpath: pathlib.Path,
|
42
|
-
write_config: tp.Optional[xml.WriterConfig] = None) -> None:
|
36
|
+
- Adding new children
|
43
37
|
|
44
|
-
|
45
|
-
self.input_fpath = input_fpath
|
46
|
-
self.tree = ET.parse(self.input_fpath)
|
47
|
-
self.root = self.tree.getroot()
|
48
|
-
self.tag_adds = xml.TagAddList()
|
49
|
-
self.attr_chgs = xml.AttrChangeSet()
|
38
|
+
- Adding grafts
|
50
39
|
|
51
|
-
|
40
|
+
Attributes: values: Dict with the following possible key, value pairs:
|
52
41
|
|
53
|
-
|
54
|
-
|
55
|
-
|
42
|
+
- ``src_parent`` - The parent of the root of the AST specifying a
|
43
|
+
sub-tree to write out as a child of ``new_children_parent``, or
|
44
|
+
``None`` to write out entire AST. This key is required. If ``None``
|
45
|
+
omitted then then tree rooted at ``src_tag`` is written out.
|
46
|
+
Otherwise, the subtree rooted at ``<src_parent>/<src_tag>`` is written
|
47
|
+
out instead.
|
56
48
|
|
57
|
-
|
58
|
-
|
49
|
+
- ``src_tag`` - Unique query path expression for the child element
|
50
|
+
within ``src_parent`` to write out; that is this tag is the root of
|
51
|
+
the sub-tree within the experiment definition to write out. This key
|
52
|
+
is required.
|
59
53
|
|
60
|
-
|
61
|
-
|
54
|
+
- ``rename_to`` - String to rename the root of the AST written out.
|
55
|
+
This key is optional, and should be processed *after* ``{src_parent,
|
56
|
+
src_tag}``.
|
62
57
|
|
63
|
-
|
64
|
-
|
58
|
+
- ``new_children_parent`` - Unique query path expression for the parent
|
59
|
+
element to create new child elements under via ``new_children``. This
|
60
|
+
key is optional; can be omitted or set to ``None``.
|
61
|
+
|
62
|
+
- ``new_children`` - Ordered List of
|
63
|
+
:class:`~sierra.core.experiment.definition.ElementAdd` objects to use
|
64
|
+
to create new child elements under ``new_children_parent``. Must form
|
65
|
+
a tree with a single root when added in order.
|
66
|
+
|
67
|
+
- ``opath_leaf`` - Additional bits added to whatever the opath file stem
|
68
|
+
that is set for the
|
69
|
+
:class:`~sierra.core.experiment.definition.BaseExpDef` instance. This
|
70
|
+
key is optional. Can be used to add an extension; this is helpful
|
71
|
+
because some engines require input files to have a certain
|
72
|
+
extension, and SIERRA strips out the extension passed to
|
73
|
+
``--expdef-template`` used as the bases for creating experiments.
|
74
|
+
|
75
|
+
- ``child_grafts_parent`` - Unique query path expression for the parent
|
76
|
+
element to for grafting elements under via ``child_grafts``. This
|
77
|
+
path expression is *relative* to ``<src_tag>`` due to ordering. This
|
78
|
+
key is optional; can be omitted or set to ``None``.
|
79
|
+
|
80
|
+
- ``child_grafts`` - Additional bits of the current AST to add under
|
81
|
+
``child_grafts_parent`` in the written out experiment definition,
|
82
|
+
specified as a list of query path strings. This key is optional.
|
83
|
+
"""
|
84
|
+
|
85
|
+
def __init__(self, values: tp.List[dict]) -> None:
|
86
|
+
assert isinstance(values, list), "values must be a list of dicts"
|
87
|
+
|
88
|
+
self.values = values
|
89
|
+
|
90
|
+
def add(self, value: dict) -> None:
|
91
|
+
self.values.append(value)
|
92
|
+
|
93
|
+
|
94
|
+
class BaseExpDef(implements.Interface):
|
95
|
+
"""Base class for experiment definitions."""
|
96
|
+
|
97
|
+
def __init__(
|
98
|
+
self, input_fpath: pathlib.Path, write_config: tp.Optional[WriterConfig] = None
|
99
|
+
) -> None:
|
100
|
+
pass
|
65
101
|
|
66
102
|
def write(self, base_opath: pathlib.Path) -> None:
|
67
|
-
"""Write the
|
103
|
+
"""Write the definition stored in the object to the filesystem."""
|
104
|
+
raise NotImplementedError
|
105
|
+
|
106
|
+
def n_mods(self) -> tp.Tuple[int, int]:
|
107
|
+
"""
|
108
|
+
Get the # (adds, changes) as a tuple.
|
109
|
+
"""
|
110
|
+
raise NotImplementedError
|
68
111
|
|
112
|
+
def flatten(self, keys: tp.List[str]) -> None:
|
69
113
|
"""
|
70
|
-
|
71
|
-
"Can't write without write config"
|
114
|
+
Replace the specified filepath attributes with their contents.
|
72
115
|
|
73
|
-
|
74
|
-
|
116
|
+
Filepaths are interpreted relative to the directory in which the
|
117
|
+
original experiment definition template resides, and assumed to be
|
118
|
+
defined as such.
|
119
|
+
"""
|
120
|
+
raise NotImplementedError
|
75
121
|
|
76
|
-
def attr_get(self, path: str, attr: str):
|
122
|
+
def attr_get(self, path: str, attr: str) -> tp.Union[str, int, float, None]:
|
77
123
|
"""Retrieve the specified attribute of the element at the specified path.
|
78
124
|
|
79
125
|
If it does not exist, None is returned.
|
80
126
|
|
81
127
|
"""
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
noprint: bool = False) -> bool:
|
128
|
+
raise NotImplementedError
|
129
|
+
|
130
|
+
def attr_change(
|
131
|
+
self,
|
132
|
+
path: str,
|
133
|
+
attr: str,
|
134
|
+
value: tp.Union[str, int, float],
|
135
|
+
noprint: bool = False,
|
136
|
+
) -> bool:
|
92
137
|
"""Change the specified attribute of the element at the specified path.
|
93
138
|
|
94
139
|
Only the attribute of the *FIRST* element matching the specified path is
|
@@ -96,43 +141,24 @@ class XMLExpDef:
|
|
96
141
|
|
97
142
|
Arguments:
|
98
143
|
|
99
|
-
path: An
|
100
|
-
attribute to change.
|
144
|
+
path: An expression uniquely identifying the element containing the
|
145
|
+
attribute to change. The element must exist or an error will be
|
101
146
|
raised.
|
102
147
|
|
103
|
-
attr: An
|
104
|
-
|
148
|
+
attr: An expression uniquely identify the attribute to change within
|
149
|
+
the enclosing element.
|
105
150
|
|
106
151
|
value: The value to set the attribute to.
|
107
|
-
|
108
152
|
"""
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
attr,
|
119
|
-
path)
|
120
|
-
return False
|
121
|
-
|
122
|
-
el.attrib[attr] = value
|
123
|
-
self.logger.trace("Modify attr: '%s/%s' = '%s'", # type: ignore
|
124
|
-
path,
|
125
|
-
attr,
|
126
|
-
value)
|
127
|
-
|
128
|
-
self.attr_chgs.add(xml.AttrChange(path, attr, value))
|
129
|
-
return True
|
130
|
-
|
131
|
-
def attr_add(self,
|
132
|
-
path: str,
|
133
|
-
attr: str,
|
134
|
-
value: str,
|
135
|
-
noprint: bool = False) -> bool:
|
153
|
+
raise NotImplementedError
|
154
|
+
|
155
|
+
def attr_add(
|
156
|
+
self,
|
157
|
+
path: str,
|
158
|
+
attr: str,
|
159
|
+
value: tp.Union[str, int, float],
|
160
|
+
noprint: bool = False,
|
161
|
+
) -> bool:
|
136
162
|
"""Add the specified attribute to the element matching the specified path.
|
137
163
|
|
138
164
|
Only the *FIRST* element matching the specified path searching from the
|
@@ -140,216 +166,359 @@ class XMLExpDef:
|
|
140
166
|
|
141
167
|
Arguments:
|
142
168
|
|
143
|
-
path: An
|
169
|
+
path: An expression uniquely identifying the element containing the
|
144
170
|
attribute to add. The element must exist or an error will be
|
145
171
|
raised.
|
146
172
|
|
147
|
-
attr: An
|
173
|
+
attr: An expression uniquely identifying the attribute to change
|
148
174
|
within the enclosing element.
|
149
175
|
|
150
176
|
value: The value to set the attribute to.
|
151
177
|
|
152
178
|
"""
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
if attr in el.attrib:
|
160
|
-
if not noprint:
|
161
|
-
self.logger.warning("Attribute '%s' already in path '%s'",
|
162
|
-
attr,
|
163
|
-
path)
|
164
|
-
return False
|
165
|
-
|
166
|
-
el.set(attr, value)
|
167
|
-
self.logger.trace("Add new attribute: '%s/%s' = '%s'", # type: ignore
|
168
|
-
path,
|
169
|
-
attr,
|
170
|
-
value)
|
171
|
-
self.attr_chgs.add(xml.AttrChange(path, attr, value))
|
172
|
-
return True
|
173
|
-
|
174
|
-
def has_tag(self, path: str) -> bool:
|
175
|
-
return self.root.find(path) is not None
|
179
|
+
raise NotImplementedError
|
180
|
+
|
181
|
+
def has_element(self, path: str) -> bool:
|
182
|
+
"""Determine if the element uniquely identified by ``path`` exists."""
|
183
|
+
raise NotImplementedError
|
176
184
|
|
177
185
|
def has_attr(self, path: str, attr: str) -> bool:
|
178
|
-
|
179
|
-
|
180
|
-
return False
|
181
|
-
return attr in el.attrib
|
186
|
+
"""Determine if the attribute uniquely identified by ``path`` exists."""
|
187
|
+
raise NotImplementedError
|
182
188
|
|
183
|
-
def
|
189
|
+
def element_change(self, path: str, tag: str, value: str) -> bool:
|
184
190
|
"""
|
185
191
|
Change the specified tag of the element matching the specified path.
|
186
192
|
|
187
193
|
Arguments:
|
188
194
|
|
189
|
-
path: An
|
190
|
-
change. The element must exist or an error will be
|
195
|
+
path: An expression uniquely identifying the element containing the
|
196
|
+
tag to change. The element must exist or an error will be
|
197
|
+
raised.
|
191
198
|
|
192
|
-
tag: An
|
193
|
-
element.
|
199
|
+
tag: An expression uniquely identifying the tag to change within the
|
200
|
+
enclosing element.
|
194
201
|
|
195
202
|
value: The value to set the tag to.
|
196
203
|
"""
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
for child in el:
|
203
|
-
if child.tag == tag:
|
204
|
-
child.tag = value
|
205
|
-
self.logger.trace("Modify tag: '%s/%s' = '%s'", # type: ignore
|
206
|
-
path,
|
207
|
-
tag,
|
208
|
-
value)
|
209
|
-
return True
|
210
|
-
|
211
|
-
self.logger.warning("No such element '%s' found in '%s'", tag, path)
|
212
|
-
return False
|
213
|
-
|
214
|
-
def tag_remove(self, path: str, tag: str, noprint: bool = False) -> bool:
|
215
|
-
"""Remove the specified child in the enclosing parent specified by the path.
|
204
|
+
raise NotImplementedError
|
205
|
+
|
206
|
+
def element_remove(self, path: str, tag: str, noprint: bool = False) -> bool:
|
207
|
+
"""Remove the specified child ``tag`` in the enclosing parent.
|
216
208
|
|
217
209
|
If more than one tag matches, only one is removed. If the path does not
|
218
210
|
exist, nothing is done.
|
219
211
|
|
220
212
|
Arguments:
|
221
213
|
|
222
|
-
path: An
|
223
|
-
remove. The element must exist or an error will be
|
214
|
+
path: An expression uniquely identifying the element containing the
|
215
|
+
tag to remove. The element must exist or an error will be
|
216
|
+
raised.
|
224
217
|
|
225
|
-
tag: An
|
226
|
-
element.
|
218
|
+
tag: An expression uniquely identifying the tag to remove within the
|
219
|
+
enclosing element.
|
227
220
|
|
228
221
|
"""
|
222
|
+
raise NotImplementedError
|
229
223
|
|
230
|
-
|
224
|
+
def element_remove_all(self, path: str, tag: str, noprint: bool = False) -> bool:
|
225
|
+
"""Remove the specified child tag(s) in the enclosing parent.
|
231
226
|
|
232
|
-
|
233
|
-
|
234
|
-
self.logger.warning("Parent node '%s' not found", path)
|
235
|
-
return False
|
227
|
+
If more than one tag matches in the parent, all matching child tags are
|
228
|
+
removed.
|
236
229
|
|
237
|
-
|
238
|
-
if victim is None:
|
239
|
-
if not noprint:
|
240
|
-
self.logger.warning("No victim '%s' found in parent '%s'",
|
241
|
-
tag,
|
242
|
-
path)
|
243
|
-
return False
|
230
|
+
Arguments:
|
244
231
|
|
245
|
-
|
246
|
-
|
232
|
+
path: An expression uniquely identifying the element containing the
|
233
|
+
tag(s) to remove. The element must exist or an error will be
|
234
|
+
raised.
|
247
235
|
|
248
|
-
|
249
|
-
|
250
|
-
tag: str,
|
251
|
-
noprint: bool = False) -> bool:
|
252
|
-
"""Remove the specified tag(s) in the enclosing parent specified by the path.
|
236
|
+
tag: An expression uniquely identifying the tag to remove within the
|
237
|
+
enclosing element.
|
253
238
|
|
254
|
-
|
255
|
-
|
239
|
+
"""
|
240
|
+
raise NotImplementedError
|
241
|
+
|
242
|
+
def element_add(
|
243
|
+
self,
|
244
|
+
path: str,
|
245
|
+
tag: str,
|
246
|
+
attr: tp.Optional[types.StrDict] = None,
|
247
|
+
allow_dup: bool = True,
|
248
|
+
noprint: bool = False,
|
249
|
+
) -> bool:
|
250
|
+
"""
|
251
|
+
Add tag name as a child element of enclosing parent.
|
252
|
+
"""
|
253
|
+
raise NotImplementedError
|
254
|
+
|
255
|
+
|
256
|
+
class AttrChange:
|
257
|
+
"""
|
258
|
+
Specification for a change to an existing expdef attribute.
|
259
|
+
"""
|
260
|
+
|
261
|
+
def __init__(self, path: str, attr: str, value: tp.Union[str, int, float]) -> None:
|
262
|
+
self.path = path
|
263
|
+
self.attr = attr
|
264
|
+
self.value = value
|
265
|
+
|
266
|
+
def __iter__(self):
|
267
|
+
yield from [self.path, self.attr, self.value]
|
268
|
+
|
269
|
+
def __repr__(self) -> str:
|
270
|
+
return self.path + "/" + self.attr + ": " + str(self.value)
|
271
|
+
|
272
|
+
|
273
|
+
class NullMod:
|
274
|
+
"""
|
275
|
+
Specification for a null-change (no change) to an existing expdef.
|
276
|
+
"""
|
277
|
+
|
278
|
+
def __init__(self) -> None:
|
279
|
+
pass
|
280
|
+
|
281
|
+
def __iter__(self):
|
282
|
+
yield from []
|
283
|
+
|
284
|
+
|
285
|
+
class ElementRm:
|
286
|
+
"""
|
287
|
+
Specification for removal of an existing expdef tag.
|
288
|
+
"""
|
289
|
+
|
290
|
+
def __init__(self, path: str, tag: str):
|
291
|
+
"""
|
292
|
+
Init the object.
|
256
293
|
|
257
294
|
Arguments:
|
258
295
|
|
259
|
-
|
260
|
-
|
296
|
+
path: The path to the **parent** of the tag you want to remove, in
|
297
|
+
relevant syntax.
|
298
|
+
|
299
|
+
tag: The name of the tag to remove.
|
300
|
+
"""
|
301
|
+
self.path = path
|
302
|
+
self.tag = tag
|
303
|
+
|
304
|
+
def __iter__(self):
|
305
|
+
yield from [self.path, self.tag]
|
306
|
+
|
307
|
+
def __repr__(self) -> str:
|
308
|
+
return self.path + "/" + self.tag
|
309
|
+
|
261
310
|
|
262
|
-
|
263
|
-
|
311
|
+
class ElementAdd:
|
312
|
+
"""
|
313
|
+
Specification for adding a new expdef tag.
|
314
|
+
|
315
|
+
The tag may be added idempotently, or duplicates can be allowed.
|
316
|
+
"""
|
264
317
|
|
318
|
+
@staticmethod
|
319
|
+
def as_root(tag: str, attr: types.StrDict) -> "ElementAdd":
|
320
|
+
return ElementAdd("", tag, attr, False, True)
|
321
|
+
|
322
|
+
def __init__(
|
323
|
+
self,
|
324
|
+
path: str,
|
325
|
+
tag: str,
|
326
|
+
attr: types.StrDict,
|
327
|
+
allow_dup: bool,
|
328
|
+
as_root: bool = False,
|
329
|
+
):
|
265
330
|
"""
|
331
|
+
Init the object.
|
332
|
+
|
333
|
+
Arguments:
|
334
|
+
|
335
|
+
path: The path to the **parent** tag you want to add a new tag
|
336
|
+
under, in appropriate syntax. If None, then the tag will be
|
337
|
+
added as the root tag.
|
266
338
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
self.logger.warning("Parent node '%s' not found", path)
|
272
|
-
return False
|
273
|
-
|
274
|
-
victims = parent.findall(tag)
|
275
|
-
if not victims:
|
276
|
-
if not noprint:
|
277
|
-
self.logger.warning("No victim '%s' found in parent '%s'",
|
278
|
-
tag,
|
279
|
-
path)
|
280
|
-
return False
|
281
|
-
|
282
|
-
for victim in victims:
|
283
|
-
parent.remove(victim)
|
284
|
-
self.logger.trace("Remove matching tag: '%s/%s'", # type: ignore
|
285
|
-
path,
|
286
|
-
tag)
|
287
|
-
|
288
|
-
return True
|
289
|
-
|
290
|
-
def tag_add(self,
|
291
|
-
path: str,
|
292
|
-
tag: str,
|
293
|
-
attr: types.StrDict = {},
|
294
|
-
allow_dup: bool = True,
|
295
|
-
noprint: bool = False) -> bool:
|
339
|
+
tag: The name of the tag to add.
|
340
|
+
|
341
|
+
attr: A dictionary of (attribute, value) pairs to also create as
|
342
|
+
children of the new tag when creating the new tag.
|
296
343
|
"""
|
297
|
-
|
344
|
+
|
345
|
+
self.path = path
|
346
|
+
self.tag = tag
|
347
|
+
self.attr = attr
|
348
|
+
self.allow_dup = allow_dup
|
349
|
+
self.as_root_elt = as_root
|
350
|
+
|
351
|
+
def __iter__(self):
|
352
|
+
yield from [self.path, self.tag, self.attr]
|
353
|
+
|
354
|
+
def __repr__(self) -> str:
|
355
|
+
return self.path + "/" + self.tag + ": " + str(self.attr)
|
356
|
+
|
357
|
+
|
358
|
+
class AttrChangeSet:
|
359
|
+
"""
|
360
|
+
Data structure for :class:`AttrChange` objects.
|
361
|
+
|
362
|
+
The order in which attributes are changed doesn't matter from the standpoint
|
363
|
+
of correctness (i.e., different orders won't cause crashes).
|
364
|
+
|
365
|
+
"""
|
366
|
+
|
367
|
+
@staticmethod
|
368
|
+
def unpickle(fpath: pathlib.Path) -> "AttrChangeSet":
|
369
|
+
"""Unpickle changes.
|
370
|
+
|
371
|
+
You don't know how many there are, so go until you get an exception.
|
372
|
+
|
298
373
|
"""
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
child = ET.Element(tag, attrib=attr)
|
323
|
-
parent.append(child)
|
324
|
-
self.logger.trace("Add new tag: '%s/%s' = '%s'", # type: ignore
|
325
|
-
path,
|
326
|
-
tag,
|
327
|
-
str(attr))
|
328
|
-
|
329
|
-
self.tag_adds.append(xml.TagAdd(path, tag, attr, allow_dup))
|
330
|
-
return True
|
331
|
-
|
332
|
-
|
333
|
-
def unpickle(fpath: pathlib.Path) -> tp.Optional[tp.Union[xml.AttrChangeSet,
|
334
|
-
xml.TagAddList]]:
|
335
|
-
"""Unickle all XML modifications from the pickle file at the path.
|
336
|
-
|
337
|
-
You don't know how many there are, so go until you get an exception.
|
374
|
+
exp_def = AttrChangeSet()
|
375
|
+
|
376
|
+
try:
|
377
|
+
with open(fpath, "rb") as f:
|
378
|
+
while True:
|
379
|
+
exp_def |= AttrChangeSet(*pickle.load(f))
|
380
|
+
except EOFError:
|
381
|
+
pass
|
382
|
+
return exp_def
|
383
|
+
|
384
|
+
def __init__(self, *args: tp.Union[AttrChange, NullMod]) -> None:
|
385
|
+
self.changes = set(args)
|
386
|
+
self.logger = logging.getLogger(__name__)
|
387
|
+
|
388
|
+
def __len__(self) -> int:
|
389
|
+
return len(self.changes)
|
390
|
+
|
391
|
+
def __iter__(self) -> tp.Iterator[tp.Union[AttrChange, NullMod]]:
|
392
|
+
return iter(self.changes)
|
393
|
+
|
394
|
+
def __ior__(self, other: "AttrChangeSet") -> "AttrChangeSet":
|
395
|
+
self.changes |= other.changes
|
396
|
+
return self
|
338
397
|
|
398
|
+
def __or__(self, other: "AttrChangeSet") -> "AttrChangeSet":
|
399
|
+
new = AttrChangeSet(*self.changes)
|
400
|
+
new |= other
|
401
|
+
return new
|
402
|
+
|
403
|
+
def __repr__(self) -> str:
|
404
|
+
return str(self.changes)
|
405
|
+
|
406
|
+
def add(self, chg: AttrChange) -> None:
|
407
|
+
self.changes.add(chg)
|
408
|
+
|
409
|
+
def pickle(self, fpath: pathlib.Path, delete: bool = False) -> None:
|
410
|
+
from sierra.core import utils
|
411
|
+
|
412
|
+
if delete and utils.path_exists(fpath):
|
413
|
+
fpath.unlink()
|
414
|
+
|
415
|
+
with open(fpath, "ab") as f:
|
416
|
+
utils.pickle_dump(self.changes, f)
|
417
|
+
|
418
|
+
|
419
|
+
class ElementRmList:
|
339
420
|
"""
|
340
|
-
|
341
|
-
return xml.AttrChangeSet.unpickle(fpath)
|
342
|
-
except EOFError:
|
343
|
-
pass
|
421
|
+
Data structure for :class:`ElementRm` objects.
|
344
422
|
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
423
|
+
The order in which tags are removed matters (i.e., if you remove dependent
|
424
|
+
tags in the wrong order you will get an exception), hence the list
|
425
|
+
representation.
|
426
|
+
|
427
|
+
"""
|
428
|
+
|
429
|
+
def __init__(self, *args: ElementRm) -> None:
|
430
|
+
self.rms = list(args)
|
431
|
+
|
432
|
+
def __len__(self) -> int:
|
433
|
+
return len(self.rms)
|
434
|
+
|
435
|
+
def __iter__(self) -> tp.Iterator[ElementRm]:
|
436
|
+
return iter(self.rms)
|
437
|
+
|
438
|
+
def __repr__(self) -> str:
|
439
|
+
return str(self.rms)
|
440
|
+
|
441
|
+
def extend(self, other: "ElementRmList") -> None:
|
442
|
+
self.rms.extend(other.rms)
|
443
|
+
|
444
|
+
def append(self, other: ElementRm) -> None:
|
445
|
+
self.rms.append(other)
|
446
|
+
|
447
|
+
def pickle(self, fpath: pathlib.Path, delete: bool = False) -> None:
|
448
|
+
from sierra.core import utils
|
449
|
+
|
450
|
+
if delete and utils.path_exists(fpath):
|
451
|
+
fpath.unlink()
|
452
|
+
|
453
|
+
with open(fpath, "ab") as f:
|
454
|
+
utils.pickle_dump(self.rms, f)
|
455
|
+
|
456
|
+
|
457
|
+
class ElementAddList:
|
458
|
+
"""
|
459
|
+
Data structure for :class:`ElementAdd` objects.
|
460
|
+
|
461
|
+
The order in which tags are added matters (i.e., if you add dependent tags
|
462
|
+
in the wrong order you will get an exception), hence the list
|
463
|
+
representation.
|
464
|
+
"""
|
465
|
+
|
466
|
+
@staticmethod
|
467
|
+
def unpickle(fpath: pathlib.Path) -> tp.Optional["ElementAddList"]:
|
468
|
+
"""Unpickle modifications.
|
469
|
+
|
470
|
+
You don't know how many there are, so go until you get an exception.
|
471
|
+
|
472
|
+
"""
|
473
|
+
exp_def = ElementAddList()
|
474
|
+
|
475
|
+
try:
|
476
|
+
with open(fpath, "rb") as f:
|
477
|
+
while True:
|
478
|
+
exp_def.append(*pickle.load(f))
|
479
|
+
except EOFError:
|
480
|
+
pass
|
481
|
+
return exp_def
|
482
|
+
|
483
|
+
def __init__(self, *args: ElementAdd) -> None:
|
484
|
+
self.adds = list(args)
|
485
|
+
|
486
|
+
def __len__(self) -> int:
|
487
|
+
return len(self.adds)
|
488
|
+
|
489
|
+
def __iter__(self) -> tp.Iterator[ElementAdd]:
|
490
|
+
return iter(self.adds)
|
491
|
+
|
492
|
+
def __repr__(self) -> str:
|
493
|
+
return str(self.adds)
|
494
|
+
|
495
|
+
def extend(self, other: "ElementAddList") -> None:
|
496
|
+
self.adds.extend(other.adds)
|
497
|
+
|
498
|
+
def append(self, other: ElementAdd) -> None:
|
499
|
+
self.adds.append(other)
|
500
|
+
|
501
|
+
def prepend(self, other: ElementAdd) -> None:
|
502
|
+
self.adds.insert(0, other)
|
503
|
+
|
504
|
+
def pickle(self, fpath: pathlib.Path, delete: bool = False) -> None:
|
505
|
+
from sierra.core import utils
|
506
|
+
|
507
|
+
if delete and utils.path_exists(fpath):
|
508
|
+
fpath.unlink()
|
349
509
|
|
350
|
-
|
510
|
+
with open(fpath, "ab") as f:
|
511
|
+
utils.pickle_dump(self.adds, f)
|
351
512
|
|
352
513
|
|
353
|
-
|
354
|
-
|
514
|
+
__all__ = [
|
515
|
+
"BaseExpDef",
|
516
|
+
"WriterConfig",
|
517
|
+
"AttrChange",
|
518
|
+
"NullMod",
|
519
|
+
"AttrChangeSet",
|
520
|
+
"ElementAdd",
|
521
|
+
"ElementAddList",
|
522
|
+
"ElementRm",
|
523
|
+
"ElementRmList",
|
355
524
|
]
|