openjd-cli 0.4.3__tar.gz → 0.5.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/PKG-INFO +10 -5
  2. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/README.md +6 -1
  3. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/hatch.toml +1 -1
  4. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_check/_check_command.py +1 -1
  5. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_common/_validation_utils.py +1 -1
  6. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_run/_local_session/_session_manager.py +38 -9
  7. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_run/_run_command.py +11 -13
  8. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_schema/_schema_command.py +1 -4
  9. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_version.py +9 -4
  10. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/pyproject.toml +2 -2
  11. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/.gitignore +0 -0
  12. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/LICENSE +0 -0
  13. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/NOTICE +0 -0
  14. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/__main__.py +0 -0
  15. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/__init__.py +0 -0
  16. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_check/__init__.py +0 -0
  17. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_common/__init__.py +0 -0
  18. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_common/_job_from_template.py +0 -0
  19. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_create_argparser.py +0 -0
  20. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_run/__init__.py +0 -0
  21. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_run/_local_session/__init__.py +0 -0
  22. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_run/_local_session/_actions.py +0 -0
  23. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_run/_local_session/_logs.py +0 -0
  24. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_schema/__init__.py +0 -0
  25. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_summary/__init__.py +0 -0
  26. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_summary/_summary_command.py +0 -0
  27. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/_summary/_summary_output.py +0 -0
  28. {openjd_cli-0.4.3 → openjd_cli-0.5.1}/openjd/cli/py.typed +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: openjd-cli
3
- Version: 0.4.3
3
+ Version: 0.5.1
4
4
  Summary: Provides a command-line interface for working with Open Job Description templates.
5
5
  Project-URL: Homepage, https://github.com/OpenJobDescription/openjd-cli
6
6
  Project-URL: Source, https://github.com/OpenJobDescription/openjd-cli
@@ -22,8 +22,8 @@ Classifier: Programming Language :: Python :: 3.10
22
22
  Classifier: Programming Language :: Python :: 3.11
23
23
  Classifier: Programming Language :: Python :: 3.12
24
24
  Requires-Python: >=3.9
25
- Requires-Dist: openjd-model==0.4.*
26
- Requires-Dist: openjd-sessions==0.7.*
25
+ Requires-Dist: openjd-model==0.6.*
26
+ Requires-Dist: openjd-sessions==0.10.*
27
27
  Description-Content-Type: text/markdown
28
28
 
29
29
  ## Open Job Description - CLI
@@ -307,7 +307,12 @@ For example, if you would like to verify your download of the wheel for version
307
307
 
308
308
  ## Security
309
309
 
310
- See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
310
+ We take all security reports seriously. When we receive such reports, we will
311
+ investigate and subsequently address any potential vulnerabilities as quickly
312
+ as possible. If you discover a potential security issue in this project, please
313
+ notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/)
314
+ or directly via email to [AWS Security](aws-security@amazon.com). Please do not
315
+ create a public GitHub issue in this project.
311
316
 
312
317
  ## License
313
318
 
@@ -279,7 +279,12 @@ For example, if you would like to verify your download of the wheel for version
279
279
 
280
280
  ## Security
281
281
 
282
- See [CONTRIBUTING](CONTRIBUTING.md#security-issue-notifications) for more information.
282
+ We take all security reports seriously. When we receive such reports, we will
283
+ investigate and subsequently address any potential vulnerabilities as quickly
284
+ as possible. If you discover a potential security issue in this project, please
285
+ notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/)
286
+ or directly via email to [AWS Security](aws-security@amazon.com). Please do not
287
+ create a public GitHub issue in this project.
283
288
 
284
289
  ## License
285
290
 
@@ -21,7 +21,7 @@ lint = [
21
21
  ]
22
22
 
23
23
  [[envs.all.matrix]]
24
- python = ["3.9", "3.10", "3.11"]
24
+ python = ["3.9", "3.10", "3.11", "3.12", "3.13"]
25
25
 
26
26
  [envs.codebuild.scripts]
27
27
  build = "hatch build"
@@ -27,7 +27,7 @@ def do_check(args: Namespace) -> OpenJDCliResult:
27
27
 
28
28
  # Raises: DecodeValidationError
29
29
  if TemplateSpecificationVersion.is_job_template(template_version):
30
- decode_job_template(template=template_object)
30
+ decode_job_template(template=template_object, supported_extensions=["TASK_CHUNKING"])
31
31
  elif TemplateSpecificationVersion.is_environment_template(template_version):
32
32
  decode_environment_template(template=template_object)
33
33
  else:
@@ -62,7 +62,7 @@ def read_job_template(template_file: Path) -> JobTemplate:
62
62
  template_object = read_template(template_file)
63
63
 
64
64
  # Raises: DecodeValidationError
65
- template = decode_job_template(template=template_object)
65
+ template = decode_job_template(template=template_object, supported_extensions=["TASK_CHUNKING"])
66
66
 
67
67
  return template
68
68
 
