sierra-research 1.3.11__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.
Files changed (254) hide show
  1. sierra/__init__.py +3 -3
  2. sierra/core/__init__.py +3 -3
  3. sierra/core/batchroot.py +223 -0
  4. sierra/core/cmdline.py +681 -1057
  5. sierra/core/compare.py +11 -0
  6. sierra/core/config.py +96 -88
  7. sierra/core/engine.py +306 -0
  8. sierra/core/execenv.py +380 -0
  9. sierra/core/expdef.py +11 -0
  10. sierra/core/experiment/__init__.py +1 -0
  11. sierra/core/experiment/bindings.py +150 -101
  12. sierra/core/experiment/definition.py +414 -245
  13. sierra/core/experiment/spec.py +83 -85
  14. sierra/core/exproot.py +44 -0
  15. sierra/core/generators/__init__.py +10 -0
  16. sierra/core/generators/experiment.py +528 -0
  17. sierra/core/generators/generator_factory.py +138 -137
  18. sierra/core/graphs/__init__.py +23 -0
  19. sierra/core/graphs/bcbridge.py +94 -0
  20. sierra/core/graphs/heatmap.py +245 -324
  21. sierra/core/graphs/pathset.py +27 -0
  22. sierra/core/graphs/schema.py +77 -0
  23. sierra/core/graphs/stacked_line.py +341 -0
  24. sierra/core/graphs/summary_line.py +506 -0
  25. sierra/core/logging.py +3 -2
  26. sierra/core/models/__init__.py +3 -1
  27. sierra/core/models/info.py +19 -0
  28. sierra/core/models/interface.py +52 -122
  29. sierra/core/pipeline/__init__.py +2 -5
  30. sierra/core/pipeline/pipeline.py +228 -126
  31. sierra/core/pipeline/stage1/__init__.py +10 -0
  32. sierra/core/pipeline/stage1/pipeline_stage1.py +45 -31
  33. sierra/core/pipeline/stage2/__init__.py +10 -0
  34. sierra/core/pipeline/stage2/pipeline_stage2.py +8 -11
  35. sierra/core/pipeline/stage2/runner.py +401 -0
  36. sierra/core/pipeline/stage3/__init__.py +12 -0
  37. sierra/core/pipeline/stage3/gather.py +321 -0
  38. sierra/core/pipeline/stage3/pipeline_stage3.py +37 -84
  39. sierra/core/pipeline/stage4/__init__.py +12 -2
  40. sierra/core/pipeline/stage4/pipeline_stage4.py +36 -354
  41. sierra/core/pipeline/stage5/__init__.py +12 -0
  42. sierra/core/pipeline/stage5/pipeline_stage5.py +33 -208
  43. sierra/core/pipeline/yaml.py +48 -0
  44. sierra/core/plugin.py +529 -62
  45. sierra/core/proc.py +11 -0
  46. sierra/core/prod.py +11 -0
  47. sierra/core/ros1/__init__.py +5 -1
  48. sierra/core/ros1/callbacks.py +22 -21
  49. sierra/core/ros1/cmdline.py +59 -88
  50. sierra/core/ros1/generators.py +159 -175
  51. sierra/core/ros1/variables/__init__.py +3 -0
  52. sierra/core/ros1/variables/exp_setup.py +122 -116
  53. sierra/core/startup.py +106 -76
  54. sierra/core/stat_kernels.py +4 -5
  55. sierra/core/storage.py +13 -32
  56. sierra/core/trampoline.py +30 -0
  57. sierra/core/types.py +116 -71
  58. sierra/core/utils.py +103 -106
  59. sierra/core/variables/__init__.py +1 -1
  60. sierra/core/variables/base_variable.py +12 -17
  61. sierra/core/variables/batch_criteria.py +387 -481
  62. sierra/core/variables/builtin.py +135 -0
  63. sierra/core/variables/exp_setup.py +19 -39
  64. sierra/core/variables/population_size.py +72 -76
  65. sierra/core/variables/variable_density.py +44 -68
  66. sierra/core/vector.py +1 -1
  67. sierra/main.py +256 -88
  68. sierra/plugins/__init__.py +119 -0
  69. sierra/plugins/compare/__init__.py +14 -0
  70. sierra/plugins/compare/graphs/__init__.py +19 -0
  71. sierra/plugins/compare/graphs/cmdline.py +120 -0
  72. sierra/plugins/compare/graphs/comparator.py +291 -0
  73. sierra/plugins/compare/graphs/inter_controller.py +531 -0
  74. sierra/plugins/compare/graphs/inter_scenario.py +297 -0
  75. sierra/plugins/compare/graphs/namecalc.py +53 -0
  76. sierra/plugins/compare/graphs/outputroot.py +73 -0
  77. sierra/plugins/compare/graphs/plugin.py +147 -0
  78. sierra/plugins/compare/graphs/preprocess.py +172 -0
  79. sierra/plugins/compare/graphs/schema.py +37 -0
  80. sierra/plugins/engine/__init__.py +14 -0
  81. sierra/plugins/engine/argos/__init__.py +18 -0
  82. sierra/plugins/{platform → engine}/argos/cmdline.py +144 -151
  83. sierra/plugins/{platform/argos/variables → engine/argos/generators}/__init__.py +5 -0
  84. sierra/plugins/engine/argos/generators/engine.py +394 -0
  85. sierra/plugins/engine/argos/plugin.py +393 -0
  86. sierra/plugins/{platform/argos/generators → engine/argos/variables}/__init__.py +5 -0
  87. sierra/plugins/engine/argos/variables/arena_shape.py +183 -0
  88. sierra/plugins/engine/argos/variables/cameras.py +240 -0
  89. sierra/plugins/engine/argos/variables/constant_density.py +112 -0
  90. sierra/plugins/engine/argos/variables/exp_setup.py +82 -0
  91. sierra/plugins/{platform → engine}/argos/variables/physics_engines.py +83 -87
  92. sierra/plugins/engine/argos/variables/population_constant_density.py +178 -0
  93. sierra/plugins/engine/argos/variables/population_size.py +115 -0
  94. sierra/plugins/engine/argos/variables/population_variable_density.py +123 -0
  95. sierra/plugins/engine/argos/variables/rendering.py +108 -0
  96. sierra/plugins/engine/ros1gazebo/__init__.py +18 -0
  97. sierra/plugins/engine/ros1gazebo/cmdline.py +175 -0
  98. sierra/plugins/{platform/ros1robot → engine/ros1gazebo}/generators/__init__.py +5 -0
  99. sierra/plugins/engine/ros1gazebo/generators/engine.py +125 -0
  100. sierra/plugins/engine/ros1gazebo/plugin.py +404 -0
  101. sierra/plugins/engine/ros1gazebo/variables/__init__.py +15 -0
  102. sierra/plugins/engine/ros1gazebo/variables/population_size.py +214 -0
  103. sierra/plugins/engine/ros1robot/__init__.py +18 -0
  104. sierra/plugins/engine/ros1robot/cmdline.py +159 -0
  105. sierra/plugins/{platform/ros1gazebo → engine/ros1robot}/generators/__init__.py +4 -0
  106. sierra/plugins/engine/ros1robot/generators/engine.py +95 -0
  107. sierra/plugins/engine/ros1robot/plugin.py +410 -0
  108. sierra/plugins/{hpc/local → engine/ros1robot/variables}/__init__.py +5 -0
  109. sierra/plugins/engine/ros1robot/variables/population_size.py +146 -0
  110. sierra/plugins/execenv/__init__.py +11 -0
  111. sierra/plugins/execenv/hpc/__init__.py +18 -0
  112. sierra/plugins/execenv/hpc/adhoc/__init__.py +18 -0
  113. sierra/plugins/execenv/hpc/adhoc/cmdline.py +30 -0
  114. sierra/plugins/execenv/hpc/adhoc/plugin.py +131 -0
  115. sierra/plugins/execenv/hpc/cmdline.py +137 -0
  116. sierra/plugins/execenv/hpc/local/__init__.py +18 -0
  117. sierra/plugins/execenv/hpc/local/cmdline.py +31 -0
  118. sierra/plugins/execenv/hpc/local/plugin.py +145 -0
  119. sierra/plugins/execenv/hpc/pbs/__init__.py +18 -0
  120. sierra/plugins/execenv/hpc/pbs/cmdline.py +30 -0
  121. sierra/plugins/execenv/hpc/pbs/plugin.py +121 -0
  122. sierra/plugins/execenv/hpc/slurm/__init__.py +18 -0
  123. sierra/plugins/execenv/hpc/slurm/cmdline.py +30 -0
  124. sierra/plugins/execenv/hpc/slurm/plugin.py +133 -0
  125. sierra/plugins/execenv/prefectserver/__init__.py +18 -0
  126. sierra/plugins/execenv/prefectserver/cmdline.py +66 -0
  127. sierra/plugins/execenv/prefectserver/dockerremote/__init__.py +18 -0
  128. sierra/plugins/execenv/prefectserver/dockerremote/cmdline.py +66 -0
  129. sierra/plugins/execenv/prefectserver/dockerremote/plugin.py +132 -0
  130. sierra/plugins/execenv/prefectserver/flow.py +66 -0
  131. sierra/plugins/execenv/prefectserver/local/__init__.py +18 -0
  132. sierra/plugins/execenv/prefectserver/local/cmdline.py +29 -0
  133. sierra/plugins/execenv/prefectserver/local/plugin.py +133 -0
  134. sierra/plugins/{hpc/adhoc → execenv/robot}/__init__.py +1 -0
  135. sierra/plugins/execenv/robot/turtlebot3/__init__.py +18 -0
  136. sierra/plugins/execenv/robot/turtlebot3/plugin.py +204 -0
  137. sierra/plugins/expdef/__init__.py +14 -0
  138. sierra/plugins/expdef/json/__init__.py +14 -0
  139. sierra/plugins/expdef/json/plugin.py +504 -0
  140. sierra/plugins/expdef/xml/__init__.py +14 -0
  141. sierra/plugins/expdef/xml/plugin.py +386 -0
  142. sierra/{core/hpc → plugins/proc}/__init__.py +1 -1
  143. sierra/plugins/proc/collate/__init__.py +15 -0
  144. sierra/plugins/proc/collate/cmdline.py +47 -0
  145. sierra/plugins/proc/collate/plugin.py +271 -0
  146. sierra/plugins/proc/compress/__init__.py +18 -0
  147. sierra/plugins/proc/compress/cmdline.py +47 -0
  148. sierra/plugins/proc/compress/plugin.py +123 -0
  149. sierra/plugins/proc/decompress/__init__.py +18 -0
  150. sierra/plugins/proc/decompress/plugin.py +96 -0
  151. sierra/plugins/proc/imagize/__init__.py +15 -0
  152. sierra/plugins/proc/imagize/cmdline.py +49 -0
  153. sierra/plugins/proc/imagize/plugin.py +270 -0
  154. sierra/plugins/proc/modelrunner/__init__.py +16 -0
  155. sierra/plugins/proc/modelrunner/plugin.py +250 -0
  156. sierra/plugins/proc/statistics/__init__.py +15 -0
  157. sierra/plugins/proc/statistics/cmdline.py +64 -0
  158. sierra/plugins/proc/statistics/plugin.py +390 -0
  159. sierra/plugins/{hpc → prod}/__init__.py +1 -0
  160. sierra/plugins/prod/graphs/__init__.py +18 -0
  161. sierra/plugins/prod/graphs/cmdline.py +269 -0
  162. sierra/plugins/prod/graphs/collate.py +279 -0
  163. sierra/plugins/prod/graphs/inter/__init__.py +13 -0
  164. sierra/plugins/prod/graphs/inter/generate.py +83 -0
  165. sierra/plugins/prod/graphs/inter/heatmap.py +86 -0
  166. sierra/plugins/prod/graphs/inter/line.py +134 -0
  167. sierra/plugins/prod/graphs/intra/__init__.py +15 -0
  168. sierra/plugins/prod/graphs/intra/generate.py +202 -0
  169. sierra/plugins/prod/graphs/intra/heatmap.py +74 -0
  170. sierra/plugins/prod/graphs/intra/line.py +114 -0
  171. sierra/plugins/prod/graphs/plugin.py +103 -0
  172. sierra/plugins/prod/graphs/targets.py +63 -0
  173. sierra/plugins/prod/render/__init__.py +18 -0
  174. sierra/plugins/prod/render/cmdline.py +72 -0
  175. sierra/plugins/prod/render/plugin.py +282 -0
  176. sierra/plugins/storage/__init__.py +5 -0
  177. sierra/plugins/storage/arrow/__init__.py +18 -0
  178. sierra/plugins/storage/arrow/plugin.py +38 -0
  179. sierra/plugins/storage/csv/__init__.py +9 -0
  180. sierra/plugins/storage/csv/plugin.py +12 -5
  181. sierra/version.py +3 -2
  182. sierra_research-1.5.0.dist-info/METADATA +238 -0
  183. sierra_research-1.5.0.dist-info/RECORD +186 -0
  184. {sierra_research-1.3.11.dist-info → sierra_research-1.5.0.dist-info}/WHEEL +1 -2
  185. sierra/core/experiment/xml.py +0 -454
  186. sierra/core/generators/controller_generator_parser.py +0 -34
  187. sierra/core/generators/exp_creator.py +0 -351
  188. sierra/core/generators/exp_generators.py +0 -142
  189. sierra/core/graphs/scatterplot2D.py +0 -109
  190. sierra/core/graphs/stacked_line_graph.py +0 -251
  191. sierra/core/graphs/stacked_surface_graph.py +0 -220
  192. sierra/core/graphs/summary_line_graph.py +0 -371
  193. sierra/core/hpc/cmdline.py +0 -142
  194. sierra/core/models/graphs.py +0 -87
  195. sierra/core/pipeline/stage2/exp_runner.py +0 -286
  196. sierra/core/pipeline/stage3/imagizer.py +0 -149
  197. sierra/core/pipeline/stage3/run_collator.py +0 -317
  198. sierra/core/pipeline/stage3/statistics_calculator.py +0 -478
  199. sierra/core/pipeline/stage4/graph_collator.py +0 -320
  200. sierra/core/pipeline/stage4/inter_exp_graph_generator.py +0 -240
  201. sierra/core/pipeline/stage4/intra_exp_graph_generator.py +0 -317
  202. sierra/core/pipeline/stage4/model_runner.py +0 -168
  203. sierra/core/pipeline/stage4/rendering.py +0 -283
  204. sierra/core/pipeline/stage4/yaml_config_loader.py +0 -103
  205. sierra/core/pipeline/stage5/inter_scenario_comparator.py +0 -328
  206. sierra/core/pipeline/stage5/intra_scenario_comparator.py +0 -989
  207. sierra/core/platform.py +0 -493
  208. sierra/core/plugin_manager.py +0 -369
  209. sierra/core/root_dirpath_generator.py +0 -241
  210. sierra/plugins/hpc/adhoc/plugin.py +0 -125
  211. sierra/plugins/hpc/local/plugin.py +0 -81
  212. sierra/plugins/hpc/pbs/__init__.py +0 -9
  213. sierra/plugins/hpc/pbs/plugin.py +0 -126
  214. sierra/plugins/hpc/slurm/__init__.py +0 -9
  215. sierra/plugins/hpc/slurm/plugin.py +0 -130
  216. sierra/plugins/platform/__init__.py +0 -9
  217. sierra/plugins/platform/argos/__init__.py +0 -9
  218. sierra/plugins/platform/argos/generators/platform_generators.py +0 -383
  219. sierra/plugins/platform/argos/plugin.py +0 -337
  220. sierra/plugins/platform/argos/variables/arena_shape.py +0 -145
  221. sierra/plugins/platform/argos/variables/cameras.py +0 -243
  222. sierra/plugins/platform/argos/variables/constant_density.py +0 -136
  223. sierra/plugins/platform/argos/variables/exp_setup.py +0 -113
  224. sierra/plugins/platform/argos/variables/population_constant_density.py +0 -175
  225. sierra/plugins/platform/argos/variables/population_size.py +0 -102
  226. sierra/plugins/platform/argos/variables/population_variable_density.py +0 -132
  227. sierra/plugins/platform/argos/variables/rendering.py +0 -104
  228. sierra/plugins/platform/ros1gazebo/__init__.py +0 -9
  229. sierra/plugins/platform/ros1gazebo/cmdline.py +0 -213
  230. sierra/plugins/platform/ros1gazebo/generators/platform_generators.py +0 -137
  231. sierra/plugins/platform/ros1gazebo/plugin.py +0 -335
  232. sierra/plugins/platform/ros1gazebo/variables/__init__.py +0 -10
  233. sierra/plugins/platform/ros1gazebo/variables/population_size.py +0 -204
  234. sierra/plugins/platform/ros1robot/__init__.py +0 -9
  235. sierra/plugins/platform/ros1robot/cmdline.py +0 -175
  236. sierra/plugins/platform/ros1robot/generators/platform_generators.py +0 -112
  237. sierra/plugins/platform/ros1robot/plugin.py +0 -373
  238. sierra/plugins/platform/ros1robot/variables/__init__.py +0 -10
  239. sierra/plugins/platform/ros1robot/variables/population_size.py +0 -146
  240. sierra/plugins/robot/__init__.py +0 -9
  241. sierra/plugins/robot/turtlebot3/__init__.py +0 -9
  242. sierra/plugins/robot/turtlebot3/plugin.py +0 -194
  243. sierra_research-1.3.11.data/data/share/man/man1/sierra-cli.1 +0 -2349
  244. sierra_research-1.3.11.data/data/share/man/man7/sierra-examples.7 +0 -508
  245. sierra_research-1.3.11.data/data/share/man/man7/sierra-exec-envs.7 +0 -331
  246. sierra_research-1.3.11.data/data/share/man/man7/sierra-glossary.7 +0 -285
  247. sierra_research-1.3.11.data/data/share/man/man7/sierra-platforms.7 +0 -358
  248. sierra_research-1.3.11.data/data/share/man/man7/sierra-usage.7 +0 -729
  249. sierra_research-1.3.11.data/data/share/man/man7/sierra.7 +0 -78
  250. sierra_research-1.3.11.dist-info/METADATA +0 -492
  251. sierra_research-1.3.11.dist-info/RECORD +0 -133
  252. sierra_research-1.3.11.dist-info/top_level.txt +0 -1
  253. {sierra_research-1.3.11.dist-info → sierra_research-1.5.0.dist-info}/entry_points.txt +0 -0
  254. {sierra_research-1.3.11.dist-info → sierra_research-1.5.0.dist-info/licenses}/LICENSE +0 -0
