idmtools-cli 0.0.0.dev0__tar.gz → 0.0.3__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 (36) hide show
  1. idmtools_cli-0.0.3/.bumpversion.cfg +28 -0
  2. idmtools_cli-0.0.3/LICENSE.TXT +3 -0
  3. idmtools_cli-0.0.3/MANIFEST.in +4 -0
  4. idmtools_cli-0.0.3/Makefile +2 -0
  5. idmtools_cli-0.0.3/PKG-INFO +208 -0
  6. idmtools_cli-0.0.3/README.md +181 -0
  7. idmtools_cli-0.0.3/idmtools_cli/__init__.py +12 -0
  8. idmtools_cli-0.0.3/idmtools_cli/cli/__init__.py +1 -0
  9. idmtools_cli-0.0.3/idmtools_cli/cli/common_project_templates.json +19 -0
  10. idmtools_cli-0.0.3/idmtools_cli/cli/config_file.py +199 -0
  11. idmtools_cli-0.0.3/idmtools_cli/cli/entrypoint.py +45 -0
  12. idmtools_cli-0.0.3/idmtools_cli/cli/gitrepo.py +393 -0
  13. idmtools_cli-0.0.3/idmtools_cli/cli/init.py +113 -0
  14. idmtools_cli-0.0.3/idmtools_cli/cli/package.py +106 -0
  15. idmtools_cli-0.0.3/idmtools_cli/cli/system_info.py +158 -0
  16. idmtools_cli-0.0.3/idmtools_cli/cli/utils.py +49 -0
  17. idmtools_cli-0.0.3/idmtools_cli/iplatform_cli.py +141 -0
  18. idmtools_cli-0.0.3/idmtools_cli/main.py +52 -0
  19. idmtools_cli-0.0.3/idmtools_cli/utils/__init__.py +1 -0
  20. idmtools_cli-0.0.3/idmtools_cli/utils/cols.py +135 -0
  21. idmtools_cli-0.0.3/idmtools_cli/utils/formatters.py +105 -0
  22. idmtools_cli-0.0.3/idmtools_cli/utils/utils.py +63 -0
  23. idmtools_cli-0.0.3/idmtools_cli.egg-info/PKG-INFO +208 -0
  24. idmtools_cli-0.0.3/idmtools_cli.egg-info/SOURCES.txt +28 -0
  25. idmtools_cli-0.0.3/idmtools_cli.egg-info/entry_points.txt +2 -0
  26. idmtools_cli-0.0.3/idmtools_cli.egg-info/requires.txt +11 -0
  27. idmtools_cli-0.0.3/pyproject.toml +70 -0
  28. {idmtools_cli-0.0.0.dev0 → idmtools_cli-0.0.3}/setup.cfg +4 -4
  29. idmtools_cli-0.0.0.dev0/PKG-INFO +0 -41
  30. idmtools_cli-0.0.0.dev0/README.md +0 -21
  31. idmtools_cli-0.0.0.dev0/idmtools_cli/__init__.py +0 -8
  32. idmtools_cli-0.0.0.dev0/idmtools_cli.egg-info/PKG-INFO +0 -41
  33. idmtools_cli-0.0.0.dev0/idmtools_cli.egg-info/SOURCES.txt +0 -7
  34. idmtools_cli-0.0.0.dev0/pyproject.toml +0 -32
  35. {idmtools_cli-0.0.0.dev0 → idmtools_cli-0.0.3}/idmtools_cli.egg-info/dependency_links.txt +0 -0
  36. {idmtools_cli-0.0.0.dev0 → idmtools_cli-0.0.3}/idmtools_cli.egg-info/top_level.txt +0 -0
