hpcflow-new2 0.2.0a50__py3-none-any.whl → 0.2.0a52__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 (38) hide show
  1. hpcflow/_version.py +1 -1
  2. hpcflow/sdk/__init__.py +1 -1
  3. hpcflow/sdk/api.py +1 -1
  4. hpcflow/sdk/app.py +20 -11
  5. hpcflow/sdk/cli.py +34 -59
  6. hpcflow/sdk/core/__init__.py +13 -1
  7. hpcflow/sdk/core/actions.py +235 -126
  8. hpcflow/sdk/core/command_files.py +32 -24
  9. hpcflow/sdk/core/element.py +110 -114
  10. hpcflow/sdk/core/errors.py +57 -0
  11. hpcflow/sdk/core/loop.py +18 -34
  12. hpcflow/sdk/core/parameters.py +5 -3
  13. hpcflow/sdk/core/task.py +135 -131
  14. hpcflow/sdk/core/task_schema.py +11 -4
  15. hpcflow/sdk/core/utils.py +110 -2
  16. hpcflow/sdk/core/workflow.py +964 -676
  17. hpcflow/sdk/data/template_components/environments.yaml +0 -44
  18. hpcflow/sdk/data/template_components/task_schemas.yaml +52 -10
  19. hpcflow/sdk/persistence/__init__.py +21 -33
  20. hpcflow/sdk/persistence/base.py +1340 -458
  21. hpcflow/sdk/persistence/json.py +424 -546
  22. hpcflow/sdk/persistence/pending.py +563 -0
  23. hpcflow/sdk/persistence/store_resource.py +131 -0
  24. hpcflow/sdk/persistence/utils.py +57 -0
  25. hpcflow/sdk/persistence/zarr.py +852 -841
  26. hpcflow/sdk/submission/jobscript.py +133 -112
  27. hpcflow/sdk/submission/shells/bash.py +62 -16
  28. hpcflow/sdk/submission/shells/powershell.py +87 -16
  29. hpcflow/sdk/submission/submission.py +59 -35
  30. hpcflow/tests/unit/test_element.py +4 -9
  31. hpcflow/tests/unit/test_persistence.py +218 -0
  32. hpcflow/tests/unit/test_task.py +11 -12
  33. hpcflow/tests/unit/test_utils.py +82 -0
  34. hpcflow/tests/unit/test_workflow.py +3 -1
  35. {hpcflow_new2-0.2.0a50.dist-info → hpcflow_new2-0.2.0a52.dist-info}/METADATA +3 -1
  36. {hpcflow_new2-0.2.0a50.dist-info → hpcflow_new2-0.2.0a52.dist-info}/RECORD +38 -34
  37. {hpcflow_new2-0.2.0a50.dist-info → hpcflow_new2-0.2.0a52.dist-info}/WHEEL +0 -0
  38. {hpcflow_new2-0.2.0a50.dist-info → hpcflow_new2-0.2.0a52.dist-info}/entry_points.txt +0 -0