sierra/main.py CHANGED
@@ -11,139 +11,307 @@ from collections.abc import Iterable
11
11
  import os
12
12
  import multiprocessing as mp
13
13
  import pathlib
14
+ import argparse
15
+ import typing as tp
14
16
 
15
17
  # 3rd party packages
16
18
 
17
19
  # Project packages
18
- import sierra.core.cmdline as cmd
19
- from sierra.core import platform, plugin
20
+ import sierra.core.cmdline as corecmd
21
+ from sierra import version
22
+ from sierra.core import engine, startup, batchroot, execenv, utils
20
23
  from sierra.core.pipeline.pipeline import Pipeline
21
- from sierra.core.generators.controller_generator_parser import ControllerGeneratorParser
22
- import sierra.core.root_dirpath_generator as rdg
23
- import sierra.core.plugin_manager as pm
24
+ import sierra.core.plugin as pm
24
25
  import sierra.core.logging # type: ignore
25
- import sierra.core.startup
26
- import sierra.version
26
+ from sierra.core import expdef, prod, proc, storage, compare
27
27
 
28
28
  kIssuesURL = "https://github.com/jharwell/sierra/issues"
29
29
 
30
30
 
31
- class SIERRA():
31
+ class SIERRA:
32
32
  """Initialize SIERRA and then launch the pipeline."""
