yellowdog-python-examples 7.2.5__tar.gz → 7.2.7__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 (65) hide show
  1. {yellowdog-python-examples-7.2.5/yellowdog_python_examples.egg-info → yellowdog-python-examples-7.2.7}/PKG-INFO +1 -1
  2. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/README.md +111 -68
  3. yellowdog-python-examples-7.2.7/tests/test_dryruns.py +50 -0
  4. yellowdog-python-examples-7.2.7/yd_commands/__init__.py +1 -0
  5. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/cancel.py +5 -4
  6. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/config_types.py +2 -10
  7. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/csv_data.py +25 -10
  8. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/instantiate.py +10 -5
  9. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/load_config.py +44 -20
  10. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/printing.py +100 -123
  11. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/property_names.py +8 -0
  12. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/provision.py +4 -3
  13. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/provision_utils.py +21 -8
  14. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/remove.py +10 -8
  15. yellowdog-python-examples-7.2.7/yd_commands/settings.py +94 -0
  16. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/submit.py +40 -17
  17. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/submit_utils.py +9 -10
  18. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/upload_utils.py +5 -1
  19. yellowdog-python-examples-7.2.7/yd_commands/utils.py +219 -0
  20. yellowdog-python-examples-7.2.7/yd_commands/variables.py +483 -0
  21. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7/yellowdog_python_examples.egg-info}/PKG-INFO +1 -1
  22. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yellowdog_python_examples.egg-info/SOURCES.txt +2 -0
  23. yellowdog-python-examples-7.2.5/yd_commands/__init__.py +0 -1
  24. yellowdog-python-examples-7.2.5/yd_commands/utils.py +0 -94
  25. yellowdog-python-examples-7.2.5/yd_commands/variables.py +0 -340
  26. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/LICENSE +0 -0
  27. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/PYPI_README.md +0 -0
  28. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/pyproject.toml +0 -0
  29. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/requirements.txt +0 -0
  30. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/setup.cfg +0 -0
  31. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/setup.py +0 -0
  32. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/tests/test_create_remove.py +0 -0
  33. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/tests/test_demos.py +0 -0
  34. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/tests/test_entrypoints.py +0 -0
  35. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/tests/test_list.py +0 -0
  36. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/tests/test_objects.py +0 -0
  37. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/abort.py +0 -0
  38. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/admin.py +0 -0
  39. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/args.py +0 -0
  40. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/check_imports.py +0 -0
  41. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/compact_json.py +0 -0
  42. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/create.py +0 -0
  43. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/delete.py +0 -0
  44. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/download.py +0 -0
  45. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/follow.py +0 -0
  46. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/follow_utils.py +0 -0
  47. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/id_utils.py +0 -0
  48. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/interactive.py +0 -0
  49. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/jsonnet2json.py +0 -0
  50. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/list.py +0 -0
  51. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/load_resources.py +0 -0
  52. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/object_utilities.py +0 -0
  53. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/reformat_json.py +0 -0
  54. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/resize.py +0 -0
  55. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/shutdown.py +0 -0
  56. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/terminate.py +0 -0
  57. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/type_check.py +0 -0
  58. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/upload.py +0 -0
  59. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/validate_properties.py +0 -0
  60. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/version.py +0 -0
  61. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yd_commands/wrapper.py +0 -0
  62. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yellowdog_python_examples.egg-info/dependency_links.txt +0 -0
  63. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yellowdog_python_examples.egg-info/entry_points.txt +0 -0
  64. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yellowdog_python_examples.egg-info/requires.txt +0 -0
  65. {yellowdog-python-examples-7.2.5 → yellowdog-python-examples-7.2.7}/yellowdog_python_examples.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: yellowdog-python-examples
3
- Version: 7.2.5
3
+ Version: 7.2.7
4
4
  Summary: Example Python commands using the YellowDog Python SDK
5
5
  Home-page: https://github.com/yellowdog/python-examples
6
6
  Author: YellowDog Limited
