Open-AutoTools 0.0.5__tar.gz → 0.0.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.
- {open_autotools-0.0.5 → open_autotools-0.0.7/Open_AutoTools.egg-info}/PKG-INFO +13 -2
- {open_autotools-0.0.5 → open_autotools-0.0.7}/Open_AutoTools.egg-info/SOURCES.txt +4 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/Open_AutoTools.egg-info/requires.txt +1 -0
- {open_autotools-0.0.5/Open_AutoTools.egg-info → open_autotools-0.0.7}/PKG-INFO +13 -2
- {open_autotools-0.0.5 → open_autotools-0.0.7}/README.md +11 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autocaps/core.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autocolor/core.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/commands.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/convert_image.py +10 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/convert_video.py +3 -2
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/core.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoip/core.py +8 -5
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autolower/core.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autounit/core.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autozip/commands.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autozip/core.py +3 -3
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/cli.py +84 -33
- open_autotools-0.0.7/autotools/tool_registry.py +19 -0
- open_autotools-0.0.7/autotools/utils/__init__.py +14 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/utils/commands.py +59 -11
- open_autotools-0.0.7/autotools/utils/loading.py +41 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/utils/performance.py +1 -1
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/utils/requirements.py +1 -1
- open_autotools-0.0.7/autotools/utils/updates.py +116 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/requirements.txt +1 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/setup.py +14 -20
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autocaps/test_autocaps_core.py +8 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autocolor/test_autocolor_core.py +7 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/unit/test_convert_core.py +2 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/unit/test_convert_image.py +49 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autolower/test_autolower_core.py +8 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autounit/test_autounit_core.py +8 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/test_commands_discovery.py +36 -0
- open_autotools-0.0.7/tests/autotools/utils/test_loading.py +99 -0
- open_autotools-0.0.7/tests/autotools/utils/test_updates.py +287 -0
- open_autotools-0.0.7/tests/autotools/utils/test_utils_init.py +20 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/test_version.py +9 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/test_cli.py +129 -21
- open_autotools-0.0.7/tests/test_docker_benchmark_runner.py +222 -0
- open_autotools-0.0.5/autotools/utils/__init__.py +0 -5
- open_autotools-0.0.5/autotools/utils/loading.py +0 -24
- open_autotools-0.0.5/autotools/utils/updates.py +0 -38
- open_autotools-0.0.5/tests/autotools/utils/test_updates.py +0 -95
- {open_autotools-0.0.5 → open_autotools-0.0.7}/LICENSE +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/MANIFEST.in +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/Open_AutoTools.egg-info/dependency_links.txt +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/Open_AutoTools.egg-info/entry_points.txt +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/Open_AutoTools.egg-info/top_level.txt +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autocaps/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autocaps/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autocolor/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autocolor/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/convert_audio.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/convert_text.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoip/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoip/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autolower/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autolower/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autonote/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autonote/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autonote/core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autopassword/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autopassword/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autopassword/core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autotest/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autotest/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autotodo/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autotodo/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autotodo/core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autounit/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autounit/commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autozip/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/utils/smoke.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/utils/text.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/utils/version.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/pyproject.toml +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/setup.cfg +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autocaps/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autocaps/test_autocaps_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autocolor/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autocolor/test_autocolor_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/conftest.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/integration/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/integration/test_convert_commands.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/unit/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/unit/test_convert_audio.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/unit/test_convert_text.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoconvert/unit/test_convert_video.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoip/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoip/test_autoip_core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autoip/test_autoip_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autolower/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autolower/test_autolower_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autonote/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autonote/conftest.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autonote/test_autonote_core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autonote/test_autonote_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autopassword/test_autopassword_core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autopassword/test_autopassword_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotest/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotest/test_autotest_core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/conftest.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_coverage.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_file_operations.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_operations.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_sections.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_tasks.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autotodo/test_autotodo_utils.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autounit/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autounit/test_autounit_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autozip/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autozip/test_autozip_core.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/autozip/test_autozip_integration.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/__init__.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/test_performance.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/test_requirements.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/test_smoke.py +0 -0
- {open_autotools-0.0.5 → open_autotools-0.0.7}/tests/autotools/utils/test_text.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Open-AutoTools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.7
|
|
4
4
|
Summary: A suite of automated tools accessible via CLI with a simple `autotools` command
|
|
5
5
|
Home-page: https://github.com/BabylooPro/Open-AutoTools
|
|
6
6
|
Author: BabylooPro
|
|
@@ -26,6 +26,7 @@ Requires-Dist: speedtest-cli>=2.1.3
|
|
|
26
26
|
Requires-Dist: psutil>=5.9.0
|
|
27
27
|
Requires-Dist: cryptography>=42.0.2
|
|
28
28
|
Requires-Dist: Pillow>=10.0.0
|
|
29
|
+
Requires-Dist: pillow-heif>=0.16.0
|
|
29
30
|
Requires-Dist: pydub>=0.25.1
|
|
30
31
|
Requires-Dist: moviepy>=1.0.3
|
|
31
32
|
Requires-Dist: pint>=0.23
|
|
@@ -63,14 +64,24 @@ Dynamic: summary
|
|
|
63
64
|
|
|
64
65
|
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
65
66
|
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
67
|
+
|
|
68
|
+
[PYPI_DOWNLOADS_BADGE]: https://img.shields.io/pypi/dm/Open-AutoTools
|
|
69
|
+
[PYPI_DOWNLOADS_URL]: https://pypi.org/project/Open-AutoTools/
|
|
70
|
+
|
|
66
71
|
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.10+-blue.svg
|
|
67
72
|
[PYTHON_URL]: https://www.python.org/downloads/
|
|
73
|
+
|
|
68
74
|
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
69
75
|
[CHANGELOG_URL]: CHANGELOG.md
|
|
76
|
+
|
|
70
77
|
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
71
78
|
[TODO_URL]: TODO.md
|
|
72
79
|
|
|
73
|
-
[![PyPI][PYPI_BADGE]][PYPI_URL]
|
|
80
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL]
|
|
81
|
+
[![Python][PYTHON_BADGE]][PYTHON_URL]
|
|
82
|
+
[![Downloads][PYPI_DOWNLOADS_BADGE]][PYPI_DOWNLOADS_URL]
|
|
83
|
+
[![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL]
|
|
84
|
+
[![TODO][TODO_BADGE]][TODO_URL]
|
|
74
85
|
|
|
75
86
|
Python CLI toolkit for everyday developer tasks. Boost productivity directly from your terminal.
|
|
76
87
|
|
|
@@ -12,6 +12,7 @@ Open_AutoTools.egg-info/requires.txt
|
|
|
12
12
|
Open_AutoTools.egg-info/top_level.txt
|
|
13
13
|
autotools/__init__.py
|
|
14
14
|
autotools/cli.py
|
|
15
|
+
autotools/tool_registry.py
|
|
15
16
|
autotools/autocaps/__init__.py
|
|
16
17
|
autotools/autocaps/commands.py
|
|
17
18
|
autotools/autocaps/core.py
|
|
@@ -60,6 +61,7 @@ autotools/utils/updates.py
|
|
|
60
61
|
autotools/utils/version.py
|
|
61
62
|
tests/__init__.py
|
|
62
63
|
tests/test_cli.py
|
|
64
|
+
tests/test_docker_benchmark_runner.py
|
|
63
65
|
tests/autotools/autocaps/__init__.py
|
|
64
66
|
tests/autotools/autocaps/test_autocaps_core.py
|
|
65
67
|
tests/autotools/autocaps/test_autocaps_integration.py
|
|
@@ -107,9 +109,11 @@ tests/autotools/autozip/test_autozip_core.py
|
|
|
107
109
|
tests/autotools/autozip/test_autozip_integration.py
|
|
108
110
|
tests/autotools/utils/__init__.py
|
|
109
111
|
tests/autotools/utils/test_commands_discovery.py
|
|
112
|
+
tests/autotools/utils/test_loading.py
|
|
110
113
|
tests/autotools/utils/test_performance.py
|
|
111
114
|
tests/autotools/utils/test_requirements.py
|
|
112
115
|
tests/autotools/utils/test_smoke.py
|
|
113
116
|
tests/autotools/utils/test_text.py
|
|
114
117
|
tests/autotools/utils/test_updates.py
|
|
118
|
+
tests/autotools/utils/test_utils_init.py
|
|
115
119
|
tests/autotools/utils/test_version.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: Open-AutoTools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.7
|
|
4
4
|
Summary: A suite of automated tools accessible via CLI with a simple `autotools` command
|
|
5
5
|
Home-page: https://github.com/BabylooPro/Open-AutoTools
|
|
6
6
|
Author: BabylooPro
|
|
@@ -26,6 +26,7 @@ Requires-Dist: speedtest-cli>=2.1.3
|
|
|
26
26
|
Requires-Dist: psutil>=5.9.0
|
|
27
27
|
Requires-Dist: cryptography>=42.0.2
|
|
28
28
|
Requires-Dist: Pillow>=10.0.0
|
|
29
|
+
Requires-Dist: pillow-heif>=0.16.0
|
|
29
30
|
Requires-Dist: pydub>=0.25.1
|
|
30
31
|
Requires-Dist: moviepy>=1.0.3
|
|
31
32
|
Requires-Dist: pint>=0.23
|
|
@@ -63,14 +64,24 @@ Dynamic: summary
|
|
|
63
64
|
|
|
64
65
|
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
65
66
|
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
67
|
+
|
|
68
|
+
[PYPI_DOWNLOADS_BADGE]: https://img.shields.io/pypi/dm/Open-AutoTools
|
|
69
|
+
[PYPI_DOWNLOADS_URL]: https://pypi.org/project/Open-AutoTools/
|
|
70
|
+
|
|
66
71
|
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.10+-blue.svg
|
|
67
72
|
[PYTHON_URL]: https://www.python.org/downloads/
|
|
73
|
+
|
|
68
74
|
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
69
75
|
[CHANGELOG_URL]: CHANGELOG.md
|
|
76
|
+
|
|
70
77
|
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
71
78
|
[TODO_URL]: TODO.md
|
|
72
79
|
|
|
73
|
-
[![PyPI][PYPI_BADGE]][PYPI_URL]
|
|
80
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL]
|
|
81
|
+
[![Python][PYTHON_BADGE]][PYTHON_URL]
|
|
82
|
+
[![Downloads][PYPI_DOWNLOADS_BADGE]][PYPI_DOWNLOADS_URL]
|
|
83
|
+
[![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL]
|
|
84
|
+
[![TODO][TODO_BADGE]][TODO_URL]
|
|
74
85
|
|
|
75
86
|
Python CLI toolkit for everyday developer tasks. Boost productivity directly from your terminal.
|
|
76
87
|
|
|
@@ -2,14 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
4
4
|
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
5
|
+
|
|
6
|
+
[PYPI_DOWNLOADS_BADGE]: https://img.shields.io/pypi/dm/Open-AutoTools
|
|
7
|
+
[PYPI_DOWNLOADS_URL]: https://pypi.org/project/Open-AutoTools/
|
|
8
|
+
|
|
5
9
|
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.10+-blue.svg
|
|
6
10
|
[PYTHON_URL]: https://www.python.org/downloads/
|
|
11
|
+
|
|
7
12
|
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
8
13
|
[CHANGELOG_URL]: CHANGELOG.md
|
|
14
|
+
|
|
9
15
|
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
10
16
|
[TODO_URL]: TODO.md
|
|
11
17
|
|
|
12
|
-
[![PyPI][PYPI_BADGE]][PYPI_URL]
|
|
18
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL]
|
|
19
|
+
[![Python][PYTHON_BADGE]][PYTHON_URL]
|
|
20
|
+
[![Downloads][PYPI_DOWNLOADS_BADGE]][PYPI_DOWNLOADS_URL]
|
|
21
|
+
[![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL]
|
|
22
|
+
[![TODO][TODO_BADGE]][TODO_URL]
|
|
13
23
|
|
|
14
24
|
Python CLI toolkit for everyday developer tasks. Boost productivity directly from your terminal.
|
|
15
25
|
|
|
@@ -94,6 +94,6 @@ def autocolor_convert(color_input, output_format='hex'):
|
|
|
94
94
|
result = _format_output(r, g, b, alpha, output_format)
|
|
95
95
|
|
|
96
96
|
try: pyperclip.copy(result)
|
|
97
|
-
except pyperclip.PyperclipException: pass
|
|
97
|
+
except (pyperclip.PyperclipException, OSError): pass
|
|
98
98
|
|
|
99
99
|
return result
|
|
@@ -10,7 +10,7 @@ TOOL_CATEGORY = 'Files'
|
|
|
10
10
|
|
|
11
11
|
# SMOKE TEST CASES (USED BY 'autotools smoke')
|
|
12
12
|
SMOKE_TESTS = [
|
|
13
|
-
{'name': 'md-json', 'args': ['README.md', '/
|
|
13
|
+
{'name': 'md-json', 'args': ['README.md', '.autotools-smoke/autoconvert-smoke.json']},
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
# CLI COMMAND TO CONVERT FILES BETWEEN DIFFERENT FORMATS
|
{open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/convert_image.py
RENAMED
|
@@ -6,11 +6,21 @@ from typing import Optional
|
|
|
6
6
|
def convert_image(input_path: str, output_path: str, output_format: Optional[str] = None) -> bool:
|
|
7
7
|
try:
|
|
8
8
|
from PIL import Image
|
|
9
|
+
input_ext = Path(input_path).suffix[1:].lower()
|
|
10
|
+
if input_ext in ('heic', 'heif'):
|
|
11
|
+
try:
|
|
12
|
+
from pillow_heif import register_heif_opener
|
|
13
|
+
register_heif_opener()
|
|
14
|
+
except ImportError:
|
|
15
|
+
pass
|
|
9
16
|
|
|
10
17
|
if not os.path.exists(input_path):
|
|
11
18
|
raise FileNotFoundError(f"INPUT FILE NOT FOUND: {input_path}")
|
|
12
19
|
if output_format is None: output_format = Path(output_path).suffix[1:].upper()
|
|
13
20
|
|
|
21
|
+
format_aliases = {'JPG': 'JPEG', 'TIF': 'TIFF'}
|
|
22
|
+
output_format = format_aliases.get(output_format.upper(), output_format.upper())
|
|
23
|
+
|
|
14
24
|
with Image.open(input_path) as img:
|
|
15
25
|
if output_format in ['JPG', 'JPEG'] and img.mode in ('RGBA', 'LA', 'P'):
|
|
16
26
|
rgb_img = Image.new('RGB', img.size, (255, 255, 255))
|
{open_autotools-0.0.5 → open_autotools-0.0.7}/autotools/autoconvert/conversion/convert_video.py
RENAMED
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import os
|
|
2
|
+
import importlib
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import Optional
|
|
4
5
|
|
|
5
6
|
# CONVERTS VIDEO BETWEEN FORMATS
|
|
6
7
|
def convert_video(input_path: str, output_path: str, output_format: Optional[str] = None) -> bool:
|
|
7
8
|
try:
|
|
8
|
-
|
|
9
|
+
video_file_clip = importlib.import_module("moviepy.editor").VideoFileClip
|
|
9
10
|
|
|
10
11
|
if not os.path.exists(input_path):
|
|
11
12
|
raise FileNotFoundError(f"INPUT FILE NOT FOUND: {input_path}")
|
|
12
13
|
if output_format is None: output_format = Path(output_path).suffix[1:].lower()
|
|
13
14
|
|
|
14
|
-
with
|
|
15
|
+
with video_file_clip(input_path) as video: video.write_videofile(output_path, codec='libx264', audio_codec='aac')
|
|
15
16
|
|
|
16
17
|
return True
|
|
17
18
|
|
|
@@ -15,7 +15,7 @@ def detect_file_type(file_path: str) -> str:
|
|
|
15
15
|
if ext in text_formats: return 'text'
|
|
16
16
|
|
|
17
17
|
# IMAGE FORMATS
|
|
18
|
-
image_formats = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff', 'tif', 'ico', 'svg']
|
|
18
|
+
image_formats = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'tiff', 'tif', 'ico', 'svg', 'heic', 'heif']
|
|
19
19
|
if ext in image_formats: return 'image'
|
|
20
20
|
|
|
21
21
|
# AUDIO FORMATS
|
|
@@ -7,6 +7,9 @@ import speedtest
|
|
|
7
7
|
import psutil
|
|
8
8
|
from ..utils.text import is_ci_environment, mask_ipv4, mask_ipv6, mask_sensitive_info
|
|
9
9
|
|
|
10
|
+
GOOGLE_DNS_IPV4 = str(ipaddress.IPv4Address(0x08080808))
|
|
11
|
+
CLOUDFLARE_DNS_IPV4 = str(ipaddress.IPv4Address(0x01010101))
|
|
12
|
+
|
|
10
13
|
# NORMALIZES psutil.net_if_addrs() OUTPUT TO A netifaces-LIKE STRUCTURE:
|
|
11
14
|
def _psutil_addrs_to_family_map(addrs):
|
|
12
15
|
family_map = {}
|
|
@@ -61,14 +64,14 @@ def get_public_ips():
|
|
|
61
64
|
try:
|
|
62
65
|
ips['ipv4'] = requests.get(service, timeout=2).text.strip()
|
|
63
66
|
if ips['ipv4']: break
|
|
64
|
-
except
|
|
67
|
+
except requests.RequestException:
|
|
65
68
|
continue
|
|
66
69
|
|
|
67
70
|
for service in ipv6_services:
|
|
68
71
|
try:
|
|
69
72
|
ips['ipv6'] = requests.get(service, timeout=2).text.strip()
|
|
70
73
|
if ips['ipv6']: break
|
|
71
|
-
except
|
|
74
|
+
except requests.RequestException:
|
|
72
75
|
continue
|
|
73
76
|
|
|
74
77
|
return ips
|
|
@@ -77,8 +80,8 @@ def get_public_ips():
|
|
|
77
80
|
def test_connectivity():
|
|
78
81
|
results = []
|
|
79
82
|
test_hosts = {
|
|
80
|
-
'Google DNS': (
|
|
81
|
-
'CloudFlare DNS': (
|
|
83
|
+
'Google DNS': (GOOGLE_DNS_IPV4, 53),
|
|
84
|
+
'CloudFlare DNS': (CLOUDFLARE_DNS_IPV4, 53),
|
|
82
85
|
'Google': ('google.com', 443),
|
|
83
86
|
'Cloudflare': ('cloudflare.com', 443),
|
|
84
87
|
'GitHub': ('github.com', 443),
|
|
@@ -150,7 +153,7 @@ def get_local_ip():
|
|
|
150
153
|
# FALLBACK: UDP SOCKET TRICK
|
|
151
154
|
try:
|
|
152
155
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
153
|
-
s.connect((
|
|
156
|
+
s.connect((GOOGLE_DNS_IPV4, 80))
|
|
154
157
|
ip = s.getsockname()[0]
|
|
155
158
|
s.close()
|
|
156
159
|
return ip
|
|
@@ -9,7 +9,7 @@ TOOL_CATEGORY = 'Files'
|
|
|
9
9
|
|
|
10
10
|
# SMOKE TEST CASES (USED BY 'autotools smoke')
|
|
11
11
|
SMOKE_TESTS = [
|
|
12
|
-
{'name': 'zip-readme', 'args': ['README.md', '--output', '/
|
|
12
|
+
{'name': 'zip-readme', 'args': ['README.md', '--output', '.autotools-smoke/autozip-smoke.zip']},
|
|
13
13
|
]
|
|
14
14
|
|
|
15
15
|
# CLI COMMAND TO COMPRESS FILES AND DIRECTORIES
|
|
@@ -69,9 +69,9 @@ def _compress_tar_xz(source_paths, output_path, compression_level=6):
|
|
|
69
69
|
# DETERMINES OUTPUT FORMAT FROM FILE EXTENSION
|
|
70
70
|
def _get_format_from_extension(output_path):
|
|
71
71
|
path_str = str(output_path).lower()
|
|
72
|
-
if path_str.endswith('.tar.gz'
|
|
73
|
-
elif path_str.endswith('.tar.bz2'
|
|
74
|
-
elif path_str.endswith('.tar.xz'
|
|
72
|
+
if path_str.endswith(('.tar.gz', '.tgz')): return 'tar.gz'
|
|
73
|
+
elif path_str.endswith(('.tar.bz2', '.tbz2')): return 'tar.bz2'
|
|
74
|
+
elif path_str.endswith(('.tar.xz', '.txz')): return 'tar.xz'
|
|
75
75
|
elif path_str.endswith('.tar'): return 'tar'
|
|
76
76
|
elif path_str.endswith('.zip'): return 'zip'
|
|
77
77
|
else:
|
|
@@ -1,26 +1,89 @@
|
|
|
1
1
|
import click
|
|
2
|
-
import requests
|
|
3
|
-
import base64
|
|
4
|
-
import argparse
|
|
5
2
|
import json as json_module
|
|
6
|
-
import sys
|
|
7
3
|
import os
|
|
8
4
|
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
from .utils.commands import get_tool_names, get_wrapped_tool_command, get_wrapped_tool_commands
|
|
6
|
+
from .tool_registry import LAZY_TOOL_NAMES
|
|
7
|
+
|
|
8
|
+
def _public_tool_name(tool_name):
|
|
9
|
+
return 'test' if tool_name == 'autotest' else tool_name
|
|
10
|
+
|
|
11
|
+
def _internal_tool_name(public_name):
|
|
12
|
+
return 'autotest' if public_name == 'test' else public_name
|
|
13
|
+
|
|
14
|
+
def _load_dotenv_if_present():
|
|
15
|
+
if not os.path.exists('.env'): return
|
|
16
|
+
try:
|
|
17
|
+
from dotenv import load_dotenv
|
|
18
|
+
load_dotenv()
|
|
19
|
+
except ImportError:
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
def print_version(ctx, value):
|
|
23
|
+
if not value or ctx.resilient_parsing: return
|
|
24
|
+
_load_dotenv_if_present()
|
|
25
|
+
from .utils.version import print_version as _print_version
|
|
26
|
+
return _print_version(ctx, value)
|
|
27
|
+
|
|
28
|
+
def check_for_updates():
|
|
29
|
+
from .utils.updates import check_for_updates as _check_for_updates
|
|
30
|
+
return _check_for_updates()
|
|
31
|
+
|
|
32
|
+
def _ctx_has_perf_flag(ctx):
|
|
33
|
+
current = ctx
|
|
34
|
+
while current:
|
|
35
|
+
if current.params.get('perf', False): return True
|
|
36
|
+
current = getattr(current, 'parent', None)
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
def should_enable_metrics(ctx):
|
|
40
|
+
if not _ctx_has_perf_flag(ctx): return False
|
|
41
|
+
from .utils.performance import should_enable_metrics as _should_enable_metrics
|
|
42
|
+
return _should_enable_metrics(ctx)
|
|
43
|
+
|
|
44
|
+
def init_metrics():
|
|
45
|
+
from .utils.performance import init_metrics as _init_metrics
|
|
46
|
+
return _init_metrics()
|
|
47
|
+
|
|
48
|
+
def finalize_metrics(ctx):
|
|
49
|
+
from .utils.performance import finalize_metrics as _finalize_metrics
|
|
50
|
+
return _finalize_metrics(ctx)
|
|
51
|
+
|
|
52
|
+
def get_metrics():
|
|
53
|
+
from .utils.performance import get_metrics as _get_metrics
|
|
54
|
+
return _get_metrics()
|
|
55
|
+
|
|
56
|
+
# CLICK COMMAND PROXY USED BY console_scripts AND TESTS WITHOUT IMPORTING EVERY TOOL
|
|
57
|
+
class LazyToolCommand(click.Command):
|
|
58
|
+
def __init__(self, tool_name):
|
|
59
|
+
self.tool_name = tool_name
|
|
60
|
+
super().__init__(name=_public_tool_name(tool_name))
|
|
61
|
+
|
|
62
|
+
def _load_command(self):
|
|
63
|
+
cmd = get_wrapped_tool_command(self.tool_name)
|
|
64
|
+
if cmd is None:
|
|
65
|
+
raise click.ClickException(f"Unknown tool: {self.tool_name}")
|
|
66
|
+
return cmd
|
|
67
|
+
|
|
68
|
+
def main(self, *args, **kwargs):
|
|
69
|
+
return self._load_command().main(*args, **kwargs)
|
|
70
|
+
|
|
71
|
+
# LAZY GROUP: LISTS TOOLS WITHOUT IMPORTING THEM, IMPORTS ONLY THE SELECTED COMMAND
|
|
72
|
+
class LazyAutoToolsGroup(click.Group):
|
|
73
|
+
def list_commands(self, ctx):
|
|
74
|
+
commands = set(super().list_commands(ctx))
|
|
75
|
+
commands.update(_public_tool_name(tool_name) for tool_name in get_tool_names())
|
|
76
|
+
return sorted(commands)
|
|
77
|
+
|
|
78
|
+
def get_command(self, ctx, cmd_name):
|
|
79
|
+
cmd = super().get_command(ctx, cmd_name)
|
|
80
|
+
if cmd is not None: return cmd
|
|
81
|
+
|
|
82
|
+
tool_name = _internal_tool_name(cmd_name)
|
|
83
|
+
return get_wrapped_tool_command(tool_name)
|
|
21
84
|
|
|
22
85
|
# MAIN CLI ENTRY POINT - REGISTERS ALL COMMANDS AND HANDLES GLOBAL OPTIONS
|
|
23
|
-
@click.group(invoke_without_command=True)
|
|
86
|
+
@click.group(cls=LazyAutoToolsGroup, invoke_without_command=True)
|
|
24
87
|
@click.option('--version', '--v', is_flag=True, callback=lambda ctx, param, value: print_version(ctx, value),
|
|
25
88
|
expose_value=False, is_eager=True, help='Show version and check for updates')
|
|
26
89
|
@click.option('--help', '-h', is_flag=True, callback=lambda ctx, param, value:
|
|
@@ -50,6 +113,7 @@ def cli(ctx, perf):
|
|
|
50
113
|
"""
|
|
51
114
|
|
|
52
115
|
# INITIALIZE METRICS IF NEEDED
|
|
116
|
+
_load_dotenv_if_present()
|
|
53
117
|
if should_enable_metrics(ctx):
|
|
54
118
|
init_metrics()
|
|
55
119
|
get_metrics().step_start('startup')
|
|
@@ -63,17 +127,6 @@ def cli(ctx, perf):
|
|
|
63
127
|
get_metrics().end_process()
|
|
64
128
|
finalize_metrics(ctx)
|
|
65
129
|
|
|
66
|
-
# DISCOVER AND REGISTER ALL TOOL COMMANDS
|
|
67
|
-
_wrapped_tool_commands = get_wrapped_tool_commands()
|
|
68
|
-
for _tool_name in sorted(_wrapped_tool_commands):
|
|
69
|
-
_cmd = _wrapped_tool_commands[_tool_name]
|
|
70
|
-
|
|
71
|
-
if _tool_name == 'autotest': cli.add_command(_cmd, name='test')
|
|
72
|
-
else: cli.add_command(_cmd)
|
|
73
|
-
|
|
74
|
-
# EXPOSE TOOL COMMANDS FOR console_scripts ENTRYPOINTS (setup.py)
|
|
75
|
-
for _tool_name, _cmd in _wrapped_tool_commands.items(): globals()[_tool_name] = _cmd
|
|
76
|
-
|
|
77
130
|
# DISPLAYS COMMAND OPTIONS
|
|
78
131
|
def _display_command_options(cmd_obj):
|
|
79
132
|
if not hasattr(cmd_obj, 'params'): return
|
|
@@ -122,11 +175,7 @@ def autotools():
|
|
|
122
175
|
@cli.command(name='list-tools')
|
|
123
176
|
@click.option('--json', 'as_json', is_flag=True, help='OUTPUT JSON')
|
|
124
177
|
def list_tools(as_json):
|
|
125
|
-
tools = []
|
|
126
|
-
for tool_name, cmd in get_wrapped_tool_commands().items():
|
|
127
|
-
public_name = 'test' if tool_name == 'autotest' else (cmd.name or tool_name)
|
|
128
|
-
tools.append(public_name)
|
|
129
|
-
|
|
178
|
+
tools = [_public_tool_name(tool_name) for tool_name in get_tool_names()]
|
|
130
179
|
tools = sorted(set(tools))
|
|
131
180
|
if as_json: click.echo(json_module.dumps(tools))
|
|
132
181
|
else: click.echo("\n".join(tools))
|
|
@@ -157,4 +206,6 @@ def smoke(workdir, timeout, include_tools, exclude_tools, as_json, verbose):
|
|
|
157
206
|
failed = [r for r in results if r.get('status') != 'OK']
|
|
158
207
|
raise SystemExit(1 if failed else 0)
|
|
159
208
|
|
|
209
|
+
globals().update({tool_name: LazyToolCommand(tool_name) for tool_name in LAZY_TOOL_NAMES})
|
|
210
|
+
|
|
160
211
|
if __name__ == '__main__': cli()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
CONSOLE_TOOL_NAMES = (
|
|
2
|
+
'autocaps',
|
|
3
|
+
'autolower',
|
|
4
|
+
'autopassword',
|
|
5
|
+
'autoip',
|
|
6
|
+
'autoconvert',
|
|
7
|
+
'autocolor',
|
|
8
|
+
'autounit',
|
|
9
|
+
'autozip',
|
|
10
|
+
'autotodo',
|
|
11
|
+
'autonote',
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
LAZY_TOOL_NAMES = CONSOLE_TOOL_NAMES + ('autotest',)
|
|
15
|
+
|
|
16
|
+
CONSOLE_SCRIPT_ENTRY_POINTS = (
|
|
17
|
+
'autotools=autotools.cli:cli',
|
|
18
|
+
*(f'{tool_name}=autotools.cli:{tool_name}' for tool_name in CONSOLE_TOOL_NAMES),
|
|
19
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
__all__ = ['LoadingAnimation', 'check_for_updates', 'print_version']
|
|
2
|
+
|
|
3
|
+
def __getattr__(name):
|
|
4
|
+
if name == 'LoadingAnimation':
|
|
5
|
+
from .loading import LoadingAnimation
|
|
6
|
+
return LoadingAnimation
|
|
7
|
+
if name == 'check_for_updates':
|
|
8
|
+
from .updates import check_for_updates
|
|
9
|
+
return check_for_updates
|
|
10
|
+
if name == 'print_version':
|
|
11
|
+
from .version import print_version
|
|
12
|
+
return print_version
|
|
13
|
+
|
|
14
|
+
raise AttributeError(f"module 'autotools.utils' has no attribute {name!r}")
|
|
@@ -5,10 +5,11 @@ import pkgutil
|
|
|
5
5
|
from types import ModuleType
|
|
6
6
|
from typing import Dict, Iterable, List, Tuple
|
|
7
7
|
|
|
8
|
-
from .performance import init_metrics, finalize_metrics, get_metrics, should_enable_metrics, track_step
|
|
9
|
-
|
|
10
8
|
__all__ = [
|
|
11
9
|
'discover_tool_command_entries',
|
|
10
|
+
'get_tool_names',
|
|
11
|
+
'get_tool_command_entry',
|
|
12
|
+
'get_wrapped_tool_command',
|
|
12
13
|
'get_wrapped_tool_commands',
|
|
13
14
|
'register_commands',
|
|
14
15
|
'get_tool_category'
|
|
@@ -17,6 +18,34 @@ __all__ = [
|
|
|
17
18
|
# PACKAGES THAT SHOULD NEVER BE TREATED AS TOOLS
|
|
18
19
|
_EXCLUDED_TOOL_PACKAGES = {'utils', '__pycache__'}
|
|
19
20
|
|
|
21
|
+
def _ctx_has_perf_flag(ctx) -> bool:
|
|
22
|
+
current = ctx
|
|
23
|
+
while current:
|
|
24
|
+
if current.params.get('perf', False): return True
|
|
25
|
+
current = getattr(current, 'parent', None)
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
def init_metrics():
|
|
29
|
+
from .performance import init_metrics as _init_metrics
|
|
30
|
+
return _init_metrics()
|
|
31
|
+
|
|
32
|
+
def finalize_metrics(ctx):
|
|
33
|
+
from .performance import finalize_metrics as _finalize_metrics
|
|
34
|
+
return _finalize_metrics(ctx)
|
|
35
|
+
|
|
36
|
+
def get_metrics():
|
|
37
|
+
from .performance import get_metrics as _get_metrics
|
|
38
|
+
return _get_metrics()
|
|
39
|
+
|
|
40
|
+
def should_enable_metrics(ctx):
|
|
41
|
+
if not _ctx_has_perf_flag(ctx): return False
|
|
42
|
+
from .performance import should_enable_metrics as _should_enable_metrics
|
|
43
|
+
return _should_enable_metrics(ctx)
|
|
44
|
+
|
|
45
|
+
def track_step(name: str):
|
|
46
|
+
from .performance import track_step as _track_step
|
|
47
|
+
return _track_step(name)
|
|
48
|
+
|
|
20
49
|
# ITERATES ALL TOP-LEVEL TOOL PACKAGES (autotools/<tool>/)
|
|
21
50
|
def _iter_tool_packages() -> Iterable[str]:
|
|
22
51
|
import autotools as autotools_pkg
|
|
@@ -28,6 +57,10 @@ def _iter_tool_packages() -> Iterable[str]:
|
|
|
28
57
|
if name == 'cli': continue
|
|
29
58
|
yield name
|
|
30
59
|
|
|
60
|
+
# RETURNS DISCOVERED TOP-LEVEL TOOL PACKAGE NAMES WITHOUT IMPORTING COMMAND MODULES
|
|
61
|
+
def get_tool_names() -> List[str]:
|
|
62
|
+
return sorted(_iter_tool_packages())
|
|
63
|
+
|
|
31
64
|
# IMPORTS autotools.<tool>.commands IF IT EXISTS
|
|
32
65
|
def _import_tool_commands_module(tool_name: str) -> ModuleType | None:
|
|
33
66
|
full_name = f'autotools.{tool_name}.commands'
|
|
@@ -64,17 +97,32 @@ def _select_command_for_tool(cmds: List[click.Command], tool_name: str, mod_name
|
|
|
64
97
|
# DISCOVERS TOOL COMMANDS AS (MODULE, CLICK COMMAND) BY TOOL PACKAGE NAME
|
|
65
98
|
def discover_tool_command_entries() -> Dict[str, Tuple[ModuleType, click.Command]]:
|
|
66
99
|
entries: Dict[str, Tuple[ModuleType, click.Command]] = {}
|
|
67
|
-
for tool_name in
|
|
68
|
-
|
|
69
|
-
if
|
|
70
|
-
cmds = _extract_click_commands(mod)
|
|
71
|
-
if not cmds: continue
|
|
72
|
-
|
|
73
|
-
selected = _select_command_for_tool(cmds, tool_name, mod.__name__)
|
|
74
|
-
entries[tool_name] = (mod, selected)
|
|
100
|
+
for tool_name in get_tool_names():
|
|
101
|
+
entry = get_tool_command_entry(tool_name)
|
|
102
|
+
if entry is not None: entries[tool_name] = entry
|
|
75
103
|
|
|
76
104
|
return entries
|
|
77
105
|
|
|
106
|
+
# RETURNS A SINGLE TOOL COMMAND ENTRY WITHOUT IMPORTING EVERY OTHER TOOL
|
|
107
|
+
def get_tool_command_entry(tool_name: str) -> Tuple[ModuleType, click.Command] | None:
|
|
108
|
+
if tool_name not in set(get_tool_names()): return None
|
|
109
|
+
|
|
110
|
+
mod = _import_tool_commands_module(tool_name)
|
|
111
|
+
if mod is None: return None
|
|
112
|
+
cmds = _extract_click_commands(mod)
|
|
113
|
+
if not cmds: return None
|
|
114
|
+
|
|
115
|
+
selected = _select_command_for_tool(cmds, tool_name, mod.__name__)
|
|
116
|
+
return mod, selected
|
|
117
|
+
|
|
118
|
+
# RETURNS ONE WRAPPED TOOL COMMAND BY PACKAGE NAME
|
|
119
|
+
def get_wrapped_tool_command(tool_name: str) -> click.Command | None:
|
|
120
|
+
entry = get_tool_command_entry(tool_name)
|
|
121
|
+
if entry is None: return None
|
|
122
|
+
|
|
123
|
+
_mod, cmd = entry
|
|
124
|
+
return _wrap_command_with_metrics(cmd)
|
|
125
|
+
|
|
78
126
|
# RETURNS WRAPPED TOOL COMMANDS (USED BY CLI GROUP AND CONSOLE_SCRIPTS EXPORTS)
|
|
79
127
|
def get_wrapped_tool_commands() -> Dict[str, click.Command]:
|
|
80
128
|
wrapped: Dict[str, click.Command] = {}
|
|
@@ -84,10 +132,10 @@ def get_wrapped_tool_commands() -> Dict[str, click.Command]:
|
|
|
84
132
|
|
|
85
133
|
# EXECUTES COMMAND WITH PERFORMANCE TRACKING
|
|
86
134
|
def _execute_with_metrics(ctx, original_callback, *args, **kwargs):
|
|
87
|
-
metrics = get_metrics()
|
|
88
135
|
kwargs.pop('perf', None)
|
|
89
136
|
|
|
90
137
|
if not should_enable_metrics(ctx): return original_callback(*args, **kwargs)
|
|
138
|
+
metrics = get_metrics()
|
|
91
139
|
if metrics.process_start is None:
|
|
92
140
|
init_metrics()
|
|
93
141
|
get_metrics().end_startup()
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
import threading
|
|
4
|
+
|
|
5
|
+
# PATCHES THREAD SET DAEMON METHOD TO PREVENT WARNINGS
|
|
6
|
+
def _patched_set_daemon(self, daemon):
|
|
7
|
+
self.daemon = daemon
|
|
8
|
+
|
|
9
|
+
_original_set_daemon = None
|
|
10
|
+
|
|
11
|
+
def _should_show_spinner():
|
|
12
|
+
if os.getenv('CI') or os.getenv('PYTEST_CURRENT_TEST'): return False
|
|
13
|
+
if os.getenv('TERM', '').lower() == 'dumb': return False
|
|
14
|
+
return bool(getattr(sys.stderr, 'isatty', lambda: False)())
|
|
15
|
+
|
|
16
|
+
def _create_spinner():
|
|
17
|
+
global _original_set_daemon
|
|
18
|
+
if _original_set_daemon is None:
|
|
19
|
+
_original_set_daemon = threading.Thread.daemon
|
|
20
|
+
threading.Thread.daemon = _patched_set_daemon
|
|
21
|
+
|
|
22
|
+
from halo import Halo
|
|
23
|
+
return Halo(spinner={'interval': 200, 'frames': [' ', '. ', '.. ', '...']})
|
|
24
|
+
|
|
25
|
+
# CONTEXT MANAGER FOR DISPLAYING LOADING ANIMATION
|
|
26
|
+
class LoadingAnimation:
|
|
27
|
+
# INITIALIZES SPINNER WITH CUSTOM ANIMATION FRAMES
|
|
28
|
+
def __init__(self):
|
|
29
|
+
self._spinner = None
|
|
30
|
+
self._enabled = _should_show_spinner()
|
|
31
|
+
|
|
32
|
+
# STARTS THE LOADING ANIMATION
|
|
33
|
+
def __enter__(self):
|
|
34
|
+
if self._enabled:
|
|
35
|
+
self._spinner = _create_spinner()
|
|
36
|
+
self._spinner.start()
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
# STOPS THE LOADING ANIMATION
|
|
40
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
41
|
+
if self._spinner is not None: self._spinner.stop()
|