33
33
 
34
- def __init__(self, bootstrap: cmd.BootstrapCmdline) -> None:
34
+ def __init__(self, bootstrap: corecmd.BootstrapCmdline) -> None:
35
+ bootstrap_args, other_args = self._bootstrap(bootstrap)
36
+ manager = self._load_plugins(bootstrap_args)
37
+ self._verify_plugins(manager, bootstrap_args)
38
+ self.args = self._load_cmdline(bootstrap_args, other_args)
39
+
40
+ # Configure cmdopts for engine + execution environment by modifying
41
+ # arguments/adding new arguments as needed, and perform additional
42
+ # validation.
43
+ self.args = execenv.cmdline_postparse_configure(
44
+ bootstrap_args.execenv, self.args
45
+ )
46
+ self.args = engine.cmdline_postparse_configure(
47
+ bootstrap_args.engine, bootstrap_args.execenv, self.args
48
+ )
49
+
50
+ # Inject bootstrap arguments into the namespace for non-bootstrap
51
+ # arguments to make setting up the pipeline downstream much more
52
+ # uniform.
53
+ self.args.__dict__["project"] = bootstrap_args.project
54
+ self.args.__dict__["engine"] = bootstrap_args.engine
55
+ self.args.__dict__["execenv"] = bootstrap_args.execenv
56
+ self.args.__dict__["expdef"] = bootstrap_args.expdef
57
+ self.args.__dict__["storage"] = bootstrap_args.storage
58
+ self.args.__dict__["proc"] = bootstrap_args.proc
59
+ self.args.__dict__["prod"] = bootstrap_args.prod
60
+ self.args.__dict__["compare"] = bootstrap_args.compare
61
+
62
+ def __call__(self) -> None:
63
+ # If only 1 pipeline stage is passed, then the list of stages to run is
64
+ # parsed as a non-iterable integer, which can cause the generator to
65
+ # fail to be created. So make it iterable in that case as well.
66
+ if not isinstance(self.args.pipeline, Iterable):
67
+ self.args.pipeline = [self.args.pipeline]
68
+
69
+ if 5 not in self.args.pipeline:
70
+ self.logger.info(
71
+ "Controller=%s, Scenario=%s", self.args.controller, self.args.scenario
72
+ )
73
+ pathset = batchroot.from_cmdline(self.args)
74
+
75
+ pipeline = Pipeline(self.args, self.args.controller, pathset)
76
+ else:
77
+ pipeline = Pipeline(self.args, None)
78
+
79
+ try:
80
+ pipeline.run()
81
+ except KeyboardInterrupt:
82
+ self.logger.info("Exiting on user cancel")
83
+ sys.exit()
84
+
85
+ def _bootstrap(
86
+ self, bootstrap: corecmd.BootstrapCmdline
87
+ ) -> tp.Tuple[argparse.Namespace, tp.List[str]]:
35
88
  # Bootstrap the cmdline