@@ -0,0 +1,28 @@
1
+ [bumpversion]
2
+ current_version = 3.0.0+nightly
3
+ commit = False
4
+ tag = False
5
+ parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?P<release>\+\w+)?(\.(?P<build>\d+))?
6
+ serialize =
7
+ {major}.{minor}.{patch}{release}.{build}
8
+ {major}.{minor}.{patch}{release}
9
+ {major}.{minor}.{patch}
10
+
11
+ [bumpversion:part:release]
12
+ optional_value = prod
13
+ first_value = prod
14
+ values =
15
+ prod
16
+ +nightly
17
+
18
+ [bumpversion:file:./idmtools_cli/__init__.py]
19
+ search = __version__ = "{current_version}"
20
+ replace = __version__ = "{new_version}"
21
+ serialize = {major}.{minor}.{patch}{release}
22
+ {major}.{minor}.{patch}
23
+
24
+ [bumpversion:file:./pyproject.toml]
25
+ search = version = "{current_version}"
26
+ replace = version = "{new_version}"
27
+ serialize = {major}.{minor}.{patch}{release}
28
+ {major}.{minor}.{patch}
@@ -0,0 +1,3 @@
1
+ idmtools is licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 License.
2
+
3
+ To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
@@ -0,0 +1,4 @@
1
+ include idmtools_cli/cli/common_project_templates.json
2
+ include README.md
3
+ include LICENSE.TXT
4
+ prune tests
@@ -0,0 +1,2 @@
1
+ PACKAGE_NAME=idmtools_cli
2
+ include $(abspath ../dev_scripts/package_general.mk)
@@ -0,0 +1,208 @@
1
+ Metadata-Version: 2.4
2
+ Name: idmtools_cli
3
+ Version: 0.0.3
4
+ Summary: CLI for IDM-Tools
5
+ Author-email: Sharon Chen <schen@idmod.org>, Clinton Collins <ccollins@idmod.org>, Zhaowei Du <zdu@idmod.org>, Mary Fisher <mfisher@idmod.org>, Clark Kirkman IV <ckirkman@idmod.org>, Benoit Raybaud <braybaud@idmod.org>
6
+ Project-URL: Homepage, https://github.com/InstituteforDiseaseModeling/idmtools
7
+ Keywords: modeling,IDM,cli
8
+ Classifier: Programming Language :: Python :: 3.8
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Requires-Python: >=3.8
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE.TXT
16
+ Requires-Dist: click~=8.1.7
17
+ Requires-Dist: click-plugins
18
+ Requires-Dist: colorama~=0.4.6
19
+ Requires-Dist: cookiecutter~=2.6.0
20
+ Requires-Dist: idmtools<1.0.0,>=0.0.0
21
+ Requires-Dist: tabulate<0.10,>=0.8.9
22
+ Requires-Dist: pyperclip~=1.8
23
+ Requires-Dist: yaspin<3.1.0,>=1.2.0
24
+ Provides-Extra: test
25
+ Requires-Dist: idmtools[test]; extra == "test"
26
+ Dynamic: license-file
27
+
28
+ ![Staging: idmtools-cli](https://github.com/InstituteforDiseaseModeling/idmtools/workflows/Staging:%20idmtools-cli/badge.svg?branch=dev)
29
+
30
+ # idmtools-cli
31
+
32
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
33
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
34
+ **Table of Contents**
35
+
36
+ - [Installing](#installing)
37
+ - [Development tips](#development-tips)
38
+ - [Using the CLI](#using-the-cli)
39
+ - [Version command](#version-command)
40
+ - [Experiment commands for Local Platform](#experiment-commands-for-local-platform)
41
+ - [Status](#status)
42
+ - [Delete](#delete)
43
+ - [Simulation commands for Local Platform](#simulation-commands-for-local-platform)
44
+ - [Status](#status-1)
45
+ - [GitRepo commands](#gitrepo-commands)
46
+ - [View](#view)
47
+ - [Repos](#repos)
48
+ - [Releases](#releases)
49
+ - [Peep](#peep)
50
+ - [Download](#download)
51
+
52
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
53
+
54
+ ## Installing
55
+
56
+ ```bash
57
+ pip install idmtools-cli --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
58
+ ```
59
+
60
+ # Development tips
61
+
62
+ There is a Makefile file available for most common development tasks. Here is a list of commands
63
+ ```bash
64
+ clean - Clean up temproary files
65
+ lint - Lint package and tests
66
+ test - Run All tests
67
+ coverage - Run tests and generate coverage report that is shown in browser
68
+ ```
69
+ On Windows, you can use `pymake` instead of `make`
70
+
71
+ # Using the CLI
72
+
73
+ The CLI requires the workers service to already be running.
74
+ `idmtools`
75
+
76
+ ## Version command
77
+
78
+ To determine version of idmtools and related plugins, use the version cli command.
79
+
80
+
81
+ ```
82
+ > idmtools version
83
+ ```
84
+
85
+ Example output
86
+ ```bash
87
+ emodpy Version: 1.3.0
88
+ Plugins:
89
+ EMODTask
90
+ idmtools Version: 1.4.0+nightly.0
91
+ Plugins:
92
+ CommandTask
93
+ idmtools-cli Version: 1.4.0+nightly.0
94
+ idmtools-models Version: 1.4.0+nightly.0
95
+ Plugins:
96
+ JSONConfiguredPythonTask
97
+ JSONConfiguredRTask
98
+ JSONConfiguredTask
99
+ PythonTask
100
+ RTask
101
+ ScriptWrapperTask
102
+ TemplatedScriptTask
103
+ idmtools-platform-comps Version: 1.4.0+nightly.0
104
+ Plugins:
105
+ COMPSPlatform
106
+ SSMTPlatform
107
+ idmtools-platform-slurm Version: 1.0.0+nightly
108
+ Plugins:
109
+ SlurmPlatform
110
+ ```
111
+
112
+
113
+ ## Experiment commands for Local Platform
114
+
115
+ ### Status
116
+
117
+ You can check the status of experiments use the follow command. It will also summarize the simulations under
118
+ the experiment as a progress bar with green section for completed tasks, yellow for in progress, red for failed, and
119
+ white for queued.
120
+
121
+ ```
122
+ > idmtools experiment --platform Local status --help
123
+ ```
124
+
125
+
126
+ In addition, we used in conjunction with a console that supports auto-highlighting of hyperlinks, you will be able to
127
+ easily open up the asset directories by clicking on the data path URLs.
128
+
129
+ You can also perform filtering on the experiments
130
+ ```bash
131
+ > idmtools experiment --platform Local status --tag type PythonExperiment
132
+ > idmtools experiment --platform Local status --id 8EHU147Z
133
+ ```
134
+
135
+ ### Delete
136
+
137
+ You can delete experiments and their child simulations using the following command. Optionally you can also delete
138
+ the associated data directories as well by using the *--data* option.
139
+
140
+ ```
141
+ >idmtools experiment --platform Local delete <experiment_id>
142
+ ```
143
+
144
+ ## Simulation commands for Local Platform
145
+
146
+ ## Status
147
+
148
+ You can check the status of simulations use the follow command.
149
+
150
+ ```
151
+ >idmtools simulation --platform Local status
152
+ ```
153
+
154
+ You can also filter by a either id, experiment id, status, and tags or any combination of the aforementioned
155
+
156
+ ```bash
157
+ > idmtools simulation --platform Local status --experiment-id EFX6JXBV
158
+ > idmtools simulation --platform Local status --id XDT0VMVV
159
+ > idmtools simulation --platform Local status --tag a 5 --tag b
160
+ > idmtools simulation --platform Local status --experiment-id --status failed
161
+ ```
162
+
163
+
164
+ ## GitRepo commands
165
+
166
+ ### View
167
+
168
+ You can check idmtools available examples. You can use --raw to determine to display in detailed or simplified format
169
+
170
+ ```
171
+ > idmtools gitrepo view
172
+ ```
173
+
174
+ ### Repos
175
+
176
+ You can list all public repos for a GitHub owner. You can use --owner to specify an owner and --page for pagination
177
+ --owner default to 'institutefordiseasemodeling'
178
+ --page default to 1
179
+
180
+ ```
181
+ > idmtools gitrepo repos
182
+ ```
183
+
184
+ ### Releases
185
+
186
+ You can list all releases of a repo by providing --owner and --repo
187
+ --owner default to 'institutefordiseasemodeling' and --repo default to 'idmtools'
188
+
189
+ ```
190
+ > idmtools gitrepo releasess
191
+ ```
192
+
193
+ ### Peep
194
+
195
+ You can list all current files/dirs of a repo folder by providing --url
196
+
197
+ ```
198
+ > idmtools gitrepo peep
199
+ ```
200
+
201
+ ### Download
202
+
203
+ You can download files from a public repo to a specified local folder (default to current folder). By default, it will
204
+ download idmtools examples. You can also download any files from any public repo by using --url (multiple is supported)
205
+
206
+ ```
207
+ > idmtools gitrepo download
208
+ ```
@@ -0,0 +1,181 @@
1
+ ![Staging: idmtools-cli](https://github.com/InstituteforDiseaseModeling/idmtools/workflows/Staging:%20idmtools-cli/badge.svg?branch=dev)
2
+
3
+ # idmtools-cli
4
+
5
+ <!-- START doctoc generated TOC please keep comment here to allow auto update -->
6
+ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
7
+ **Table of Contents**
8
+
9
+ - [Installing](#installing)
10
+ - [Development tips](#development-tips)
11
+ - [Using the CLI](#using-the-cli)
12
+ - [Version command](#version-command)
13
+ - [Experiment commands for Local Platform](#experiment-commands-for-local-platform)
14
+ - [Status](#status)
15
+ - [Delete](#delete)
16
+ - [Simulation commands for Local Platform](#simulation-commands-for-local-platform)
17
+ - [Status](#status-1)
18
+ - [GitRepo commands](#gitrepo-commands)
19
+ - [View](#view)
20
+ - [Repos](#repos)
21
+ - [Releases](#releases)
22
+ - [Peep](#peep)
23
+ - [Download](#download)
24
+
25
+ <!-- END doctoc generated TOC please keep comment here to allow auto update -->
26
+
27
+ ## Installing
28
+
29
+ ```bash
30
+ pip install idmtools-cli --index-url=https://packages.idmod.org/api/pypi/pypi-production/simple
31
+ ```
32
+
33
+ # Development tips
34
+
35
+ There is a Makefile file available for most common development tasks. Here is a list of commands
36
+ ```bash
37
+ clean - Clean up temproary files
38
+ lint - Lint package and tests
39
+ test - Run All tests
40
+ coverage - Run tests and generate coverage report that is shown in browser
41
+ ```
42
+ On Windows, you can use `pymake` instead of `make`
43
+
44
+ # Using the CLI
45
+
46
+ The CLI requires the workers service to already be running.
47
+ `idmtools`
48
+
49
+ ## Version command
50
+
51
+ To determine version of idmtools and related plugins, use the version cli command.
52
+
53
+
54
+ ```
55
+ > idmtools version
56
+ ```
57
+
58
+ Example output
59
+ ```bash
60
+ emodpy Version: 1.3.0
61
+ Plugins:
62
+ EMODTask
63
+ idmtools Version: 1.4.0+nightly.0
64
+ Plugins:
65
+ CommandTask
66
+ idmtools-cli Version: 1.4.0+nightly.0
67
+ idmtools-models Version: 1.4.0+nightly.0
68
+ Plugins:
69
+ JSONConfiguredPythonTask
70
+ JSONConfiguredRTask
71
+ JSONConfiguredTask
72
+ PythonTask
73
+ RTask
74
+ ScriptWrapperTask
75
+ TemplatedScriptTask
76
+ idmtools-platform-comps Version: 1.4.0+nightly.0
77
+ Plugins:
78
+ COMPSPlatform
79
+ SSMTPlatform
80
+ idmtools-platform-slurm Version: 1.0.0+nightly
81
+ Plugins:
82
+ SlurmPlatform
83
+ ```
84
+
85
+
86
+ ## Experiment commands for Local Platform
87
+
88
+ ### Status
89
+
90
+ You can check the status of experiments use the follow command. It will also summarize the simulations under
91
+ the experiment as a progress bar with green section for completed tasks, yellow for in progress, red for failed, and
92
+ white for queued.
93
+
94
+ ```
95
+ > idmtools experiment --platform Local status --help
96
+ ```
97
+
98
+
99
+ In addition, we used in conjunction with a console that supports auto-highlighting of hyperlinks, you will be able to
100
+ easily open up the asset directories by clicking on the data path URLs.
101
+
102
+ You can also perform filtering on the experiments
103
+ ```bash
104
+ > idmtools experiment --platform Local status --tag type PythonExperiment
105
+ > idmtools experiment --platform Local status --id 8EHU147Z
106
+ ```
107
+
108
+ ### Delete
109
+
110
+ You can delete experiments and their child simulations using the following command. Optionally you can also delete
111
+ the associated data directories as well by using the *--data* option.
112
+
113
+ ```
114
+ >idmtools experiment --platform Local delete <experiment_id>
115
+ ```
116
+
117
+ ## Simulation commands for Local Platform
118
+
119
+ ## Status
120
+
121
+ You can check the status of simulations use the follow command.
122
+
123
+ ```
124
+ >idmtools simulation --platform Local status
125
+ ```
126
+
127
+ You can also filter by a either id, experiment id, status, and tags or any combination of the aforementioned
128
+
129
+ ```bash
130
+ > idmtools simulation --platform Local status --experiment-id EFX6JXBV
131
+ > idmtools simulation --platform Local status --id XDT0VMVV
132
+ > idmtools simulation --platform Local status --tag a 5 --tag b
133
+ > idmtools simulation --platform Local status --experiment-id --status failed
134
+ ```
135
+
136
+
137
+ ## GitRepo commands
138
+
139
+ ### View
140
+
141
+ You can check idmtools available examples. You can use --raw to determine to display in detailed or simplified format
142
+
143
+ ```
144
+ > idmtools gitrepo view
145
+ ```
146
+
147
+ ### Repos
148
+
149
+ You can list all public repos for a GitHub owner. You can use --owner to specify an owner and --page for pagination
150
+ --owner default to 'institutefordiseasemodeling'
151
+ --page default to 1
152
+
153
+ ```
154
+ > idmtools gitrepo repos
155
+ ```
156
+
157
+ ### Releases
158
+
159
+ You can list all releases of a repo by providing --owner and --repo
160
+ --owner default to 'institutefordiseasemodeling' and --repo default to 'idmtools'
161
+
162
+ ```
163
+ > idmtools gitrepo releasess
164
+ ```
165
+
166
+ ### Peep
167
+
168
+ You can list all current files/dirs of a repo folder by providing --url
169
+
170
+ ```
171
+ > idmtools gitrepo peep
172
+ ```
173
+
174
+ ### Download
175
+
176
+ You can download files from a public repo to a specified local folder (default to current folder). By default, it will
177
+ download idmtools examples. You can also download any files from any public repo by using --url (multiple is supported)
178
+
179
+ ```
180
+ > idmtools gitrepo download
181
+ ```
@@ -0,0 +1,12 @@
1
+ """iidmtools_cli version definition file."""
2
+ try:
3
+ from importlib.metadata import version, PackageNotFoundError
4
+ except ImportError:
5
+ # Python < 3.8
6
+ from importlib_metadata import version, PackageNotFoundError
7
+
8
+ try:
9
+ __version__ = version("idmtools-cli") # Use your actual package name
10
+ except PackageNotFoundError:
11
+ # Package not installed, use fallback
12
+ __version__ = "0.0.0+unknown"
@@ -0,0 +1 @@
1
+ """Package init file."""
@@ -0,0 +1,19 @@
1
+ [{
2
+ "name": "reproducible-science",
3
+ "url": "gh:mkrapp/cookiecutter-reproducible-science",
4
+ "description": "A boilerplate for reproducible and transparent science with close resemblances to the philosophy of Cookiecutter Data Science: A logical, reasonably standardized, but flexible project structure for doing and sharing data science work.",
5
+ "info": "https://github.com/mkrapp/cookiecutter-reproducible-science"
6
+ },
7
+ {
8
+ "name": "docker-science",
9
+ "url": "git@github.com:docker-science/cookiecutter-docker-science.git",
10
+ "description": "This project is a tiny template for machine learning projects developed in Docker environments. In machine learning tasks, projects glow uniquely to fit target tasks, but in the initial state, most directory structure and targets in Makefile are common. Cookiecutter Docker Science generates initial directories which fits simple machine learning tasks.",
11
+ "info": "https://docker-science.github.io/"
12
+ },
13
+ {
14
+ "name": "data-science",
15
+ "url": "https://github.com/drivendata/cookiecutter-data-science",
16
+ "description": "A logical, reasonably standardized, but flexible project structure for doing and sharing data science work.",
17
+ "info": "https://docker-science.github.io/"
18
+ }
19
+ ]
@@ -0,0 +1,199 @@
1
+ """Defines the config cli group and commands."""
2
+ import configparser
3
+ import dataclasses
4
+ import os
5
+ import re
6
+ import click
7
+ from click import secho
8
+ from colorama import Fore, Style
9
+ from idmtools.registry.platform_specification import PlatformPlugins
10
+ from idmtools_cli.cli.entrypoint import cli
11
+
12
+ IGNORED_PLATFORMS = ["Test", "Slurm", "File", "Container", "SSMT", "TestExecute", "Process"]
13
+ AVAILABLE_PLATFORMS = PlatformPlugins().get_plugin_map()
14
+ for platform in IGNORED_PLATFORMS:
15
+ if platform in AVAILABLE_PLATFORMS:
16
+ del AVAILABLE_PLATFORMS[platform]
17
+ HIDDEN_FIELD_REGEX = re.compile('^_.+$')
18
+ FIELD_BLACKLIST = ['platform_type_map', 'supported_types', 'plugin_key', 'docker_image']
19
+
20
+
21
+ @cli.group()
22
+ @click.option("--config_path", prompt="Path to the idmtools.ini file",
23
+ help="Path to the idmtools.ini file",
24
+ default=os.path.join(os.getcwd(), "idmtools.ini"),
25
+ type=click.Path(dir_okay=False, file_okay=True, exists=False, writable=True, resolve_path=True))
26
+ @click.option("--global-config/--no-global-config", default=False, help="Allow generating config in the platform default global location")
27
+ @click.pass_context
28
+ def config(ctx, config_path, global_config):
29
+ """
30
+ Contains commands related to the creation of idmtools.ini.
31
+
32
+ With the config command, you can :
33
+ - Generate an idmtools.ini file in the current directory
34
+ - Add a configuration block
35
+ """
36
+ ctx.ensure_object(dict)
37
+ if global_config:
38
+ from idmtools import IdmConfigParser
39
+ config_path = IdmConfigParser.get_global_configuration_name()
40
+
41
+ # Create a config parser and read the file if it exist
42
+ # The comment prefixes and allow_no_value is a truck to keep the comments even while editing
43
+ cp = configparser.ConfigParser(comment_prefixes='/', allow_no_value=True)
44
+ if os.path.exists(config_path):
45
+ cp.read_file(open(config_path))
46
+
47
+ # Store the config parser in the context
48
+ ctx.obj["cp"] = cp
49
+ ctx.obj["path"] = config_path
50
+
51
+
52
+ def slugify(value):
53
+ """
54
+ Slugify the option.
55
+
56
+ This means upper-casing and replacing spaces with "-"
57
+
58
+ Args:
59
+ value: Item to slugify
60
+
61
+ Returns:
62
+ Slugified string
63
+ """
64
+ value = value.upper()
65
+ value = value.replace(" ", "_")
66
+ return value
67
+
68
+
69
+ def validate_block_name(context, value):
70
+ """
71
+ Validate if a block name exists, and if so, should we overwrite it.
72
+
73
+ Args:
74
+ context: Context object
75
+ value: Value to check
76
+
77
+ Returns:
78
+ Slugified value name
79
+ """
80
+ cp = context.obj["cp"]
81
+ value = slugify(value)
82
+ if value in cp.sections():
83
+ secho(f"The {value} block already exists in the selected ini file.", fg="bright_yellow")
84
+ click.confirm(click.style("Do you want to continue and overwrite the existing block?", fg="bright_yellow"), default=False, abort=True)
85
+
86
+ # Remove the block from the config parser
87
+ del cp[value]
88
+
89
+ context.obj['cp'] = cp
90
+
91
+ return value
92
+
93
+
94
+ @config.command()
95
+ @click.option("--block_name", prompt="New block name",
96
+ help="Name of the new block in the file",
97
+ callback=lambda c, p, v: validate_block_name(c, v),
98
+ type=click.STRING)
99
+ @click.option('--platform', default='COMPS', type=click.Choice(AVAILABLE_PLATFORMS.keys()), prompt="Platform type")
100
+ @click.pass_context
101
+ def block(ctx, block_name, platform):
102
+ """
103
+ Command to create/replace a block in the selected idmtools.ini.
104
+
105
+ Args:
106
+ ctx: Context containing the path of idmtools.ini and the associated configparser
107
+ block_name: Name of the block to create/replace
108
+ platform: Selected platform
109
+ """
110
+ config_path = ctx.obj['path']
111
+ print("\n" + Style.BRIGHT + "-" * 50)
112
+ print("idmtools.ini Utility")
113
+ print(f"- INI Location: {config_path}")
114
+ print(f"- Selected block: {block_name}")
115
+ print(f"- Selected platform: {platform}")
116
+ print("-" * 50 + Style.NORMAL + "\n")
117
+
118
+ # Retrieve the platform and its associated fields
119
+ platform_obj = AVAILABLE_PLATFORMS[platform]
120
+ fields = dataclasses.fields(platform_obj.get_type())
121
+
122
+ # Dictionary to store user choices and field defaults
123
+ # Store both to allow the fields callback functions to access the previous user choices regardless of defaults
124
+ values = {"type": platform}
125
+ defaults = {}
126
+
127
+ # Ask about each field
128
+ # The field needs to contain a `help` section in the metadata to be considered
129
+ for field in filter(lambda f: "help" in f.metadata, fields):
130
+
131
+ # Display the help message
132
+ print(f"{Fore.CYAN}{field.metadata['help']}{Fore.RESET}")
133
+
134
+ # Retrieve the metadata
135
+ md = dict(field.metadata)
136
+
137
+ # If a callback exists -> execute it
138
+ if "callback" in md:
139
+ md.update(md["callback"](values, field))
140
+
141
+ # Create the default
142
+ field_default = md.get("default", field.default if field.default is not None else '')
143
+ defaults[field.name] = field.default
144
+
145
+ # Handle the choices if any
146
+ prompt_type = click.Choice(md["choices"]) if "choices" in md else field.type
147
+
148
+ # Retrieve the validation function if any
149
+ if "validate" in md:
150
+ validation = md["validate"]
151
+ else:
152
+ validation = lambda v: (True, None) # noqa: E731
153
+
154
+ # Prompt the user
155
+ while True:
156
+ user_input = click.prompt(field.name, type=prompt_type, default=field_default, prompt_suffix=f": {Fore.GREEN}")
157
+
158
+ # Call the validation
159
+ result, msg = validation(user_input)
160
+
161
+ # If positive, get out
162
+ if result:
163
+ break
164
+
165
+ # Else display the error message
166
+ secho(msg, fg="bright_red")
167
+
168
+ # Store the value
169
+ values[field.name] = user_input if user_input != "" else None
170
+ print(Fore.RESET)
171
+
172
+ # Remove the default values from the values
173
+ for k, d in defaults.items():
174
+ if values[k] == d:
175
+ del values[k]
176
+
177
+ # Display a validation prompt
178
+ print("The following block will be added to the file:\n")
179
+ longest_param = max(len(p) for p in values)
180
+ block_parameters = "\n".join(f"{param.ljust(longest_param)} = {value}" for param, value in values.items())
181
+ block_headers = f"[{block_name}]"
182
+ block = block_headers + "\n" + block_parameters
183
+ secho(f"{block}\n", fg="bright_blue")
184
+
185
+ # If we decide to go ahead -> write to file
186
+ if click.confirm("Do you want to write this block to the file?", default=True):
187
+ # First re-write the content of the config parser
188
+ cp = ctx.obj["cp"]
189
+ with open(config_path, 'w') as fp:
190
+ cp.write(fp)
191
+ fp.writelines("\n" + block)
192
+
193
+ secho("Block written successfully!", fg="bright_green")
194
+ else:
195
+ secho("Aborted...", fg="bright_red")
196
+
197
+
198
+ if __name__ == '__main__':
199
+ config(["block", '--block_name', 'test'])