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
sierra/core/plugin.py
CHANGED
@@ -1,112 +1,579 @@
|
|
1
1
|
# Copyright 2021 John Harwell, All rights reserved.
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: MIT
|
4
|
-
"""
|
5
|
-
|
6
|
-
Checks that selected plugins implement the necessary classes and
|
7
|
-
functions. Currently checkes: ``--storage-medium``, ``--exec-env``, and
|
8
|
-
``--platform``.
|
4
|
+
"""SIERRA plugin management to make SIERRA OPEN/CLOSED.
|
9
5
|
|
6
|
+
Also contains checks that selected plugins implement the necessary classes and
|
7
|
+
functions. Currently checkes: ``--storage``, ``--execenv``, and ``--engine``.
|
10
8
|
"""
|
11
9
|
|
12
10
|
# Core packages
|
13
|
-
|
11
|
+
# Core packages
|
12
|
+
import importlib.util
|
13
|
+
import importlib
|
14
|
+
import typing as tp
|
15
|
+
import sys
|
14
16
|
import logging
|
17
|
+
import pathlib
|
18
|
+
import inspect
|
15
19
|
|
16
20
|
# 3rd party packages
|
17
21
|
|
22
|
+
# 3rd party packages
|
23
|
+
import json
|
24
|
+
|
18
25
|
# Project packages
|
26
|
+
from sierra.core import types
|
27
|
+
|
28
|
+
|
29
|
+
class BasePluginManager:
|
30
|
+
"""Base class for common functionality."""
|
31
|
+
|
32
|
+
def __init__(self) -> None:
|
33
|
+
self.logger = logging.getLogger(__name__)
|
34
|
+
self.loaded = {} # type: tp.Dict[str, tp.Dict]
|
35
|
+
|
36
|
+
def available_plugins(self):
|
37
|
+
raise NotImplementedError
|
38
|
+
|
39
|
+
def loaded_plugins(self):
|
40
|
+
return self.loaded
|
41
|
+
|
42
|
+
def load_plugin(self, name: str) -> None:
|
43
|
+
"""Load a plugin module."""
|
44
|
+
plugins = self.available_plugins()
|
45
|
+
if name not in plugins:
|
46
|
+
self.logger.fatal("Cannot locate plugin %s", name)
|
47
|
+
self.logger.fatal(
|
48
|
+
"Loaded plugins: %s\n",
|
49
|
+
json.dumps(self.loaded, default=lambda x: "<ModuleSpec>", indent=4),
|
50
|
+
)
|
51
|
+
raise Exception(f"Cannot locate plugin '{name}'")
|
52
|
+
|
53
|
+
init = importlib.util.module_from_spec(plugins[name]["init_spec"])
|
54
|
+
plugins[name]["init_spec"].loader.exec_module(init)
|
55
|
+
|
56
|
+
if not hasattr(init, "sierra_plugin_type"):
|
57
|
+
self.logger.warning(
|
58
|
+
"Cannot load plugin %s: __init__.py does not define sierra_plugin_type()",
|
59
|
+
name,
|
60
|
+
)
|
61
|
+
return
|
62
|
+
|
63
|
+
plugin_type = init.sierra_plugin_type()
|
64
|
+
|
65
|
+
# The name of the module is only needed for pipeline plugins, not
|
66
|
+
# project plugins.
|
67
|
+
if plugins[name]["module_spec"] is None and plugin_type == "pipeline":
|
68
|
+
if not hasattr(init, "sierra_plugin_module"):
|
69
|
+
self.logger.warning(
|
70
|
+
"Cannot load plugin %s: __init__.py does not define sierra_plugin_module()",
|
71
|
+
name,
|
72
|
+
)
|
73
|
+
return
|
74
|
+
|
75
|
+
modname = init.sierra_plugin_module()
|
76
|
+
fpath = (
|
77
|
+
plugins[name]["parent_dir"] / name.replace(".", "/") / f"{modname}.py"
|
78
|
+
)
|
79
|
+
plugins[name]["module_spec"] = importlib.util.spec_from_file_location(
|
80
|
+
modname, fpath
|
81
|
+
)
|
82
|
+
|
83
|
+
if plugin_type == "pipeline":
|
84
|
+
self._load_pipeline_plugin(name)
|
85
|
+
|
86
|
+
elif plugin_type == "project":
|
87
|
+
self._load_project_plugin(name)
|
88
|
+
elif plugin_type == "model":
|
89
|
+
if not hasattr(init, "sierra_models"):
|
90
|
+
self.logger.warning(
|
91
|
+
"Cannot load plugin %s: __init__.py does not define sierra_models()",
|
92
|
+
name,
|
93
|
+
)
|
94
|
+
return
|
95
|
+
|
96
|
+
self._load_model_plugin(name)
|
97
|
+
else:
|
98
|
+
self.logger.warning(
|
99
|
+
"Unknown plugin type '%s' for %s: cannot load", plugin_type, name
|
100
|
+
)
|
101
|
+
|
102
|
+
def get_plugin(self, name: str) -> dict:
|
103
|
+
try:
|
104
|
+
return self.loaded[name]
|
105
|
+
except KeyError:
|
106
|
+
self.logger.fatal("No such plugin %s", name)
|
107
|
+
self.logger.fatal(
|
108
|
+
"Loaded plugins: %s\n",
|
109
|
+
json.dumps(self.loaded, default=lambda x: "<ModuleSpec>", indent=4),
|
110
|
+
)
|
111
|
+
raise
|
112
|
+
|
113
|
+
def get_plugin_module(self, name: str) -> types.ModuleType:
|
114
|
+
try:
|
115
|
+
return self.loaded[name]["module"]
|
116
|
+
except KeyError:
|
117
|
+
self.logger.fatal("No such plugin %s", name)
|
118
|
+
self.logger.fatal(
|
119
|
+
"Loaded plugins: %s\n",
|
120
|
+
json.dumps(self.loaded, default=lambda x: "<ModuleSpec>", indent=4),
|
121
|
+
)
|
122
|
+
raise
|
123
|
+
|
124
|
+
def has_plugin(self, name: str) -> bool:
|
125
|
+
return name in self.loaded
|
126
|
+
|
127
|
+
def _load_pipeline_plugin(self, name: str) -> None:
|
128
|
+
if name in self.loaded:
|
129
|
+
self.logger.warning("Pipeline plugin %s already loaded", name)
|
130
|
+
return
|
131
|
+
|
132
|
+
plugins = self.available_plugins()
|
133
|
+
|
134
|
+
# The parent directory of the plugin must be on sys.path so it can be
|
135
|
+
# imported, so we put in on there if it isn't.
|
136
|
+
new = str(plugins[name]["parent_dir"])
|
137
|
+
if new not in sys.path:
|
138
|
+
sys.path = [new] + sys.path[0:]
|
139
|
+
self.logger.debug("Updated sys.path with %s", [new])
|
140
|
+
|
141
|
+
module = importlib.util.module_from_spec(plugins[name]["module_spec"])
|
142
|
+
plugins[name]["module_spec"].loader.exec_module(module)
|
143
|
+
|
144
|
+
# When importing with importlib, the module is not automatically added
|
145
|
+
# to sys.modules. This means that trying to pickle anything in it will
|
146
|
+
# fail with a rather cryptic 'AttributeError', so we explicitly add the
|
147
|
+
# last path component of the plugin name--which is the actual name of
|
148
|
+
# the module the plugin lives in--to sys.modules so that pickling will
|
149
|
+
# work.
|
150
|
+
sys_modname = name.split(".")[1]
|
151
|
+
if sys_modname not in sys.modules:
|
152
|
+
sys.modules[sys_modname] = module
|
153
|
+
|
154
|
+
self.loaded[name] = {
|
155
|
+
"spec": plugins[name]["module_spec"],
|
156
|
+
"parent_dir": plugins[name]["parent_dir"],
|
157
|
+
"module": module,
|
158
|
+
"type": "pipeline",
|
159
|
+
}
|
160
|
+
self.logger.debug(
|
161
|
+
"Loaded pipeline plugin %s from %s -> %s",
|
162
|
+
name,
|
163
|
+
plugins[name]["parent_dir"],
|
164
|
+
name,
|
165
|
+
)
|
166
|
+
|
167
|
+
def _load_project_plugin(self, name: str) -> None:
|
168
|
+
if name in self.loaded:
|
169
|
+
self.logger.warning("Project plugin %s already loaded", name)
|
170
|
+
return
|
19
171
|
|
172
|
+
plugins = self.available_plugins()
|
20
173
|
|
21
|
-
|
174
|
+
# The parent directory of the plugin must be on sys.path so it can be
|
175
|
+
# imported, so we put in on there if it isn't.
|
176
|
+
new = str(plugins[name]["parent_dir"])
|
177
|
+
if new not in sys.path:
|
178
|
+
sys.path = [new] + sys.path[0:]
|
179
|
+
self.logger.debug("Updated sys.path with %s", [new])
|
180
|
+
|
181
|
+
self.loaded[name] = {
|
182
|
+
"spec": plugins[name]["module_spec"],
|
183
|
+
"parent_dir": plugins[name]["parent_dir"],
|
184
|
+
"type": "project",
|
185
|
+
}
|
186
|
+
|
187
|
+
self.logger.debug(
|
188
|
+
("Loaded project plugin %s from %s -> %s"),
|
189
|
+
name,
|
190
|
+
plugins[name]["parent_dir"],
|
191
|
+
name,
|
192
|
+
)
|
193
|
+
|
194
|
+
def _load_model_plugin(self, name: str) -> None:
|
195
|
+
if name in self.loaded:
|
196
|
+
self.logger.warning("Model plugin %s already loaded", name)
|
197
|
+
return
|
198
|
+
|
199
|
+
plugins = self.available_plugins()
|
200
|
+
|
201
|
+
# The parent directory of the plugin must be on sys.path so it can be
|
202
|
+
# imported, so we put in on there if it isn't.
|
203
|
+
new = str(plugins[name]["parent_dir"])
|
204
|
+
if new not in sys.path:
|
205
|
+
sys.path = [new] + sys.path[0:]
|
206
|
+
self.logger.debug("Updated sys.path with %s", [new])
|
207
|
+
|
208
|
+
self.loaded[name] = {
|
209
|
+
"spec": plugins[name]["module_spec"],
|
210
|
+
"parent_dir": plugins[name]["parent_dir"],
|
211
|
+
"type": "model",
|
212
|
+
}
|
213
|
+
|
214
|
+
self.logger.debug(
|
215
|
+
("Loaded model plugin %s from %s -> %s"),
|
216
|
+
name,
|
217
|
+
plugins[name]["parent_dir"],
|
218
|
+
name,
|
219
|
+
)
|
220
|
+
|
221
|
+
|
222
|
+
class DirectoryPluginManager(BasePluginManager):
|
223
|
+
"""Container for managing directory-based plugins."""
|
224
|
+
|
225
|
+
def __init__(self) -> None:
|
226
|
+
super().__init__()
|
227
|
+
self.plugins = {} # type: tp.Dict[str, tp.Dict]
|
228
|
+
|
229
|
+
def initialize(self, project: str, search_path: tp.List[pathlib.Path]) -> None:
|
230
|
+
self.logger.debug(
|
231
|
+
"Initializing with plugin search path %s", [str(p) for p in search_path]
|
232
|
+
)
|
233
|
+
|
234
|
+
for path in search_path:
|
235
|
+
if not path.exists():
|
236
|
+
self.logger.warning(
|
237
|
+
"Non-existent path '%s' on SIERRA_PLUGIN_PATH", path
|
238
|
+
)
|
239
|
+
continue
|
240
|
+
|
241
|
+
self.logger.debug("Searching for plugins in '%s'", path)
|
242
|
+
|
243
|
+
def recursive_search(root: pathlib.Path) -> None:
|
244
|
+
try:
|
245
|
+
for f in root.iterdir():
|
246
|
+
if not f.is_dir():
|
247
|
+
continue
|
248
|
+
recursive_search(f)
|
249
|
+
|
250
|
+
plugin = f / "plugin.py"
|
251
|
+
init = f / "__init__.py"
|
252
|
+
cookie = f / ".sierraplugin"
|
253
|
+
|
254
|
+
if not (init.exists() and (plugin.exists() or cookie.exists())):
|
255
|
+
continue
|
256
|
+
|
257
|
+
name = f"{f.parent.name}.{f.name}"
|
258
|
+
|
259
|
+
if plugin.exists():
|
260
|
+
module_spec = importlib.util.spec_from_file_location(
|
261
|
+
f.name, plugin
|
262
|
+
)
|
263
|
+
else:
|
264
|
+
module_spec = None
|
265
|
+
|
266
|
+
init_spec = importlib.util.spec_from_file_location(
|
267
|
+
"__init__", init
|
268
|
+
)
|
269
|
+
|
270
|
+
self.logger.debug("Found plugin in '%s' -> %s", f, name)
|
271
|
+
|
272
|
+
self.plugins[name] = {
|
273
|
+
"parent_dir": root.parent,
|
274
|
+
"module_spec": module_spec,
|
275
|
+
"init_spec": init_spec,
|
276
|
+
}
|
277
|
+
except FileNotFoundError:
|
278
|
+
self.logger.warning(
|
279
|
+
"Malformed plugin in %s: not loading", f.relative_to(path)
|
280
|
+
)
|
281
|
+
|
282
|
+
recursive_search(path)
|
283
|
+
|
284
|
+
def available_plugins(self):
|
285
|
+
return self.plugins
|
286
|
+
|
287
|
+
|
288
|
+
def module_exists(name: str) -> bool:
|
22
289
|
"""
|
23
|
-
Check
|
290
|
+
Check if a module exists before trying to import it.
|
24
291
|
"""
|
25
|
-
|
292
|
+
try:
|
293
|
+
_ = __import__(name)
|
294
|
+
except ImportError:
|
295
|
+
return False
|
296
|
+
else:
|
297
|
+
return True
|
298
|
+
|
299
|
+
|
300
|
+
def module_load(name: str) -> types.ModuleType:
|
301
|
+
"""
|
302
|
+
Import the specified module.
|
303
|
+
"""
|
304
|
+
return __import__(name, fromlist=["*"])
|
305
|
+
|
26
306
|
|
27
|
-
|
28
|
-
|
307
|
+
def bc_load(cmdopts: types.Cmdopts, category: str):
|
308
|
+
"""
|
309
|
+
Load the specified :term:`Batch Criteria`.
|
310
|
+
"""
|
311
|
+
path = f"variables.{category}"
|
312
|
+
return module_load_tiered(
|
313
|
+
project=cmdopts["project"], engine=cmdopts["engine"], path=path
|
314
|
+
)
|
315
|
+
|
316
|
+
|
317
|
+
def module_load_tiered(
|
318
|
+
path: str, project: tp.Optional[str] = None, engine: tp.Optional[str] = None
|
319
|
+
) -> types.ModuleType:
|
320
|
+
"""Attempt to load the specified python module with tiered precedence.
|
321
|
+
|
322
|
+
Generally, the precedence is project -> project submodule -> engine module
|
323
|
+
-> SIERRA core module, to allow users to override SIERRA core functionality
|
324
|
+
with ease. Specifically:
|
325
|
+
|
326
|
+
#. Check if the requested module directly exists. If it does, return
|
327
|
+
it.
|
328
|
+
|
329
|
+
#. Check if the requested module is a part of a project (i.e.,
|
330
|
+
``<project>.<path>`` exists). If it does, return it. This requires
|
331
|
+
that :envvar:`SIERRA_PLUGIN_PATH` to be set properly.
|
332
|
+
|
333
|
+
#. Check if the requested module is provided by the engine plugin (i.e.,
|
334
|
+
``sierra.engine.<engine>.<path>`` exists). If it does, return it.
|
335
|
+
|
336
|
+
#. Check if the requested module is part of the SIERRA core (i.e.,
|
337
|
+
``sierra.core.<path>`` exists). If it does, return it.
|
338
|
+
|
339
|
+
If no match was found using any of these, throw an error.
|
340
|
+
"""
|
341
|
+
# First, see if the requested module is a project/directly exists as
|
342
|
+
# specified.
|
343
|
+
if module_exists(path):
|
344
|
+
logging.trace("Using direct path %s", path) # type: ignore
|
345
|
+
return module_load(path)
|
346
|
+
|
347
|
+
# Next, check if the requested module is part of the project plugin
|
348
|
+
if project is not None:
|
349
|
+
component_path = f"{project}.{path}"
|
350
|
+
if module_exists(component_path):
|
351
|
+
logging.trace(
|
352
|
+
"Using project component path %s", component_path # type: ignore
|
353
|
+
)
|
354
|
+
return module_load(component_path)
|
355
|
+
else:
|
356
|
+
logging.trace(
|
357
|
+
"Project component path %s does not exist", # type: ignore
|
358
|
+
component_path,
|
359
|
+
)
|
360
|
+
|
361
|
+
# If that didn't work, check the engine plugin
|
362
|
+
if engine is not None:
|
363
|
+
engine_path = f"{engine}.{path}"
|
364
|
+
if module_exists(engine_path):
|
365
|
+
logging.trace("Using engine component path %s", engine_path) # type: ignore
|
366
|
+
return module_load(engine_path)
|
367
|
+
|
368
|
+
# If that didn't work, then check the SIERRA core
|
369
|
+
core_path = f"sierra.core.{path}"
|
370
|
+
if module_exists(core_path):
|
371
|
+
logging.trace("Using SIERRA core path %s", core_path) # type: ignore
|
372
|
+
return module_load(core_path)
|
373
|
+
else:
|
374
|
+
logging.trace("SIERRA core path %s does not exist", core_path) # type: ignore
|
375
|
+
|
376
|
+
# Module does not exist
|
377
|
+
error = (
|
378
|
+
f"project: '{project}' "
|
379
|
+
f"engine: '{engine}' "
|
380
|
+
f"path: '{path}' "
|
381
|
+
f"sys.path: {sys.path}"
|
382
|
+
)
|
383
|
+
raise ImportError(error)
|
384
|
+
|
385
|
+
|
386
|
+
def storage_sanity_checks(medium: str, module) -> None:
|
387
|
+
"""
|
388
|
+
Check the selected ``--storage`` plugin.
|
389
|
+
"""
|
390
|
+
logging.trace("Verifying --storage=%s plugin interface", medium) # type: ignore
|
391
|
+
|
392
|
+
functions = ["df_read", "df_write", "suffixes"]
|
29
393
|
in_module = inspect.getmembers(module, inspect.isfunction)
|
30
394
|
|
31
395
|
for f in functions:
|
32
|
-
assert
|
33
|
-
f
|
396
|
+
assert any(
|
397
|
+
f == name for (name, _) in in_module
|
398
|
+
), f"Storage medium {medium} does not define {f}()"
|
34
399
|
|
35
400
|
|
36
|
-
def
|
401
|
+
def expdef_sanity_checks(expdef: str, module) -> None:
|
37
402
|
"""
|
38
|
-
Check the selected ``--
|
403
|
+
Check the selected ``--expdef`` plugin.
|
39
404
|
"""
|
40
|
-
logging.trace("Verifying --
|
405
|
+
logging.trace("Verifying --expdef=%s plugin interface", expdef) # type: ignore
|
406
|
+
|
407
|
+
functions = ["root_querypath", "unpickle"]
|
408
|
+
module_funcs = inspect.getmembers(module, inspect.isfunction)
|
409
|
+
module_classes = inspect.getmembers(module, inspect.isclass)
|
410
|
+
classes = ["ExpDef", "Writer"]
|
411
|
+
|
412
|
+
for c in classes:
|
413
|
+
assert any(
|
414
|
+
c == name for (name, _) in module_classes
|
415
|
+
), f"Expdef plugin {expdef} does not define {c}"
|
416
|
+
|
417
|
+
for f in functions:
|
418
|
+
assert any(
|
419
|
+
f == name for (name, _) in module_funcs
|
420
|
+
), f"Expdef {expdef} does not define {f}()"
|
421
|
+
|
422
|
+
|
423
|
+
def proc_sanity_checks(proc: str, module) -> None:
|
424
|
+
"""
|
425
|
+
Check the selected ``--proc`` plugins.
|
426
|
+
"""
|
427
|
+
logging.trace("Verifying --proc=%s plugin interface", proc) # type: ignore
|
428
|
+
|
429
|
+
functions = ["proc_batch_exp"]
|
430
|
+
in_module = inspect.getmembers(module, inspect.isfunction)
|
431
|
+
|
432
|
+
for f in functions:
|
433
|
+
assert any(
|
434
|
+
f == name for (name, _) in in_module
|
435
|
+
), f"Processing plugin {proc} does not define {f}()"
|
436
|
+
|
437
|
+
|
438
|
+
def prod_sanity_checks(prod: str, module) -> None:
|
439
|
+
"""
|
440
|
+
Check the selected ``--prod`` plugins.
|
441
|
+
"""
|
442
|
+
logging.trace("Verifying --prod=%s plugin interface", prod) # type: ignore
|
443
|
+
|
444
|
+
functions = ["proc_batch_exp"]
|
445
|
+
in_module = inspect.getmembers(module, inspect.isfunction)
|
446
|
+
|
447
|
+
for f in functions:
|
448
|
+
assert any(
|
449
|
+
f == name for (name, _) in in_module
|
450
|
+
), f"Product plugin {prod} does not define {f}()"
|
451
|
+
|
452
|
+
|
453
|
+
def compare_sanity_checks(compare: str, module) -> None:
|
454
|
+
"""
|
455
|
+
Check the selected ``--compare`` plugins.
|
456
|
+
"""
|
457
|
+
logging.trace("Verifying --compare=%s plugin interface", compare) # type: ignore
|
458
|
+
|
459
|
+
functions = ["proc_exps"]
|
460
|
+
in_module = inspect.getmembers(module, inspect.isfunction)
|
461
|
+
|
462
|
+
for f in functions:
|
463
|
+
assert any(
|
464
|
+
f == name for (name, _) in in_module
|
465
|
+
), f"Comparison plugin {compare} does not define {f}()"
|
466
|
+
|
467
|
+
|
468
|
+
def execenv_sanity_checks(execenv: str, module) -> None:
|
469
|
+
"""
|
470
|
+
Check the selected ``--execenv`` plugin.
|
471
|
+
"""
|
472
|
+
logging.trace("Verifying --execenv=%s plugin interface", execenv) # type: ignore
|
41
473
|
|
42
474
|
in_module = inspect.getmembers(module, inspect.isclass)
|
43
475
|
|
44
|
-
|
45
|
-
|
46
|
-
'ExpShellCmdsGenerator',
|
47
|
-
'ExecEnvChecker']
|
476
|
+
opt_functions = ["cmdline_postparse_configure", "execenv_check"]
|
477
|
+
opt_classes = ["ExpRunShellCmdsGenerator", "ExpShellCmdsGenerator"]
|
48
478
|
|
49
479
|
for c in opt_classes:
|
50
|
-
if not any(c
|
51
|
-
logging.debug(
|
52
|
-
|
53
|
-
|
54
|
-
|
480
|
+
if not any(c == name for (name, _) in in_module):
|
481
|
+
logging.debug(
|
482
|
+
(
|
483
|
+
"Execution environment plugin %s does not define "
|
484
|
+
"%s--some SIERRA functionality may not be "
|
485
|
+
"available. See docs for details."
|
486
|
+
),
|
487
|
+
execenv,
|
488
|
+
c,
|
489
|
+
)
|
55
490
|
|
491
|
+
for f in opt_functions:
|
492
|
+
if not any(f in name for (name, _) in in_module):
|
493
|
+
logging.debug(
|
494
|
+
("Execution environment plugin %s does not define %s()."),
|
495
|
+
execenv,
|
496
|
+
f,
|
497
|
+
)
|
56
498
|
|
57
|
-
|
499
|
+
|
500
|
+
def engine_sanity_checks(engine: str, module) -> None:
|
58
501
|
"""
|
59
|
-
Check the selected ``--
|
502
|
+
Check the selected ``--engine`` plugin.
|
60
503
|
"""
|
61
|
-
logging.trace("Verifying --
|
504
|
+
logging.trace("Verifying --engine=%s plugin interface", engine) # type: ignore
|
62
505
|
|
63
|
-
req_classes = [
|
64
|
-
|
65
|
-
|
506
|
+
req_classes = [
|
507
|
+
"ExpConfigurer",
|
508
|
+
]
|
66
509
|
|
67
|
-
req_functions = [
|
68
|
-
|
69
|
-
|
510
|
+
req_functions = [
|
511
|
+
"population_size_from_def",
|
512
|
+
"population_size_from_pickle",
|
513
|
+
]
|
70
514
|
|
71
|
-
opt_classes = [
|
72
|
-
'ExpRunShellCmdsGenerator',
|
73
|
-
'ExpShellCmdsGenerator',
|
74
|
-
'ExecEnvChecker']
|
515
|
+
opt_classes = ["ExpRunShellCmdsGenerator", "ExpShellCmdsGenerator"]
|
75
516
|
|
76
|
-
opt_functions = [
|
77
|
-
|
517
|
+
opt_functions = [
|
518
|
+
"cmdline_postparse_configure",
|
519
|
+
"execenv_check",
|
520
|
+
"agent_prefix_extract",
|
521
|
+
"arena_dims_from_criteria",
|
522
|
+
]
|
78
523
|
|
79
524
|
in_module = inspect.getmembers(module, inspect.isclass)
|
80
525
|
|
81
526
|
for c in req_classes:
|
82
|
-
assert
|
83
|
-
|
527
|
+
assert any(
|
528
|
+
c == name for (name, _) in in_module
|
529
|
+
), f"Engine plugin {engine} does not define {c}"
|
84
530
|
|
85
531
|
for f in opt_classes:
|
86
532
|
if not any(f in name for (name, _) in in_module):
|
87
|
-
logging.debug(
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
533
|
+
logging.debug(
|
534
|
+
(
|
535
|
+
"Engine plugin %s does not define %s"
|
536
|
+
"--some SIERRA functionality may not be available. "
|
537
|
+
"See docs for details."
|
538
|
+
),
|
539
|
+
engine,
|
540
|
+
f,
|
541
|
+
)
|
92
542
|
|
93
543
|
in_module = inspect.getmembers(module, inspect.isfunction)
|
94
544
|
|
95
545
|
for f in req_functions:
|
96
|
-
assert
|
97
|
-
f
|
546
|
+
assert any(
|
547
|
+
f == name for (name, _) in in_module
|
548
|
+
), f"Engine plugin {engine} does not define {f}()"
|
98
549
|
|
99
550
|
for f in opt_functions:
|
100
|
-
if not any(f
|
101
|
-
logging.debug(
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
551
|
+
if not any(f == name for (name, _) in in_module):
|
552
|
+
logging.debug(
|
553
|
+
(
|
554
|
+
"Engine plugin %s does not define %s()"
|
555
|
+
"--some SIERRA functionality may not be available. "
|
556
|
+
"See docs for details."
|
557
|
+
),
|
558
|
+
engine,
|
559
|
+
f,
|
560
|
+
)
|
561
|
+
|
562
|
+
|
563
|
+
# Singletons
|
564
|
+
pipeline = DirectoryPluginManager()
|
565
|
+
models = DirectoryPluginManager()
|
566
|
+
|
567
|
+
__all__ = [
|
568
|
+
"DirectoryPluginManager",
|
569
|
+
"module_exists",
|
570
|
+
"module_load",
|
571
|
+
"bc_load",
|
572
|
+
"module_load_tiered",
|
573
|
+
"storage_sanity_checks",
|
574
|
+
"execenv_sanity_checks",
|
575
|
+
"engine_sanity_checks",
|
576
|
+
"proc_sanity_checks",
|
577
|
+
"prod_sanity_checks",
|
578
|
+
"compare_sanity_checks",
|
579
|
+
]
|
sierra/core/proc.py
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""Trampoline bindings for the various ``--proc`` plugins that come with SIERRA."""
|
5
|
+
|
6
|
+
# Core packages
|
7
|
+
|
8
|
+
# 3rd party packages
|
9
|
+
|
10
|
+
# Project packages
|
11
|
+
from sierra.core.trampoline import cmdline_parser # noqa: F401
|
sierra/core/prod.py
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# Copyright 2021 John Harwell, All rights reserved.
|
2
|
+
#
|
3
|
+
# SPDX-License-Identifier: MIT
|
4
|
+
"""Trampoline bindings for the various ``--prod`` plugins that come with SIERRA."""
|
5
|
+
|
6
|
+
# Core packages
|
7
|
+
|
8
|
+
# 3rd party packages
|
9
|
+
|
10
|
+
# Project packages
|
11
|
+
from sierra.core.trampoline import cmdline_parser # noqa: F401
|
sierra/core/ros1/__init__.py
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
# Copyright 2021 John Harwell, All rights reserved.
|
2
2
|
#
|
3
3
|
# SPDX-License-Identifier: MIT
|
4
|
+
"""Container module for things related to :term:`ROS1`."""
|
4
5
|
|
5
6
|
# Core packages
|
6
7
|
|
7
8
|
# 3rd party packages
|
8
9
|
|
9
10
|
# Project packages
|
10
|
-
from . import cmdline
|
11
|
+
from . import cmdline as cmdline
|
12
|
+
from . import callbacks as callbacks
|
13
|
+
from . import variables as variables
|
14
|
+
from . import generators as generators
|