36
89
  bootstrap_args, other_args = bootstrap.parser.parse_known_args()
90
+ if bootstrap_args.rcfile:
91
+ bootstrap_args.rcfile = os.path.expanduser(bootstrap_args.rcfile)
37
92
 
38
93
  # Setup logging customizations
39
94
  sierra.core.logging.initialize(bootstrap_args.log_level)
40
95
  self.logger = logging.getLogger(__name__)
41
- self.logger.info("This is SIERRA %s.", sierra.version.__version__)
96
+ self.logger.info("This is SIERRA %s.", version.__version__)
97
+
98
+ bootstrap_args = self._handle_rc(bootstrap_args.rcfile, bootstrap_args)
42
99
 
43
100
  # Check SIERRA runtime environment
44
- sierra.core.startup.startup_checks(not bootstrap_args.skip_pkg_checks)
45
- self.logger.info("Using python=%s.", sys.version.replace('\n', ''))
101
+ startup.startup_checks(not bootstrap_args.skip_pkg_checks)
102
+ self.logger.info("Using python=%s.", sys.version.replace("\n", ""))
103
+
104
+ return bootstrap_args, other_args
105
+
106
+ def _load_cmdline(
107
+ self, bootstrap_args: argparse.Namespace, other_args: tp.List[str]
108
+ ) -> argparse.Namespace:
109
+ """Build the cmdline from the selected plugins and parse args.
110
+
111
+ This is one of the places where the SIERRA magic happens. This function
112
+ dynamically combines declared cmdlines from each active plugin, in the
113
+ following partial dependency order::
114
+
115
+ --project -> {--expdef, --proc, --prod, --compare, --storage} -> --execenv --> --engine
116
+
117
+ Plugins in the {} could *probably* be reordered without breaking things,
118
+ but the other plugins (--project, --execenv, --engine) need to be where
119
+ they are in the chain. Change the order at your own risk!
120
+ """
121
+
122
+ self.logger.info("Dynamically building cmdline from selected plugins")
123
+ parents = [corecmd.CoreCmdline([], [-1, 1, 2, 3, 4, 5]).parser]
124
+ stages = [-1, 1, 2, 3, 4, 5]
125
+
126
+ # For plugin options which don't take lists, we can just iterate over
127
+ # them with some simple conf and build their portions of the cmdline.
128
+ simple = {
129
+ "engine": {"arg": "--engine", "module": engine},
130
+ "execenv": {"arg": "--execenv", "module": execenv},
131
+ "expdef": {"arg": "--expdef", "module": expdef},
132
+ "storage": {"arg": "--storage", "module": storage},
133
+ }
134
+ for name, conf in simple.items():
135
+ if parser := conf["module"].cmdline_parser(
136
+ bootstrap_args.__dict__[name], parents, stages
137
+ ):
138
+ self.logger.debug(
139
+ "Loaded %s=%s cmdline", conf["arg"], bootstrap_args.__dict__[name]
140
+ )
141
+ parents = [parser]
142
+
143
+ # These plugin options take lists of plugins to use, and so take
144
+ # slightly more complicated processing.
145
+ lists = {
146
+ "proc": {"arg": "--proc", "module": proc},
147
+ "prod": {"arg": "--prod", "module": prod},
148
+ "compare": {"arg": "--compare", "module": compare},
149
+ }
150
+ for name, conf in lists.items():
151
+ for to_load in bootstrap_args.__dict__[name]:
152
+ if parser := conf["module"].cmdline_parser(to_load, parents, stages):
153
+ self.logger.debug("Loaded %s=%s cmdline", conf["arg"], to_load)
154
+ parents = [parser]
155
+
156
+ path = f"{bootstrap_args.project}.cmdline"
157
+ module = pm.module_load(path)
46
158
 