hpcflow/_version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.2.0a50"
1
+ __version__ = "0.2.0a52"
hpcflow/sdk/__init__.py CHANGED
@@ -98,7 +98,7 @@ sdk_funcs = {
98
98
 
99
99
  sdk_objs = {**sdk_classes, **sdk_funcs}
100
100
 
101
- _SDK_CONSOLE_LOG_LEVEL = os.environ.get("HPCFLOW_SDK_CONSOLE_LOG_LEVEL", "WARNING")
101
+ _SDK_CONSOLE_LOG_LEVEL = os.environ.get("HPCFLOW_SDK_CONSOLE_LOG_LEVEL", "ERROR")
102
102
 
103
103
 
104
104
  def get_SDK_logger(name=None):
hpcflow/sdk/api.py CHANGED
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
  import importlib
5
5
  import os
6
6
  from typing import Optional, TypeVar, Union
7
- from hpcflow.sdk.core.workflow import ALL_TEMPLATE_FORMATS, DEFAULT_TEMPLATE_FORMAT
7
+ from hpcflow.sdk.core import ALL_TEMPLATE_FORMATS, DEFAULT_TEMPLATE_FORMAT
8
8
  from hpcflow.sdk.persistence import DEFAULT_STORE_FORMAT
9
9
 
10
10
  from hpcflow.sdk.submission.shells import get_shell
hpcflow/sdk/app.py CHANGED
@@ -2,14 +2,14 @@
2
2
  from __future__ import annotations
3
3
 
4
4
  import enum
5
- from functools import partial, wraps
5
+ from functools import wraps
6
6
  from importlib import resources, import_module
7
- import importlib
8
7
  from logging import Logger
9
8
  import os
10
9
  from pathlib import Path
11
10
  from typing import Any, Callable, Dict, List, Optional, Type, Union
12
11
  import warnings
12
+ from reretry import retry
13
13
 
14
14
  from setuptools import find_packages
15
15
 
@@ -18,9 +18,10 @@ from hpcflow.sdk.core.object_list import ObjectList
18
18
  from hpcflow.sdk.core.utils import read_YAML, read_YAML_file
19
19
  from hpcflow.sdk import sdk_objs, sdk_classes, sdk_funcs, get_SDK_logger
20
20
  from hpcflow.sdk.config import Config
21
- from hpcflow.sdk.core.workflow import ALL_TEMPLATE_FORMATS, DEFAULT_TEMPLATE_FORMAT
21
+ from hpcflow.sdk.core import ALL_TEMPLATE_FORMATS, DEFAULT_TEMPLATE_FORMAT
22
22
  from hpcflow.sdk.log import AppLog
23
23
  from hpcflow.sdk.persistence import DEFAULT_STORE_FORMAT
24
+ from hpcflow.sdk.persistence.base import TEMPLATE_COMP_TYPES
24
25
  from hpcflow.sdk.runtime import RunTimeInfo
25
26
  from hpcflow.sdk.cli import make_cli
26
27
  from hpcflow.sdk.submission.shells import get_shell
@@ -95,13 +96,6 @@ class BaseApp(metaclass=Singleton):
95
96
 
96
97
  """
97
98
 
98
- _template_component_types = (
99
- "parameters",
100
- "command_files",
101
- "environments",
102
- "task_schemas",
103
- )
104
-
105
99
  def __init__(
106
100
  self,
107
101
  name,
@@ -281,7 +275,7 @@ class BaseApp(metaclass=Singleton):
281
275
  f"Loading built-in template component data for package: {package!r}."
282
276
  )
283
277
  components = {}
284
- for comp_type in cls._template_component_types:
278
+ for comp_type in TEMPLATE_COMP_TYPES:
285
279
  resource = f"{comp_type}.yaml"
286
280
  try:
287
281
  fh = resources.files(package).joinpath(resource).open("rt")
@@ -336,6 +330,10 @@ class BaseApp(metaclass=Singleton):
336
330
  def config_logger(self) -> Logger:
337
331
  return self.logger.getChild("config")
338
332
 
333
+ @property
334
+ def persistence_logger(self) -> Logger:
335
+ return self.logger.getChild("persistence")
336
+
339
337
  @property
340
338
  def runtime_info_logger(self) -> Logger:
341
339
  return self.logger.getChild("runtime")
@@ -354,6 +352,17 @@ class BaseApp(metaclass=Singleton):
354
352
  self.load_config()
355
353
  return self._config
356
354
 
355
+ def perm_error_retry(self):
356
+ """Return a decorator for retrying functions on permission and OS errors that
357
+ might be associated with cloud-storage desktop sync. engine operations."""
358
+ return retry(
359
+ (PermissionError, OSError),
360
+ tries=10,
361
+ delay=1,
362
+ backoff=2,
363
+ logger=self.persistence_logger,
364
+ )
365
+
357
366
  def _load_config(self, config_dir, config_invocation_key, **overrides) -> None:
358
367
  self.logger.info("Loading configuration.")
359
368
  self._config = Config(
hpcflow/sdk/cli.py CHANGED
@@ -5,7 +5,7 @@ from termcolor import colored
5
5
  from hpcflow import __version__, _app_name
6
6
  from hpcflow.sdk.config.cli import get_config_CLI
7
7
  from hpcflow.sdk.config.errors import ConfigError
8
- from hpcflow.sdk.core.workflow import ALL_TEMPLATE_FORMATS, DEFAULT_TEMPLATE_FORMAT
8
+ from hpcflow.sdk.core import ALL_TEMPLATE_FORMATS, DEFAULT_TEMPLATE_FORMAT
9
9
  from hpcflow.sdk.demo.cli import get_demo_software_CLI
10
10
  from hpcflow.sdk.helper.cli import get_helper_CLI
11
11
  from hpcflow.sdk.persistence import ALL_STORE_FORMATS, DEFAULT_STORE_FORMAT
@@ -410,21 +410,22 @@ def _make_internal_CLI(app):
410
410
  @click.pass_context
411
411
  @click.argument("submission_idx", type=click.INT)
412
412
  @click.argument("jobscript_idx", type=click.INT)
413
- @click.argument("js_element_idx", type=click.INT)
414
413
  @click.argument("js_action_idx", type=click.INT)
414
+ @click.argument("ear_id", type=click.INT)
415
415
  def write_commands(
416
416
  ctx,
417
417
  submission_idx: int,
418
418
  jobscript_idx: int,
419
- js_element_idx: int,
420
419
  js_action_idx: int,
420
+ ear_id: int,
421
421
  ):
422
+ app.CLI_logger.info(f"write commands for EAR ID {ear_id!r}.")
422
423
  ctx.exit(
423
424
  ctx.obj["workflow"].write_commands(
424
425
  submission_idx,
425
426
  jobscript_idx,
426
- js_element_idx,
427
427
  js_action_idx,
428
+ ear_id,
428
429
  )
429
430
  )
430
431
 
@@ -432,73 +433,47 @@ def _make_internal_CLI(app):
432
433
  @click.pass_context
433
434
  @click.argument("name")
434
435
  @click.argument("value")
435
- @click.argument("submission_idx", type=click.INT)
436
- @click.argument("jobscript_idx", type=click.INT)
437
- @click.argument("js_element_idx", type=click.INT)
438
- @click.argument("js_action_idx", type=click.INT)
436
+ @click.argument("ear_id", type=click.INT)
439
437
  def save_parameter(
440
438
  ctx,
441
439
  name: str,
442
440
  value: str,
443
- submission_idx: int,
444
- jobscript_idx: int,
445
- js_element_idx: int,
446
- js_action_idx: int,
441
+ ear_id: int,
447
442
  ):
448
- ctx.exit(
449
- ctx.obj["workflow"].save_parameter(
450
- name,
451
- value,
452
- submission_idx,
453
- jobscript_idx,
454
- js_element_idx,
455
- js_action_idx,
456
- )
457
- )
443
+ app.CLI_logger.info(f"save parameter {name!r} for EAR ID {ear_id!r}.")
444
+ ctx.exit(ctx.obj["workflow"].save_parameter(name, value, ear_id))
458
445
 
459
446
  @workflow.command()
460
447
  @click.pass_context
461
- @click.argument("submission_idx", type=click.INT)
462
- @click.argument("jobscript_idx", type=click.INT)
463
- @click.argument("js_element_idx", type=click.INT)
464
- @click.argument("js_action_idx", type=click.INT)
465
- def set_EAR_start(
466
- ctx,
467
- submission_idx: int,
468
- jobscript_idx: int,
469
- js_element_idx: int,
470
- js_action_idx: int,
471
- ):
472
- ctx.exit(
473
- ctx.obj["workflow"].set_EAR_start(
474
- submission_idx,
475
- jobscript_idx,
476
- js_element_idx,
477
- js_action_idx,
478
- )
479
- )
448
+ @click.argument("ear_id", type=click.INT)
449
+ def set_EAR_start(ctx, ear_id: int):
450
+ app.CLI_logger.info(f"set EAR start for EAR ID {ear_id!r}.")
451
+ ctx.exit(ctx.obj["workflow"].set_EAR_start(ear_id))
480
452
 
481
453
  @workflow.command()
482
454
  @click.pass_context
483
- @click.argument("submission_idx", type=click.INT)
484
- @click.argument("jobscript_idx", type=click.INT)
485
- @click.argument("js_element_idx", type=click.INT)
486
- @click.argument("js_action_idx", type=click.INT)
487
- def set_EAR_end(
488
- ctx,
489
- submission_idx: int,
490
- jobscript_idx: int,
491
- js_element_idx: int,
492
- js_action_idx: int,
493
- ):
494
- ctx.exit(
495
- ctx.obj["workflow"].set_EAR_end(
496
- submission_idx,
497
- jobscript_idx,
498
- js_element_idx,
499
- js_action_idx,
500
- )
455
+ @click.argument("ear_id", type=click.INT)
456
+ @click.argument("exit_code", type=click.INT)
457
+ def set_EAR_end(ctx, ear_id: int, exit_code: int):
458
+ app.CLI_logger.info(
459
+ f"set EAR end for EAR ID {ear_id!r} with exit code {exit_code!r}."
501
460
  )
461
+ ctx.exit(ctx.obj["workflow"].set_EAR_end(ear_id, exit_code))
462
+
463
+ @workflow.command()
464
+ @click.pass_context
465
+ @click.argument("ear_id", type=click.INT)
466
+ def set_EAR_skip(ctx, ear_id: int):
467
+ app.CLI_logger.info(f"set EAR skip for EAR ID {ear_id!r}.")
468
+ ctx.exit(ctx.obj["workflow"].set_EAR_skip(ear_id))
469
+
470
+ @workflow.command()
471
+ @click.pass_context
472
+ @click.argument("ear_id", type=click.INT)
473
+ def get_EAR_skipped(ctx, ear_id: int):
474
+ """Return 1 if the given EAR is to be skipped, else return 0."""
475
+ app.CLI_logger.info(f"get EAR skip for EAR ID {ear_id!r}.")
476
+ click.echo(int(ctx.obj["workflow"].get_EAR_skipped(ear_id)))
502
477
 
503
478
  # TODO: in general, maybe the workflow command group can expose the simple Workflow
504
479
  # properties; maybe use a decorator on the Workflow property object to signify
@@ -1 +1,13 @@
1
- """Core programmatic models for hpcflow."""
1
+ """Core programmatic models for hpcflow.
2
+
3
+ EAR abort exit code is set to 64 [1].
4
+
5
+ References
6
+ ----------
7
+ https://tldp.org/LDP/abs/html/exitcodes.html
8
+
9
+ """
10
+
11
+ DEFAULT_TEMPLATE_FORMAT = "yaml"
12
+ ALL_TEMPLATE_FORMATS = ("yaml", "json")
13
+ ABORT_EXIT_CODE = 64