Open-AutoTools 0.0.3rc5__tar.gz → 0.0.4rc1__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.4rc1/MANIFEST.in +4 -0
- open_autotools-0.0.4rc1/Open_AutoTools.egg-info/PKG-INFO +103 -0
- open_autotools-0.0.4rc1/Open_AutoTools.egg-info/SOURCES.txt +53 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/Open_AutoTools.egg-info/entry_points.txt +0 -3
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/Open_AutoTools.egg-info/requires.txt +3 -18
- open_autotools-0.0.4rc1/PKG-INFO +103 -0
- open_autotools-0.0.4rc1/README.md +43 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autocaps/commands.py +3 -7
- open_autotools-0.0.4rc1/autotools/autocaps/core.py +8 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autoip/commands.py +6 -11
- open_autotools-0.0.4rc1/autotools/autoip/core.py +262 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autolower/commands.py +3 -7
- open_autotools-0.0.4rc1/autotools/autolower/core.py +8 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autopassword/commands.py +27 -33
- open_autotools-0.0.4rc1/autotools/autopassword/core.py +62 -0
- open_autotools-0.0.4rc1/autotools/autotest/__init__.py +2 -0
- open_autotools-0.0.4rc1/autotools/autotest/commands.py +205 -0
- open_autotools-0.0.4rc1/autotools/cli.py +156 -0
- open_autotools-0.0.4rc1/autotools/utils/commands.py +13 -0
- open_autotools-0.0.4rc1/autotools/utils/loading.py +24 -0
- open_autotools-0.0.4rc1/autotools/utils/performance.py +392 -0
- open_autotools-0.0.4rc1/autotools/utils/updates.py +38 -0
- open_autotools-0.0.4rc1/autotools/utils/version.py +80 -0
- open_autotools-0.0.4rc1/pyproject.toml +3 -0
- open_autotools-0.0.4rc1/requirements.txt +31 -0
- open_autotools-0.0.4rc1/setup.py +58 -0
- {open_autotools-0.0.3rc5/autotools/autocaps/tests → open_autotools-0.0.4rc1/tests/autotools/autocaps}/test_autocaps_core.py +9 -8
- {open_autotools-0.0.3rc5/autotools/autocaps/tests → open_autotools-0.0.4rc1/tests/autotools/autocaps}/test_autocaps_integration.py +0 -6
- open_autotools-0.0.4rc1/tests/autotools/autoip/test_autoip_core.py +377 -0
- {open_autotools-0.0.3rc5/autotools/autoip/tests → open_autotools-0.0.4rc1/tests/autotools/autoip}/test_autoip_integration.py +3 -21
- {open_autotools-0.0.3rc5/autotools/autolower/tests → open_autotools-0.0.4rc1/tests/autotools/autolower}/test_autolower_core.py +9 -8
- {open_autotools-0.0.3rc5/autotools/autolower/tests → open_autotools-0.0.4rc1/tests/autotools/autolower}/test_autolower_integration.py +0 -6
- open_autotools-0.0.4rc1/tests/autotools/autopassword/test_autopassword_core.py +77 -0
- open_autotools-0.0.4rc1/tests/autotools/autopassword/test_autopassword_integration.py +82 -0
- open_autotools-0.0.4rc1/tests/autotools/autotest/__init__.py +0 -0
- open_autotools-0.0.4rc1/tests/autotools/autotest/test_autotest_core.py +366 -0
- open_autotools-0.0.4rc1/tests/autotools/utils/__init__.py +0 -0
- open_autotools-0.0.4rc1/tests/autotools/utils/test_performance.py +805 -0
- open_autotools-0.0.4rc1/tests/autotools/utils/test_updates.py +95 -0
- open_autotools-0.0.4rc1/tests/autotools/utils/test_version.py +163 -0
- open_autotools-0.0.4rc1/tests/test_cli.py +317 -0
- open_autotools-0.0.3rc5/Open_AutoTools.egg-info/PKG-INFO +0 -317
- open_autotools-0.0.3rc5/Open_AutoTools.egg-info/SOURCES.txt +0 -47
- open_autotools-0.0.3rc5/PKG-INFO +0 -317
- open_autotools-0.0.3rc5/README.md +0 -244
- open_autotools-0.0.3rc5/autotools/autocaps/core.py +0 -7
- open_autotools-0.0.3rc5/autotools/autodownload/commands.py +0 -38
- open_autotools-0.0.3rc5/autotools/autodownload/core.py +0 -433
- open_autotools-0.0.3rc5/autotools/autoip/core.py +0 -311
- open_autotools-0.0.3rc5/autotools/autoip/tests/test_autoip_core.py +0 -72
- open_autotools-0.0.3rc5/autotools/autolower/core.py +0 -7
- open_autotools-0.0.3rc5/autotools/autopassword/core.py +0 -103
- open_autotools-0.0.3rc5/autotools/autospell/__init__.py +0 -3
- open_autotools-0.0.3rc5/autotools/autospell/commands.py +0 -123
- open_autotools-0.0.3rc5/autotools/autospell/core.py +0 -222
- open_autotools-0.0.3rc5/autotools/autotranslate/__init__.py +0 -3
- open_autotools-0.0.3rc5/autotools/autotranslate/commands.py +0 -42
- open_autotools-0.0.3rc5/autotools/autotranslate/core.py +0 -52
- open_autotools-0.0.3rc5/autotools/cli.py +0 -95
- open_autotools-0.0.3rc5/autotools/test/__init__.py +0 -3
- open_autotools-0.0.3rc5/autotools/test/commands.py +0 -118
- open_autotools-0.0.3rc5/autotools/utils/loading.py +0 -16
- open_autotools-0.0.3rc5/autotools/utils/updates.py +0 -30
- open_autotools-0.0.3rc5/autotools/utils/version.py +0 -74
- open_autotools-0.0.3rc5/setup.py +0 -102
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/LICENSE +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/Open_AutoTools.egg-info/dependency_links.txt +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/Open_AutoTools.egg-info/top_level.txt +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/__init__.py +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autocaps/__init__.py +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autoip/__init__.py +0 -0
- {open_autotools-0.0.3rc5/autotools/autodownload → open_autotools-0.0.4rc1/autotools/autolower}/__init__.py +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/autopassword/__init__.py +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/autotools/utils/__init__.py +0 -0
- {open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/setup.cfg +0 -0
- {open_autotools-0.0.3rc5/autotools/autolower → open_autotools-0.0.4rc1/tests}/__init__.py +0 -0
- {open_autotools-0.0.3rc5/autotools/autocaps/tests → open_autotools-0.0.4rc1/tests/autotools/autocaps}/__init__.py +0 -0
- {open_autotools-0.0.3rc5/autotools/autoip/tests → open_autotools-0.0.4rc1/tests/autotools/autoip}/__init__.py +0 -0
- {open_autotools-0.0.3rc5/autotools/autolower/tests → open_autotools-0.0.4rc1/tests/autotools/autolower}/__init__.py +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: Open-AutoTools
|
|
3
|
+
Version: 0.0.4rc1
|
|
4
|
+
Summary: A suite of automated tools accessible via CLI with a simple `autotools` command
|
|
5
|
+
Home-page: https://github.com/BabylooPro/Open-AutoTools
|
|
6
|
+
Author: BabylooPro
|
|
7
|
+
Author-email: maxremy.dev@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/BabylooPro/Open-AutoTools/issues
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: build>=1.4.0
|
|
18
|
+
Requires-Dist: wheel>=0.45.1
|
|
19
|
+
Requires-Dist: Brotli==1.1.0
|
|
20
|
+
Requires-Dist: certifi==2024.2.2
|
|
21
|
+
Requires-Dist: charset-normalizer==3.3.2
|
|
22
|
+
Requires-Dist: click==8.1.3
|
|
23
|
+
Requires-Dist: cryptography==42.0.2
|
|
24
|
+
Requires-Dist: halo>=0.0.31
|
|
25
|
+
Requires-Dist: idna==3.6
|
|
26
|
+
Requires-Dist: importlib-metadata>=7.0.1
|
|
27
|
+
Requires-Dist: packaging>=23.0
|
|
28
|
+
Requires-Dist: platformdirs==4.2.0
|
|
29
|
+
Requires-Dist: pycryptodomex==3.20.0
|
|
30
|
+
Requires-Dist: pyperclip==1.8.2
|
|
31
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
32
|
+
Requires-Dist: requests>=2.32.2
|
|
33
|
+
Requires-Dist: tomli==2.0.1
|
|
34
|
+
Requires-Dist: tqdm==4.66.2
|
|
35
|
+
Requires-Dist: urllib3==2.2.1
|
|
36
|
+
Requires-Dist: websockets==13.0.1
|
|
37
|
+
Requires-Dist: yapf==0.40.2
|
|
38
|
+
Requires-Dist: zipp==3.17.0
|
|
39
|
+
Requires-Dist: netifaces>=0.11.0
|
|
40
|
+
Requires-Dist: speedtest-cli>=2.1.3
|
|
41
|
+
Requires-Dist: psutil>=5.9.0
|
|
42
|
+
Requires-Dist: setuptools>=40.8.0
|
|
43
|
+
Requires-Dist: pytest>=7.4.0
|
|
44
|
+
Requires-Dist: pytest-cov>=4.1.0
|
|
45
|
+
Requires-Dist: pytest-sugar>=1.0.0
|
|
46
|
+
Requires-Dist: pytest-xdist>=3.5.0
|
|
47
|
+
Requires-Dist: pytest-timeout>=2.2.0
|
|
48
|
+
Dynamic: author
|
|
49
|
+
Dynamic: author-email
|
|
50
|
+
Dynamic: classifier
|
|
51
|
+
Dynamic: description
|
|
52
|
+
Dynamic: description-content-type
|
|
53
|
+
Dynamic: home-page
|
|
54
|
+
Dynamic: license
|
|
55
|
+
Dynamic: license-file
|
|
56
|
+
Dynamic: project-url
|
|
57
|
+
Dynamic: requires-dist
|
|
58
|
+
Dynamic: requires-python
|
|
59
|
+
Dynamic: summary
|
|
60
|
+
|
|
61
|
+
# Open-AutoTools
|
|
62
|
+
|
|
63
|
+
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
64
|
+
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
65
|
+
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.11-blue.svg
|
|
66
|
+
[PYTHON_URL]: https://www.python.org/downloads/
|
|
67
|
+
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
68
|
+
[CHANGELOG_URL]: CHANGELOG.md
|
|
69
|
+
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
70
|
+
[TODO_URL]: TODO.md
|
|
71
|
+
|
|
72
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL] [![Python][PYTHON_BADGE]][PYTHON_URL] [![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL] [![TODO][TODO_BADGE]][TODO_URL]
|
|
73
|
+
|
|
74
|
+
Python CLI toolkit for everyday developer tasks. Boost productivity directly from your terminal.
|
|
75
|
+
|
|
76
|
+
https://github.com/BabylooPro/Open-AutoTools/assets/35376790/d57f2b9d-55f8-4368-bb40-c0010eb9d49a
|
|
77
|
+
|
|
78
|
+
## Quick Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pip install open-autotools
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
See [Installation Guide](docs/installation.md) for more details.
|
|
85
|
+
|
|
86
|
+
## Tools
|
|
87
|
+
|
|
88
|
+
- **[AutoCaps](docs/tools/autocaps.md)** - Convert text to uppercase
|
|
89
|
+
- **[AutoLower](docs/tools/autolower.md)** - Convert text to lowercase
|
|
90
|
+
- **[AutoPassword](docs/tools/autopassword.md)** - Generate secure passwords and encryption keys
|
|
91
|
+
- **[AutoIP](docs/tools/autoip.md)** - Display network information and diagnostics
|
|
92
|
+
- **[Test Suite](docs/tools/autotest.md)** - Run the test suite (development only)
|
|
93
|
+
|
|
94
|
+
## Documentation
|
|
95
|
+
|
|
96
|
+
- [Installation](docs/installation.md)
|
|
97
|
+
- [Development](docs/development.md)
|
|
98
|
+
- [Performance](docs/performance.md)
|
|
99
|
+
- [Docker Support](docs/docker.md)
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT - see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
requirements.txt
|
|
6
|
+
setup.py
|
|
7
|
+
Open_AutoTools.egg-info/PKG-INFO
|
|
8
|
+
Open_AutoTools.egg-info/SOURCES.txt
|
|
9
|
+
Open_AutoTools.egg-info/dependency_links.txt
|
|
10
|
+
Open_AutoTools.egg-info/entry_points.txt
|
|
11
|
+
Open_AutoTools.egg-info/requires.txt
|
|
12
|
+
Open_AutoTools.egg-info/top_level.txt
|
|
13
|
+
autotools/__init__.py
|
|
14
|
+
autotools/cli.py
|
|
15
|
+
autotools/autocaps/__init__.py
|
|
16
|
+
autotools/autocaps/commands.py
|
|
17
|
+
autotools/autocaps/core.py
|
|
18
|
+
autotools/autoip/__init__.py
|
|
19
|
+
autotools/autoip/commands.py
|
|
20
|
+
autotools/autoip/core.py
|
|
21
|
+
autotools/autolower/__init__.py
|
|
22
|
+
autotools/autolower/commands.py
|
|
23
|
+
autotools/autolower/core.py
|
|
24
|
+
autotools/autopassword/__init__.py
|
|
25
|
+
autotools/autopassword/commands.py
|
|
26
|
+
autotools/autopassword/core.py
|
|
27
|
+
autotools/autotest/__init__.py
|
|
28
|
+
autotools/autotest/commands.py
|
|
29
|
+
autotools/utils/__init__.py
|
|
30
|
+
autotools/utils/commands.py
|
|
31
|
+
autotools/utils/loading.py
|
|
32
|
+
autotools/utils/performance.py
|
|
33
|
+
autotools/utils/updates.py
|
|
34
|
+
autotools/utils/version.py
|
|
35
|
+
tests/__init__.py
|
|
36
|
+
tests/test_cli.py
|
|
37
|
+
tests/autotools/autocaps/__init__.py
|
|
38
|
+
tests/autotools/autocaps/test_autocaps_core.py
|
|
39
|
+
tests/autotools/autocaps/test_autocaps_integration.py
|
|
40
|
+
tests/autotools/autoip/__init__.py
|
|
41
|
+
tests/autotools/autoip/test_autoip_core.py
|
|
42
|
+
tests/autotools/autoip/test_autoip_integration.py
|
|
43
|
+
tests/autotools/autolower/__init__.py
|
|
44
|
+
tests/autotools/autolower/test_autolower_core.py
|
|
45
|
+
tests/autotools/autolower/test_autolower_integration.py
|
|
46
|
+
tests/autotools/autopassword/test_autopassword_core.py
|
|
47
|
+
tests/autotools/autopassword/test_autopassword_integration.py
|
|
48
|
+
tests/autotools/autotest/__init__.py
|
|
49
|
+
tests/autotools/autotest/test_autotest_core.py
|
|
50
|
+
tests/autotools/utils/__init__.py
|
|
51
|
+
tests/autotools/utils/test_performance.py
|
|
52
|
+
tests/autotools/utils/test_updates.py
|
|
53
|
+
tests/autotools/utils/test_version.py
|
{open_autotools-0.0.3rc5 → open_autotools-0.0.4rc1}/Open_AutoTools.egg-info/entry_points.txt
RENAMED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
[console_scripts]
|
|
2
2
|
autocaps = autotools.cli:autocaps
|
|
3
|
-
autodownload = autotools.cli:autodownload
|
|
4
3
|
autoip = autotools.cli:autoip
|
|
5
4
|
autolower = autotools.cli:autolower
|
|
6
5
|
autopassword = autotools.cli:autopassword
|
|
7
|
-
autospell = autotools.cli:autospell
|
|
8
6
|
autotools = autotools.cli:cli
|
|
9
|
-
autotranslate = autotools.cli:autotranslate
|
|
@@ -1,44 +1,29 @@
|
|
|
1
|
+
build>=1.4.0
|
|
2
|
+
wheel>=0.45.1
|
|
1
3
|
Brotli==1.1.0
|
|
2
4
|
certifi==2024.2.2
|
|
3
5
|
charset-normalizer==3.3.2
|
|
4
6
|
click==8.1.3
|
|
5
7
|
cryptography==42.0.2
|
|
8
|
+
halo>=0.0.31
|
|
6
9
|
idna==3.6
|
|
7
10
|
importlib-metadata>=7.0.1
|
|
8
|
-
joblib==1.3.2
|
|
9
|
-
Levenshtein==0.25.0
|
|
10
|
-
mutagen==1.47.0
|
|
11
11
|
packaging>=23.0
|
|
12
12
|
platformdirs==4.2.0
|
|
13
13
|
pycryptodomex==3.20.0
|
|
14
14
|
pyperclip==1.8.2
|
|
15
|
-
python-Levenshtein==0.25.0
|
|
16
15
|
python-dotenv>=1.0.0
|
|
17
|
-
rapidfuzz==3.6.1
|
|
18
|
-
regex==2023.12.25
|
|
19
16
|
requests>=2.32.2
|
|
20
|
-
textblob==0.18.0.post0
|
|
21
17
|
tomli==2.0.1
|
|
22
18
|
tqdm==4.66.2
|
|
23
19
|
urllib3==2.2.1
|
|
24
20
|
websockets==13.0.1
|
|
25
21
|
yapf==0.40.2
|
|
26
|
-
yt-dlp>=2024.3.10
|
|
27
22
|
zipp==3.17.0
|
|
28
|
-
translate==3.6.1
|
|
29
|
-
langdetect==1.0.9
|
|
30
|
-
deep-translator==1.11.4
|
|
31
23
|
netifaces>=0.11.0
|
|
32
24
|
speedtest-cli>=2.1.3
|
|
33
25
|
psutil>=5.9.0
|
|
34
26
|
setuptools>=40.8.0
|
|
35
|
-
language-tool-python>=2.7.1
|
|
36
|
-
spacy>=3.7.2
|
|
37
|
-
beautifulsoup4>=4.12.0
|
|
38
|
-
halo>=0.0.31
|
|
39
|
-
ffmpeg-python>=0.2.0
|
|
40
|
-
|
|
41
|
-
[test]
|
|
42
27
|
pytest>=7.4.0
|
|
43
28
|
pytest-cov>=4.1.0
|
|
44
29
|
pytest-sugar>=1.0.0
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: Open-AutoTools
|
|
3
|
+
Version: 0.0.4rc1
|
|
4
|
+
Summary: A suite of automated tools accessible via CLI with a simple `autotools` command
|
|
5
|
+
Home-page: https://github.com/BabylooPro/Open-AutoTools
|
|
6
|
+
Author: BabylooPro
|
|
7
|
+
Author-email: maxremy.dev@gmail.com
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/BabylooPro/Open-AutoTools/issues
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
Requires-Dist: build>=1.4.0
|
|
18
|
+
Requires-Dist: wheel>=0.45.1
|
|
19
|
+
Requires-Dist: Brotli==1.1.0
|
|
20
|
+
Requires-Dist: certifi==2024.2.2
|
|
21
|
+
Requires-Dist: charset-normalizer==3.3.2
|
|
22
|
+
Requires-Dist: click==8.1.3
|
|
23
|
+
Requires-Dist: cryptography==42.0.2
|
|
24
|
+
Requires-Dist: halo>=0.0.31
|
|
25
|
+
Requires-Dist: idna==3.6
|
|
26
|
+
Requires-Dist: importlib-metadata>=7.0.1
|
|
27
|
+
Requires-Dist: packaging>=23.0
|
|
28
|
+
Requires-Dist: platformdirs==4.2.0
|
|
29
|
+
Requires-Dist: pycryptodomex==3.20.0
|
|
30
|
+
Requires-Dist: pyperclip==1.8.2
|
|
31
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
32
|
+
Requires-Dist: requests>=2.32.2
|
|
33
|
+
Requires-Dist: tomli==2.0.1
|
|
34
|
+
Requires-Dist: tqdm==4.66.2
|
|
35
|
+
Requires-Dist: urllib3==2.2.1
|
|
36
|
+
Requires-Dist: websockets==13.0.1
|
|
37
|
+
Requires-Dist: yapf==0.40.2
|
|
38
|
+
Requires-Dist: zipp==3.17.0
|
|
39
|
+
Requires-Dist: netifaces>=0.11.0
|
|
40
|
+
Requires-Dist: speedtest-cli>=2.1.3
|
|
41
|
+
Requires-Dist: psutil>=5.9.0
|
|
42
|
+
Requires-Dist: setuptools>=40.8.0
|
|
43
|
+
Requires-Dist: pytest>=7.4.0
|
|
44
|
+
Requires-Dist: pytest-cov>=4.1.0
|
|
45
|
+
Requires-Dist: pytest-sugar>=1.0.0
|
|
46
|
+
Requires-Dist: pytest-xdist>=3.5.0
|
|
47
|
+
Requires-Dist: pytest-timeout>=2.2.0
|
|
48
|
+
Dynamic: author
|
|
49
|
+
Dynamic: author-email
|
|
50
|
+
Dynamic: classifier
|
|
51
|
+
Dynamic: description
|
|
52
|
+
Dynamic: description-content-type
|
|
53
|
+
Dynamic: home-page
|
|
54
|
+
Dynamic: license
|
|
55
|
+
Dynamic: license-file
|
|
56
|
+
Dynamic: project-url
|
|
57
|
+
Dynamic: requires-dist
|
|
58
|
+
Dynamic: requires-python
|
|
59
|
+
Dynamic: summary
|
|
60
|
+
|
|
61
|
+
# Open-AutoTools
|
|
62
|
+
|
|
63
|
+
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
64
|
+
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
65
|
+
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.11-blue.svg
|
|
66
|
+
[PYTHON_URL]: https://www.python.org/downloads/
|
|
67
|
+
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
68
|
+
[CHANGELOG_URL]: CHANGELOG.md
|
|
69
|
+
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
70
|
+
[TODO_URL]: TODO.md
|
|
71
|
+
|
|
72
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL] [![Python][PYTHON_BADGE]][PYTHON_URL] [![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL] [![TODO][TODO_BADGE]][TODO_URL]
|
|
73
|
+
|
|
74
|
+
Python CLI toolkit for everyday developer tasks. Boost productivity directly from your terminal.
|
|
75
|
+
|
|
76
|
+
https://github.com/BabylooPro/Open-AutoTools/assets/35376790/d57f2b9d-55f8-4368-bb40-c0010eb9d49a
|
|
77
|
+
|
|
78
|
+
## Quick Install
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pip install open-autotools
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
See [Installation Guide](docs/installation.md) for more details.
|
|
85
|
+
|
|
86
|
+
## Tools
|
|
87
|
+
|
|
88
|
+
- **[AutoCaps](docs/tools/autocaps.md)** - Convert text to uppercase
|
|
89
|
+
- **[AutoLower](docs/tools/autolower.md)** - Convert text to lowercase
|
|
90
|
+
- **[AutoPassword](docs/tools/autopassword.md)** - Generate secure passwords and encryption keys
|
|
91
|
+
- **[AutoIP](docs/tools/autoip.md)** - Display network information and diagnostics
|
|
92
|
+
- **[Test Suite](docs/tools/autotest.md)** - Run the test suite (development only)
|
|
93
|
+
|
|
94
|
+
## Documentation
|
|
95
|
+
|
|
96
|
+
- [Installation](docs/installation.md)
|
|
97
|
+
- [Development](docs/development.md)
|
|
98
|
+
- [Performance](docs/performance.md)
|
|
99
|
+
- [Docker Support](docs/docker.md)
|
|
100
|
+
|
|
101
|
+
## License
|
|
102
|
+
|
|
103
|
+
MIT - see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Open-AutoTools
|
|
2
|
+
|
|
3
|
+
[PYPI_BADGE]: https://badge.fury.io/py/Open-AutoTools.svg
|
|
4
|
+
[PYPI_URL]: https://pypi.org/project/Open-AutoTools/
|
|
5
|
+
[PYTHON_BADGE]: https://img.shields.io/badge/Python-3.11-blue.svg
|
|
6
|
+
[PYTHON_URL]: https://www.python.org/downloads/
|
|
7
|
+
[CHANGELOG_BADGE]: https://img.shields.io/badge/CHANGELOG-red.svg
|
|
8
|
+
[CHANGELOG_URL]: CHANGELOG.md
|
|
9
|
+
[TODO_BADGE]: https://img.shields.io/badge/TODO-purple.svg
|
|
10
|
+
[TODO_URL]: TODO.md
|
|
11
|
+
|
|
12
|
+
[![PyPI][PYPI_BADGE]][PYPI_URL] [![Python][PYTHON_BADGE]][PYTHON_URL] [![CHANGELOG][CHANGELOG_BADGE]][CHANGELOG_URL] [![TODO][TODO_BADGE]][TODO_URL]
|
|
13
|
+
|
|
14
|
+
Python CLI toolkit for everyday developer tasks. Boost productivity directly from your terminal.
|
|
15
|
+
|
|
16
|
+
https://github.com/BabylooPro/Open-AutoTools/assets/35376790/d57f2b9d-55f8-4368-bb40-c0010eb9d49a
|
|
17
|
+
|
|
18
|
+
## Quick Install
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install open-autotools
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
See [Installation Guide](docs/installation.md) for more details.
|
|
25
|
+
|
|
26
|
+
## Tools
|
|
27
|
+
|
|
28
|
+
- **[AutoCaps](docs/tools/autocaps.md)** - Convert text to uppercase
|
|
29
|
+
- **[AutoLower](docs/tools/autolower.md)** - Convert text to lowercase
|
|
30
|
+
- **[AutoPassword](docs/tools/autopassword.md)** - Generate secure passwords and encryption keys
|
|
31
|
+
- **[AutoIP](docs/tools/autoip.md)** - Display network information and diagnostics
|
|
32
|
+
- **[Test Suite](docs/tools/autotest.md)** - Run the test suite (development only)
|
|
33
|
+
|
|
34
|
+
## Documentation
|
|
35
|
+
|
|
36
|
+
- [Installation](docs/installation.md)
|
|
37
|
+
- [Development](docs/development.md)
|
|
38
|
+
- [Performance](docs/performance.md)
|
|
39
|
+
- [Docker Support](docs/docker.md)
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT - see [LICENSE](LICENSE).
|
|
@@ -3,15 +3,11 @@ from .core import autocaps_transform
|
|
|
3
3
|
from ..utils.loading import LoadingAnimation
|
|
4
4
|
from ..utils.updates import check_for_updates
|
|
5
5
|
|
|
6
|
+
# CLI COMMAND TO TRANSFORM TEXT TO UPPERCASE
|
|
6
7
|
@click.command()
|
|
7
8
|
@click.argument('text', nargs=-1)
|
|
8
9
|
def autocaps(text):
|
|
9
|
-
|
|
10
|
-
with LoadingAnimation():
|
|
11
|
-
result = autocaps_transform(" ".join(text))
|
|
10
|
+
with LoadingAnimation(): result = autocaps_transform(" ".join(text))
|
|
12
11
|
click.echo(result)
|
|
13
|
-
|
|
14
|
-
# UPDATE CHECK AT THE END
|
|
15
12
|
update_msg = check_for_updates()
|
|
16
|
-
if update_msg:
|
|
17
|
-
click.echo(update_msg)
|
|
13
|
+
if update_msg: click.echo(update_msg)
|
|
@@ -3,6 +3,7 @@ from .core import run
|
|
|
3
3
|
from ..utils.loading import LoadingAnimation
|
|
4
4
|
from ..utils.updates import check_for_updates
|
|
5
5
|
|
|
6
|
+
# CLI COMMAND TO DISPLAY NETWORK INFORMATION AND RUN DIAGNOSTICS
|
|
6
7
|
@click.command()
|
|
7
8
|
@click.option('--test', '-t', is_flag=True, help='Run connectivity tests')
|
|
8
9
|
@click.option('--speed', '-s', is_flag=True, help='Run internet speed test')
|
|
@@ -13,17 +14,11 @@ from ..utils.updates import check_for_updates
|
|
|
13
14
|
@click.option('--location', '-l', is_flag=True, help='Show IP location info')
|
|
14
15
|
@click.option('--no-ip', '-n', is_flag=True, help='Hide IP addresses')
|
|
15
16
|
def autoip(test, speed, monitor, interval, ports, dns, location, no_ip):
|
|
16
|
-
"""Display network information and diagnostics.
|
|
17
|
-
|
|
18
|
-
Shows local and public IP addresses, runs network diagnostics,
|
|
19
|
-
performs speed tests, monitors traffic with custom intervals,
|
|
20
|
-
checks ports, displays DNS information and provides geolocation data."""
|
|
21
17
|
with LoadingAnimation():
|
|
22
|
-
output = run(
|
|
23
|
-
|
|
18
|
+
output = run(
|
|
19
|
+
test=test, speed=speed, monitor=monitor, interval=interval,
|
|
20
|
+
ports=ports, dns=dns, location=location, no_ip=no_ip
|
|
21
|
+
)
|
|
24
22
|
click.echo(output)
|
|
25
|
-
|
|
26
|
-
# UPDATE CHECK AT THE END
|
|
27
23
|
update_msg = check_for_updates()
|
|
28
|
-
if update_msg:
|
|
29
|
-
click.echo(update_msg)
|
|
24
|
+
if update_msg: click.echo(update_msg)
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import socket
|
|
2
|
+
import requests
|
|
3
|
+
import json
|
|
4
|
+
import ipaddress
|
|
5
|
+
import netifaces
|
|
6
|
+
import time
|
|
7
|
+
import speedtest
|
|
8
|
+
import psutil
|
|
9
|
+
|
|
10
|
+
# EXTRACTS IPV4 ADDRESSES FROM INTERFACE ADDRESSES
|
|
11
|
+
def _extract_ipv4_addresses(addrs):
|
|
12
|
+
ipv4_list = []
|
|
13
|
+
if netifaces.AF_INET in addrs:
|
|
14
|
+
for addr in addrs[netifaces.AF_INET]:
|
|
15
|
+
if 'addr' in addr and not addr['addr'].startswith('127.'):
|
|
16
|
+
ipv4_list.append(addr['addr'])
|
|
17
|
+
return ipv4_list
|
|
18
|
+
|
|
19
|
+
# EXTRACTS IPV6 ADDRESSES FROM INTERFACE ADDRESSES
|
|
20
|
+
def _extract_ipv6_addresses(addrs):
|
|
21
|
+
ipv6_list = []
|
|
22
|
+
if netifaces.AF_INET6 in addrs:
|
|
23
|
+
for addr in addrs[netifaces.AF_INET6]:
|
|
24
|
+
if 'addr' in addr and not addr['addr'].startswith('fe80:'):
|
|
25
|
+
clean_addr = addr['addr'].split('%')[0]
|
|
26
|
+
ipv6_list.append(clean_addr)
|
|
27
|
+
return ipv6_list
|
|
28
|
+
|
|
29
|
+
# RETRIEVES ALL LOCAL IP ADDRESSES (IPV4 AND IPV6) FROM NETWORK INTERFACES
|
|
30
|
+
def get_local_ips():
|
|
31
|
+
ips = {'ipv4': [], 'ipv6': []}
|
|
32
|
+
|
|
33
|
+
for interface in netifaces.interfaces():
|
|
34
|
+
addrs = netifaces.ifaddresses(interface)
|
|
35
|
+
ips['ipv4'].extend(_extract_ipv4_addresses(addrs))
|
|
36
|
+
ips['ipv6'].extend(_extract_ipv6_addresses(addrs))
|
|
37
|
+
|
|
38
|
+
return ips
|
|
39
|
+
|
|
40
|
+
# RETRIEVES PUBLIC IP ADDRESSES (IPV4 AND IPV6) FROM EXTERNAL SERVICES
|
|
41
|
+
def get_public_ips():
|
|
42
|
+
ips = {'ipv4': None, 'ipv6': None}
|
|
43
|
+
ipv4_services = ['https://api.ipify.org', 'https://ipv4.icanhazip.com', 'https://v4.ident.me']
|
|
44
|
+
ipv6_services = ['https://api6.ipify.org', 'https://ipv6.icanhazip.com', 'https://v6.ident.me']
|
|
45
|
+
|
|
46
|
+
for service in ipv4_services:
|
|
47
|
+
try:
|
|
48
|
+
ips['ipv4'] = requests.get(service, timeout=2).text.strip()
|
|
49
|
+
if ips['ipv4']: break
|
|
50
|
+
except (requests.RequestException, requests.Timeout, requests.ConnectionError):
|
|
51
|
+
continue
|
|
52
|
+
|
|
53
|
+
for service in ipv6_services:
|
|
54
|
+
try:
|
|
55
|
+
ips['ipv6'] = requests.get(service, timeout=2).text.strip()
|
|
56
|
+
if ips['ipv6']: break
|
|
57
|
+
except (requests.RequestException, requests.Timeout, requests.ConnectionError):
|
|
58
|
+
continue
|
|
59
|
+
|
|
60
|
+
return ips
|
|
61
|
+
|
|
62
|
+
# TESTS NETWORK CONNECTIVITY TO COMMON HOSTS
|
|
63
|
+
def test_connectivity():
|
|
64
|
+
results = []
|
|
65
|
+
test_hosts = {
|
|
66
|
+
'Google DNS': ('8.8.8.8', 53),
|
|
67
|
+
'CloudFlare DNS': ('1.1.1.1', 53),
|
|
68
|
+
'Google': ('google.com', 443),
|
|
69
|
+
'Cloudflare': ('cloudflare.com', 443),
|
|
70
|
+
'GitHub': ('github.com', 443),
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for name, (host, port) in test_hosts.items():
|
|
74
|
+
try:
|
|
75
|
+
start = time.time()
|
|
76
|
+
s = socket.create_connection((host, port), timeout=2)
|
|
77
|
+
latency = round((time.time() - start) * 1000, 2)
|
|
78
|
+
s.close()
|
|
79
|
+
results.append((name, True, latency))
|
|
80
|
+
except OSError:
|
|
81
|
+
results.append((name, False, None))
|
|
82
|
+
|
|
83
|
+
return results
|
|
84
|
+
|
|
85
|
+
# RUNS INTERNET SPEED TEST AND DISPLAYS RESULTS INCLUDING PING
|
|
86
|
+
def run_speedtest():
|
|
87
|
+
print("\nRunning speed test (this may take a minute)...")
|
|
88
|
+
try:
|
|
89
|
+
st = speedtest.Speedtest()
|
|
90
|
+
st.get_best_server()
|
|
91
|
+
|
|
92
|
+
print("Testing download speed...")
|
|
93
|
+
download_speed = st.download() / 1_000_000 # CONVERT TO MBPS
|
|
94
|
+
|
|
95
|
+
print("Testing upload speed...")
|
|
96
|
+
upload_speed = st.upload() / 1_000_000 # CONVERT TO MBPS
|
|
97
|
+
|
|
98
|
+
print("Testing ping...")
|
|
99
|
+
ping = st.results.ping
|
|
100
|
+
|
|
101
|
+
print("\nSpeed Test Results:")
|
|
102
|
+
print(f"Download: {download_speed:.2f} Mbps")
|
|
103
|
+
print(f"Upload: {upload_speed:.2f} Mbps")
|
|
104
|
+
print(f"Ping: {ping:.0f} ms")
|
|
105
|
+
|
|
106
|
+
return True
|
|
107
|
+
except Exception as e:
|
|
108
|
+
print(f"\nSpeed test failed: {str(e)}")
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
# GETS PUBLIC IP ADDRESS USING EXTERNAL API SERVICES
|
|
112
|
+
def get_public_ip():
|
|
113
|
+
try:
|
|
114
|
+
response = requests.get('https://api.ipify.org')
|
|
115
|
+
return response.text
|
|
116
|
+
except requests.RequestException:
|
|
117
|
+
try:
|
|
118
|
+
response = requests.get('https://api.ipapi.com/api/check')
|
|
119
|
+
return response.json()['ip']
|
|
120
|
+
except (requests.RequestException, KeyError, ValueError):
|
|
121
|
+
return None
|
|
122
|
+
|
|
123
|
+
# GETS LOCAL IP ADDRESS OF DEFAULT NETWORK INTERFACE
|
|
124
|
+
def get_local_ip():
|
|
125
|
+
try:
|
|
126
|
+
gateways = netifaces.gateways()
|
|
127
|
+
default_interface = gateways['default'][netifaces.AF_INET][1]
|
|
128
|
+
addrs = netifaces.ifaddresses(default_interface)
|
|
129
|
+
return addrs[netifaces.AF_INET][0]['addr']
|
|
130
|
+
except (KeyError, IndexError, OSError):
|
|
131
|
+
try:
|
|
132
|
+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
133
|
+
s.connect(("8.8.8.8", 80))
|
|
134
|
+
ip = s.getsockname()[0]
|
|
135
|
+
s.close()
|
|
136
|
+
return ip
|
|
137
|
+
except OSError:
|
|
138
|
+
return None
|
|
139
|
+
|
|
140
|
+
# RETRIEVES DETAILED INFORMATION ABOUT AN IP ADDRESS
|
|
141
|
+
def get_ip_info(ip=None):
|
|
142
|
+
if ip:
|
|
143
|
+
try:
|
|
144
|
+
ip_obj = ipaddress.ip_address(ip)
|
|
145
|
+
if ip_obj.is_private:
|
|
146
|
+
raise ValueError("Cannot get info for private IP addresses")
|
|
147
|
+
except ValueError as e:
|
|
148
|
+
raise ValueError(f"Invalid IP address: {str(e)}")
|
|
149
|
+
|
|
150
|
+
try:
|
|
151
|
+
url = f'https://ipapi.co/{ip}/json' if ip else 'https://ipapi.co/json'
|
|
152
|
+
response = requests.get(url)
|
|
153
|
+
data = response.json()
|
|
154
|
+
|
|
155
|
+
if 'error' in data: raise ValueError(f"Error getting IP info: {data['error']}")
|
|
156
|
+
|
|
157
|
+
return data
|
|
158
|
+
except requests.RequestException as e:
|
|
159
|
+
raise ValueError(f"Error connecting to IP info service: {str(e)}")
|
|
160
|
+
|
|
161
|
+
# DISPLAYS LOCAL AND PUBLIC IP ADDRESSES
|
|
162
|
+
def _display_ip_addresses(output):
|
|
163
|
+
local_ips = get_local_ips()
|
|
164
|
+
public_ips = get_public_ips()
|
|
165
|
+
output.append("\nLocal IPs:")
|
|
166
|
+
|
|
167
|
+
if local_ips['ipv4']:
|
|
168
|
+
for ip in local_ips['ipv4']: output.append(f"IPv4: {ip}")
|
|
169
|
+
else:
|
|
170
|
+
output.append("IPv4: Not available")
|
|
171
|
+
|
|
172
|
+
if local_ips['ipv6']:
|
|
173
|
+
for ip in local_ips['ipv6']: output.append(f"IPv6: {ip}")
|
|
174
|
+
else:
|
|
175
|
+
output.append("IPv6: Not available")
|
|
176
|
+
|
|
177
|
+
output.append("\nPublic IPs:")
|
|
178
|
+
output.append(f"IPv4: {public_ips['ipv4'] or 'Not available'}")
|
|
179
|
+
output.append(f"IPv6: {public_ips['ipv6'] or 'Not available'}")
|
|
180
|
+
|
|
181
|
+
# DISPLAYS CONNECTIVITY TEST RESULTS
|
|
182
|
+
def _display_connectivity_tests(output):
|
|
183
|
+
output.append("\nConnectivity Tests:")
|
|
184
|
+
results = test_connectivity()
|
|
185
|
+
for name, success, latency in results:
|
|
186
|
+
status = f"✓ {latency}ms" if success else "✗ Failed"
|
|
187
|
+
output.append(f"{name:<15} {status}")
|
|
188
|
+
|
|
189
|
+
# DISPLAYS LOCATION INFORMATION
|
|
190
|
+
def _display_location_info(output):
|
|
191
|
+
try:
|
|
192
|
+
loc = get_ip_info()
|
|
193
|
+
output.append("\nLocation Info:")
|
|
194
|
+
output.append(f"City: {loc.get('city', 'Unknown')}")
|
|
195
|
+
output.append(f"Region: {loc.get('region', 'Unknown')}")
|
|
196
|
+
output.append(f"Country: {loc.get('country', 'Unknown')}")
|
|
197
|
+
output.append(f"ISP: {loc.get('org', 'Unknown')}")
|
|
198
|
+
except Exception as e:
|
|
199
|
+
output.append(f"\nLocation lookup failed: {str(e)}")
|
|
200
|
+
|
|
201
|
+
# DISPLAYS DNS SERVER INFORMATION
|
|
202
|
+
def _display_dns_servers(output):
|
|
203
|
+
output.append("\nDNS Servers:")
|
|
204
|
+
try:
|
|
205
|
+
with open('/etc/resolv.conf', 'r') as f:
|
|
206
|
+
for line in f:
|
|
207
|
+
if 'nameserver' in line: output.append(f"DNS: {line.split()[1]}")
|
|
208
|
+
except OSError:
|
|
209
|
+
output.append("Could not read DNS configuration")
|
|
210
|
+
|
|
211
|
+
# CHECKS AND DISPLAYS COMMON PORTS STATUS
|
|
212
|
+
def _display_ports_status(output):
|
|
213
|
+
common_ports = [80, 443, 22, 21, 25, 3306]
|
|
214
|
+
output.append("\nCommon Ports Status (localhost):")
|
|
215
|
+
|
|
216
|
+
for port in common_ports:
|
|
217
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
218
|
+
result = sock.connect_ex(('127.0.0.1', port))
|
|
219
|
+
status = "Open" if result == 0 else "Closed"
|
|
220
|
+
output.append(f"Port {port}: {status}")
|
|
221
|
+
sock.close()
|
|
222
|
+
|
|
223
|
+
# MONITORS NETWORK TRAFFIC
|
|
224
|
+
def _monitor_network_traffic(output, interval):
|
|
225
|
+
output.append("\nNetwork Monitor (Press Ctrl+C to stop):")
|
|
226
|
+
try:
|
|
227
|
+
prev_bytes_sent = psutil.net_io_counters().bytes_sent
|
|
228
|
+
prev_bytes_recv = psutil.net_io_counters().bytes_recv
|
|
229
|
+
|
|
230
|
+
while True:
|
|
231
|
+
time.sleep(interval)
|
|
232
|
+
bytes_sent = psutil.net_io_counters().bytes_sent
|
|
233
|
+
bytes_recv = psutil.net_io_counters().bytes_recv
|
|
234
|
+
|
|
235
|
+
upload_speed = (bytes_sent - prev_bytes_sent) / (1024 * interval)
|
|
236
|
+
download_speed = (bytes_recv - prev_bytes_recv) / (1024 * interval)
|
|
237
|
+
|
|
238
|
+
output.append(f"\rUp: {upload_speed:.2f} KB/s | Down: {download_speed:.2f} KB/s")
|
|
239
|
+
|
|
240
|
+
prev_bytes_sent = bytes_sent
|
|
241
|
+
prev_bytes_recv = bytes_recv
|
|
242
|
+
|
|
243
|
+
except KeyboardInterrupt:
|
|
244
|
+
output.append("\nMonitoring stopped")
|
|
245
|
+
|
|
246
|
+
# MAIN FUNCTION TO RUN NETWORK DIAGNOSTICS AND DISPLAY RESULTS
|
|
247
|
+
def run(test=False, speed=False, monitor=False, interval=1, ports=False, dns=False, location=False, no_ip=False):
|
|
248
|
+
output = []
|
|
249
|
+
|
|
250
|
+
if not no_ip: _display_ip_addresses(output)
|
|
251
|
+
if test: _display_connectivity_tests(output)
|
|
252
|
+
if location: _display_location_info(output)
|
|
253
|
+
if dns: _display_dns_servers(output)
|
|
254
|
+
if ports: _display_ports_status(output)
|
|
255
|
+
if monitor: _monitor_network_traffic(output, interval)
|
|
256
|
+
|
|
257
|
+
if speed:
|
|
258
|
+
output.append("\nRunning speed test...")
|
|
259
|
+
if run_speedtest(): output.append("Speed test completed successfully")
|
|
260
|
+
else: output.append("Speed test failed")
|
|
261
|
+
|
|
262
|
+
return "\n".join(output)
|