@@ -46,7 +46,8 @@ class LocalSession:
46
46
  _start_seconds: float
47
47
  _end_seconds: float
48
48
  _inner_session: Session
49
- _action_queue: Queue[SessionAction]
49
+ _enter_env_queue: Queue[EnterEnvironmentAction]
50
+ _action_queue: Queue[RunTaskAction]
50
51
  _current_action: Optional[SessionAction]
51
52
  _action_ended: Event
52
53
  _path_mapping_rules: Optional[list[PathMappingRule]]
@@ -90,7 +91,8 @@ class LocalSession:
90
91
  )
91
92
 
92
93
  # Initialize the action queue
93
- self._action_queue: Queue[SessionAction] = Queue()
94
+ self._enter_env_queue: Queue[EnterEnvironmentAction] = Queue()
95
+ self._action_queue: Queue[RunTaskAction] = Queue()
94
96
  self._current_action = None
95
97
 
96
98
  self._should_print_logs = should_print_logs
@@ -222,25 +224,52 @@ class LocalSession:
222
224
  RunTaskAction(self._inner_session, step=step, parameters=param_set)
223
225
  )
224
226
 
225
- # Finally, enqueue ExitEnvironment Actions in reverse order to EnterEnvironment
226
- for env_id in reversed(session_environment_ids):
227
- self._action_queue.put(ExitEnvironmentAction(self._inner_session, env_id))
228
-
229
227
  def run(self) -> None:
230
228
  if self._inner_session.state != SessionState.READY:
231
229
  raise RuntimeError("Session is not in a READY state")
232
230
 
231
+ environments_entered = list[str]()
232
+ failed_action: Optional[SessionAction] = None
233
+
233
234
  self._start_seconds = time.perf_counter()
235
+
236
+ # Enter all of the Environments, and keep track of which ones we've entered
237
+ while not self._enter_env_queue.empty() and not self.failed:
238
+ self._action_ended.clear()
239
+ action = self._enter_env_queue.get()
240
+ environments_entered.append(action._id)
241
+ self._current_action = action
242
+ self._current_action.run()
243
+ self._action_ended.wait()
244
+ if self.failed:
245
+ failed_action = self._current_action
246
+
247
+ # Run all of the Tasks that are enqueued
234
248
  while not self._action_queue.empty() and not self.failed:
235
249
  self._action_ended.clear()
236
250
  self._current_action = self._action_queue.get()
237
251
  self._current_action.run()
238
252
  self._action_ended.wait()
253
+ if self.failed:
254
+ failed_action = self._current_action
255
+
256
+ # Exit all environments that were entered. We always try to exit all failed environments; even
257
+ # if an environment-enter, task, or environment exit failed.
258
+ while environments_entered:
259
+ prev_action_failed = self.failed
260
+ self._action_ended.clear()
261
+ self._current_action = ExitEnvironmentAction(
262
+ self._inner_session, environments_entered.pop()
263
+ )
264
+ self._current_action.run()
265
+ self._action_ended.wait()
266
+ if self.failed and not prev_action_failed:
267
+ failed_action = self._current_action
239
268
 
240
269
  if self.failed:
241
270
  # Action encountered an error; clean up resources and end session
242
271
  LOG.info(
243
- msg=f"Open Job Description CLI: ERROR executing action: '{str(self._current_action)}' (see Task logs for details)",
272
+ msg=f"Open Job Description CLI: ERROR executing action: '{str(failed_action)}' (see Task logs for details)",
244
273
  extra={"session_id": self.session_id},
245
274
  )
246
275
 
@@ -347,13 +376,13 @@ class LocalSession:
347
376
  if isinstance(self._current_action, RunTaskAction):
348
377
  self.tasks_run += 1
349
378
  self._action_ended.set()
350
- if new_status.state in (ActionState.FAILED, ActionState.CANCELED):
379
+ if new_status.state in (ActionState.FAILED, ActionState.CANCELED, ActionState.TIMEOUT):
351
380
  self.failed = True
352
381
  self._action_ended.set()
353
382
 
354
383
  def _add_environments(self, envs: list) -> list[str]:
355
384
  ids: list[str] = []
356
385
  for env in envs:
357
- self._action_queue.put(EnterEnvironmentAction(self._inner_session, env, env.name))
386
+ self._enter_env_queue.put(EnterEnvironmentAction(self._inner_session, env, env.name))
358
387
  ids.append(env.name)
359
388
  return ids
@@ -69,9 +69,10 @@ def add_run_arguments(run_parser: ArgumentParser):
69
69
  dest="task_params",
70
70
  metavar="PARAM=VALUE",
