multitool 0.7.2__tar.gz → 0.9.0__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 (27) hide show
  1. {multitool-0.7.2 → multitool-0.9.0}/PKG-INFO +99 -50
  2. {multitool-0.7.2 → multitool-0.9.0}/README.rst +97 -49
  3. {multitool-0.7.2 → multitool-0.9.0}/multitool/__init__.py +1 -1
  4. {multitool-0.7.2 → multitool-0.9.0}/multitool/__main__.py +4 -8
  5. multitool-0.9.0/multitool/bootstrap/commands.py +57 -0
  6. {multitool-0.7.2 → multitool-0.9.0}/multitool/console.py +1 -1
  7. multitool-0.9.0/multitool/plugins/commands.py +682 -0
  8. multitool-0.9.0/multitool/run/commands.py +9 -0
  9. {multitool-0.7.2 → multitool-0.9.0}/multitool.egg-info/PKG-INFO +99 -50
  10. {multitool-0.7.2 → multitool-0.9.0}/multitool.egg-info/SOURCES.txt +2 -0
  11. {multitool-0.7.2 → multitool-0.9.0}/multitool.egg-info/requires.txt +1 -0
  12. {multitool-0.7.2 → multitool-0.9.0}/pyproject.toml +3 -2
  13. multitool-0.7.2/multitool/plugins/commands.py +0 -425
  14. {multitool-0.7.2 → multitool-0.9.0}/LICENSE +0 -0
  15. {multitool-0.7.2 → multitool-0.9.0}/multitool/cls.py +0 -0
  16. {multitool-0.7.2 → multitool-0.9.0}/multitool/exceptions.py +0 -0
  17. {multitool-0.7.2 → multitool-0.9.0}/multitool/plugins/__init__.py +0 -0
  18. {multitool-0.7.2 → multitool-0.9.0}/multitool/silent.py +0 -0
  19. {multitool-0.7.2 → multitool-0.9.0}/multitool/utils.py +0 -0
  20. {multitool-0.7.2 → multitool-0.9.0}/multitool/utils_init.py +0 -0
  21. {multitool-0.7.2 → multitool-0.9.0}/multitool/verbose.py +0 -0
  22. {multitool-0.7.2 → multitool-0.9.0}/multitool.egg-info/dependency_links.txt +0 -0
  23. {multitool-0.7.2 → multitool-0.9.0}/multitool.egg-info/entry_points.txt +0 -0
  24. {multitool-0.7.2 → multitool-0.9.0}/multitool.egg-info/top_level.txt +0 -0
  25. {multitool-0.7.2 → multitool-0.9.0}/setup.cfg +0 -0
  26. {multitool-0.7.2 → multitool-0.9.0}/tests/__init__.py +0 -0
  27. {multitool-0.7.2 → multitool-0.9.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: multitool
3
- Version: 0.7.2
3
+ Version: 0.9.0
4
4
  Summary: Create and run plugin-based command-line tools.
5
5
  Author-email: Matthew Delotavo <matthew.t.delotavo@gmail.com>
6
6
  License-Expression: MIT
@@ -19,6 +19,7 @@ Requires-Dist: click>=8.1.3
19
19
  Requires-Dist: click-aliases>=1.0.1
20
20
  Requires-Dist: click-option-group>=0.5.5
21
21
  Requires-Dist: GitPython>=3.1.30
22
+ Requires-Dist: packaging>=26.2
22
23
  Dynamic: license-file
23
24
 
24
25
  multitool
@@ -51,8 +52,7 @@ Run the example command::
51
52
  -vv \
52
53
  --enabled \
53
54
  --tag alpha \
54
- --tag beta \
55
- --output result.json
55
+ --tag beta
56
56
 
57
57
  Edit the generated source code::
58
58
 
@@ -73,8 +73,9 @@ Usage
73
73
  -h, --help Show this message and exit.
74
74
 
75
75
  Commands:
76
- plugins Manage plugin repositories.
77
- run Run installed plugin commands.
76
+ bootstrap Create the directory structure for a new Python package...
77
+ plugins Manage plugin repositories.
78
+ run Run installed plugin commands.
78
79
 
79
80
  ----------------
80
81
  Managing plugins
@@ -145,23 +146,45 @@ plugins directory to use it locally.
145
146
  Configuring
146
147
  ^^^^^^^^^^^
147
148
 
148
- Configure plugin repositories with::
149
+ Add a plugin repository with::
149
150
 
150
- multitool plugins configure -a
151
+ multitool plugins add https://github.com/mdelotavo/multitool-plugins.git
152
+
153
+ By default, the repository name is used as the source key. To specify your own
154
+ key::
155
+
156
+ multitool plugins add https://github.com/mdelotavo/multitool-plugins.git --key example
157
+
158
+ Remove a configured plugin source by key or URL::
159
+
160
+ multitool plugins remove multitool-plugins
161
+
162
+ multitool plugins remove https://github.com/mdelotavo/multitool-plugins.git
163
+
164
+ Apply configuration changes (install new plugins and update existing plugins)
165
+ with::
166
+
167
+ multitool plugins update
168
+
169
+ For bulk edits, you can edit the configuration file directly::
170
+
171
+ multitool plugins configure
151
172
 
152
- This opens your editor to modify the plugin configuration. Omit ``-a`` if you
153
- don't want changes applied automatically.
173
+ To automatically apply configuration changes after saving and closing the file
174
+ (install new plugins, update existing plugins, and prune removed plugins), use::
175
+
176
+ multitool plugins configure -a
154
177
 
155
178
  Example configuration::
156
179
 
157
180
  [sources]
158
- mdelotavo-multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git
181
+ multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git
159
182
 
160
- After saving, Multitool clones each configured repository into::
183
+ Configured repositories are cloned into::
161
184
 
162
185
  ~/.multitool/plugins/
163
186
 
164
- You can configure multiple repositories as long as each key is unique.
187
+ Multiple repositories may be configured as long as each source key is unique.
165
188
 
166
189
  ^^^^^^^^^^
167
190
  Installing
@@ -169,14 +192,14 @@ Installing
169
192
 
170
193
  Install the example plugins::
171
194
 
172
- echo -e '[sources]\nmdelotavo-multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git' >> ~/.multitool/plugins/config
195
+ multitool plugins add https://github.com/mdelotavo/multitool-plugins.git
173
196
 
174
197
  multitool plugins update
198
+
175
199
  multitool plugins show
176
- multitool plugins show -n mdelotavo-multitool-plugins
177
- multitool plugins show -n mdelotavo-multitool-plugins --show-commit-only
178
- multitool plugins show -n mdelotavo-multitool-plugins --show-dependencies-only
179
- pip3 install $(multitool plugins show -n mdelotavo-multitool-plugins --show-dependencies-only)
200
+ multitool plugins show -n multitool-plugins
201
+ multitool plugins show -n multitool-plugins --show-commit-only
202
+ multitool plugins show -n multitool-plugins --show-dependencies-only
180
203
 
181
204
  multitool run examples -h
182
205
 
@@ -184,18 +207,75 @@ Install the example plugins::
184
207
  Updating
185
208
  ^^^^^^^^
186
209
 
187
- Install new plugins and update existing ones::
210
+ Install new plugins, update existing ones, and automatically install any Python
211
+ dependencies declared in the Requires field of the plugin's
212
+ multitool-info.json file::
188
213
 
189
214
  multitool plugins update
190
215
 
216
+ Update a specific plugin only::
217
+
218
+ multitool plugins update -n PLUGIN_NAME
219
+
220
+ The Requires field is where a plugin declares the Python packages it
221
+ depends on. Any packages listed will be installed automatically when
222
+ multitool plugins update is run. For example::
223
+
224
+ {
225
+ "Homepage": "",
226
+ "Requires": "click>=8.1.3 click-aliases>=1.0.1 click-option-group>=0.5.5 GitPython>=3.1.30",
227
+ "Maintainer": "",
228
+ "Description-en": ""
229
+ }
230
+
231
+ If one or more dependencies could not be installed automatically, multitool
232
+ will report the failures and display the appropriate pip command to install
233
+ the remaining packages manually. For example::
234
+
235
+ Updating plugins
236
+ ----------------
237
+ Updating multitool-plugins... Done
238
+ Updating test... Skipped Git pull (not a Git repository)
239
+
240
+ Checking Python package dependencies
241
+ ------------------------------------
242
+ Checked GitPython (GitPython>=3.1.30)... 3.1.50 installed
243
+ Installing asdfasdfasdf... Failed
244
+ Checked click-aliases (click-aliases>=1.0.1)... 1.0.1 installed
245
+ Checked click-option-group (click-option-group>=0.5.5)... 0.5.5 installed
246
+ Checked click (click>=8.1.3)... 8.1.8 installed
247
+ Installing qwerqwerqwer>=8.1.3... Failed
248
+ Checked tabulate (tabulate)... 0.9.0 installed
249
+
250
+ The following dependencies could not be installed automatically:
251
+ asdfasdfasdf
252
+ qwerqwerqwer>=8.1.3
253
+
254
+ Try installing them manually:
255
+ /usr/bin/python3 -m pip install asdfasdfasdf qwerqwerqwer>=8.1.3
256
+
257
+ You can also display a plugin's declared dependencies at any time::
258
+
259
+ multitool plugins show --name PLUGIN_NAME --show-dependencies-only
260
+
191
261
  ^^^^^^^
192
262
  Pruning
193
263
  ^^^^^^^
194
264
 
195
- Remove repositories no longer listed in the configuration::
265
+ To uninstall a plugin repository, first remove it from the configured sources::
266
+
267
+ multitool plugins remove multitool-plugins
268
+
269
+ Then remove any local repositories that are no longer configured::
196
270
 
197
271
  multitool plugins prune
198
272
 
273
+ Alternatively, running::
274
+
275
+ multitool plugins configure -a
276
+
277
+ automatically prunes repositories removed from the configuration.
278
+
199
279
  ^^^^^^^
200
280
  Showing
201
281
  ^^^^^^^
@@ -209,11 +289,6 @@ Or inspect a specific repository::
209
289
  multitool plugins show -n PLUGIN_NAME --show-commit-only
210
290
  multitool plugins show -n PLUGIN_NAME --show-dependencies-only
211
291
 
212
- If a plugin declares Python dependencies in ``multitool-info.json``, install
213
- them with::
214
-
215
- pip3 install $(multitool plugins show -n PLUGIN_NAME --show-dependencies-only)
216
-
217
292
  ---------------
218
293
  Troubleshooting
219
294
  ---------------
@@ -224,32 +299,6 @@ If a plugin fails to install or load, check the log file::
224
299
 
225
300
  It contains installation, dependency, and Git-related errors.
226
301
 
227
- -----------
228
- Limitations
229
- -----------
230
-
231
- Plugin command names must be unique across all installed repositories.
232
-
233
- To avoid naming conflicts, plugin modules should follow the convention of
234
- including the repository owner and repository name in the command name.
235
-
236
- For example, a repository configured as::
237
-
238
- [sources]
239
- mdelotavo-multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git
240
-
241
- should expose commands using a unique name such as::
242
-
243
- mdelotavo-multitool-plugins
244
-
245
- This reduces the likelihood of collisions when multiple repositories expose
246
- plugins with the same command name.
247
-
248
- If duplicate command names are detected, Multitool will display an error
249
- prompting you to delete the detected conflicting plugin repositories and, if
250
- applicable, remove the corresponding remote sources from your plugin
251
- configuration.
252
-
253
302
 
254
303
  .. _`click`: https://click.palletsprojects.com/
255
304
  .. _`multitool-plugins`: https://github.com/mdelotavo/multitool-plugins
@@ -28,8 +28,7 @@ Run the example command::
28
28
  -vv \
29
29
  --enabled \
30
30
  --tag alpha \
31
- --tag beta \
32
- --output result.json
31
+ --tag beta
33
32
 
34
33
  Edit the generated source code::
35
34
 
@@ -50,8 +49,9 @@ Usage
50
49
  -h, --help Show this message and exit.
51
50
 
52
51
  Commands:
53
- plugins Manage plugin repositories.
54
- run Run installed plugin commands.
52
+ bootstrap Create the directory structure for a new Python package...
53
+ plugins Manage plugin repositories.
54
+ run Run installed plugin commands.
55
55
 
56
56
  ----------------
57
57
  Managing plugins
@@ -122,23 +122,45 @@ plugins directory to use it locally.
122
122
  Configuring
123
123
  ^^^^^^^^^^^
124
124
 
125
- Configure plugin repositories with::
125
+ Add a plugin repository with::
126
126
 
127
- multitool plugins configure -a
127
+ multitool plugins add https://github.com/mdelotavo/multitool-plugins.git
128
+
129
+ By default, the repository name is used as the source key. To specify your own
130
+ key::
131
+
132
+ multitool plugins add https://github.com/mdelotavo/multitool-plugins.git --key example
133
+
134
+ Remove a configured plugin source by key or URL::
135
+
136
+ multitool plugins remove multitool-plugins
137
+
138
+ multitool plugins remove https://github.com/mdelotavo/multitool-plugins.git
139
+
140
+ Apply configuration changes (install new plugins and update existing plugins)
141
+ with::
142
+
143
+ multitool plugins update
144
+
145
+ For bulk edits, you can edit the configuration file directly::
146
+
147
+ multitool plugins configure
128
148
 
129
- This opens your editor to modify the plugin configuration. Omit ``-a`` if you
130
- don't want changes applied automatically.
149
+ To automatically apply configuration changes after saving and closing the file
150
+ (install new plugins, update existing plugins, and prune removed plugins), use::
151
+
152
+ multitool plugins configure -a
131
153
 
132
154
  Example configuration::
133
155
 
134
156
  [sources]
135
- mdelotavo-multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git
157
+ multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git
136
158
 
137
- After saving, Multitool clones each configured repository into::
159
+ Configured repositories are cloned into::
138
160
 
139
161
  ~/.multitool/plugins/
140
162
 
141
- You can configure multiple repositories as long as each key is unique.
163
+ Multiple repositories may be configured as long as each source key is unique.
142
164
 
143
165
  ^^^^^^^^^^
144
166
  Installing
@@ -146,14 +168,14 @@ Installing
146
168
 
147
169
  Install the example plugins::
148
170
 
149
- echo -e '[sources]\nmdelotavo-multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git' >> ~/.multitool/plugins/config
171
+ multitool plugins add https://github.com/mdelotavo/multitool-plugins.git
150
172
 
151
173
  multitool plugins update
174
+
152
175
  multitool plugins show
153
- multitool plugins show -n mdelotavo-multitool-plugins
154
- multitool plugins show -n mdelotavo-multitool-plugins --show-commit-only
155
- multitool plugins show -n mdelotavo-multitool-plugins --show-dependencies-only
156
- pip3 install $(multitool plugins show -n mdelotavo-multitool-plugins --show-dependencies-only)
176
+ multitool plugins show -n multitool-plugins
177
+ multitool plugins show -n multitool-plugins --show-commit-only
178
+ multitool plugins show -n multitool-plugins --show-dependencies-only
157
179
 
158
180
  multitool run examples -h
159
181
 
@@ -161,18 +183,75 @@ Install the example plugins::
161
183
  Updating
162
184
  ^^^^^^^^
163
185
 
164
- Install new plugins and update existing ones::
186
+ Install new plugins, update existing ones, and automatically install any Python
187
+ dependencies declared in the Requires field of the plugin's
188
+ multitool-info.json file::
165
189
 
166
190
  multitool plugins update
167
191
 
192
+ Update a specific plugin only::
193
+
194
+ multitool plugins update -n PLUGIN_NAME
195
+
196
+ The Requires field is where a plugin declares the Python packages it
197
+ depends on. Any packages listed will be installed automatically when
198
+ multitool plugins update is run. For example::
199
+
200
+ {
201
+ "Homepage": "",
202
+ "Requires": "click>=8.1.3 click-aliases>=1.0.1 click-option-group>=0.5.5 GitPython>=3.1.30",
203
+ "Maintainer": "",
204
+ "Description-en": ""
205
+ }
206
+
207
+ If one or more dependencies could not be installed automatically, multitool
208
+ will report the failures and display the appropriate pip command to install
209
+ the remaining packages manually. For example::
210
+
211
+ Updating plugins
212
+ ----------------
213
+ Updating multitool-plugins... Done
214
+ Updating test... Skipped Git pull (not a Git repository)
215
+
216
+ Checking Python package dependencies
217
+ ------------------------------------
218
+ Checked GitPython (GitPython>=3.1.30)... 3.1.50 installed
219
+ Installing asdfasdfasdf... Failed
220
+ Checked click-aliases (click-aliases>=1.0.1)... 1.0.1 installed
221
+ Checked click-option-group (click-option-group>=0.5.5)... 0.5.5 installed
222
+ Checked click (click>=8.1.3)... 8.1.8 installed
223
+ Installing qwerqwerqwer>=8.1.3... Failed
224
+ Checked tabulate (tabulate)... 0.9.0 installed
225
+
226
+ The following dependencies could not be installed automatically:
227
+ asdfasdfasdf
228
+ qwerqwerqwer>=8.1.3
229
+
230
+ Try installing them manually:
231
+ /usr/bin/python3 -m pip install asdfasdfasdf qwerqwerqwer>=8.1.3
232
+
233
+ You can also display a plugin's declared dependencies at any time::
234
+
235
+ multitool plugins show --name PLUGIN_NAME --show-dependencies-only
236
+
168
237
  ^^^^^^^
169
238
  Pruning
170
239
  ^^^^^^^
171
240
 
172
- Remove repositories no longer listed in the configuration::
241
+ To uninstall a plugin repository, first remove it from the configured sources::
242
+
243
+ multitool plugins remove multitool-plugins
244
+
245
+ Then remove any local repositories that are no longer configured::
173
246
 
174
247
  multitool plugins prune
175
248
 
249
+ Alternatively, running::
250
+
251
+ multitool plugins configure -a
252
+
253
+ automatically prunes repositories removed from the configuration.
254
+
176
255
  ^^^^^^^
177
256
  Showing
178
257
  ^^^^^^^
@@ -186,11 +265,6 @@ Or inspect a specific repository::
186
265
  multitool plugins show -n PLUGIN_NAME --show-commit-only
187
266
  multitool plugins show -n PLUGIN_NAME --show-dependencies-only
188
267
 
189
- If a plugin declares Python dependencies in ``multitool-info.json``, install
190
- them with::
191
-
192
- pip3 install $(multitool plugins show -n PLUGIN_NAME --show-dependencies-only)
193
-
194
268
  ---------------
195
269
  Troubleshooting
196
270
  ---------------
@@ -201,32 +275,6 @@ If a plugin fails to install or load, check the log file::
201
275
 
202
276
  It contains installation, dependency, and Git-related errors.
203
277
 
204
- -----------
205
- Limitations
206
- -----------
207
-
208
- Plugin command names must be unique across all installed repositories.
209
-
210
- To avoid naming conflicts, plugin modules should follow the convention of
211
- including the repository owner and repository name in the command name.
212
-
213
- For example, a repository configured as::
214
-
215
- [sources]
216
- mdelotavo-multitool-plugins = https://github.com/mdelotavo/multitool-plugins.git
217
-
218
- should expose commands using a unique name such as::
219
-
220
- mdelotavo-multitool-plugins
221
-
222
- This reduces the likelihood of collisions when multiple repositories expose
223
- plugins with the same command name.
224
-
225
- If duplicate command names are detected, Multitool will display an error
226
- prompting you to delete the detected conflicting plugin repositories and, if
227
- applicable, remove the corresponding remote sources from your plugin
228
- configuration.
229
-
230
278
 
231
279
  .. _`click`: https://click.palletsprojects.com/
232
280
  .. _`multitool-plugins`: https://github.com/mdelotavo/multitool-plugins
@@ -1,5 +1,5 @@
1
1
  APP = "multitool"
2
- __version__ = "0.7.2"
2
+ __version__ = "0.9.0"
3
3
  description = "Create and run plugin-based command-line tools."
4
4
  long_description = ("Create and run plugin-based command-line tools by dynamically loading Click commands from local or Git-managed plugin repositories.")
5
5
 
@@ -5,10 +5,12 @@ import click
5
5
 
6
6
  from multitool import APP, MULTITOOL_LOG_FILE, MULTITOOL_PLUGINS_DIRECTORY
7
7
  from multitool import __version__ as version
8
+ from multitool.bootstrap.commands import bootstrap
8
9
  from multitool.cls import AliasedGroup
9
10
  from multitool.exceptions import wrap_with_exception_handling
10
11
  from multitool.plugins.commands import plugins
11
- from multitool.utils import (configure_root_logger, for_each_file, load_plugins)
12
+ from multitool.run.commands import run
13
+ from multitool.utils import configure_root_logger, for_each_file, load_plugins
12
14
 
13
15
  CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])