159
+ nonbootstrap_cmdline = module.build(parents, stages)
160
+ args = nonbootstrap_cmdline.parser.parse_args(other_args)
161
+ args.sierra_root = os.path.expanduser(args.sierra_root)
162
+ args = self._handle_rc(bootstrap_args.rcfile, args)
163
+ return args
164
+
165
+ def _load_plugins(self, bootstrap_args: argparse.Namespace):
47
166
  this_file = pathlib.Path(__file__)
48
167
  install_root = pathlib.Path(this_file.parent)
49
168
 
50
169
  # Load plugins
51
170
  self.logger.info("Loading plugins")
52
- project = bootstrap_args.project
53
- plugin_core_path = [install_root / 'plugins' / 'hpc',
54
- install_root / 'plugins' / 'storage',
55
- install_root / 'plugins' / 'robot',
56
- install_root / 'plugins' / 'platform']
57
- plugin_search_path = plugin_core_path
58
- env = os.environ.get('SIERRA_PLUGIN_PATH')
59
- if env is not None:
171
+ plugin_search_path = [install_root / "plugins"]
172
+ if env := os.environ.get("SIERRA_PLUGIN_PATH"):
60
173
  for p in env.split(os.pathsep):
61
174
  plugin_search_path.append(pathlib.Path(p))