71
71
  help=(
72
- "This argument instructs the command to run a single task in a Session with the given value for one of the task parameters "
73
- "defined for the Step. The option must be provided once for each task parameter defined for the Step, with each instance "
74
- "providing the value for a different task parameter. Mutually exclusive with --tasks and --maximum-tasks."
72
+ "This argument instructs the command to run a single task or chunk of tasks in a Session with the given value for "
73
+ "one of the task parameters defined for the Step. The option must be provided once for each task parameter defined "
74
+ "for the Step, with each instance providing the value for a different task parameter. Mutually exclusive with "
75
+ "--tasks and --maximum-tasks."
75
76
  ),
76
77
  )
77
78
  group.add_argument(
@@ -81,9 +82,9 @@ def add_run_arguments(run_parser: ArgumentParser):
81
82
  dest="tasks",
82
83
  metavar='file://tasks.json OR file://tasks.yaml OR [{"Param": "Value1", ...}, {"Param": "Value2", ...}]',
83
84
  help=(
84
- "This argument instructs the command to run one or more tasks for the Step in a Session. The argument must be either "
85
- "the filename of a JSON or YAML file containing an array of maps from task parameter name to value; or an inlined "
86
- "JSON string of the same. Mutually exclusive with --task-param/-tp and --maximum-tasks."
85
+ "This argument instructs the command to run one or more tasks/chunks of tasks for the Step in a Session. "
86
+ "The argument must be either the filename of a JSON or YAML file containing an array of maps from task parameter "
87
+ "name to value; or an inlined JSON string of the same. Mutually exclusive with --task-param/-tp and --maximum-tasks."
87
88
  ),
88
89
  )
89
90
  group.add_argument(
@@ -206,10 +207,8 @@ def _process_task_params(arguments: list[str]) -> dict[str, str]:
206
207
  )
207
208
 
208
209
  if error_list:
209
- error_msg = "Found the following errors collecting Task parameters:"
210
- for error in error_list:
211
- error_msg += f"\n- {error}"
212
- raise RuntimeError(error_msg)
210
+ error_msgs = "".join(f"\n - {error}" for error in error_list)
211
+ raise RuntimeError("Found the following errors collecting Task parameters:" + error_msgs)
213
212
 
214
213
  return parameter_set
215
214
 
@@ -278,8 +277,8 @@ def _validate_task_params(step: Step, task_params: list[dict[str, str]]) -> None
278
277
 
279
278
  # Collect the names of all of the task parameters defined in the step.
280
279
  if step.parameterSpace is not None:
281
- parameter_space = StepParameterSpaceIterator(space=step.parameterSpace)
282
- task_parameter_names: set[str] = set(parameter_space.names)
280
+ param_space_iter = StepParameterSpaceIterator(space=step.parameterSpace)
281
+ task_parameter_names: set[str] = set(param_space_iter.names)
283
282
  else:
284
283
  task_parameter_names = set[str]()
285
284
 
@@ -298,7 +297,6 @@ def _validate_task_params(step: Step, task_params: list[dict[str, str]]) -> None
298
297
  error_list.append(
299
298
  f"Task {i} is missing values for parameters: {', '.join(sorted(missing_names))}"
300
299
  )
301
-
302
300
  if error_list:
303
301
  error_msg = "Errors defining task parameter values:\n - "
304
302
  error_msg += "\n - ".join(error_list)
@@ -59,10 +59,7 @@ def do_get_schema(args: Namespace) -> OpenJDCliResult:
59
59
  schema_doc: dict = {}
60
60
 
61
61
  try:
62
- # The `schema` attribute will have to be updated if/when Pydantic
63
- # is updated to v2.
64
- # (AFAIK it can be replaced with `model_json_schema()`.)
65
- schema_doc = Template.schema()
62
+ schema_doc = Template.model_json_schema()
66
63
  _process_regex(schema_doc)
67
64
  except Exception as e:
68
65
  return OpenJDCliResult(status="error", message=f"ERROR generating schema: {str(e)}")
@@ -1,8 +1,13 @@
1
- # file generated by setuptools_scm
1
+ # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
3
6
  TYPE_CHECKING = False
4
7
  if TYPE_CHECKING:
5
- from typing import Tuple, Union
8
+ from typing import Tuple
9
+ from typing import Union
10
+
6
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
7
12
  else:
8
13
  VERSION_TUPLE = object
@@ -12,5 +17,5 @@ __version__: str
12
17
  __version_tuple__: VERSION_TUPLE
13
18
  version_tuple: VERSION_TUPLE
14
19
 
15
- __version__ = version = '0.4.3'
16
- __version_tuple__ = version_tuple = (0, 4, 3)
20
+ __version__ = version = '0.5.1'
21
+ __version_tuple__ = version_tuple = (0, 5, 1)
@@ -29,8 +29,8 @@ classifiers = [
29
29
  "Intended Audience :: End Users/Desktop"
30
30
  ]
31
31
  dependencies = [
32
- "openjd-sessions == 0.7.*",
33
- "openjd-model == 0.4.*"
32
+ "openjd-sessions == 0.10.*",
33
+ "openjd-model == 0.6.*"
34
34
  ]
35
35
 
36
36
  [project.urls]
File without changes
File without changes
File without changes