@@ -18,6 +18,7 @@
18
18
  * [User-Defined Variables](#user-defined-variables)
19
19
  * [Nested Variables](#nested-variables)
20
20
  * [Providing Default Values for User-Defined Variables](#providing-default-values-for-user-defined-variables)
21
+ * [Variable Substitutions in Worker Pool and Compute Requirement Specifications, and in User Data](#variable-substitutions-in-worker-pool-and-compute-requirement-specifications-and-in-user-data)
21
22
  * [Work Requirement Properties](#work-requirement-properties)
22
23
  * [Work Requirement JSON File Structure](#work-requirement-json-file-structure)
23
24
  * [Property Inheritance](#property-inheritance)
@@ -107,7 +108,7 @@
107
108
  * [yd-remove](#yd-remove)
108
109
  * [yd-follow](#yd-follow)
109
110
 
110
- <!-- Added by: pwt, at: Wed Sep 13 15:24:39 BST 2023 -->
111
+ <!-- Added by: pwt, at: Mon Sep 18 16:03:18 BST 2023 -->
111
112
 
112
113
  <!--te-->
113
114
 
@@ -335,11 +336,17 @@ Variable substitutions provide a powerful way of introducing variable values int
335
336
 
336
337
  Variable substitutions are expressed using `{{variable}}` notation, where the expression is replaced by the value of `variable`.
337
338
 
338
- Substitutions can also be performed for non-string (number and boolean) values using the `num:` and `bool:` prefixes within the variable substitution:
339
+ Substitutions can also be performed for non-string (number, boolean, array, and table) values using the `num:`, `bool:`, `array:`, and `table:` prefixes within the variable substitution:
339
340
 
340
- - Define the variable substitution using one of the following patterns: `"{{num:my_int}}"`, `"{{num:my_float}}"`, `"{{bool:my_bool}}"`
341
- - Variable definitions supplied on the command line would then be of the form: `-m my_int=5 -m my_float=2.5 -m my_bool=true`
342
- - In the processed JSON or TOML, these values would become `5`, `2.5` and `true`, respectively, converted from strings to their correct JSON types
341
+ - Define the variable substitution using one of the following patterns: `"{{num:my_int}}"`, `"{{num:my_float}}"`, `"{{bool:my_bool}}"`, `"{{array:my_array}}"`, `"{{table:my_table}}"`
342
+ - Variable definitions supplied on the command line would then be of the form, e.g.:
343
+
344
+ ```shell
345
+ yd-submit -v my_int=5 -v my_float=2.5 -v my_bool=true \
346
+ -v my_array="[1,2,3]" -v my_table="{'A': 100, 'B': 200}"
347
+ ```
348
+
349
+ - In the processed JSON (or TOML), these values would become `5`, `2.5`, `true`, `[1,2,3]`, and `{"A": 100, "B": 200}`, respectively, converted from strings to their correct JSON types
343
350
 
344
351
  ## Default Variables
345
352
 
@@ -406,10 +413,12 @@ Nesting can be up to three levels deep including the top level.
406
413
 
407
414
  Each variable can be supplied with a default value to be used if a value is not provided for that variable name. The syntax for providing a default is:
408
415
 
409
- ```shell
416
+ ```
410
417
  {{variable_name:=default_value}} or
411
418
  {{num:numeric_variable_name:=default_numeric_value}} or
412
- {{bool:boolean_variable_name:=default_boolean_value}}
419
+ {{bool:boolean_variable_name:=default_boolean_value}} or
420
+ {{array:array_name:=default_array}} or
421
+ {{table:table_name:=default_table}}
413
422
  ```
414
423
 
415
424
  Examples of use in a TOML file:
@@ -418,10 +427,24 @@ Examples of use in a TOML file:
418
427
  name = "{{name:=my_name}}"
419
428
  taskCount = "{{num:task_count:=5}}"
420
429
  finishIfAllTasksFinished = "{{bool:fiaft:=true}}"
430
+ arguments = "{{array:args:=[1,2,3]}}"
431
+ environment = "{{table:env:={'A':100,'B':200}}}"
421
432
  ```
422
433
 
423
434
  Default values can be used anywhere that variable substitutions are allowed.
424
435
 
436
+ In TOML files only, nested variable substitutions can be used inside default values, e.g.:
437
+
438
+ ```toml
439
+ name = "{{name_var:={{tag}}-{{datetime}}}}"
440
+ ```
441
+
442
+ ## Variable Substitutions in Worker Pool and Compute Requirement Specifications, and in User Data
443
+
444
+ In JSON specifications for Worker Pools and Compute Requirements, variable substitutions can be used, but they must be prefixed and postfixed by a double underscore `__`, e.g., `__{{username}}__`. This is to disambiguate them from variable substitutions intended for Mustache processing at the platform end.
445
+
446
+ Variable substitutions can also be used within **User Data** to be supplied to instances, for which the same prefix/postfix requirement applies, **including** for User Data supplied directly using the `userData` property in the `workerPool` section of the TOML file.
447
+
425
448
  # Work Requirement Properties
426
449
 
427
450
  The `workRequirement` section of the configuration file is optional. It's used only by the `yd-submit` command, and controls the Work Requirement that is submitted to the Platform.
@@ -480,54 +503,55 @@ The following table outlines all the properties available for defining Work Requ
480
503
 
481
504
  All properties are optional except for **`taskType`** (or **`taskTypes`**).
482
505
 
483
- | Property Name | Description | TOML | WR | TGrp | Task |
484
- |:---------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----|:----|:-----|:-----|
485
- | `alwaysUpload` | Whether to attempt to upload task outputs on failure. Default: `true`. | Yes | Yes | Yes | Yes |
486
- | `arguments` | The list of arguments to be passed to the Task when it is executed. E.g.: `[1, "Two"]`. | Yes | Yes | Yes | Yes |
487
- | `captureTaskOutput` | Whether the console output of a Task's process should be uploaded to the YellowDog Object Store on Task completion. Default: `true`. | Yes | Yes | Yes | Yes |
488
- | `completedTaskTtl` | The time (in minutes) to live for completed Tasks. If set, Tasks that have been completed for longer than this period will be deleted. E.g.: `10.0`. | Yes | Yes | Yes | |
489
- | `csvFile` | The name of the CSV file used to derive Task data. An alternative to `csvFiles` that can be used when there's only a single CSV file. E.g. `"file.csv"`. | Yes | | | |
490
- | `csvFiles` | A list of CSV files used to derive Task data. E.g. `["file.csv", "file_2.csv:2]`. | Yes | | | |
491
- | `dependentOn` | The name of another Task Group within the same Work Requirement that must be successfully completed before the Task Group is started. E.g. `"task_group_1"`. | | | Yes | |
492
- | `dockerEnvironment` | The environment to be passed to a Docker container. Only used by the `docker` Task Type. E.g., JSON: `{"VAR_1": "abc"}`, TOML: `{VAR_1 = "abc", VAR_2 = "def"}`. | Yes | Yes | Yes | Yes |
493
- | `dockerPassword` | The password for DockerHub, only used by the `docker` Task Type. E,g., `"my_password"`. | Yes | Yes | Yes | Yes |
494
- | `dockerUsername` | The username for DockerHub, only used by the `docker` Task Type. E,g., `"my_username"`. | Yes | Yes | Yes | Yes |
495
- | `environment` | The environment variables to set for a Task when it's executed. E.g., JSON: `{"VAR_1": "abc", "VAR_2": "def"}`, TOML: `{VAR_1 = "abc", VAR_2 = "def"}`. | Yes | Yes | Yes | Yes |
496
- | `exclusiveWorkers` | If true, then do not allow claimed Workers to be shared with other Task Groups; otherwise, Workers can be shared. Default:`false`. | Yes | Yes | Yes | |
497
- | `executable` | The 'executable' to run when a Bash or Docker Task is executed. Bash script for Bash, container image for Docker. Optional: omit to suppress automatic processing. | Yes | Yes | Yes | Yes |
498
- | `finishIfAllTasksFinished` | If true, the Task Group will finish automatically if all contained tasks finish. Default:`true`. | Yes | Yes | Yes | |
499
- | `finishIfAnyTaskFailed` | If true, the Task Group will be failed automatically if any contained tasks fail. Default:`false`. | Yes | Yes | Yes | |
500
- | `flattenInputPaths` | Determines whether input object paths should be flattened (i.e., directory structure removed) when downloaded to a node. Default: `false`. | Yes | Yes | Yes | Yes |
501
- | `flattenUploadPaths` | Ignore local directory paths when uploading files to the Object Store; place in `<namespace>:<work-req-name>/`. Default: `false`. | Yes | Yes | | |
502
- | `fulfilOnSubmit` | Indicates if the Work Requirement should be fulfilled when it is submitted, rather than being allowed to wait in PENDING status. Default:`false`. | Yes | Yes | | |
503
- | `inputs` | The list of input files to be uploaded to the YellowDog Object Store, and required by the Task (implies `verifyAtStart`). E.g. `["a.sh", "b.sh"]` or `["*.sh"]`. | Yes | Yes | Yes | Yes |
504
- | `inputsOptional` | A list of input files required by a Task, but which are not subject to verification. Can contain wildcards. E.g.: `["task_group_1/**/results.txt"]`. | Yes | Yes | Yes | Yes |
505
- | `instanceTypes` | The machine instance types that can be used to execute Tasks. E.g., `["t3.micro", "t3a.micro"]`. | Yes | Yes | Yes | |
506
- | `maximumTaskRetries` | The maximum number of times a Task can be retried after it has failed. E.g.: `5`. | Yes | Yes | Yes | |
507
- | `maxWorkers` | The maximum number of Workers that can be claimed for the associated Task Group. E.g., `10`. | Yes | Yes | Yes | |
508
- | `minWorkers` | The minimum number of Workers that the associated Task Group requires. This many workers must be claimed before the associated Task Group will start working. E.g., `1`. | Yes | Yes | Yes | |
509
- | `name` | The name of the Work Requirement, Task Group or Task. E.g., `"wr_name"`. Note that the `name` property is not inherited. | Yes | Yes | Yes | Yes |
510
- | `outputs` | The files to be uploaded to the YellowDog Object Store by a Worker node on completion of the Task. E.g., `["results_1.txt", "results_2.txt"]`. | Yes | Yes | Yes | Yes |
511
- | `outputsRequired` | The files that *must* be uploaded to the YellowDog Object Store by a Worker node on completion of the Task. The Task will fail if any outputs are unavailable. | Yes | Yes | Yes | Yes |
512
- | `priority` | The priority of Work Requirements and Task Groups. Higher priority acquires Workers ahead of lower priority. E.g., `0.0`. | Yes | Yes | Yes | |
513
- | `providers` | Constrains the YellowDog Scheduler only to execute tasks from the associated Task Group on the specified providers. E.g., `["AWS", "GOOGLE"]`. | Yes | Yes | Yes | |
514
- | `ram` | Range constraint on GB of RAM that are required to execute Tasks. E.g., `[2.5, 4.0]`. | Yes | Yes | Yes | |
515
- | `regions` | Constrains the YellowDog Scheduler only to execute Tasks from the associated Task Group in the specified regions. E.g., `["eu-west-2]`. | Yes | Yes | Yes | |
516
- | `taskBatchSize` | Determines the batch size used to add Tasks to Task Groups. Default is 2,000. | Yes | | | |
517
- | `taskCount` | The number of times to execute the Task. Can be set in the TOML file or in any JSON Task Group definition. Note: no inheritance from TOML to JSON. | Yes | | Yes | |
518
- | `taskData` | The data to be passed to the Worker when the Task is started. E.g., `"mydata"`. Becomes file `taskdata.txt` in the Task's working directory when The Task executes. | Yes | Yes | Yes | Yes |
519
- | `taskDataFile` | Populate the `taskData` property above with the contents of the specified file. E.g., `"my_task_data_file.txt"`. | Yes | Yes | Yes | Yes |
520
- | `taskName` | The name to use for the Task. Only usable in the TOML file. Mostly useful in conjunction with CSV Task data. E.g., `"my_task_number_{{task_number}}"`. | Yes | | | |
521
- | `taskGroupName` | The name to use for the Task Group. Only usable in the TOML file. E.g., `"my_tg_number_{{task_group_number}}"`. | Yes | | | |
522
- | `taskType` | The Task Type of a Task. E.g., `"docker"`. | Yes | | | Yes |
523
- | `taskTypes` | The list of Task Types required by the range of Tasks in a Task Group. E.g., `["docker", bash"]`. | | Yes | Yes | |
524
- | `tasksPerWorker` | Determines the number of Worker claims based on splitting the number of unfinished Tasks across Workers. E.g., `1`. | Yes | Yes | Yes | |
525
- | `uploadFiles` | The list of files to be uploaded to the YellowDog Object Store. E.g., (JSON): `[{"localPath": file_1.txt", "uploadPath": "file_1.txt"}]`. | Yes | Yes | Yes | Yes |
526
- | `vcpus` | Range constraint on number of vCPUs that are required to execute Tasks E.g., `[2.0, 4.0]`. | Yes | Yes | Yes | |
527
- | `verifyAtStart` | A list of files required by a Task. Must be present when the Task is ready to start or the Task will fail. E.g.: `["task_group_1/task_1/results.txt"]`. | Yes | Yes | Yes | Yes |
528
- | `verifyWait` | A list of files required by a Task. The Task will wait until the files are available before starting. E.g.: `["task_group_1/task_1/results.txt"]`. | Yes | Yes | Yes | Yes |
529
- | `workerTags` | The list of Worker Tags that will be used to match against the Worker Tag of a candidate Worker. E.g., `["tag_x", "tag_y"]`. | Yes | Yes | Yes | |
530
- | `workRequirementData` | The name of the file containing the JSON document in which the Work Requirement is defined. E.g., `"test_workreq.json"`. | Yes | | | |
506
+ | Property Name | Description | TOML | WR | TGrp | Task |
507
+ |:---------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----|:----|:-----|:-----|
508
+ | `alwaysUpload` | Whether to attempt to upload task outputs on failure. Default: `true`. | Yes | Yes | Yes | Yes |
509
+ | `arguments` | The list of arguments to be passed to the Task when it is executed. E.g.: `[1, "Two"]`. | Yes | Yes | Yes | Yes |
510
+ | `captureTaskOutput` | Whether the console output of a Task's process should be uploaded to the YellowDog Object Store on Task completion. Default: `true`. | Yes | Yes | Yes | Yes |
511
+ | `completedTaskTtl` | The time (in minutes) to live for completed Tasks. If set, Tasks that have been completed for longer than this period will be deleted. E.g.: `10.0`. | Yes | Yes | Yes | |
512
+ | `csvFile` | The name of the CSV file used to derive Task data. An alternative to `csvFiles` that can be used when there's only a single CSV file. E.g. `"file.csv"`. | Yes | | | |
513
+ | `csvFiles` | A list of CSV files used to derive Task data. E.g. `["file.csv", "file_2.csv:2]`. | Yes | | | |
514
+ | `dependentOn` | The name of another Task Group within the same Work Requirement that must be successfully completed before the Task Group is started. E.g. `"task_group_1"`. | | | Yes | |
515
+ | `dockerEnvironment` | The environment to be passed to a Docker container. Only used by the `docker` Task Type. E.g., JSON: `{"VAR_1": "abc"}`, TOML: `{VAR_1 = "abc", VAR_2 = "def"}`. | Yes | Yes | Yes | Yes |
516
+ | `dockerPassword` | The password for DockerHub, only used by the `docker` Task Type. E,g., `"my_password"`. | Yes | Yes | Yes | Yes |
517
+ | `dockerUsername` | The username for DockerHub, only used by the `docker` Task Type. E,g., `"my_username"`. | Yes | Yes | Yes | Yes |
518
+ | `environment` | The environment variables to set for a Task when it's executed. E.g., JSON: `{"VAR_1": "abc", "VAR_2": "def"}`, TOML: `{VAR_1 = "abc", VAR_2 = "def"}`. | Yes | Yes | Yes | Yes |
519
+ | `exclusiveWorkers` | If true, then do not allow claimed Workers to be shared with other Task Groups; otherwise, Workers can be shared. Default:`false`. | Yes | Yes | Yes | |
520
+ | `executable` | The 'executable' to run when a Bash or Docker Task is executed. Bash script for Bash, container image for Docker. Optional: omit to suppress automatic processing. | Yes | Yes | Yes | Yes |
521
+ | `finishIfAllTasksFinished` | If true, the Task Group will finish automatically if all contained tasks finish. Default:`true`. | Yes | Yes | Yes | |
522
+ | `finishIfAnyTaskFailed` | If true, the Task Group will be failed automatically if any contained tasks fail. Default:`false`. | Yes | Yes | Yes | |
523
+ | `flattenInputPaths` | Determines whether input object paths should be flattened (i.e., directory structure removed) when downloaded to a node. Default: `false`. | Yes | Yes | Yes | Yes |
524
+ | `flattenUploadPaths` | Ignore local directory paths when uploading files to the Object Store; place in `<namespace>:<work-req-name>/`. Default: `false`. | Yes | Yes | | |
525
+ | `fulfilOnSubmit` | Indicates if the Work Requirement should be fulfilled when it is submitted, rather than being allowed to wait in PENDING status. Default:`false`. | Yes | Yes | | |
526
+ | `inputs` | The list of input files to be uploaded to the YellowDog Object Store, and required by the Task (implies `verifyAtStart`). E.g. `["a.sh", "b.sh"]` or `["*.sh"]`. | Yes | Yes | Yes | Yes |
527
+ | `inputsOptional` | A list of input files required by a Task, but which are not subject to verification. Can contain wildcards. E.g.: `["task_group_1/**/results.txt"]`. | Yes | Yes | Yes | Yes |
528
+ | `instanceTypes` | The machine instance types that can be used to execute Tasks. E.g., `["t3.micro", "t3a.micro"]`. | Yes | Yes | Yes | |
529
+ | `maximumTaskRetries` | The maximum number of times a Task can be retried after it has failed. E.g.: `5`. | Yes | Yes | Yes | |
530
+ | `maxWorkers` | The maximum number of Workers that can be claimed for the associated Task Group. E.g., `10`. | Yes | Yes | Yes | |
531
+ | `minWorkers` | The minimum number of Workers that the associated Task Group requires. This many workers must be claimed before the associated Task Group will start working. E.g., `1`. | Yes | Yes | Yes | |
532
+ | `name` | The name of the Work Requirement, Task Group or Task. E.g., `"wr_name"`. Note that the `name` property is not inherited. | Yes | Yes | Yes | Yes |
533
+ | `outputs` | The files to be uploaded to the YellowDog Object Store by a Worker node on completion of the Task. E.g., `["results_1.txt", "results_2.txt"]`. | Yes | Yes | Yes | Yes |
534
+ | `outputsOther` | Files to be uploaded to the YellowDog Object Store from outside the Tasks's Working Directory by a Worker node on completion of a Task. E.g., `outputsOther = [{"directoryName" = "tmp", "filePattern" = "out.txt", "required" = false}]`. | Yes | Yes | Yes | Yes |
535
+ | `outputsRequired` | The files that *must* be uploaded to the YellowDog Object Store by a Worker node on completion of the Task. The Task will fail if any outputs are unavailable. | Yes | Yes | Yes | Yes |
536
+ | `priority` | The priority of Work Requirements and Task Groups. Higher priority acquires Workers ahead of lower priority. E.g., `0.0`. | Yes | Yes | Yes | |
537
+ | `providers` | Constrains the YellowDog Scheduler only to execute tasks from the associated Task Group on the specified providers. E.g., `["AWS", "GOOGLE"]`. | Yes | Yes | Yes | |
538
+ | `ram` | Range constraint on GB of RAM that are required to execute Tasks. E.g., `[2.5, 4.0]`. | Yes | Yes | Yes | |
539
+ | `regions` | Constrains the YellowDog Scheduler only to execute Tasks from the associated Task Group in the specified regions. E.g., `["eu-west-2]`. | Yes | Yes | Yes | |
540
+ | `taskBatchSize` | Determines the batch size used to add Tasks to Task Groups. Default is 2,000. | Yes | | | |
541
+ | `taskCount` | The number of times to execute the Task. | Yes | Yes | Yes | |
542
+ | `taskData` | The data to be passed to the Worker when the Task is started. E.g., `"mydata"`. Becomes file `taskdata.txt` in the Task's working directory when The Task executes. | Yes | Yes | Yes | Yes |
543
+ | `taskDataFile` | Populate the `taskData` property above with the contents of the specified file. E.g., `"my_task_data_file.txt"`. | Yes | Yes | Yes | Yes |
544
+ | `taskName` | The name to use for the Task. Only usable in the TOML file. Mostly useful in conjunction with CSV Task data. E.g., `"my_task_number_{{task_number}}"`. | Yes | | | |
545
+ | `taskGroupName` | The name to use for the Task Group. Only usable in the TOML file. E.g., `"my_tg_number_{{task_group_number}}"`. | Yes | | | |
546
+ | `taskType` | The Task Type of a Task. E.g., `"docker"`. | Yes | | | Yes |
547
+ | `taskTypes` | The list of Task Types required by the range of Tasks in a Task Group. E.g., `["docker", bash"]`. | | Yes | Yes | |
548
+ | `tasksPerWorker` | Determines the number of Worker claims based on splitting the number of unfinished Tasks across Workers. E.g., `1`. | Yes | Yes | Yes | |
549
+ | `uploadFiles` | The list of files to be uploaded to the YellowDog Object Store. E.g., (JSON): `[{"localPath": file_1.txt", "uploadPath": "file_1.txt"}]`. | Yes | Yes | Yes | Yes |
550
+ | `vcpus` | Range constraint on number of vCPUs that are required to execute Tasks E.g., `[2.0, 4.0]`. | Yes | Yes | Yes | |
551
+ | `verifyAtStart` | A list of files required by a Task. Must be present when the Task is ready to start or the Task will fail. E.g.: `["task_group_1/task_1/results.txt"]`. | Yes | Yes | Yes | Yes |
552
+ | `verifyWait` | A list of files required by a Task. The Task will wait until the files are available before starting. E.g.: `["task_group_1/task_1/results.txt"]`. | Yes | Yes | Yes | Yes |
553
+ | `workerTags` | The list of Worker Tags that will be used to match against the Worker Tag of a candidate Worker. E.g., `["tag_x", "tag_y"]`. | Yes | Yes | Yes | |
554
+ | `workRequirementData` | The name of the file containing the JSON document in which the Work Requirement is defined. E.g., `"test_workreq.json"`. | Yes | | | |
531
555
 
532
556
  ## Automatic Properties
533
557
 
@@ -618,13 +642,9 @@ If the `executable` property is not supplied, the automatic processing described
618
642
 
619
643
  ### Task Counts
620
644
 
621
- This property will expand the number of Tasks to match `taskCount`.
622
-
623
- The `taskCount` property can be set only in the `workRequirement` section of the `config.toml` file, or in the `taskGroup` section(s) of a JSON Work Requirement definition.
624
-
625
- In the former case, the `taskCount` applies only to the Task specified within the `config.toml` file and is not inherited by JSON Work Requirement specifications.
645
+ The `taskCount` property can be used to expand the number of Tasks within a Task Group, by creating duplicates of a single Task. In JSON specifications, there must be zero or one Task(s) listed within each Task Group or `taskCount` is ignored.
626
646
 
627
- In the latter case, the `taskCount` applies to the Task specified within the Task Group, and there must be zero or one Task(s) listed within the group or `taskCount` is ignored.
647
+ This property can also be set on the command line using the `--task-count`/`-C` option of `yd-submit` followed by the required number of Tasks.
628
648
 
629
649
  ## Examples
630
650
 
@@ -662,6 +682,7 @@ Here's an example of the `workRequirement` section of a TOML configuration file,
662
682
  minWorkers = 1
663
683
  name = "my-work-requirement"
664
684
  outputs = ["results.txt"]
685
+ outputsOther = [{"directoryName" = "my_output_dir", "filePattern" = "out.txt", "required" = true}]
665
686
  outputsRequired = ["results_required.txt"]
666
687
  priority = 0.0
667
688
  providers = ["AWS"]
@@ -712,11 +733,13 @@ Showing all possible properties at the Work Requirement level:
712
733
  "minWorkers": 1,
713
734
  "name": "my-work-requirement",
714
735
  "outputs": ["results.txt"],
736
+ "outputsOther": [{"directoryName": "my_output_dir", "filePattern": "out.txt", "required": true}],
715
737
  "outputsRequired": ["results_required.txt"],
716
738
  "priority": 0.0,
717
739
  "providers": ["AWS"],
718
740
  "ram": [0.5, 2],
719
741
  "regions": ["eu-west-2"],
742
+ "taskCount": 100,
720
743
  "taskData": "my_task_data_string",
721
744
  "taskDataFile": "my_data_file.txt",
722
745
  "taskTypes": ["docker"],
@@ -766,6 +789,7 @@ Showing all possible properties at the Task Group level:
766
789
  "minWorkers": 1,
767
790
  "name": "first-task-group",
768
791
  "outputs": ["results.txt"],
792
+ "outputsOther": [{"directoryName": "my_output_dir", "filePattern": "out.txt", "required": true}],
769
793
  "outputsRequired": ["results_required.txt"],
770
794
  "priority": 0.0,
771
795
  "providers": ["AWS"],
@@ -819,6 +843,7 @@ Showing all possible properties at the Task level:
819
843
  "inputsOptional": ["optional.txt"],
820
844
  "name": "my-task",
821
845
  "outputs": ["results.txt"],
846
+ "outputsOther": [{"directoryName": "my_output_dir", "filePattern": "out.txt", "required": true}],
822
847
  "outputsRequired": ["results_required.txt"],
823
848
  "taskData": "my_task_data_string",
824
849
  "taskDataFile": "my_data_file.txt",
@@ -1148,7 +1173,7 @@ The Work Requirement name would then be available to the Task in the environment
1148
1173
 
1149
1174
  ### Files Uploaded from a Node to the Object Store after Task Execution
1150
1175
 
1151
- After Task completion, the Agent will upload specified output files to the Object Store. The files to be uploaded are those listed in the `outputs` and `outputsRequired` properties for the Task.
1176
+ After Task completion, the Agent will upload specified output files to the Object Store. The files to be uploaded are those listed in the `outputs`, `outputsRequired`, and `outputsOther` properties for the Task.
1152
1177
 
1153
1178
  In addition, the console output of the Task is captured in a file called `taskoutput.txt` in the root of the Task's working directory. Whether the `taskoutput.txt` file is uploaded to the Object Store is determined by the `captureTaskOutput` property for the Task, and this is set to 'true' by default.
1154
1179
 
@@ -1168,6 +1193,20 @@ The **`outputsRequired`** property can be used instead of (or in addition to) th
1168
1193
 
1169
1194
  `"outputsRequired": ["results/process_output.txt"]`
1170
1195
 
1196
+ The **`outputsOther`** property is used to collect outputs from directories that are not contained under the Task's working directory. In this case, the YellowDog Agent must be explicitly configured to allow upload from these directories by establishing this in the `application.yaml` file. For example:
1197
+
1198
+ ```yaml
1199
+ yda.outputSources:
1200
+ - name: "my_output_dir"
1201
+ path: "/tmp/outputs"
1202
+ ```
1203
+
1204
+ Then, in the list of entries in the `outputsOther` property, the `directoryName` property is set to be the **`name`** specified in the `application.yaml`. For example:
1205
+
1206
+ ```json
1207
+ "outputsOther": [{"directoryName": "my_output_dir", "filePattern": "out.txt", "required": true}]
1208
+ ```
1209
+
1171
1210
  ### Files Downloaded from the Object Store to Local Storage
1172
1211
 
1173
1212
  The `yd-download` command can download all objects from the Object Store to a local directory, on a per Work Requirement basis (including any files that have been uploaded). A local directory is created with the same name as the Namespace and containing the Work Requirement directories.
@@ -1212,7 +1251,7 @@ When a Task is allocated to a Worker on a node by the YellowDog Scheduler, the f
1212
1251
  4. The Agent then gathers any files in the `outputs` and `outputsRequired` lists and uploads them to the Object Store. If a file in the `outputsRequired` list is not found, the Task will be reported as failed. The Agent will also optionally upload the console output (including both `stdout` and `stderr`) of the Task, contained in the `taskoutput.txt` file.
1213
1252
  5. The ephemeral Task directory is then deleted.
1214
1253
 
1215
- Note that if a Task is aborted during execution, the Task's subprocess is sent a `SIGINT`, allowing the Task an opportunity to terminate any child processes or other resources (e.g., containers) that may have been started as part of Task execution.
1254
+ Note that if a Task is aborted during execution, the Task's subprocess is sent a `SIGTERM`, allowing the Task an opportunity to terminate any child processes or other resources (e.g., containers) that may have been started as part of Task execution.
1216
1255
 
1217
1256
  Once the steps above have been completed, the Worker is ready to accept its next Task from the YellowDog scheduler.
1218
1257
 
@@ -1337,6 +1376,8 @@ All variable substitutions unrelated to the CSV file data are left unchanged, fo
1337
1376
 
1338
1377
  If the value to be inserted is a number (an integer or floating point value) or Boolean, the `{{num:my_number_var}}` and `{{bool:my_boolean_var}}` forms can be used in the JSON file, as with their use in other parts of the JSON Work Requirement specification. The substituted value will assume the nominated type rather than being a string.
1339
1378
 
1379
+ The same is true for `array:` and `table:` for their respective data structures.
1380
+
1340
1381
  ### Property Inheritance
1341
1382
 
1342
1383
  All the usual property inheritance features operate as normal. Properties are inherited from the `config.toml` file, and from the relevant sections of the JSON Work Requirement file. Any properties set within a Task prototype are copied to all the generated Tasks.
@@ -1626,7 +1667,7 @@ When a JSON Worker Pool specification is used, the following properties from the
1626
1667
 
1627
1668
  Variable substitutions can be used within any property value in TOML configuration files or Worker Pool JSON files. See the description [above](#variable-substitutions) for more details on variable substitutions. This is a powerful feature that allows Worker Pools to be parameterised by supplying values on the command line, via environment variables, or via the TOML file.
1628
1669
 
1629
- An important distinction when using variable substitutions within Worker Pool (or Compute Requirement) JSON (or Jsonnet) documents is that each variable directive **must be preceded by a `__` (double underscore)** to disambiguate it from variable substitutions that are to be passed directly to the API. For example, use: `__{{username}}` to apply a substitution for the `username` default substitution.
1670
+ An important distinction when using variable substitutions within Worker Pool (or Compute Requirement) JSON (or Jsonnet) documents is that each variable directive **must be prefixed and postfixed by a `__` (double underscore)** to disambiguate it from variable substitutions that are to be passed directly to the API. For example, use: `__{{username}}__` to apply a substitution for the `username` default substitution.
1630
1671
 
1631
1672
  ## Dry-Running Worker Pool Provisioning
1632
1673
 
@@ -2008,7 +2049,7 @@ Please get in touch with YellowDog if you get stuck.
2008
2049
 
2009
2050
  ## Variable Substitutions in Jsonnet Files
2010
2051
 
2011
- The scripts provide full support for variable substitutions in Jsonnet files, using the same rules as for the JSON specifications. Remember that for **Worker Pool** and **Compute Requirement** specifications, variable substitutions must be prefixed by `__`, e.g. `"__{{username}}}"`.
2052
+ The scripts provide full support for variable substitutions in Jsonnet files, using the same rules as for the JSON specifications. Remember that for **Worker Pool** and **Compute Requirement** specifications, variable substitutions must be prefixed and postfixed by `__`, e.g. `"__{{username}}}__"`.
2012
2053
 
2013
2054
  Variable substitution is performed before Jsonnet expansion into JSON, and again after the expansion.
2014
2055
 
@@ -2293,15 +2334,17 @@ The `yd-instantiate` command instantiates a Compute Requirement (i.e., a set of
2293
2334
 
2294
2335
  This command uses the data from the `workerPool` configuration section (or, synonymously, the `computeRequirement` section), but only uses the `name`, `templateId`, `targetInstanceCount`, `instanceTags`, `userData`, and `imagesId` properties. In addition, the Boolean property `maintainInstanceCount` (default = `false`) is available for use with `yd-instantiate`.
2295
2336
 
2296
- Variable substitutions must be preceeded by a double underscore (`__`), e.g.: `"__{{my_variable}}"`.
2337
+ Compute Requirements can be instantiated directly from JSON (or Jsonnet) specifications, using the `--compute-requirement` (or `-C`) command line option, followed by the filename, or by using the `computeRequirementData` property in the `workerPool`/`computeRequirement` section. The properties listed above will be inherited from the config.toml `workerPool` specification if they are not present in the JSON file.
2338
+
2339
+ Variable substitutions must be prefixed and postfixed by a double underscore (`__`), e.g.: `"__{{my_variable}}__"`.
2297
2340
 
2298
- Compute Requirements can be instantiated directly from JSON (or Jsonnet) specifications, using the `--compute-requirement` (or `-C`) command line option, followed by the filename, or by using the `computeRequirementData` property in the `workerPool`/`computeRequirement` section. The properties listed above will be inherited from the config.toml `workerPool` specification if they are not present in the JSON file. An example JSON specification is shown below:
2341
+ An example JSON specification is shown below:
2299
2342
 
2300
2343
  ```json
2301
2344
  {
2302
2345
  "imagesId": "ydid:imgfam:000000:41962592-577c-4fde-ab03-d852465e7f8b",
2303
2346
  "instanceTags": {"a1": "one", "a2": "two"},
2304
- "requirementName": "cr_test_{{datetime}}",
2347
+ "requirementName": "cr_test___{{datetime}}__",
2305
2348
  "requirementNamespace": "pyexamples",
2306
2349
  "requirementTag": "pyexamples-test",
2307
2350
  "templateId": "ydid:crt:000000:230e9a42-97db-4d69-aa91-29ff309951b4",
@@ -0,0 +1,50 @@
1
+ """
2
+ Tests that run the standard demo dry-runs.
3
+ """
4
+
5
+ from cli_test_helpers import shell
6
+
7
+ DEMO_DIR = "../python-examples-demos"
8
+ CMD_SEQ = "yd-provision -D && yd-submit -D"
9
+
10
+
11
+ class TestDemoDryRuns:
12
+ def test_bash(self):
13
+ result = shell(f"cd {DEMO_DIR}/bash && {CMD_SEQ}")
14
+ assert result.exit_code == 0
15
+
16
+ def test_primes(self):
17
+ result = shell(f"cd {DEMO_DIR}/primes && {CMD_SEQ}")
18
+ assert result.exit_code == 0
19
+
20
+ def test_image_montage(self):
21
+ result = shell(f"cd {DEMO_DIR}/image-montage && {CMD_SEQ}")
22
+ assert result.exit_code == 0
23
+
24
+ def test_openfoam(self):
25
+ result = shell(f"cd {DEMO_DIR}/openfoam && {CMD_SEQ}")
26
+ assert result.exit_code == 0
27
+
28
+ def test_slurm_cluster(self):
29
+ result = shell(f"cd {DEMO_DIR}/slurm-cluster && {CMD_SEQ}")
30
+ assert result.exit_code == 0
31
+
32
+ def test_common_factors(self):
33
+ result = shell(f"cd {DEMO_DIR}/common-factors-csv && {CMD_SEQ}")
34
+ assert result.exit_code == 0
35
+
36
+ def test_virtual_screening(self):
37
+ result = shell(f"cd {DEMO_DIR}/virtual-screening && {CMD_SEQ}")
38
+ assert result.exit_code == 0
39
+
40
+ def test_benchmark(self):
41
+ result = shell(f"cd {DEMO_DIR}/benchmark && {CMD_SEQ}")
42
+ assert result.exit_code == 0
43
+
44
+ def test_powershell(self):
45
+ result = shell(f"cd {DEMO_DIR}/powershell && {CMD_SEQ}")
46
+ assert result.exit_code == 0
47
+
48
+ def test_cmd_exe(self):
49
+ result = shell(f"cd {DEMO_DIR}/cmd.exe && {CMD_SEQ}")
50
+ assert result.exit_code == 0
@@ -0,0 +1 @@
1
+ __version__ = "7.2.7"
@@ -24,11 +24,10 @@ from yd_commands.object_utilities import (
24
24
  get_work_requirement_summary_by_name_or_id,
25
25
  )
26
26
  from yd_commands.printing import print_error, print_log
27
+ from yd_commands.settings import TASK_ABORT_CHECK_INTERVAL
27
28
  from yd_commands.utils import link_entity
28
29
  from yd_commands.wrapper import ARGS_PARSER, CLIENT, CONFIG_COMMON, main_wrapper
29
30
 
30
- ABORT_RETRY_INTERVAL = 20 # Seconds
31
-
32
31
 
33
32
  @main_wrapper
34
33
  def main():
@@ -201,8 +200,10 @@ def abort_and_follow(work_requirement_summaries: List[WorkRequirementSummary]):
201
200
  print_log(f"Collecting Tasks to abort (attempt {attempt})")
202
201
  if abort_all_tasks(work_requirement_summaries) == 0:
203
202
  break
204
- print_log(f"Waiting {ABORT_RETRY_INTERVAL}s for abort confirmation ...")
205
- sleep(ABORT_RETRY_INTERVAL)
203
+ print_log(
204
+ f"Waiting {TASK_ABORT_CHECK_INTERVAL}s for abort confirmation ..."
205
+ )
206
+ sleep(TASK_ABORT_CHECK_INTERVAL)
206
207
  else:
207
208
  print_log("Aborting all currently running Tasks")
208
209
  abort_all_tasks(work_requirement_summaries)
@@ -5,16 +5,7 @@ Configuration classes and constants.
5
5
  from dataclasses import dataclass, field
6
6
  from typing import Dict, List, Optional
7
7
 
8
- YD_KEY = "YD_KEY"
9
- YD_SECRET = "YD_SECRET"
10
- YD_NAMESPACE = "YD_NAMESPACE"
11
- YD_TAG = "YD_TAG"
12
- YD_URL = "YD_URL"
13
- TASK_BATCH_SIZE_DEFAULT = 2000
14
- DEFAULT_URL = "https://portal.yellowdog.co/api"
15
- NAMESPACE_SEPARATOR = "::"
16
- CR_BATCH_SIZE_DEFAULT = 10000
17
- WP_VARIABLES_PREFIX = "__"
8
+ from yd_commands.settings import CR_BATCH_SIZE_DEFAULT, TASK_BATCH_SIZE_DEFAULT
18
9
 
19
10
 
20
11
  @dataclass
@@ -52,6 +43,7 @@ class ConfigWorkRequirement:
52
43
  max_workers: Optional[int] = None
53
44
  min_workers: Optional[int] = None
54
45
  outputs_optional: List[str] = field(default_factory=list)
46
+ outputs_other: List[Dict] = field(default_factory=list)
55
47
  outputs_required: List[str] = field(default_factory=list)
56
48
  priority: float = 0.0
57
49
  providers: Optional[List[str]] = None
@@ -15,11 +15,15 @@ from yd_commands.args import ARGS_PARSER
15
15
  from yd_commands.config_types import ConfigWorkRequirement
16
16
  from yd_commands.printing import print_json, print_log
17
17
  from yd_commands.property_names import *
18
+ from yd_commands.settings import (
19
+ BOOL_TYPE_TAG,
20
+ CSV_VAR_CLOSING_DELIMITER,
21
+ CSV_VAR_OPENING_DELIMITER,
22
+ NUMBER_TYPE_TAG,
23
+ )
18
24
  from yd_commands.variables import (
19
- BOOL_SUB,
20
- NUMBER_SUB,
21
25
  load_jsonnet_file_with_variable_substitutions,
22
- process_variable_substitutions,
26
+ process_variable_substitutions_in_dict_insitu,
23
27
  )
24
28
 
25
29
 
@@ -216,7 +220,7 @@ def perform_csv_task_expansion(wr_data: Dict, csv_files: List[str]) -> Dict:
216
220
  exit(0)
217
221
 
218
222
  # Process remaining substitutions
219
- process_variable_substitutions(wr_data)
223
+ process_variable_substitutions_in_dict_insitu(wr_data)
220
224
  return wr_data
221
225
 
222
226
 
@@ -238,9 +242,11 @@ def make_string_substitutions(input: str, var_name: str, value: str) -> str:
238
242
  """
239
243
  Helper function to make string substitutions for CSV variables only.
240
244
  """
241
- input = input.replace(f"{{{{{var_name}}}}}", value)
245
+ input = input.replace(
246
+ f"{CSV_VAR_OPENING_DELIMITER}{var_name}{CSV_VAR_CLOSING_DELIMITER}", value
247
+ )
242
248
 
243
- num_sub_str = f"{{{{{NUMBER_SUB}{var_name}}}}}"
249
+ num_sub_str = f"{CSV_VAR_OPENING_DELIMITER}{NUMBER_TYPE_TAG}{var_name}{CSV_VAR_CLOSING_DELIMITER}"
244
250
  if num_sub_str in input:
245
251
  try:
246
252
  float(value)
@@ -248,7 +254,7 @@ def make_string_substitutions(input: str, var_name: str, value: str) -> str:
248
254
  raise Exception(f"Invalid number substitution in CSV: '{value}'")
249
255
  input = input.replace(f"'{num_sub_str}'", value)
250
256
 
251
- bool_sub_str = f"{{{{{BOOL_SUB}{var_name}}}}}"
257
+ bool_sub_str = f"{CSV_VAR_OPENING_DELIMITER}{BOOL_TYPE_TAG}{var_name}{CSV_VAR_CLOSING_DELIMITER}"
252
258
  if bool_sub_str in input:
253
259
  if value.lower() == "true":
254
260
  value = "True"
@@ -314,13 +320,20 @@ def substitions_present(var_names: List[str], task_prototype: str) -> bool:
314
320
  Check if there are any CSV substitutions present in the Task prototype.
315
321
  """
316
322
  return (
317
- any(f"{{{{{var_name}}}}}" in task_prototype for var_name in var_names)
323
+ any(
324
+ f"{CSV_VAR_OPENING_DELIMITER}{var_name}{CSV_VAR_CLOSING_DELIMITER}"
325
+ in task_prototype
326
+ for var_name in var_names
327
+ )
318
328
  or any(
319
- f"{{{{{NUMBER_SUB}{var_name}}}}}" in task_prototype
329
+ f"{CSV_VAR_OPENING_DELIMITER}{NUMBER_TYPE_TAG}{var_name}{CSV_VAR_CLOSING_DELIMITER}"
330
+ in task_prototype
320
331
  for var_name in var_names
321
332
  )
322
333
  or any(
323
- f"{{{{{BOOL_SUB}{var_name}}}}}" in task_prototype for var_name in var_names
334
+ f"{CSV_VAR_OPENING_DELIMITER}{BOOL_TYPE_TAG}{var_name}{CSV_VAR_CLOSING_DELIMITER}"
335
+ in task_prototype
336
+ for var_name in var_names
324
337
  )
325
338
  )
326
339
 
@@ -347,6 +360,7 @@ def csv_expand_toml_tasks(config_wr: ConfigWorkRequirement, csv_file: str) -> Di
347
360
  (config_wr.inputs_optional, INPUTS_OPTIONAL),
348
361
  (config_wr.inputs_required, INPUTS_REQUIRED),
349
362
  (config_wr.outputs_optional, OUTPUTS_OPTIONAL),
363
+ (config_wr.outputs_other, OUTPUTS_OTHER),
350
364
  (config_wr.outputs_required, OUTPUTS_REQUIRED),
351
365
  (config_wr.task_data, TASK_DATA),
352
366
  (config_wr.task_data_file, TASK_DATA_FILE),
@@ -356,6 +370,7 @@ def csv_expand_toml_tasks(config_wr: ConfigWorkRequirement, csv_file: str) -> Di
356
370
  (config_wr.upload_files, UPLOAD_FILES),
357
371
  (config_wr.verify_at_start, VERIFY_AT_START),
358
372
  (config_wr.verify_wait, VERIFY_WAIT),
373
+ # Note: not TASK_COUNT; count determined by CSV data
359
374
  ]:
360
375
  if config_value is not None and substitions_present(
361
376
  csv_data.var_names, str(config_value)
@@ -15,7 +15,7 @@ from yellowdog_client.model import (
15
15
  ComputeRequirementTemplateUsage,
16
16
  )
17
17
 
18
- from yd_commands.config_types import WP_VARIABLES_PREFIX, ConfigWorkerPool
18
+ from yd_commands.config_types import ConfigWorkerPool
19
19
  from yd_commands.follow_utils import follow_events, follow_ids
20
20
  from yd_commands.id_utils import YDIDType
21
21
  from yd_commands.load_config import load_config_worker_pool
@@ -26,6 +26,7 @@ from yd_commands.printing import (
26
26
  print_yd_object,
27
27
  )
28
28
  from yd_commands.provision_utils import get_user_data_property
29
+ from yd_commands.settings import WP_VARIABLES_POSTFIX, WP_VARIABLES_PREFIX
29
30
  from yd_commands.utils import add_batch_number_postfix, generate_id, link_entity
30
31
  from yd_commands.variables import (
31
32
  load_json_file_with_variable_substitutions,
@@ -60,7 +61,9 @@ def main():
60
61
 
61
62
  if cr_json_file is not None:
62
63
  print_log(f"Loading Compute Requirement data from: '{cr_json_file}'")
63
- create_compute_requirement_from_json(cr_json_file, WP_VARIABLES_PREFIX)
64
+ create_compute_requirement_from_json(
65
+ cr_json_file, WP_VARIABLES_PREFIX, WP_VARIABLES_POSTFIX
66
+ )
64
67
  return
65
68
 
66
69
  if CONFIG_WP.template_id is None:
@@ -195,7 +198,9 @@ def _allocate_nodes_to_batches(
195
198
  return batches
196
199
 
197
200
 
198
- def create_compute_requirement_from_json(cr_json_file: str, prefix: str = "") -> None:
201
+ def create_compute_requirement_from_json(
202
+ cr_json_file: str, prefix: str = "", postfix: str = ""
203
+ ) -> None:
199
204
  """
200
205
  Directly create the Compute Requirement using the YellowDog REST API.
201
206
  """
@@ -208,11 +213,11 @@ def create_compute_requirement_from_json(cr_json_file: str, prefix: str = "") ->
208
213
 
209
214
  if cr_json_file.lower().endswith(".jsonnet"):
210
215
  cr_data = load_jsonnet_file_with_variable_substitutions(
211
- cr_json_file, prefix=prefix
216
+ cr_json_file, prefix=prefix, postfix=postfix
212
217
  )
213
218
  else:
214
219
  cr_data = load_json_file_with_variable_substitutions(
215
- cr_json_file, prefix=prefix
220
+ cr_json_file, prefix=prefix, postfix=postfix
216
221
  )
217
222
 
218
223
  # Use only the 'requirementTemplateUsage' value (if present);