62
175
 
63
176
  manager = pm.pipeline
64
- manager.initialize(project, plugin_search_path)
177
+ manager.initialize(bootstrap_args.project, plugin_search_path)
65
178
 
179
+ # 2025-06-14 [JRH]: All found plugins are loaded/executed as python
180
+ # modules, even if they are not currently selected. I don't know if this
181
+ # is a good idea or not.
66
182
  for p in manager.available_plugins():
67
183
  manager.load_plugin(p)
68
184
 
69
- # Verify platform plugin
70
- module = manager.get_plugin_module(bootstrap_args.platform)
71
- plugin.platform_sanity_checks(module)
185
+ return manager
186
+
187
+ def _verify_plugins(
188
+ self,
189
+ manager,
190
+ bootstrap_args: argparse.Namespace,
191
+ ) -> None:
192
+ # Verify engine plugin
193
+ module = manager.get_plugin_module(bootstrap_args.engine)
194
+ pm.engine_sanity_checks(bootstrap_args.engine, module)
72
195
 
73
196
  # Verify execution environment plugin
74
- module = manager.get_plugin_module(bootstrap_args.exec_env)
75
- plugin.exec_env_sanity_checks(module)
197
+ module = manager.get_plugin_module(bootstrap_args.execenv)
198
+ pm.execenv_sanity_checks(bootstrap_args.execenv, module)
76
199
 
77
- # Load platform cmdline extensions
78
- platform_parser = platform.CmdlineParserGenerator(
79
- bootstrap_args.platform)()
200
+ # Verify processing plugins
201
+ for p in bootstrap_args.proc:
202
+ module = manager.get_plugin_module(p)
203
+ pm.proc_sanity_checks(p, module)
80
204
 
81
- # Load project cmdline extensions
82
- self.logger.info("Loading cmdline extensions from project '%s'",
83
- project)
84
- path = f"{project}.cmdline"
85
- module = pm.module_load(path)
205
+ # Verify product plugins
206
+ for p in bootstrap_args.prod:
207
+ module = manager.get_plugin_module(p)
208
+ pm.prod_sanity_checks(p, module)
86
209
 
87
- # Validate cmdline args
88
- self.args = module.Cmdline([bootstrap.parser, platform_parser],
89
- [-1, 1, 2, 3, 4, 5]).parser.parse_args(other_args)
90
- module.CmdlineValidator()(self.args)
210
+ # Verify comparison plugins
211
+ for p in bootstrap_args.compare:
212
+ module = manager.get_plugin_module(p)
213
+ pm.compare_sanity_checks(p, module)
91
214
 
92
- # Verify storage plugin (declared as part of core cmdline arguments
93
- # rather than bootstrap, so we have to wait until after all arguments
94
- # are parsed to verify it)
95
- module = manager.get_plugin_module(self.args.storage_medium)
96
- plugin.storage_sanity_checks(module)
215
+ # Verify expdef plugin
216
+ module = manager.get_plugin_module(bootstrap_args.expdef)
217
+ pm.expdef_sanity_checks(bootstrap_args.expdef, module)
97
218
 
98
- # Configure cmdopts for platform + execution environment by modifying
99
- # arguments/adding new arguments as needed.
100
- configurer = platform.ParsedCmdlineConfigurer(bootstrap_args.platform,
101
- bootstrap_args.exec_env)
102
- self.args = configurer(self.args)
103
- self.args.__dict__['project'] = project
219
+ # Verify storage plugin
220
+ module = manager.get_plugin_module(bootstrap_args.storage)
221
+ pm.storage_sanity_checks(bootstrap_args.storage, module)
104
222
 