14
16
 
@@ -21,17 +23,11 @@ def cli(ctx):
21
23
  ctx.ensure_object(dict)
22
24
 
23
25
 
24
- @click.group(cls=AliasedGroup)
25
- def run():
26
- """Run installed plugin commands."""
27
- pass
28
-
29
-
30
26
  @wrap_with_exception_handling
31
27
  def main():
32
28
  configure_root_logger(MULTITOOL_LOG_FILE)
33
29
 
34
- cli_commands = {plugins, run}
30
+ cli_commands = {plugins, run, bootstrap}
35
31
 
36
32
  run_commands = {}
37
33
 
@@ -0,0 +1,57 @@
1
+ from pathlib import Path
2
+
3
+ import click
4
+
5
+ from multitool import console
6
+ from multitool.silent import common_silent_options
7
+ from multitool.utils import mkdir, touch
8
+ from multitool.verbose import common_verbose_options
9
+
10
+ PROJECT_STRUCTURE = {
11
+ "pyproject.toml": None,
12
+ "{app}": {
13
+ "__init__.py": None,
14
+ "__main__.py": None,
15
+ # "cls.py": None,
16
+ "console.py": None,
17
+ "exceptions.py": None,
18
+ "silent.py": None,
19
+ "utils.py": None,
20
+ "utils_init.py": None,
21
+ "verbose.py": None,
22
+ "submodule": {
23
+ "__init__.py": None,
24
+ "commands.py": None,
25
+ },
26
+ },
27
+ }
28
+
29
+
30
+ def create_structure(root: Path, structure: dict, app: str):
31
+ for name, children in structure.items():
32
+ path = root / name.format(app=app)
33
+
34
+ if children is None:
35
+ touch(path)
36
+ else:
37
+ mkdir(path)
38
+ create_structure(path, children, app)
39
+
40
+
41
+ @click.command(help="Create the directory structure for a new Python package project.")
42
+ @click.argument("name")
43
+ @click.argument(
44
+ "directory",
45
+ type=click.Path(path_type=Path),
46
+ default=".",
47
+ required=False,
48
+ )
49
+ @common_silent_options
50
+ @common_verbose_options
51
+ def bootstrap(silent, verbose, name, directory):
52
+ root = directory / name
53
+ mkdir(root)
54
+
55
+ create_structure(root, PROJECT_STRUCTURE, name)
56
+
57
+ console.echo(f"Created project: {root}")
@@ -1,6 +1,6 @@
1
- from dataclasses import dataclass, fields, replace
2
1
  import builtins
3
2
  import sys
3
+ from dataclasses import dataclass, fields, replace
4
4
 
5
5
 
6
6
  @dataclass(slots=True)