multitool 0.4.0__tar.gz → 0.6.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.
- {multitool-0.4.0 → multitool-0.6.0}/LICENSE +0 -0
- {multitool-0.4.0 → multitool-0.6.0}/PKG-INFO +29 -27
- {multitool-0.4.0 → multitool-0.6.0}/README.rst +15 -19
- {multitool-0.4.0 → multitool-0.6.0}/multitool/__init__.py +3 -3
- {multitool-0.4.0 → multitool-0.6.0}/multitool/__main__.py +7 -19
- {multitool-0.4.0 → multitool-0.6.0}/multitool/cls.py +1 -0
- multitool-0.6.0/multitool/console.py +25 -0
- {multitool-0.4.0 → multitool-0.6.0}/multitool/exceptions.py +1 -0
- {multitool-0.4.0 → multitool-0.6.0}/multitool/plugins/__init__.py +0 -0
- multitool-0.6.0/multitool/plugins/commands.py +224 -0
- {multitool-0.4.0 → multitool-0.6.0}/multitool/silent.py +5 -5
- {multitool-0.4.0 → multitool-0.6.0}/multitool/utils.py +15 -16
- {multitool-0.4.0 → multitool-0.6.0}/multitool/verbose.py +5 -5
- {multitool-0.4.0 → multitool-0.6.0}/multitool.egg-info/PKG-INFO +29 -27
- {multitool-0.4.0 → multitool-0.6.0}/multitool.egg-info/SOURCES.txt +1 -1
- {multitool-0.4.0 → multitool-0.6.0}/multitool.egg-info/dependency_links.txt +0 -0
- {multitool-0.4.0 → multitool-0.6.0}/multitool.egg-info/entry_points.txt +0 -0
- multitool-0.6.0/multitool.egg-info/requires.txt +4 -0
- {multitool-0.4.0 → multitool-0.6.0}/multitool.egg-info/top_level.txt +0 -1
- multitool-0.6.0/pyproject.toml +45 -0
- {multitool-0.4.0 → multitool-0.6.0}/setup.cfg +0 -0
- {multitool-0.4.0 → multitool-0.6.0}/tests/__init__.py +0 -0
- {multitool-0.4.0 → multitool-0.6.0}/tests/test_utils.py +1 -0
- multitool-0.4.0/multitool/console.py +0 -23
- multitool-0.4.0/multitool/plugins/commands.py +0 -229
- multitool-0.4.0/multitool.egg-info/requires.txt +0 -11
- multitool-0.4.0/setup.py +0 -53
|
File without changes
|
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: multitool
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Quickly create and distribute command-line tools.
|
|
5
|
+
Author-email: Matthew Delotavo <matthew.t.delotavo@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mdelotavo/multitool
|
|
8
|
+
Project-URL: Repository, https://github.com/mdelotavo/multitool
|
|
9
|
+
Keywords: cli,tooling,automation
|
|
9
10
|
Classifier: Development Status :: 4 - Beta
|
|
10
11
|
Classifier: Environment :: Console
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Operating System :: OS Independent
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.7
|
|
15
15
|
Requires-Python: >=3.7
|
|
16
|
+
Description-Content-Type: text/x-rst
|
|
16
17
|
License-File: LICENSE
|
|
18
|
+
Requires-Dist: click>=8.1.3
|
|
19
|
+
Requires-Dist: click-aliases>=1.0.1
|
|
20
|
+
Requires-Dist: click-option-group>=0.5.5
|
|
21
|
+
Requires-Dist: GitPython>=3.1.30
|
|
22
|
+
Dynamic: license-file
|
|
17
23
|
|
|
18
24
|
multitool
|
|
19
25
|
=========
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
--------------------
|
|
24
|
-
Why does this exist?
|
|
25
|
-
--------------------
|
|
26
|
-
|
|
27
|
-
I built this tool so that I can quickly create and distribute command-line tools for consulting work and personal use.
|
|
28
|
-
|
|
29
|
-
The plugins manager uses ``git`` to manage plugins installed from remote ``git`` repositories.
|
|
27
|
+
Quickly create and distribute command-line tools with plugins.
|
|
30
28
|
|
|
31
29
|
-----
|
|
32
30
|
Usage
|
|
@@ -36,20 +34,14 @@ Usage
|
|
|
36
34
|
|
|
37
35
|
Usage: multitool [OPTIONS] COMMAND [ARGS]...
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
PyPI: https://pypi.org/project/multitool/
|
|
42
|
-
GitHub: https://github.com/mdelotavo/multitool
|
|
37
|
+
Quickly create and distribute command-line tools.
|
|
43
38
|
|
|
44
39
|
Options:
|
|
45
40
|
-V, --version Show the version and exit.
|
|
46
41
|
-h, --help Show this message and exit.
|
|
47
42
|
|
|
48
43
|
Commands:
|
|
49
|
-
plugins
|
|
50
|
-
|
|
51
|
-
.. ..
|
|
52
|
-
The plugins features are based off those found in the `apigeecli`_.
|
|
44
|
+
plugins Plugins manager for distributing commands.
|
|
53
45
|
|
|
54
46
|
----------------
|
|
55
47
|
Managing plugins
|
|
@@ -122,7 +114,7 @@ This will install and update plugins.
|
|
|
122
114
|
Pruning
|
|
123
115
|
^^^^^^^
|
|
124
116
|
|
|
125
|
-
If you specified the ``-a`` option when running ``multitool plugins configure`` then the removal of plugins will occur automatically.
|
|
117
|
+
If you remove plugins from the config file or comment them out, and you then specified the ``-a`` option when running ``multitool plugins configure`` then the removal of plugins will occur automatically.
|
|
126
118
|
Otherwise you can run::
|
|
127
119
|
|
|
128
120
|
multitool plugins prune
|
|
@@ -146,6 +138,17 @@ In order for this to work, the plugin needs to have the ``Requires`` key in the
|
|
|
146
138
|
|
|
147
139
|
pip3 install $(multitool plugins show -n PLUGIN_NAME --show-dependencies-only)
|
|
148
140
|
|
|
141
|
+
^^^^^^^^^^^^^^^
|
|
142
|
+
Troubleshooting
|
|
143
|
+
^^^^^^^^^^^^^^^
|
|
144
|
+
|
|
145
|
+
If you encounter issues with plugins or commands, you can find more detailed debug information and error messages in the log file:
|
|
146
|
+
::
|
|
147
|
+
|
|
148
|
+
~/.multitool/multitool.log
|
|
149
|
+
|
|
150
|
+
Reviewing this file can help you diagnose installation problems, missing dependencies, or Git-related errors.
|
|
151
|
+
|
|
149
152
|
.. ..
|
|
150
153
|
----------------------------
|
|
151
154
|
Create a virtual environment
|
|
@@ -167,6 +170,5 @@ In order for this to work, the plugin needs to have the ``Requires`` key in the
|
|
|
167
170
|
deactivate
|
|
168
171
|
|
|
169
172
|
.. _`click`: https://click.palletsprojects.com/
|
|
170
|
-
.. _`apigeecli`: https://pypi.org/project/apigeecli/
|
|
171
173
|
.. _`multitool-plugins`: https://github.com/mdelotavo/multitool-plugins
|
|
172
174
|
.. _`public plugins repository`: https://github.com/mdelotavo/multitool-plugins
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
multitool
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
--------------------
|
|
7
|
-
Why does this exist?
|
|
8
|
-
--------------------
|
|
9
|
-
|
|
10
|
-
I built this tool so that I can quickly create and distribute command-line tools for consulting work and personal use.
|
|
11
|
-
|
|
12
|
-
The plugins manager uses ``git`` to manage plugins installed from remote ``git`` repositories.
|
|
4
|
+
Quickly create and distribute command-line tools with plugins.
|
|
13
5
|
|
|
14
6
|
-----
|
|
15
7
|
Usage
|
|
@@ -19,20 +11,14 @@ Usage
|
|
|
19
11
|
|
|
20
12
|
Usage: multitool [OPTIONS] COMMAND [ARGS]...
|
|
21
13
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
PyPI: https://pypi.org/project/multitool/
|
|
25
|
-
GitHub: https://github.com/mdelotavo/multitool
|
|
14
|
+
Quickly create and distribute command-line tools.
|
|
26
15
|
|
|
27
16
|
Options:
|
|
28
17
|
-V, --version Show the version and exit.
|
|
29
18
|
-h, --help Show this message and exit.
|
|
30
19
|
|
|
31
20
|
Commands:
|
|
32
|
-
plugins
|
|
33
|
-
|
|
34
|
-
.. ..
|
|
35
|
-
The plugins features are based off those found in the `apigeecli`_.
|
|
21
|
+
plugins Plugins manager for distributing commands.
|
|
36
22
|
|
|
37
23
|
----------------
|
|
38
24
|
Managing plugins
|
|
@@ -105,7 +91,7 @@ This will install and update plugins.
|
|
|
105
91
|
Pruning
|
|
106
92
|
^^^^^^^
|
|
107
93
|
|
|
108
|
-
If you specified the ``-a`` option when running ``multitool plugins configure`` then the removal of plugins will occur automatically.
|
|
94
|
+
If you remove plugins from the config file or comment them out, and you then specified the ``-a`` option when running ``multitool plugins configure`` then the removal of plugins will occur automatically.
|
|
109
95
|
Otherwise you can run::
|
|
110
96
|
|
|
111
97
|
multitool plugins prune
|
|
@@ -129,6 +115,17 @@ In order for this to work, the plugin needs to have the ``Requires`` key in the
|
|
|
129
115
|
|
|
130
116
|
pip3 install $(multitool plugins show -n PLUGIN_NAME --show-dependencies-only)
|
|
131
117
|
|
|
118
|
+
^^^^^^^^^^^^^^^
|
|
119
|
+
Troubleshooting
|
|
120
|
+
^^^^^^^^^^^^^^^
|
|
121
|
+
|
|
122
|
+
If you encounter issues with plugins or commands, you can find more detailed debug information and error messages in the log file:
|
|
123
|
+
::
|
|
124
|
+
|
|
125
|
+
~/.multitool/multitool.log
|
|
126
|
+
|
|
127
|
+
Reviewing this file can help you diagnose installation problems, missing dependencies, or Git-related errors.
|
|
128
|
+
|
|
132
129
|
.. ..
|
|
133
130
|
----------------------------
|
|
134
131
|
Create a virtual environment
|
|
@@ -150,6 +147,5 @@ In order for this to work, the plugin needs to have the ``Requires`` key in the
|
|
|
150
147
|
deactivate
|
|
151
148
|
|
|
152
149
|
.. _`click`: https://click.palletsprojects.com/
|
|
153
|
-
.. _`apigeecli`: https://pypi.org/project/apigeecli/
|
|
154
150
|
.. _`multitool-plugins`: https://github.com/mdelotavo/multitool-plugins
|
|
155
151
|
.. _`public plugins repository`: https://github.com/mdelotavo/multitool-plugins
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
APP = 'multitool'
|
|
2
|
-
__version__ =
|
|
3
|
-
description = '
|
|
4
|
-
|
|
2
|
+
__version__ = "0.6.0"
|
|
3
|
+
description = 'Quickly create and distribute command-line tools.'
|
|
4
|
+
long_description = 'Quickly create and distribute command-line tools with plugins.'
|
|
5
5
|
|
|
6
6
|
import builtins
|
|
7
7
|
from pathlib import Path
|
|
@@ -8,28 +8,16 @@ from multitool import __version__ as version
|
|
|
8
8
|
from multitool.cls import AliasedGroup
|
|
9
9
|
from multitool.exceptions import wrap_with_exception_handling
|
|
10
10
|
from multitool.plugins.commands import plugins
|
|
11
|
-
from multitool.utils import (import_plugins_from_directory
|
|
12
|
-
execute_function_on_directory_files, configure_global_logger)
|
|
11
|
+
from multitool.utils import (configure_global_logger, execute_function_on_directory_files, import_plugins_from_directory)
|
|
13
12
|
|
|
14
13
|
CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
|
|
15
14
|
|
|
16
15
|
|
|
17
|
-
@click.group(
|
|
18
|
-
context_settings=CONTEXT_SETTINGS, cls=AliasedGroup, invoke_without_command=False, chain=False
|
|
19
|
-
)
|
|
16
|
+
@click.group(context_settings=CONTEXT_SETTINGS, cls=AliasedGroup, invoke_without_command=False, chain=False)
|
|
20
17
|
@click.version_option(version, '-V', '--version')
|
|
21
18
|
@click.pass_context
|
|
22
19
|
def cli(ctx):
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
\b
|
|
26
|
-
PyPI: https://pypi.org/project/multitool/
|
|
27
|
-
GitHub: https://github.com/mdelotavo/multitool
|
|
28
|
-
|
|
29
|
-
\f
|
|
30
|
-
|
|
31
|
-
:param click.core.Context ctx: Click context.
|
|
32
|
-
"""
|
|
20
|
+
"""Quickly create and distribute command-line tools."""
|
|
33
21
|
ctx.ensure_object(dict)
|
|
34
22
|
|
|
35
23
|
|
|
@@ -40,10 +28,10 @@ def main():
|
|
|
40
28
|
cli_commands = {plugins}
|
|
41
29
|
|
|
42
30
|
execute_function_on_directory_files(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
31
|
+
MULTITOOL_PLUGINS_DIRECTORY,
|
|
32
|
+
import_plugins_from_directory,
|
|
33
|
+
args=(cli_commands, ),
|
|
34
|
+
glob='[!.][!__]*/__init__.py',
|
|
47
35
|
)
|
|
48
36
|
|
|
49
37
|
for command in cli_commands:
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import builtins
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def echo(
|
|
6
|
+
*message,
|
|
7
|
+
exit_status=None,
|
|
8
|
+
make_silent=False,
|
|
9
|
+
current_verbosity=0,
|
|
10
|
+
expected_verbosity=0,
|
|
11
|
+
line_ending="\n",
|
|
12
|
+
should_flush=False,
|
|
13
|
+
):
|
|
14
|
+
if make_silent or builtins.MULTITOOL_TOGGLE_SILENT:
|
|
15
|
+
if exit_status is not None:
|
|
16
|
+
sys.exit(exit_status)
|
|
17
|
+
return
|
|
18
|
+
|
|
19
|
+
verbosity = max(current_verbosity, builtins.MULTITOOL_TOGGLE_VERBOSE)
|
|
20
|
+
|
|
21
|
+
if verbosity >= expected_verbosity:
|
|
22
|
+
print(*message, end=line_ending, flush=should_flush)
|
|
23
|
+
|
|
24
|
+
if exit_status is not None:
|
|
25
|
+
sys.exit(exit_status)
|
|
File without changes
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import configparser
|
|
2
|
+
import os
|
|
3
|
+
import shutil
|
|
4
|
+
import stat
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
from click_option_group import MutuallyExclusiveOptionGroup, optgroup
|
|
10
|
+
|
|
11
|
+
from multitool import (
|
|
12
|
+
APP,
|
|
13
|
+
MULTITOOL_PLUGINS_CONFIG_FILE,
|
|
14
|
+
MULTITOOL_PLUGINS_DIRECTORY,
|
|
15
|
+
MULTITOOL_PLUGINS_PATH,
|
|
16
|
+
console,
|
|
17
|
+
)
|
|
18
|
+
from multitool.silent import common_silent_options
|
|
19
|
+
from multitool.utils import (
|
|
20
|
+
create_directory,
|
|
21
|
+
create_empty_file,
|
|
22
|
+
execute_function_on_directory_files,
|
|
23
|
+
is_directory,
|
|
24
|
+
is_regular_file,
|
|
25
|
+
read_file_content,
|
|
26
|
+
)
|
|
27
|
+
from multitool.verbose import common_verbose_options
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
from git import Repo
|
|
31
|
+
|
|
32
|
+
HAS_GIT = True
|
|
33
|
+
HELP = "Plugins manager for distributing commands."
|
|
34
|
+
except ImportError:
|
|
35
|
+
HAS_GIT = False
|
|
36
|
+
HELP = "Plugins manager. Git is required."
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def require_git():
|
|
40
|
+
if not HAS_GIT:
|
|
41
|
+
sys.exit(0)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def init():
|
|
45
|
+
create_directory(MULTITOOL_PLUGINS_DIRECTORY)
|
|
46
|
+
create_empty_file(MULTITOOL_PLUGINS_PATH)
|
|
47
|
+
create_empty_file(MULTITOOL_PLUGINS_CONFIG_FILE)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def config(section="sources"):
|
|
51
|
+
cfg = configparser.ConfigParser(allow_no_value=True)
|
|
52
|
+
cfg.read(MULTITOOL_PLUGINS_CONFIG_FILE)
|
|
53
|
+
return dict(cfg._sections.get(section, {}))
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def clone():
|
|
57
|
+
init()
|
|
58
|
+
for name, uri in config().items():
|
|
59
|
+
dest = Path(MULTITOOL_PLUGINS_DIRECTORY) / name
|
|
60
|
+
if is_directory(dest):
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
console.echo(f"Installing {name}... ", line_ending="", should_flush=True)
|
|
64
|
+
try:
|
|
65
|
+
Repo.clone_from(uri, dest)
|
|
66
|
+
console.echo("Done")
|
|
67
|
+
except Exception as e:
|
|
68
|
+
console.echo(e)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def update_repos():
|
|
72
|
+
|
|
73
|
+
def fn(p):
|
|
74
|
+
if not is_directory(p):
|
|
75
|
+
return
|
|
76
|
+
|
|
77
|
+
console.echo(f"Updating {Path(p).stem}... ", line_ending="", should_flush=True)
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
repo = Repo(p)
|
|
81
|
+
if not repo.bare:
|
|
82
|
+
repo.remotes["origin"].pull()
|
|
83
|
+
console.echo("Done")
|
|
84
|
+
except Exception as e:
|
|
85
|
+
console.echo(e)
|
|
86
|
+
|
|
87
|
+
execute_function_on_directory_files(MULTITOOL_PLUGINS_DIRECTORY, fn, glob="[!.][!__]*")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def prune():
|
|
91
|
+
sources = config()
|
|
92
|
+
|
|
93
|
+
def fn(p):
|
|
94
|
+
if not is_directory(p):
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
name = Path(p).stem
|
|
98
|
+
if name in sources:
|
|
99
|
+
return
|
|
100
|
+
|
|
101
|
+
console.echo(f"Removing {name}... ", line_ending="", should_flush=True)
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
shutil.rmtree(p, onerror=_chmod)
|
|
105
|
+
console.echo("Done")
|
|
106
|
+
except Exception as e:
|
|
107
|
+
console.echo(e)
|
|
108
|
+
|
|
109
|
+
execute_function_on_directory_files(MULTITOOL_PLUGINS_DIRECTORY, fn, glob="[!.][!__]*")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _chmod(func, p, _):
|
|
113
|
+
os.chmod(p, stat.S_IRWXU)
|
|
114
|
+
func(p)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# def prune():
|
|
118
|
+
# sources = config()
|
|
119
|
+
|
|
120
|
+
# def fn(p):
|
|
121
|
+
# if not is_directory(p):
|
|
122
|
+
# return
|
|
123
|
+
|
|
124
|
+
# name = Path(p).stem
|
|
125
|
+
# if name in sources:
|
|
126
|
+
# return
|
|
127
|
+
|
|
128
|
+
# console.echo(f"Removing {name}... ", line_ending="", should_flush=True)
|
|
129
|
+
|
|
130
|
+
# try:
|
|
131
|
+
# shutil.rmtree(p, onexc=_chmod)
|
|
132
|
+
# console.echo("Done")
|
|
133
|
+
# except Exception as e:
|
|
134
|
+
# console.echo(e)
|
|
135
|
+
|
|
136
|
+
# execute_function_on_directory_files(PLUGINS_DIR, fn, glob="[!.][!__]*")
|
|
137
|
+
|
|
138
|
+
# def _chmod(func, path, exc):
|
|
139
|
+
# os.chmod(path, stat.S_IRWXU)
|
|
140
|
+
# func(path)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def plugin_info(name):
|
|
144
|
+
f = Path(MULTITOOL_PLUGINS_DIRECTORY) / name / f"{APP}-info.json"
|
|
145
|
+
|
|
146
|
+
if not is_regular_file(f):
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
return read_file_content(f, type="json")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def print_commit(name):
|
|
153
|
+
repo = Repo(Path(MULTITOOL_PLUGINS_DIRECTORY) / name)
|
|
154
|
+
console.echo(repo.git.log("--pretty=format:%h - %s (%cr) <%an>", "-1"))
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@click.group(help=HELP)
|
|
158
|
+
def plugins():
|
|
159
|
+
pass
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@plugins.command()
|
|
163
|
+
@common_silent_options
|
|
164
|
+
@common_verbose_options
|
|
165
|
+
@click.option("-a/-A", "--apply-changes/--no-apply-changes", default=False)
|
|
166
|
+
def configure(silent, verbose, apply_changes):
|
|
167
|
+
require_git()
|
|
168
|
+
init()
|
|
169
|
+
|
|
170
|
+
click.edit(filename=MULTITOOL_PLUGINS_CONFIG_FILE)
|
|
171
|
+
|
|
172
|
+
if apply_changes:
|
|
173
|
+
clone()
|
|
174
|
+
prune()
|
|
175
|
+
else:
|
|
176
|
+
console.echo(f"\nRun `{APP} plugins update` to apply changes.\n")
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
@plugins.command()
|
|
180
|
+
@common_silent_options
|
|
181
|
+
@common_verbose_options
|
|
182
|
+
def update(silent, verbose):
|
|
183
|
+
require_git()
|
|
184
|
+
clone()
|
|
185
|
+
update_repos()
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@plugins.command()
|
|
189
|
+
@common_silent_options
|
|
190
|
+
@common_verbose_options
|
|
191
|
+
@click.option("-n", "--name")
|
|
192
|
+
@optgroup.group("Filter options", cls=MutuallyExclusiveOptionGroup)
|
|
193
|
+
@optgroup.option("--show-commit-only/--no-show-commit-only", default=False)
|
|
194
|
+
@optgroup.option("--show-dependencies-only/--no-show-dependencies-only", default=False)
|
|
195
|
+
def show(silent, verbose, name, show_commit_only, show_dependencies_only):
|
|
196
|
+
if not name:
|
|
197
|
+
for k, v in config().items():
|
|
198
|
+
console.echo(f"{k}: {v}")
|
|
199
|
+
return
|
|
200
|
+
|
|
201
|
+
info = plugin_info(name)
|
|
202
|
+
if not info:
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
if show_commit_only:
|
|
206
|
+
require_git()
|
|
207
|
+
print_commit(name)
|
|
208
|
+
return
|
|
209
|
+
|
|
210
|
+
if show_dependencies_only:
|
|
211
|
+
if info.get("Requires"):
|
|
212
|
+
console.echo(info["Requires"])
|
|
213
|
+
return
|
|
214
|
+
|
|
215
|
+
for k, v in info.items():
|
|
216
|
+
console.echo(f"{k}: {v}")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@plugins.command()
|
|
220
|
+
@common_silent_options
|
|
221
|
+
@common_verbose_options
|
|
222
|
+
def prune_cmd(silent, verbose):
|
|
223
|
+
require_git()
|
|
224
|
+
prune()
|
|
@@ -9,10 +9,10 @@ def silent_callback(ctx, param, value):
|
|
|
9
9
|
|
|
10
10
|
def common_silent_options(func):
|
|
11
11
|
func = click.option(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
'--silent',
|
|
13
|
+
show_default='toggle silent output',
|
|
14
|
+
flag_value=True,
|
|
15
|
+
default=False,
|
|
16
|
+
callback=silent_callback,
|
|
17
17
|
)(func)
|
|
18
18
|
return func
|
|
@@ -15,7 +15,7 @@ def apply_function_on_iterable(iterable, func, state_op="append", args=(), kwarg
|
|
|
15
15
|
kwargs = {}
|
|
16
16
|
state = []
|
|
17
17
|
for item in iterable:
|
|
18
|
-
_tuple = (item,)
|
|
18
|
+
_tuple = (item, )
|
|
19
19
|
result = func(*(_tuple + args), **kwargs)
|
|
20
20
|
if result:
|
|
21
21
|
getattr(state, state_op)(result)
|
|
@@ -26,9 +26,9 @@ def configure_global_logger(log_file):
|
|
|
26
26
|
create_empty_file(log_file)
|
|
27
27
|
remove_file_if_above_size(log_file, size_kb=1000)
|
|
28
28
|
logging.basicConfig(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
filename=log_file,
|
|
30
|
+
level=logging.WARNING,
|
|
31
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
32
32
|
)
|
|
33
33
|
|
|
34
34
|
|
|
@@ -57,7 +57,7 @@ def execute_function_on_directory_files(dir, func, glob="**/*", args=(), kwargs=
|
|
|
57
57
|
kwargs = {}
|
|
58
58
|
state = []
|
|
59
59
|
for file_path in Path(get_resolved_directory_path(dir)).resolve().glob(glob):
|
|
60
|
-
_tuple = (str(file_path),)
|
|
60
|
+
_tuple = (str(file_path), )
|
|
61
61
|
result = func(*(_tuple + args), **kwargs)
|
|
62
62
|
if result:
|
|
63
63
|
state.append(result)
|
|
@@ -72,23 +72,22 @@ def get_resolved_directory_path(target_directory=None):
|
|
|
72
72
|
return os.getcwd()
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
def import_plugins_from_directory(
|
|
75
|
+
def import_plugins_from_directory(init_file, commands):
|
|
76
76
|
try:
|
|
77
|
-
spec = importlib.util.spec_from_file_location(
|
|
77
|
+
spec = importlib.util.spec_from_file_location("plugins_modules", init_file)
|
|
78
78
|
module = importlib.util.module_from_spec(spec)
|
|
79
79
|
sys.modules[spec.name] = module
|
|
80
80
|
spec.loader.exec_module(module)
|
|
81
|
-
import plugins_modules # type: ignore
|
|
82
|
-
from plugins_modules import __all__ as all_plugins_modules # type: ignore
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
plugins = getattr(module, "__all__", [])
|
|
83
|
+
|
|
84
|
+
for name in plugins:
|
|
85
|
+
obj = getattr(module, name)
|
|
86
|
+
if isinstance(obj, (click.Command, click.Group)):
|
|
87
|
+
commands.add(obj)
|
|
88
|
+
|
|
88
89
|
except ImportError:
|
|
89
|
-
logging.warning(
|
|
90
|
-
f'{inspect.stack()[0][3]}; will skip loading plugin: {module}', exc_info=True
|
|
91
|
-
)
|
|
90
|
+
logging.warning("Failed to load plugin", exc_info=True)
|
|
92
91
|
|
|
93
92
|
|
|
94
93
|
def is_directory(d):
|
|
@@ -14,10 +14,10 @@ def verbose_callback(ctx, param, value):
|
|
|
14
14
|
|
|
15
15
|
def common_verbose_options(func):
|
|
16
16
|
func = click.option(
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
'-v',
|
|
18
|
+
'--verbose',
|
|
19
|
+
show_default='toggle verbose output',
|
|
20
|
+
count=True,
|
|
21
|
+
callback=verbose_callback,
|
|
22
22
|
)(func)
|
|
23
23
|
return func
|
|
@@ -1,32 +1,30 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: multitool
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Quickly create and distribute command-line tools.
|
|
5
|
+
Author-email: Matthew Delotavo <matthew.t.delotavo@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/mdelotavo/multitool
|
|
8
|
+
Project-URL: Repository, https://github.com/mdelotavo/multitool
|
|
9
|
+
Keywords: cli,tooling,automation
|
|
9
10
|
Classifier: Development Status :: 4 - Beta
|
|
10
11
|
Classifier: Environment :: Console
|
|
11
12
|
Classifier: Intended Audience :: Developers
|
|
12
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
13
13
|
Classifier: Operating System :: OS Independent
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.7
|
|
15
15
|
Requires-Python: >=3.7
|
|
16
|
+
Description-Content-Type: text/x-rst
|
|
16
17
|
License-File: LICENSE
|
|
18
|
+
Requires-Dist: click>=8.1.3
|
|
19
|
+
Requires-Dist: click-aliases>=1.0.1
|
|
20
|
+
Requires-Dist: click-option-group>=0.5.5
|
|
21
|
+
Requires-Dist: GitPython>=3.1.30
|
|
22
|
+
Dynamic: license-file
|
|
17
23
|
|
|
18
24
|
multitool
|
|
19
25
|
=========
|
|
20
26
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
--------------------
|
|
24
|
-
Why does this exist?
|
|
25
|
-
--------------------
|
|
26
|
-
|
|
27
|
-
I built this tool so that I can quickly create and distribute command-line tools for consulting work and personal use.
|
|
28
|
-
|
|
29
|
-
The plugins manager uses ``git`` to manage plugins installed from remote ``git`` repositories.
|
|
27
|
+
Quickly create and distribute command-line tools with plugins.
|
|
30
28
|
|
|
31
29
|
-----
|
|
32
30
|
Usage
|
|
@@ -36,20 +34,14 @@ Usage
|
|
|
36
34
|
|
|
37
35
|
Usage: multitool [OPTIONS] COMMAND [ARGS]...
|
|
38
36
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
PyPI: https://pypi.org/project/multitool/
|
|
42
|
-
GitHub: https://github.com/mdelotavo/multitool
|
|
37
|
+
Quickly create and distribute command-line tools.
|
|
43
38
|
|
|
44
39
|
Options:
|
|
45
40
|
-V, --version Show the version and exit.
|
|
46
41
|
-h, --help Show this message and exit.
|
|
47
42
|
|
|
48
43
|
Commands:
|
|
49
|
-
plugins
|
|
50
|
-
|
|
51
|
-
.. ..
|
|
52
|
-
The plugins features are based off those found in the `apigeecli`_.
|
|
44
|
+
plugins Plugins manager for distributing commands.
|
|
53
45
|
|
|
54
46
|
----------------
|
|
55
47
|
Managing plugins
|
|
@@ -122,7 +114,7 @@ This will install and update plugins.
|
|
|
122
114
|
Pruning
|
|
123
115
|
^^^^^^^
|
|
124
116
|
|
|
125
|
-
If you specified the ``-a`` option when running ``multitool plugins configure`` then the removal of plugins will occur automatically.
|
|
117
|
+
If you remove plugins from the config file or comment them out, and you then specified the ``-a`` option when running ``multitool plugins configure`` then the removal of plugins will occur automatically.
|
|
126
118
|
Otherwise you can run::
|
|
127
119
|
|
|
128
120
|
multitool plugins prune
|
|
@@ -146,6 +138,17 @@ In order for this to work, the plugin needs to have the ``Requires`` key in the
|
|
|
146
138
|
|
|
147
139
|
pip3 install $(multitool plugins show -n PLUGIN_NAME --show-dependencies-only)
|
|
148
140
|
|
|
141
|
+
^^^^^^^^^^^^^^^
|
|
142
|
+
Troubleshooting
|
|
143
|
+
^^^^^^^^^^^^^^^
|
|
144
|
+
|
|
145
|
+
If you encounter issues with plugins or commands, you can find more detailed debug information and error messages in the log file:
|
|
146
|
+
::
|
|
147
|
+
|
|
148
|
+
~/.multitool/multitool.log
|
|
149
|
+
|
|
150
|
+
Reviewing this file can help you diagnose installation problems, missing dependencies, or Git-related errors.
|
|
151
|
+
|
|
149
152
|
.. ..
|
|
150
153
|
----------------------------
|
|
151
154
|
Create a virtual environment
|
|
@@ -167,6 +170,5 @@ In order for this to work, the plugin needs to have the ``Requires`` key in the
|
|
|
167
170
|
deactivate
|
|
168
171
|
|
|
169
172
|
.. _`click`: https://click.palletsprojects.com/
|
|
170
|
-
.. _`apigeecli`: https://pypi.org/project/apigeecli/
|
|
171
173
|
.. _`multitool-plugins`: https://github.com/mdelotavo/multitool-plugins
|
|
172
174
|
.. _`public plugins repository`: https://github.com/mdelotavo/multitool-plugins
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "multitool"
|
|
7
|
+
version = "0.6.0"
|
|
8
|
+
description = "Quickly create and distribute command-line tools."
|
|
9
|
+
readme = { file = "README.rst", content-type = "text/x-rst" }
|
|
10
|
+
requires-python = ">=3.7"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Matthew Delotavo", email = "matthew.t.delotavo@gmail.com" }
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
keywords = ["cli", "tooling", "automation"]
|
|
18
|
+
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Environment :: Console",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3.7"
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
dependencies = [
|
|
28
|
+
"click>=8.1.3",
|
|
29
|
+
"click-aliases>=1.0.1",
|
|
30
|
+
"click-option-group>=0.5.5",
|
|
31
|
+
"GitPython>=3.1.30"
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/mdelotavo/multitool"
|
|
36
|
+
Repository = "https://github.com/mdelotavo/multitool"
|
|
37
|
+
|
|
38
|
+
[project.scripts]
|
|
39
|
+
multitool = "multitool.__main__:main"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools]
|
|
42
|
+
include-package-data = true
|
|
43
|
+
|
|
44
|
+
[tool.setuptools.packages.find]
|
|
45
|
+
include = ["multitool*"]
|
|
File without changes
|
|
File without changes
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import builtins
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
def echo(
|
|
6
|
-
*message,
|
|
7
|
-
exit_status=None,
|
|
8
|
-
make_silent=False,
|
|
9
|
-
current_verbosity=0,
|
|
10
|
-
expected_verbosity=0,
|
|
11
|
-
line_ending="\n",
|
|
12
|
-
should_flush=False
|
|
13
|
-
):
|
|
14
|
-
toggle_silent = builtins.MULTITOOL_TOGGLE_SILENT
|
|
15
|
-
toggle_verbose = builtins.MULTITOOL_TOGGLE_VERBOSE
|
|
16
|
-
if make_silent or toggle_silent:
|
|
17
|
-
if exit_status:
|
|
18
|
-
sys.exit(exit_status)
|
|
19
|
-
return
|
|
20
|
-
if current_verbosity or toggle_verbose >= expected_verbosity:
|
|
21
|
-
print(*message, end=line_ending, flush=should_flush)
|
|
22
|
-
if exit_status:
|
|
23
|
-
sys.exit(exit_status)
|
|
@@ -1,229 +0,0 @@
|
|
|
1
|
-
import configparser
|
|
2
|
-
import os
|
|
3
|
-
import shutil
|
|
4
|
-
import stat
|
|
5
|
-
import sys
|
|
6
|
-
from os import path
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
import click
|
|
10
|
-
from click_option_group import MutuallyExclusiveOptionGroup, optgroup
|
|
11
|
-
|
|
12
|
-
from multitool import (MULTITOOL_PLUGINS_CONFIG_FILE,
|
|
13
|
-
MULTITOOL_PLUGINS_DIRECTORY, MULTITOOL_PLUGINS_PATH,
|
|
14
|
-
console)
|
|
15
|
-
from multitool.silent import common_silent_options
|
|
16
|
-
from multitool.utils import (is_directory, is_regular_file, create_directory, read_file_content,
|
|
17
|
-
execute_function_on_directory_files, create_empty_file)
|
|
18
|
-
from multitool.verbose import common_verbose_options
|
|
19
|
-
|
|
20
|
-
is_git_installed = False
|
|
21
|
-
plugins_command_help = 'Simple plugins manager for distributing commands.'
|
|
22
|
-
|
|
23
|
-
try:
|
|
24
|
-
from git import Repo
|
|
25
|
-
|
|
26
|
-
is_git_installed = True
|
|
27
|
-
except ImportError:
|
|
28
|
-
plugins_command_help = '[Git not found! Please install Git first.] Simple plugins manager for distributing commands. This command requires Git to be installed.'
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def chmod_directory(directory, mode):
|
|
32
|
-
"""
|
|
33
|
-
Recursively changes the permissions of a directory and its contents.
|
|
34
|
-
|
|
35
|
-
Reference: https://stackoverflow.com/a/58878271
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
directory (str): Path to the directory.
|
|
39
|
-
mode (int): Permissions to be set (e.g., 0o0700).
|
|
40
|
-
|
|
41
|
-
"""
|
|
42
|
-
for root, dirs, files in os.walk(directory):
|
|
43
|
-
for dir in dirs:
|
|
44
|
-
os.chmod(path.join(root, dir), mode)
|
|
45
|
-
for file in files:
|
|
46
|
-
os.chmod(path.join(root, file), mode)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def clone_plugin_repositories(section="sources"):
|
|
50
|
-
initialize_MULTITOOL_plugins()
|
|
51
|
-
config = load_plugin_config()
|
|
52
|
-
if not config._sections:
|
|
53
|
-
return
|
|
54
|
-
sources = dict(config._sections[section])
|
|
55
|
-
for name, uri in sources.items():
|
|
56
|
-
dest = Path(MULTITOOL_PLUGINS_DIRECTORY) / name
|
|
57
|
-
if is_directory(dest):
|
|
58
|
-
continue
|
|
59
|
-
try:
|
|
60
|
-
console.echo(f"Installing {name}... ", line_ending="", should_flush=True)
|
|
61
|
-
Repo.clone_from(uri, dest)
|
|
62
|
-
console.echo("Done")
|
|
63
|
-
except Exception as e:
|
|
64
|
-
console.echo(e)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def exit_quietly_if_git_not_installed():
|
|
68
|
-
if not is_git_installed:
|
|
69
|
-
sys.exit(0)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def initialize_and_save_plugin_config():
|
|
73
|
-
initialize_MULTITOOL_plugins()
|
|
74
|
-
config = load_plugin_config()
|
|
75
|
-
if not config._sections:
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def initialize_MULTITOOL_plugins():
|
|
80
|
-
create_directory(MULTITOOL_PLUGINS_DIRECTORY)
|
|
81
|
-
create_empty_file(MULTITOOL_PLUGINS_PATH)
|
|
82
|
-
create_empty_file(MULTITOOL_PLUGINS_CONFIG_FILE)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def load_plugin_config(config_file=MULTITOOL_PLUGINS_CONFIG_FILE):
|
|
86
|
-
config = configparser.ConfigParser(allow_no_value=True)
|
|
87
|
-
config.read(config_file)
|
|
88
|
-
return config
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def prune_unused_plugin_directories(section="sources"):
|
|
92
|
-
initialize_MULTITOOL_plugins()
|
|
93
|
-
config = load_plugin_config()
|
|
94
|
-
if not config._sections:
|
|
95
|
-
return
|
|
96
|
-
sources = dict(config._sections[section])
|
|
97
|
-
|
|
98
|
-
def _func(path):
|
|
99
|
-
if not is_directory(path):
|
|
100
|
-
return
|
|
101
|
-
name = Path(path).stem
|
|
102
|
-
if name in sources:
|
|
103
|
-
return
|
|
104
|
-
console.echo(f"Removing {name}... ", line_ending="", should_flush=True)
|
|
105
|
-
plugin_directory = Path(MULTITOOL_PLUGINS_DIRECTORY) / name
|
|
106
|
-
try:
|
|
107
|
-
chmod_directory(str(Path(plugin_directory) / ".git"), stat.S_IRWXU)
|
|
108
|
-
shutil.rmtree(plugin_directory)
|
|
109
|
-
console.echo("Done")
|
|
110
|
-
except Exception as e:
|
|
111
|
-
console.echo(e)
|
|
112
|
-
|
|
113
|
-
return execute_function_on_directory_files(MULTITOOL_PLUGINS_DIRECTORY, _func, glob="[!.][!__]*")
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def update_plugin_repositories():
|
|
117
|
-
def _func(path):
|
|
118
|
-
if not is_directory(path):
|
|
119
|
-
return
|
|
120
|
-
console.echo(f"Updating {Path(path).stem}... ", line_ending="", should_flush=True)
|
|
121
|
-
repo = Repo(path)
|
|
122
|
-
if repo.bare:
|
|
123
|
-
return
|
|
124
|
-
try:
|
|
125
|
-
repo.remotes["origin"].pull()
|
|
126
|
-
console.echo("Done")
|
|
127
|
-
except Exception as e:
|
|
128
|
-
console.echo(e)
|
|
129
|
-
|
|
130
|
-
return execute_function_on_directory_files(MULTITOOL_PLUGINS_DIRECTORY, _func, glob="[!.][!__]*")
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
@click.group(help=plugins_command_help)
|
|
134
|
-
def plugins():
|
|
135
|
-
pass
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
@plugins.command(help="Edit config file manually.")
|
|
139
|
-
@common_silent_options
|
|
140
|
-
@common_verbose_options
|
|
141
|
-
@click.option(
|
|
142
|
-
"-a/-A",
|
|
143
|
-
"--apply-changes/--no-apply-changes",
|
|
144
|
-
default=False,
|
|
145
|
-
help="Install plugins from new sources after exiting the editor.",
|
|
146
|
-
show_default=True,
|
|
147
|
-
)
|
|
148
|
-
def configure(silent, verbose, apply_changes):
|
|
149
|
-
exit_quietly_if_git_not_installed()
|
|
150
|
-
initialize_MULTITOOL_plugins()
|
|
151
|
-
click.edit(filename=MULTITOOL_PLUGINS_CONFIG_FILE)
|
|
152
|
-
if apply_changes:
|
|
153
|
-
clone_plugin_repositories()
|
|
154
|
-
prune_unused_plugin_directories()
|
|
155
|
-
else:
|
|
156
|
-
console.echo("\n Run `apigee plugins update` to apply any changes,")
|
|
157
|
-
console.echo(" or rerun `apigee plugins configure` with `-a`")
|
|
158
|
-
console.echo(" to apply changes automatically.\n")
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
@plugins.command(help="Update or install plugins.")
|
|
162
|
-
@common_silent_options
|
|
163
|
-
@common_verbose_options
|
|
164
|
-
def update(silent, verbose, section="sources"):
|
|
165
|
-
exit_quietly_if_git_not_installed()
|
|
166
|
-
clone_plugin_repositories()
|
|
167
|
-
update_plugin_repositories()
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
@plugins.command(help="Show plugins information.")
|
|
171
|
-
@common_silent_options
|
|
172
|
-
@common_verbose_options
|
|
173
|
-
@click.option("-n", "--name", help="name of the plugins package")
|
|
174
|
-
@optgroup.group(
|
|
175
|
-
"Filter options", cls=MutuallyExclusiveOptionGroup, help="The filter options"
|
|
176
|
-
)
|
|
177
|
-
@optgroup.option(
|
|
178
|
-
"--show-commit-only/--no-show-commit-only",
|
|
179
|
-
default=False,
|
|
180
|
-
help="only print latest Git commit log",
|
|
181
|
-
)
|
|
182
|
-
@optgroup.option(
|
|
183
|
-
"--show-dependencies-only/--no-show-dependencies-only",
|
|
184
|
-
default=False,
|
|
185
|
-
help="only print list of required packages",
|
|
186
|
-
)
|
|
187
|
-
def show(
|
|
188
|
-
silent,
|
|
189
|
-
verbose,
|
|
190
|
-
name,
|
|
191
|
-
section="sources",
|
|
192
|
-
show_commit_only=False,
|
|
193
|
-
show_dependencies_only=False,
|
|
194
|
-
):
|
|
195
|
-
if not name:
|
|
196
|
-
config = load_plugin_config()
|
|
197
|
-
if not config._sections:
|
|
198
|
-
return
|
|
199
|
-
sources = dict(config._sections[section])
|
|
200
|
-
for name, uri in sources.items():
|
|
201
|
-
console.echo(f"{name}: {uri}")
|
|
202
|
-
return
|
|
203
|
-
plugins_info_file = Path(MULTITOOL_PLUGINS_DIRECTORY) / name / "apigee-cli.info"
|
|
204
|
-
if not is_regular_file(plugins_info_file):
|
|
205
|
-
return
|
|
206
|
-
plugins_info = read_file_content(plugins_info_file, type="json")
|
|
207
|
-
if show_commit_only:
|
|
208
|
-
exit_quietly_if_git_not_installed()
|
|
209
|
-
console.echo(
|
|
210
|
-
Repo(Path(MULTITOOL_PLUGINS_DIRECTORY) / name).git.log(
|
|
211
|
-
"--pretty=format:%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset",
|
|
212
|
-
"-1",
|
|
213
|
-
)
|
|
214
|
-
)
|
|
215
|
-
return
|
|
216
|
-
if show_dependencies_only:
|
|
217
|
-
if plugins_info.get("Requires"):
|
|
218
|
-
console.echo(plugins_info.get("Requires"))
|
|
219
|
-
return
|
|
220
|
-
for k, v in plugins_info.items():
|
|
221
|
-
console.echo(f"{k}: {v}")
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
@plugins.command(help="Prune plugins with removed sources.")
|
|
225
|
-
@common_silent_options
|
|
226
|
-
@common_verbose_options
|
|
227
|
-
def prune(silent, verbose, section="sources"):
|
|
228
|
-
exit_quietly_if_git_not_installed()
|
|
229
|
-
prune_unused_plugin_directories()
|
multitool-0.4.0/setup.py
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
from multitool import APP
|
|
4
|
-
from multitool import __version__ as version
|
|
5
|
-
from multitool import description
|
|
6
|
-
|
|
7
|
-
readme = os.path.join(os.path.dirname(__file__), 'README.rst')
|
|
8
|
-
long_description = open(readme).read()
|
|
9
|
-
|
|
10
|
-
SETUP_ARGS = dict(
|
|
11
|
-
name=APP,
|
|
12
|
-
version=version,
|
|
13
|
-
description=(description),
|
|
14
|
-
long_description=long_description,
|
|
15
|
-
url='https://github.com/mdelotavo/multitool',
|
|
16
|
-
author='Matthew Delotavo',
|
|
17
|
-
author_email='matthew.t.delotavo@gmail.com',
|
|
18
|
-
license='MIT',
|
|
19
|
-
include_package_data=True,
|
|
20
|
-
classifiers=[
|
|
21
|
-
'Development Status :: 4 - Beta',
|
|
22
|
-
'Environment :: Console',
|
|
23
|
-
'Intended Audience :: Developers',
|
|
24
|
-
'License :: OSI Approved :: MIT License',
|
|
25
|
-
'Operating System :: OS Independent',
|
|
26
|
-
'Programming Language :: Python :: 3.7',
|
|
27
|
-
],
|
|
28
|
-
entry_points = {
|
|
29
|
-
'console_scripts': [
|
|
30
|
-
'multitool=multitool.__main__:main'
|
|
31
|
-
]
|
|
32
|
-
},
|
|
33
|
-
install_requires = [
|
|
34
|
-
'requests>=2.28.1',
|
|
35
|
-
'click>=8.1.3',
|
|
36
|
-
'click-aliases>=1.0.1',
|
|
37
|
-
'click-option-group>=0.5.5',
|
|
38
|
-
'colorama>=0.4.6',
|
|
39
|
-
'pyotp>=2.8.0',
|
|
40
|
-
'tqdm>=4.64.1',
|
|
41
|
-
'tabulate>=0.9.0',
|
|
42
|
-
'pyjwt>=2.6.0',
|
|
43
|
-
'python-gnupg>=0.4.9',
|
|
44
|
-
'gitpython>=3.1.30'
|
|
45
|
-
],
|
|
46
|
-
python_requires=">=3.7",
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
if __name__ == '__main__':
|
|
50
|
-
from setuptools import setup, find_packages
|
|
51
|
-
|
|
52
|
-
SETUP_ARGS['packages'] = find_packages()
|
|
53
|
-
setup(**SETUP_ARGS)
|