105
- def __call__(self) -> None:
106
- # If only 1 pipeline stage is passed, then the list of stages to run is
107
- # parsed as a non-iterable integer, which can cause the generator to
108
- # fail to be created. So make it iterable in that case as well.
109
- if not isinstance(self.args.pipeline, Iterable):
110
- self.args.pipeline = [self.args.pipeline]
223
+ def _handle_rc(
224
+ self, rcfile_path: tp.Optional[str], args: argparse.Namespace
225
+ ) -> argparse.Namespace:
226
+ """
227
+ Populate cmdline arguments from a .sierrarc file.
111
228
 
112
- if 5 not in self.args.pipeline:
113
- controller = ControllerGeneratorParser()(self.args)
114
- sgp = pm.module_load_tiered(project=self.args.project,
115
- path='generators.scenario_generator_parser')
116
- scenario = sgp.ScenarioGeneratorParser().to_scenario_name(self.args)
117
-
118
- self.logger.info("Controller=%s, Scenario=%s", controller, scenario)
119
- cmdopts = rdg.from_cmdline(self.args)
120
- pipeline = Pipeline(self.args, controller, cmdopts)
121
- else:
122
- pipeline = Pipeline(self.args, None, {})
229
+ In order of priority:
123
230
 
124
- try:
125
- pipeline.run()
126
- except KeyboardInterrupt:
127
- self.logger.info("Exiting on user cancel")
128
- sys.exit()
231
+ #. ``--rcfile``
232
+
233
+ #. ``SIERRA_RCFILE``
234
+
235
+ #. ``~/.sierrarc``
236
+
237
+
238
+ Anything passed on the cmdline overrides, if both are present.
239
+
240
+ """
241
+ # Check rcfile envvar first, so that you can override it on cmdline if
242
+ # desired.
243
+ realpath = os.getenv("SIERRA_RCFILE", None)
244
+
245
+ if realpath:
246
+ self.logger.debug("Reading rcfile from envvar")
247
+
248
+ if rcfile_path:
249
+ self.logger.debug("Reading rcfile from cmdline")
250
+ realpath = rcfile_path
251
+
252
+ if not realpath and os.path.exists(os.path.expanduser("~/.sierrarc")):
253
+ self.logger.debug("Reading rcfile from ~/.sierrarc")
254
+ realpath = "~/.sierrarc"
255
+
256
+ if not realpath:
257
+ return args
258
+
259
+ path = pathlib.Path(realpath).expanduser()
260
+
261
+ with utils.utf8open(path, "r") as rcfile:
262
+ for line in rcfile.readlines():
263
+ # There are 3 ways to pass arguments in the rcfile:
264
+ #
265
+ # 1. --arg
266
+ # 2. --arg=foo
267
+ # 3. --arg foo
268
+ #
269
+ # If you encounter a ~, we assume its a path, so we expand it to
270
+ # match cmdline behavior.
271
+ line = line.strip("\n")
272
+ components = line.split()
273
+
274
+ if len(components) == 1 and "=" not in components[0]: # boolean
275
+ key = line[2:].replace("-", "_")
276
+ args.__dict__[key] = True
277
+
278
+ elif len(components) == 1 and "=" in components[0]:
279
+ key = line.split("=")[0][2:].replace("-", "_")
280
+ value = os.path.expanduser(line.split("=")[1])
281
+
282
+ args.__dict__[key] = value
283
+ else:
284
+ key = line.split()[0][2:].replace("-", "_")
285
+ value = os.path.expanduser(line.split()[1])
286
+ args.__dict__[key] = value
287
+
288
+ self.logger.trace(
289
+ "Applied cmdline arg from rcfile='%s': %s", path, line
290
+ )
291
+
292
+ return args
129
293
 
130
294
 
131
295
  def excepthook(exc_type, exc_value, exc_traceback):
132
- logging.fatal(("SIERRA has encountered an unexpected error and will now "
133
- "terminate.\n\n"
134
- "If you think this is a bug, please report it at:\n\n%s\n\n"
135
- "When reporting, please include as much information as you "
136
- "can. Ideally:\n\n"
137
- "1. What you were trying to do in SIERRA.\n"
138
- "2. The terminal output of sierra-cli, including the "
139
- "below traceback.\n"
140
- "3. The exact command you used to run SIERRA.\n"
141
- "\n"
142
- "In some cases, creating a Minimum Working Example (MWE) "
143
- "reproducing the error with specific input files and/or "
144
- "data is also helpful for quick triage and fix.\n"),
145
- kIssuesURL,
146
- exc_info=(exc_type, exc_value, exc_traceback))
296
+ logging.fatal(
297
+ (
298
+ "SIERRA has encountered an unexpected error and will now "
299
+ "terminate.\n\n"
300
+ "If you think this is a bug, please report it at:\n\n%s\n\n"
301
+ "When reporting, please include as much information as you "
302
+ "can. Ideally:\n\n"
303
+ "1. What you were trying to do in SIERRA.\n"
304
+ "2. The terminal output of sierra-cli, including the "
305
+ "below traceback.\n"
306
+ "3. The exact command you used to run SIERRA.\n"
307
+ "\n"
308
+ "In some cases, creating a Minimum Working Example (MWE) "
309
+ "reproducing the error with specific input files and/or "
310
+ "data is also helpful for quick triage and fix.\n"
311
+ ),
312
+ kIssuesURL,
313
+ exc_info=(exc_type, exc_value, exc_traceback),
314
+ )
147
315
 
148
316
 
149
317
  def main():
@@ -156,11 +324,11 @@ def main():
156
324
  sys.excepthook = excepthook
157
325
 
158
326
  # Bootstrap the cmdline to print version if needed
159
- bootstrap = cmd.BootstrapCmdline()
327
+ bootstrap = corecmd.BootstrapCmdline()
160
328
  bootstrap_args, _ = bootstrap.parser.parse_known_args()
161
329
 
162
330
  if bootstrap_args.version:
163
- sys.stdout.write(cmd.kVersionMsg)
331
+ sys.stdout.write(corecmd.kVersionMsg)
164
332
  else:
