evolver-tools 1.5.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.
- evolver_tools-1.5.0/LICENSE +21 -0
- evolver_tools-1.5.0/PKG-INFO +107 -0
- evolver_tools-1.5.0/README.md +85 -0
- evolver_tools-1.5.0/pyproject.toml +72 -0
- evolver_tools-1.5.0/setup.cfg +4 -0
- evolver_tools-1.5.0/src/evolver_tools/__init__.py +2 -0
- evolver_tools-1.5.0/src/evolver_tools/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/cli.py +93 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/b64/__init__.py +2 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/b64/b64.py +176 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/cal_tool/__init__.py +1 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/cal_tool/cli.py +234 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/chart_cli/__init__.py +444 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/chart_cli/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/colors/__init__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/colors/__main__.py +97 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/cron/__init__.py +413 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/cron/__main__.py +4 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/csv_stats/__init__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/csv_stats/__main__.py +4 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/csv_stats/analyzer.py +258 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/csv_stats/cli.py +45 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/diff_tool/__init__.py +217 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/diff_tool/__main__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/dirsize/__init__.py +183 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/dt_convert.py +123 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/envcheck/__init__.py +426 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ff/__init__.py +427 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ff/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/find_dups/__init__.py +7 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/find_dups/cli.py +392 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/hashsum/__init__.py +211 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/hashsum/__main__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/http_live/__init__.py +265 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/http_live/__main__.py +2 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ipcalc/__init__.py +155 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ipcalc/__main__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ipinfo/__init__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ipinfo/__main__.py +30 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/jq_lite/__init__.py +257 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/jq_lite/__main__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/json2csv/__init__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/json2csv/__main__.py +82 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/jsonql/__init__.py +326 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/jsonql/__main__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/license_cli/__init__.py +1 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/license_cli/__main__.py +4 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/license_cli/cli.py +289 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/markdown_check/__init__.py +211 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/nb/__init__.py +319 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/nb/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/passgen/__init__.py +224 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/portcheck/__init__.py +2 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/portcheck/__main__.py +66 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/project_doctor/__init__.py +412 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/project_doctor/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ren/__init__.py +283 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/ren/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/siege_lite/__init__.py +250 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/siege_lite/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/smellfinder/__init__.py +376 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/smellfinder/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/sqlite_cli/__init__.py +326 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/sqlite_cli/__main__.py +5 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/sysmon/__init__.py +305 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/sysmon/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/timer/__init__.py +127 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/treedir/__init__.py +2 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/treedir/__main__.py +128 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/urlparse_tool/__init__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/urlparse_tool/cli.py +212 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/uuid_tool/__init__.py +235 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/uuid_tool/__main__.py +6 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/web_summary/__init__.py +341 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/web_summary/__main__.py +3 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/wordcount/__init__.py +2 -0
- evolver_tools-1.5.0/src/evolver_tools/vendor/wordcount/__main__.py +101 -0
- evolver_tools-1.5.0/src/evolver_tools.egg-info/PKG-INFO +107 -0
- evolver_tools-1.5.0/src/evolver_tools.egg-info/SOURCES.txt +80 -0
- evolver_tools-1.5.0/src/evolver_tools.egg-info/dependency_links.txt +1 -0
- evolver_tools-1.5.0/src/evolver_tools.egg-info/entry_points.txt +38 -0
- evolver_tools-1.5.0/src/evolver_tools.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EVOLVER
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: evolver-tools
|
|
3
|
+
Version: 1.5.0
|
|
4
|
+
Summary: 36 essential CLI tools - one pip install
|
|
5
|
+
Author: EVOLVER
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://evolver-dev.github.io/evolver-tools
|
|
8
|
+
Project-URL: Repository, https://github.com/evolver-dev/evolver-tools
|
|
9
|
+
Keywords: cli,devops,productivity,developer-tools,terminal
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Environment :: Console
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: System Administrators
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
+
Classifier: Topic :: Utilities
|
|
18
|
+
Requires-Python: >=3.8
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
License-File: LICENSE
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# EVOLVER Tools
|
|
24
|
+
|
|
25
|
+
**36 essential CLI tools — one `pip install`.**
|
|
26
|
+
|
|
27
|
+
Zero-dependency (35/36), cross-platform, production-ready.
|
|
28
|
+
Monitor systems, analyze code, fuzzy-search data, query databases, and more.
|
|
29
|
+
104KB total — one install, not 32.
|
|
30
|
+
|
|
31
|
+
## Quick Start
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install evolver-tools
|
|
35
|
+
evtool list # Show all 32 tools
|
|
36
|
+
evtool ff < data.txt # Fuzzy search through data
|
|
37
|
+
evtool sysmon # Launch system monitor
|
|
38
|
+
evtool sqlite-cli my.db "SELECT * FROM users LIMIT 10"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Tools
|
|
42
|
+
|
|
43
|
+
### Ops
|
|
44
|
+
|
|
45
|
+
| Tool | Description |
|
|
46
|
+
|------|-------------|
|
|
47
|
+
| **sysmon** | Real-time system monitor (curses TUI — CPU/mem/disk/net/processes) |
|
|
48
|
+
| **dirsize** | Recursive directory space analyzer |
|
|
49
|
+
| **envcheck** | Environment variable validator (missing keys, formats) |
|
|
50
|
+
| **portcheck** | TCP port scanner & service detection |
|
|
51
|
+
| **siege-lite** | HTTP load tester (concurrency, latency percentile) |
|
|
52
|
+
| **http-live** | SSE hot-reload HTTP server for development |
|
|
53
|
+
| **ipinfo** | Public IP & geolocation lookup |
|
|
54
|
+
| **hashsum** | File hash verification (MD5/SHA-1/256/512/BLAKE2, auto-detect) |
|
|
55
|
+
| **find-dups** | Find duplicate files by SHA256 hash, size, or name |
|
|
56
|
+
|
|
57
|
+
### Developer
|
|
58
|
+
|
|
59
|
+
| Tool | Description |
|
|
60
|
+
|------|-------------|
|
|
61
|
+
| **smellfinder** | Python code smell detector (AST-based, 10+ patterns) |
|
|
62
|
+
| **project-doctor** | Project health checker (meta, structure, quality) |
|
|
63
|
+
| **license-cli** | Open-source license generator/validator |
|
|
64
|
+
| **markdown-check** | Markdown format validator & style checker |
|
|
65
|
+
| **sqlite-cli** | SQLite query tool — CSV/JSON/table output |
|
|
66
|
+
| **b64** | Base64 encode/decode with auto-detection |
|
|
67
|
+
| **jsonql** | Zero-dep JSON query tool (SQL-like syntax) |
|
|
68
|
+
| **jq-lite** | jq-style JSON query — filter, extract, transform |
|
|
69
|
+
| **urlparse** | URL parser & debugger |
|
|
70
|
+
| **colors** | 256-color table & HEX↔RGB conversion |
|
|
71
|
+
|
|
72
|
+
### Data & Analysis
|
|
73
|
+
|
|
74
|
+
| Tool | Description |
|
|
75
|
+
|------|-------------|
|
|
76
|
+
| **csv-stats** | CSV column analysis — histograms, frequencies, correlations |
|
|
77
|
+
| **json2csv** | JSON to CSV converter with nested key flattening |
|
|
78
|
+
| **chart-cli** | Terminal chart generator — bar, line, pie, histogram |
|
|
79
|
+
| **cal** | Calendar & date calculator |
|
|
80
|
+
| **web-summary** | Web page content extractor (title, body, links) |
|
|
81
|
+
|
|
82
|
+
### Productivity
|
|
83
|
+
|
|
84
|
+
| Tool | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| **ff** | Interactive fuzzy finder (like fzf, pure Python curses TUI) |
|
|
87
|
+
| **nb** | Command-line notebook (JSON storage, full-text search) |
|
|
88
|
+
| **ren** | Batch file renamer (prefix/suffix/regex/numbering) |
|
|
89
|
+
| **timer** | Countdown timer & stopwatch with desktop notifications |
|
|
90
|
+
| **treedir** | Directory tree visualizer with depth control |
|
|
91
|
+
| **wordcount** | Enhanced word/char/line counter with language detection |
|
|
92
|
+
| **dt** | Date/time format converter (timestamps, timezones) |
|
|
93
|
+
|
|
94
|
+
### Security
|
|
95
|
+
|
|
96
|
+
| Tool | Description |
|
|
97
|
+
|------|-------------|
|
|
98
|
+
| **passgen** | Password generator with entropy display & charset rules |
|
|
99
|
+
|
|
100
|
+
## Requirements
|
|
101
|
+
|
|
102
|
+
- Python 3.8+
|
|
103
|
+
- No external dependencies (31 of 32 tools use stdlib only; ipinfo uses ip-api.com)
|
|
104
|
+
|
|
105
|
+
## License
|
|
106
|
+
|
|
107
|
+
MIT
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# EVOLVER Tools
|
|
2
|
+
|
|
3
|
+
**36 essential CLI tools — one `pip install`.**
|
|
4
|
+
|
|
5
|
+
Zero-dependency (35/36), cross-platform, production-ready.
|
|
6
|
+
Monitor systems, analyze code, fuzzy-search data, query databases, and more.
|
|
7
|
+
104KB total — one install, not 32.
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install evolver-tools
|
|
13
|
+
evtool list # Show all 32 tools
|
|
14
|
+
evtool ff < data.txt # Fuzzy search through data
|
|
15
|
+
evtool sysmon # Launch system monitor
|
|
16
|
+
evtool sqlite-cli my.db "SELECT * FROM users LIMIT 10"
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Tools
|
|
20
|
+
|
|
21
|
+
### Ops
|
|
22
|
+
|
|
23
|
+
| Tool | Description |
|
|
24
|
+
|------|-------------|
|
|
25
|
+
| **sysmon** | Real-time system monitor (curses TUI — CPU/mem/disk/net/processes) |
|
|
26
|
+
| **dirsize** | Recursive directory space analyzer |
|
|
27
|
+
| **envcheck** | Environment variable validator (missing keys, formats) |
|
|
28
|
+
| **portcheck** | TCP port scanner & service detection |
|
|
29
|
+
| **siege-lite** | HTTP load tester (concurrency, latency percentile) |
|
|
30
|
+
| **http-live** | SSE hot-reload HTTP server for development |
|
|
31
|
+
| **ipinfo** | Public IP & geolocation lookup |
|
|
32
|
+
| **hashsum** | File hash verification (MD5/SHA-1/256/512/BLAKE2, auto-detect) |
|
|
33
|
+
| **find-dups** | Find duplicate files by SHA256 hash, size, or name |
|
|
34
|
+
|
|
35
|
+
### Developer
|
|
36
|
+
|
|
37
|
+
| Tool | Description |
|
|
38
|
+
|------|-------------|
|
|
39
|
+
| **smellfinder** | Python code smell detector (AST-based, 10+ patterns) |
|
|
40
|
+
| **project-doctor** | Project health checker (meta, structure, quality) |
|
|
41
|
+
| **license-cli** | Open-source license generator/validator |
|
|
42
|
+
| **markdown-check** | Markdown format validator & style checker |
|
|
43
|
+
| **sqlite-cli** | SQLite query tool — CSV/JSON/table output |
|
|
44
|
+
| **b64** | Base64 encode/decode with auto-detection |
|
|
45
|
+
| **jsonql** | Zero-dep JSON query tool (SQL-like syntax) |
|
|
46
|
+
| **jq-lite** | jq-style JSON query — filter, extract, transform |
|
|
47
|
+
| **urlparse** | URL parser & debugger |
|
|
48
|
+
| **colors** | 256-color table & HEX↔RGB conversion |
|
|
49
|
+
|
|
50
|
+
### Data & Analysis
|
|
51
|
+
|
|
52
|
+
| Tool | Description |
|
|
53
|
+
|------|-------------|
|
|
54
|
+
| **csv-stats** | CSV column analysis — histograms, frequencies, correlations |
|
|
55
|
+
| **json2csv** | JSON to CSV converter with nested key flattening |
|
|
56
|
+
| **chart-cli** | Terminal chart generator — bar, line, pie, histogram |
|
|
57
|
+
| **cal** | Calendar & date calculator |
|
|
58
|
+
| **web-summary** | Web page content extractor (title, body, links) |
|
|
59
|
+
|
|
60
|
+
### Productivity
|
|
61
|
+
|
|
62
|
+
| Tool | Description |
|
|
63
|
+
|------|-------------|
|
|
64
|
+
| **ff** | Interactive fuzzy finder (like fzf, pure Python curses TUI) |
|
|
65
|
+
| **nb** | Command-line notebook (JSON storage, full-text search) |
|
|
66
|
+
| **ren** | Batch file renamer (prefix/suffix/regex/numbering) |
|
|
67
|
+
| **timer** | Countdown timer & stopwatch with desktop notifications |
|
|
68
|
+
| **treedir** | Directory tree visualizer with depth control |
|
|
69
|
+
| **wordcount** | Enhanced word/char/line counter with language detection |
|
|
70
|
+
| **dt** | Date/time format converter (timestamps, timezones) |
|
|
71
|
+
|
|
72
|
+
### Security
|
|
73
|
+
|
|
74
|
+
| Tool | Description |
|
|
75
|
+
|------|-------------|
|
|
76
|
+
| **passgen** | Password generator with entropy display & charset rules |
|
|
77
|
+
|
|
78
|
+
## Requirements
|
|
79
|
+
|
|
80
|
+
- Python 3.8+
|
|
81
|
+
- No external dependencies (31 of 32 tools use stdlib only; ipinfo uses ip-api.com)
|
|
82
|
+
|
|
83
|
+
## License
|
|
84
|
+
|
|
85
|
+
MIT
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=64.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "evolver-tools"
|
|
7
|
+
version = "1.5.0"
|
|
8
|
+
description = "36 essential CLI tools - one pip install"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
keywords = ["cli", "devops", "productivity", "developer-tools", "terminal"]
|
|
13
|
+
authors = [
|
|
14
|
+
{name = "EVOLVER"},
|
|
15
|
+
]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 5 - Production/Stable",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"Intended Audience :: System Administrators",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
24
|
+
"Topic :: Utilities",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://evolver-dev.github.io/evolver-tools"
|
|
29
|
+
Repository = "https://github.com/evolver-dev/evolver-tools"
|
|
30
|
+
|
|
31
|
+
[project.scripts]
|
|
32
|
+
evtool = "evolver_tools.cli:main"
|
|
33
|
+
b64 = "evolver_tools.vendor.b64:main"
|
|
34
|
+
ff = "evolver_tools.vendor.ff:main"
|
|
35
|
+
cal = "evolver_tools.vendor.cal_tool.cli:main"
|
|
36
|
+
chart-cli = "evolver_tools.vendor.chart_cli:main"
|
|
37
|
+
colors = "evolver_tools.vendor.colors:main"
|
|
38
|
+
cron = "evolver_tools.vendor.cron:main"
|
|
39
|
+
csv-stats = "evolver_tools.vendor.csv_stats.cli:main"
|
|
40
|
+
diff = "evolver_tools.vendor.diff_tool:main"
|
|
41
|
+
dirsize = "evolver_tools.vendor.dirsize:entry"
|
|
42
|
+
dt = "evolver_tools.vendor.dt_convert:main"
|
|
43
|
+
envcheck = "evolver_tools.vendor.envcheck:main"
|
|
44
|
+
find-dups = "evolver_tools.vendor.find_dups.cli:main"
|
|
45
|
+
hashsum = "evolver_tools.vendor.hashsum:main"
|
|
46
|
+
http-live = "evolver_tools.vendor.http_live:main"
|
|
47
|
+
ipcalc = "evolver_tools.vendor.ipcalc:main"
|
|
48
|
+
ipinfo = "evolver_tools.vendor.ipinfo:main"
|
|
49
|
+
jq-lite = "evolver_tools.vendor.jq_lite:main"
|
|
50
|
+
json2csv = "evolver_tools.vendor.json2csv:main"
|
|
51
|
+
jsonql = "evolver_tools.vendor.jsonql:main"
|
|
52
|
+
license-cli = "evolver_tools.vendor.license_cli.cli:main"
|
|
53
|
+
markdown-check = "evolver_tools.vendor.markdown_check:main"
|
|
54
|
+
nb = "evolver_tools.vendor.nb:main"
|
|
55
|
+
passgen = "evolver_tools.vendor.passgen:entry"
|
|
56
|
+
portcheck = "evolver_tools.vendor.portcheck.__main__:main"
|
|
57
|
+
project-doctor = "evolver_tools.vendor.project_doctor:main"
|
|
58
|
+
ren = "evolver_tools.vendor.ren:main"
|
|
59
|
+
siege-lite = "evolver_tools.vendor.siege_lite:main"
|
|
60
|
+
smellfinder = "evolver_tools.vendor.smellfinder:main"
|
|
61
|
+
sqlite-cli = "evolver_tools.vendor.sqlite_cli:main"
|
|
62
|
+
sysmon = "evolver_tools.vendor.sysmon:entry"
|
|
63
|
+
timer = "evolver_tools.vendor.timer:entry"
|
|
64
|
+
treedir = "evolver_tools.vendor.treedir.__main__:main"
|
|
65
|
+
urlparse = "evolver_tools.vendor.urlparse_tool.cli:main"
|
|
66
|
+
uuid = "evolver_tools.vendor.uuid_tool:main"
|
|
67
|
+
web-summary = "evolver_tools.vendor.web_summary:main"
|
|
68
|
+
wordcount = "evolver_tools.vendor.wordcount.__main__:main"
|
|
69
|
+
|
|
70
|
+
[tool.setuptools.packages.find]
|
|
71
|
+
where = ["src"]
|
|
72
|
+
include = ["evolver_tools*"]
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""evolver CLI - Unified interface for all EVOLVER tools."""
|
|
3
|
+
|
|
4
|
+
import sys, importlib, os
|
|
5
|
+
|
|
6
|
+
# Tool registry
|
|
7
|
+
TOOLS = {
|
|
8
|
+
"b64": {"module": "evolver_tools.vendor.b64", "func": "main", "desc": "b64"},
|
|
9
|
+
"cal": {"module": "evolver_tools.vendor.cal_tool.cli", "func": "main", "desc": "Cal"},
|
|
10
|
+
"chart-cli": {"module": "evolver_tools.vendor.chart_cli", "func": "main", "desc": "Chart CLI"},
|
|
11
|
+
"colors": {"module": "evolver_tools.vendor.colors", "func": "main", "desc": "Colors"},
|
|
12
|
+
"cron": {"module": "evolver_tools.vendor.cron", "func": "main", "desc": "Cron expression parser"},
|
|
13
|
+
"csv-stats": {"module": "evolver_tools.vendor.csv_stats.cli", "func": "main", "desc": "csv-stats"},
|
|
14
|
+
"diff": {"module": "evolver_tools.vendor.diff_tool", "func": "main", "desc": "File comparator"},
|
|
15
|
+
"dirsize": {"module": "evolver_tools.vendor.dirsize", "func": "entry", "desc": "Dirsize"},
|
|
16
|
+
"dt": {"module": "evolver_tools.vendor.dt_convert", "func": "main", "desc": "Dt"},
|
|
17
|
+
"ff": {"module": "evolver_tools.vendor.ff", "func": "main", "desc": "Fuzzy Finder"},
|
|
18
|
+
"envcheck": {"module": "evolver_tools.vendor.envcheck", "func": "main", "desc": "Envcheck"},
|
|
19
|
+
"find-dups": {"module": "evolver_tools.vendor.find_dups.cli", "func": "main", "desc": "Find Dups"},
|
|
20
|
+
"hashsum": {"module": "evolver_tools.vendor.hashsum", "func": "main", "desc": "Hashsum"},
|
|
21
|
+
"http-live": {"module": "evolver_tools.vendor.http_live", "func": "main", "desc": "HTTP Live Server"},
|
|
22
|
+
"ipcalc": {"module": "evolver_tools.vendor.ipcalc", "func": "main", "desc": "IP/CIDR calculator"},
|
|
23
|
+
"ipinfo": {"module": "evolver_tools.vendor.ipinfo", "func": "main", "desc": "Ipinfo"},
|
|
24
|
+
"jq-lite": {"module": "evolver_tools.vendor.jq_lite", "func": "main", "desc": "Jq Lite"},
|
|
25
|
+
"json2csv": {"module": "evolver_tools.vendor.json2csv", "func": "main", "desc": "Json2Csv"},
|
|
26
|
+
"jsonql": {"module": "evolver_tools.vendor.jsonql", "func": "main", "desc": "JSONQL"},
|
|
27
|
+
"license-cli": {"module": "evolver_tools.vendor.license_cli.cli", "func": "main", "desc": "License CLI"},
|
|
28
|
+
"markdown-check": {"module": "evolver_tools.vendor.markdown_check", "func": "main", "desc": "Markdown Check"},
|
|
29
|
+
"nb": {"module": "evolver_tools.vendor.nb", "func": "main", "desc": "nb"},
|
|
30
|
+
"passgen": {"module": "evolver_tools.vendor.passgen", "func": "entry", "desc": "Passgen"},
|
|
31
|
+
"portcheck": {"module": "evolver_tools.vendor.portcheck.__main__", "func": "main", "desc": "Portcheck"},
|
|
32
|
+
"project-doctor": {"module": "evolver_tools.vendor.project_doctor", "func": "main", "desc": "Project Doctor"},
|
|
33
|
+
"ren": {"module": "evolver_tools.vendor.ren", "func": "main", "desc": "Ren"},
|
|
34
|
+
"siege-lite": {"module": "evolver_tools.vendor.siege_lite", "func": "main", "desc": "Siege Lite"},
|
|
35
|
+
"smellfinder": {"module": "evolver_tools.vendor.smellfinder", "func": "main", "desc": "Smellfinder"},
|
|
36
|
+
"sqlite-cli": {"module": "evolver_tools.vendor.sqlite_cli", "func": "main", "desc": "Sqlite CLI"},
|
|
37
|
+
"sysmon": {"module": "evolver_tools.vendor.sysmon", "func": "entry", "desc": "Sysmon"},
|
|
38
|
+
"timer": {"module": "evolver_tools.vendor.timer", "func": "entry", "desc": "Timer"},
|
|
39
|
+
"treedir": {"module": "evolver_tools.vendor.treedir.__main__", "func": "main", "desc": "Treedir"},
|
|
40
|
+
"urlparse": {"module": "evolver_tools.vendor.urlparse_tool.cli", "func": "main", "desc": "URL Parse"},
|
|
41
|
+
"uuid": {"module": "evolver_tools.vendor.uuid_tool", "func": "main", "desc": "UUID generator"},
|
|
42
|
+
"web-summary": {"module": "evolver_tools.vendor.web_summary", "func": "main", "desc": "Web Summary"},
|
|
43
|
+
"wordcount": {"module": "evolver_tools.vendor.wordcount.__main__", "func": "main", "desc": "Wordcount"},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
def list_tools():
|
|
47
|
+
"""Display all available tools."""
|
|
48
|
+
print('\x1b[1;36m===== EVOLVER Tools v1.5.0 =====\x1b[0m')
|
|
49
|
+
print()
|
|
50
|
+
for name, info in sorted(TOOLS.items()):
|
|
51
|
+
print(f' \033[1;33m{name:<18}\033[0m {info["desc"]}')
|
|
52
|
+
print()
|
|
53
|
+
print(f' Total: {len(TOOLS)} tools')
|
|
54
|
+
print()
|
|
55
|
+
print('Usage: evolver <toolname> [args...]')
|
|
56
|
+
print(' evolver list')
|
|
57
|
+
|
|
58
|
+
def run_tool(tool_name, args):
|
|
59
|
+
if tool_name not in TOOLS:
|
|
60
|
+
print(f'Unknown tool: {tool_name}')
|
|
61
|
+
sys.exit(1)
|
|
62
|
+
info = TOOLS[tool_name]
|
|
63
|
+
mod_path = info["module"]
|
|
64
|
+
func_name = info["func"]
|
|
65
|
+
old_argv = sys.argv
|
|
66
|
+
sys.argv = [tool_name] + args
|
|
67
|
+
try:
|
|
68
|
+
mod = importlib.import_module(mod_path)
|
|
69
|
+
func = getattr(mod, func_name)
|
|
70
|
+
result = func()
|
|
71
|
+
if result is not None:
|
|
72
|
+
print(result)
|
|
73
|
+
except KeyboardInterrupt:
|
|
74
|
+
pass
|
|
75
|
+
except Exception as e:
|
|
76
|
+
print(f'Error running {tool_name}: {e}', file=sys.stderr)
|
|
77
|
+
sys.exit(1)
|
|
78
|
+
finally:
|
|
79
|
+
sys.argv = old_argv
|
|
80
|
+
|
|
81
|
+
def main():
|
|
82
|
+
if len(sys.argv) < 2 or sys.argv[1] in ("-h", "--help"):
|
|
83
|
+
list_tools()
|
|
84
|
+
return
|
|
85
|
+
tool_name = sys.argv[1]
|
|
86
|
+
args = sys.argv[2:]
|
|
87
|
+
if tool_name == "list":
|
|
88
|
+
list_tools()
|
|
89
|
+
return
|
|
90
|
+
run_tool(tool_name, args)
|
|
91
|
+
|
|
92
|
+
if __name__ == "__main__":
|
|
93
|
+
main()
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""b64 — 零依赖 Base64 编解码工具
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
echo "hello" | b64 encode # 从 stdin 编码
|
|
6
|
+
echo "aGVsbG8K" | b64 decode # 从 stdin 解码
|
|
7
|
+
b64 encode file.txt # 从文件编码
|
|
8
|
+
b64 decode file.b64 # 从文件解码
|
|
9
|
+
b64 -n "hello" encode # 从参数编码
|
|
10
|
+
b64 -n "aGVsbG8K" decode # 从参数解码
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import sys
|
|
14
|
+
import base64
|
|
15
|
+
import os
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
STDIN_MODE_AUTO = 'auto' # read stdin if no file and no -n
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def encode_bytes(data: bytes) -> str:
|
|
22
|
+
return base64.b64encode(data).decode('ascii')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def decode_bytes(data: bytes, strict: bool = False) -> bytes:
|
|
26
|
+
try:
|
|
27
|
+
if strict:
|
|
28
|
+
# Strict mode: reject non-base64 characters
|
|
29
|
+
return base64.b64decode(data.strip(), validate=True)
|
|
30
|
+
return base64.b64decode(data.strip())
|
|
31
|
+
except Exception as e:
|
|
32
|
+
print(f"Error: invalid base64 input — {e}", file=sys.stderr)
|
|
33
|
+
sys.exit(1)
|
|
34
|
+
|
|
35
|
+
def is_valid_base64(data: bytes) -> bool:
|
|
36
|
+
"""Check if data is valid base64 by testing decode+re-encode roundtrip."""
|
|
37
|
+
try:
|
|
38
|
+
# Use strict validation to reject non-base64 chars
|
|
39
|
+
decoded = base64.b64decode(data.strip(), validate=True)
|
|
40
|
+
# Verify roundtrip: re-encode and compare (stripped)
|
|
41
|
+
reencoded = base64.b64encode(decoded).rstrip(b'=')
|
|
42
|
+
cleaned = data.strip().rstrip(b'=')
|
|
43
|
+
return reencoded == cleaned
|
|
44
|
+
except Exception:
|
|
45
|
+
return False
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def read_stdin() -> bytes:
|
|
49
|
+
try:
|
|
50
|
+
return sys.stdin.buffer.read()
|
|
51
|
+
except KeyboardInterrupt:
|
|
52
|
+
sys.exit(1)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def main():
|
|
56
|
+
args = sys.argv[1:]
|
|
57
|
+
|
|
58
|
+
# Parse --help / -h
|
|
59
|
+
if not args:
|
|
60
|
+
# Check for piped stdin — auto-detect mode
|
|
61
|
+
if not sys.stdin.isatty():
|
|
62
|
+
raw_stdin = read_stdin()
|
|
63
|
+
if not raw_stdin:
|
|
64
|
+
sys.exit(0)
|
|
65
|
+
if is_valid_base64(raw_stdin):
|
|
66
|
+
result = base64.b64decode(raw_stdin.strip()).decode('utf-8', errors='replace')
|
|
67
|
+
sys.stdout.write(result)
|
|
68
|
+
if not result.endswith('\n'):
|
|
69
|
+
sys.stdout.write('\n')
|
|
70
|
+
else:
|
|
71
|
+
sys.stdout.write(base64.b64encode(raw_stdin).decode('ascii') + '\n')
|
|
72
|
+
return
|
|
73
|
+
print(__doc__.strip())
|
|
74
|
+
return
|
|
75
|
+
|
|
76
|
+
if args[0] in ('-h', '--help'):
|
|
77
|
+
print(__doc__.strip())
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
# Check for -n (inline value)
|
|
81
|
+
if args[0] == '-n':
|
|
82
|
+
if len(args) < 3:
|
|
83
|
+
print("Error: -n requires both <value> and <action>", file=sys.stderr)
|
|
84
|
+
sys.exit(1)
|
|
85
|
+
value = args[1]
|
|
86
|
+
action = args[2]
|
|
87
|
+
|
|
88
|
+
if action == 'encode':
|
|
89
|
+
result = encode_bytes(value.encode('utf-8'))
|
|
90
|
+
elif action == 'decode':
|
|
91
|
+
result = decode_bytes(value)
|
|
92
|
+
result = result.decode('utf-8', errors='replace')
|
|
93
|
+
else:
|
|
94
|
+
print(f"Error: unknown action '{action}' (use encode/decode)", file=sys.stderr)
|
|
95
|
+
sys.exit(1)
|
|
96
|
+
|
|
97
|
+
sys.stdout.write(result)
|
|
98
|
+
if not result.endswith('\n'):
|
|
99
|
+
sys.stdout.write('\n')
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
# Parse <file> <action> or stdin
|
|
103
|
+
action = None
|
|
104
|
+
file_path = None
|
|
105
|
+
|
|
106
|
+
for i, arg in enumerate(args):
|
|
107
|
+
if arg in ('encode', 'decode'):
|
|
108
|
+
action = arg
|
|
109
|
+
elif arg.startswith('-'):
|
|
110
|
+
print(f"Error: unknown option '{arg}'", file=sys.stderr)
|
|
111
|
+
sys.exit(1)
|
|
112
|
+
else:
|
|
113
|
+
file_path = arg
|
|
114
|
+
|
|
115
|
+
if action is None and file_path:
|
|
116
|
+
if not os.path.isfile(file_path):
|
|
117
|
+
print(f"Error: file not found: {file_path}", file=sys.stderr)
|
|
118
|
+
sys.exit(1)
|
|
119
|
+
# Auto-detect: read file, check if it's valid base64
|
|
120
|
+
raw = open(file_path, 'rb').read()
|
|
121
|
+
if is_valid_base64(raw):
|
|
122
|
+
action = 'decode'
|
|
123
|
+
else:
|
|
124
|
+
action = 'encode'
|
|
125
|
+
|
|
126
|
+
if action is None:
|
|
127
|
+
# Remaining args are just the action
|
|
128
|
+
for arg in args:
|
|
129
|
+
if arg in ('encode', 'decode'):
|
|
130
|
+
action = arg
|
|
131
|
+
else:
|
|
132
|
+
file_path = arg
|
|
133
|
+
|
|
134
|
+
if action is None:
|
|
135
|
+
# Try to auto-detect from stdin content if piped
|
|
136
|
+
if not sys.stdin.isatty():
|
|
137
|
+
raw_stdin = read_stdin()
|
|
138
|
+
if not raw_stdin:
|
|
139
|
+
sys.exit(0)
|
|
140
|
+
# Heuristic: if looks like base64, decode; else encode
|
|
141
|
+
try:
|
|
142
|
+
base64.b64decode(raw_stdin.strip())
|
|
143
|
+
result = base64.b64decode(raw_stdin.strip()).decode('utf-8', errors='replace')
|
|
144
|
+
sys.stdout.write(result)
|
|
145
|
+
if not result.endswith('\n'):
|
|
146
|
+
sys.stdout.write('\n')
|
|
147
|
+
except Exception:
|
|
148
|
+
sys.stdout.write(base64.b64encode(raw_stdin).decode('ascii') + '\n')
|
|
149
|
+
return
|
|
150
|
+
print(__doc__.strip())
|
|
151
|
+
return
|
|
152
|
+
|
|
153
|
+
# Read source
|
|
154
|
+
if file_path:
|
|
155
|
+
if not os.path.isfile(file_path):
|
|
156
|
+
print(f"Error: file not found: {file_path}", file=sys.stderr)
|
|
157
|
+
sys.exit(1)
|
|
158
|
+
raw = open(file_path, 'rb').read()
|
|
159
|
+
else:
|
|
160
|
+
raw = read_stdin()
|
|
161
|
+
if not raw:
|
|
162
|
+
sys.exit(0)
|
|
163
|
+
|
|
164
|
+
if action == 'encode':
|
|
165
|
+
result = encode_bytes(raw)
|
|
166
|
+
else:
|
|
167
|
+
decoded = decode_bytes(raw)
|
|
168
|
+
result = decoded.decode('utf-8', errors='replace')
|
|
169
|
+
|
|
170
|
+
sys.stdout.write(result)
|
|
171
|
+
if not result.endswith('\n'):
|
|
172
|
+
sys.stdout.write('\n')
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
if __name__ == '__main__':
|
|
176
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.0.0"
|