165
333
  app = SIERRA(bootstrap)
166
334
  app()
@@ -1,9 +1,128 @@
1
1
  # Copyright 2021 John Harwell, All rights reserved.
2
2
  #
3
3
  # SPDX-License-Identifier: MIT
4
+ """Container module for all plugins in SIERRA."""
4
5
 
5
6
  # Core packages
7
+ import typing as tp
8
+ import argparse
6
9
 
7
10
  # 3rd party packages
8
11
 
9
12
  # Project packages
13
+ from sierra.core import cmdline
14
+
15
+
16
+ class PluginCmdline(cmdline.BaseCmdline):
17
+ """Base class for plugin cmdlines using :class:`argparse`.
18
+
19
+ Note that this can't be in a cmdline.py in this folder because SIERRA will
20
+ erroneouly pick it up as a plugin cmdline module.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ parents: tp.List[argparse.ArgumentParser],
26
+ stages: tp.List[int],
27
+ ) -> None:
28
+ super().__init__()
29
+ self._scaffold_cli(parents)
30
+ self._init_cli(stages)
31
+
32
+ def _scaffold_cli(self, parents: tp.List[argparse.ArgumentParser]) -> None:
33
+ """
34
+ Scaffold CLI by defining the parser and common argument groups.
35
+ """
36
+ if parents:
37
+ self.parser = argparse.ArgumentParser(
38
+ prog="sierra-cli", parents=parents, add_help=False, allow_abbrev=False
39
+ )
40
+ else:
41
+ self.parser = argparse.ArgumentParser(
42
+ prog="sierra-cli", add_help=False, allow_abbrev=False
43
+ )
44
+
45
+ self.multistage = self.parser.add_argument_group(
46
+ self.multistage_desc[0], self.multistage_desc[1]
47
+ )
48
+ self.stage1 = self.parser.add_argument_group(
49
+ self.stage1_desc[0], self.stage1_desc[1]
50
+ )
51
+ self.stage2 = self.parser.add_argument_group(
52
+ self.stage2_desc[0], self.stage2_desc[1]
53
+ )
54
+ self.stage3 = self.parser.add_argument_group(
55
+ self.stage3_desc[0], self.stage3_desc[1]
56
+ )
57
+ self.stage4 = self.parser.add_argument_group(
58
+ self.stage4_desc[0], self.stage4_desc[1]
59
+ )
60
+ self.stage5 = self.parser.add_argument_group(
61
+ self.stage5_desc[0], self.stage5_desc[1]
62
+ )
63
+ self.shortforms = self.parser.add_argument_group(
64
+ title="Shortform aliases",
65
+ description="""
66
+ Most cmdline options to SIERRA are longform (i.e.,
67
+ ``--option``), but some families of options have
68
+ shortforms (i.e., ``-o`` for ``--option``) as
69
+ well. Shortform arguments behave the same as their
70
+ longform counterparts.
71
+ """,
72
+ )
73
+
74
+ def _init_cli(self, stages: tp.List[int]) -> None:
75
+ """Define cmdline arguments for stages 1-5."""
76
+ if -1 in stages:
77
+ self.init_shortforms()
78
+ self.init_multistage()
79
+
80
+ if 1 in stages:
81
+ self.init_stage1()
82
+
83
+ if 2 in stages:
84
+ self.init_stage2()
85
+
86
+ if 3 in stages:
87
+ self.init_stage3()
88
+
89
+ if 4 in stages:
90
+ self.init_stage4()
91
+
92
+ if 5 in stages:
93
+ self.init_stage5()
94
+
95
+ def init_shortforms(self) -> None:
96
+ """
97
+ Define cmdline shortform arguments for all pipeline stages.
98
+ """
99
+
100
+ def init_multistage(self) -> None:
101
+ """
102
+ Define cmdline arguments for all pipeline stages.
103
+ """
104
+
105
+ def init_stage1(self) -> None:
106
+ """
107
+ Define cmdline arguments for stage 1.
108
+ """
109
+
110
+ def init_stage2(self) -> None:
111
+ """
112
+ Define cmdline arguments for stage 2.
113
+ """
114
+
115
+ def init_stage3(self) -> None:
116
+ """
117
+ Define cmdline arguments for stage 3.
118
+ """
119
+
120
+ def init_stage4(self) -> None:
121
+ """
122
+ Define cmdline arguments for stage 4.
123
+ """
124
+
125
+ def init_stage5(self) -> None:
126
+ """
127
+ Define cmdline arguments for stage 5.
128
+ """
@@ -0,0 +1,14 @@
1
+ #
2
+ # Copyright 2025 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """Container module for plugins related to product comparison.
7
+
8
+ Driven by ``--compare``.
9
+ """
10
+ # Core packages
11
+
12
+ # 3rd party packages
13
+
14
+ # Project packages
@@ -0,0 +1,19 @@
1
+ #
2
+ # Copyright 2025 John Harwell, All rights reserved.
3
+ #
4
+ # SPDX-License Identifier: MIT
5
+ #
6
+ """Container module for the graph product comparison plugin.
7
+
8
+ See :ref:`plugins/compare/graphs`.
9
+ """
10
+
11
+ # Core packages
12
+
13
+ # 3rd party packages
14
+
15
+ # Project packages
16
+
17
+
18
+ def sierra_plugin_type() -> str:
19
+ return "pipeline"