recdelete 1.0.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.
- recdelete-1.0.0/LICENSE +21 -0
- recdelete-1.0.0/PKG-INFO +246 -0
- recdelete-1.0.0/README.md +203 -0
- recdelete-1.0.0/pyproject.toml +100 -0
- recdelete-1.0.0/setup.cfg +4 -0
- recdelete-1.0.0/setup.py +54 -0
- recdelete-1.0.0/src/recdelete/__init__.py +61 -0
- recdelete-1.0.0/src/recdelete/api.py +522 -0
- recdelete-1.0.0/src/recdelete/cli.py +122 -0
- recdelete-1.0.0/src/recdelete/py.typed +2 -0
- recdelete-1.0.0/src/recdelete.egg-info/PKG-INFO +246 -0
- recdelete-1.0.0/src/recdelete.egg-info/SOURCES.txt +14 -0
- recdelete-1.0.0/src/recdelete.egg-info/dependency_links.txt +1 -0
- recdelete-1.0.0/src/recdelete.egg-info/entry_points.txt +2 -0
- recdelete-1.0.0/src/recdelete.egg-info/requires.txt +7 -0
- recdelete-1.0.0/src/recdelete.egg-info/top_level.txt +1 -0
recdelete-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 BSR
|
|
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.
|
recdelete-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: recdelete
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Fast, secure, cross-platform recursive file/folder deletion tool
|
|
5
|
+
Author-email: BSR <bhumasairam123@gmail.com>
|
|
6
|
+
Maintainer-email: BSR <bhumasairam123@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/BhumaSai/cli-tool-recdelete
|
|
9
|
+
Project-URL: Documentation, https://github.com/BhumaSai/cli-tool-recdelete#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/BhumaSai/cli-tool-recdelete.git
|
|
11
|
+
Project-URL: Issues, https://github.com/BhumaSai/cli-tool-recdelete/issues
|
|
12
|
+
Project-URL: Changelog, https://github.com/BhumaSai/cli-tool-recdelete/blob/main/CHANGELOG.md
|
|
13
|
+
Project-URL: Funding, https://buymeacoffee.com/bhumasai
|
|
14
|
+
Keywords: cli,delete,recursive,file-management,cleanup,node_modules,cache,cross-platform,fast,secure
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Environment :: Console
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Intended Audience :: System Administrators
|
|
19
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
22
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
23
|
+
Classifier: Operating System :: MacOS
|
|
24
|
+
Classifier: Programming Language :: Python :: 3
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
29
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
30
|
+
Classifier: Topic :: System :: Filesystems
|
|
31
|
+
Classifier: Topic :: Utilities
|
|
32
|
+
Classifier: Typing :: Typed
|
|
33
|
+
Requires-Python: >=3.8
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
License-File: LICENSE
|
|
36
|
+
Provides-Extra: dev
|
|
37
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
38
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
39
|
+
Requires-Dist: black>=23.0; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy>=1.0; extra == "dev"
|
|
41
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
|
|
44
|
+
# 🗑️ RecDelete for Python
|
|
45
|
+
|
|
46
|
+
[](https://pypi.org/project/recdelete/)
|
|
47
|
+
[](https://pypi.org/project/recdelete/)
|
|
48
|
+
[](https://opensource.org/licenses/MIT)
|
|
49
|
+
|
|
50
|
+
> **Fast, secure, cross-platform recursive file/folder deletion tool for Python**
|
|
51
|
+
|
|
52
|
+
## 📥 Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install recdelete
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The binary is automatically downloaded for your platform during installation.
|
|
59
|
+
|
|
60
|
+
## 🚀 Quick Start
|
|
61
|
+
|
|
62
|
+
### CLI
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
# Dry run (preview only)
|
|
66
|
+
recdelete ./projects node_modules --dry-run
|
|
67
|
+
|
|
68
|
+
# Actually delete
|
|
69
|
+
recdelete ./projects node_modules --force
|
|
70
|
+
|
|
71
|
+
# Delete log files
|
|
72
|
+
recdelete ./logs "*.log" --only-files
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Python API
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
from recdelete import delete, clean_node_modules, RecDelete
|
|
79
|
+
|
|
80
|
+
# Simple delete
|
|
81
|
+
result = delete("./projects", "node_modules", dry_run=True, only_dirs=True)
|
|
82
|
+
print(f"Would delete {result.total_deleted} items")
|
|
83
|
+
print(f"Would free {result.bytes_freed_human}")
|
|
84
|
+
|
|
85
|
+
# Clean node_modules
|
|
86
|
+
result = clean_node_modules("./projects", dry_run=True)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 📖 API Reference
|
|
90
|
+
|
|
91
|
+
### RecDelete Class
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from recdelete import RecDelete
|
|
95
|
+
|
|
96
|
+
rd = RecDelete()
|
|
97
|
+
|
|
98
|
+
# Main delete method
|
|
99
|
+
result = rd.delete(
|
|
100
|
+
start_path="./projects",
|
|
101
|
+
target_name="node_modules",
|
|
102
|
+
dry_run=True, # Preview only
|
|
103
|
+
only_dirs=True, # Only directories
|
|
104
|
+
only_files=False, # Only files
|
|
105
|
+
force=True, # Skip confirmation
|
|
106
|
+
max_depth=None, # None for unlimited
|
|
107
|
+
parallel=4, # Worker count
|
|
108
|
+
include=["*.cache"], # Include patterns
|
|
109
|
+
exclude=["*important*"], # Exclude patterns
|
|
110
|
+
verbose=False, # Detailed output
|
|
111
|
+
log_file="./log.txt" # Log to file
|
|
112
|
+
)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Convenience Functions
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from recdelete import (
|
|
119
|
+
delete,
|
|
120
|
+
scan,
|
|
121
|
+
clean_node_modules,
|
|
122
|
+
clean_python_cache,
|
|
123
|
+
clean_build_artifacts
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Scan (dry run)
|
|
127
|
+
result = scan("./projects", "*.tmp")
|
|
128
|
+
|
|
129
|
+
# Clean node_modules
|
|
130
|
+
result = clean_node_modules("./projects", dry_run=True)
|
|
131
|
+
|
|
132
|
+
# Clean Python cache (__pycache__, .pytest_cache, *.pyc)
|
|
133
|
+
result = clean_python_cache("./projects")
|
|
134
|
+
|
|
135
|
+
# Clean build artifacts (dist, build, .next, etc.)
|
|
136
|
+
result = clean_build_artifacts("./projects")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### DeleteResult Class
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
@dataclass
|
|
143
|
+
class DeleteResult:
|
|
144
|
+
files_deleted: int # Files deleted
|
|
145
|
+
dirs_deleted: int # Directories deleted
|
|
146
|
+
files_matched: int # Files matched
|
|
147
|
+
dirs_matched: int # Directories matched
|
|
148
|
+
bytes_freed: int # Bytes freed
|
|
149
|
+
bytes_freed_human: str # Human-readable size (e.g., "1.5 GB")
|
|
150
|
+
items_scanned: int # Total items scanned
|
|
151
|
+
errors: int # Error count
|
|
152
|
+
deleted_paths: list # List of deleted paths
|
|
153
|
+
error_messages: list # List of error messages
|
|
154
|
+
start_path: str # Start path
|
|
155
|
+
target_name: str # Target pattern
|
|
156
|
+
dry_run: bool # Was this a dry run
|
|
157
|
+
elapsed_ms: int # Elapsed milliseconds
|
|
158
|
+
success: bool # Success status
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def total_deleted(self) -> int:
|
|
162
|
+
"""Total deleted items (files + directories)."""
|
|
163
|
+
return self.files_deleted + self.dirs_deleted
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 💡 Examples
|
|
167
|
+
|
|
168
|
+
### Clean Up Node.js Projects
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
from recdelete import clean_node_modules
|
|
172
|
+
|
|
173
|
+
# Preview what would be deleted
|
|
174
|
+
preview = clean_node_modules("./projects", dry_run=True)
|
|
175
|
+
print(f"Would free {preview.bytes_freed_human}")
|
|
176
|
+
|
|
177
|
+
# Actually delete
|
|
178
|
+
result = clean_node_modules("./projects")
|
|
179
|
+
print(f"Freed {result.bytes_freed_human}!")
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Delete Log Files
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from recdelete import delete
|
|
186
|
+
|
|
187
|
+
result = delete(
|
|
188
|
+
"./logs",
|
|
189
|
+
"*.log",
|
|
190
|
+
only_files=True,
|
|
191
|
+
exclude=["*important*", "*backup*"],
|
|
192
|
+
dry_run=True
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
print(f"Found {result.files_matched} log files")
|
|
196
|
+
for path in result.deleted_paths:
|
|
197
|
+
print(f" - {path}")
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Clean Python Project
|
|
201
|
+
|
|
202
|
+
```python
|
|
203
|
+
from recdelete import clean_python_cache, clean_build_artifacts
|
|
204
|
+
|
|
205
|
+
# Clean all Python cache
|
|
206
|
+
result = clean_python_cache("./my_project")
|
|
207
|
+
print(f"Cleaned {result.total_deleted} cache items")
|
|
208
|
+
|
|
209
|
+
# Clean build artifacts
|
|
210
|
+
result = clean_build_artifacts("./my_project")
|
|
211
|
+
print(f"Removed {result.dirs_deleted} build directories")
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Using with Context
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from recdelete import RecDelete
|
|
218
|
+
|
|
219
|
+
# Create instance once, reuse
|
|
220
|
+
rd = RecDelete()
|
|
221
|
+
|
|
222
|
+
# Multiple operations
|
|
223
|
+
for project in ["./project1", "./project2", "./project3"]:
|
|
224
|
+
result = rd.clean_node_modules(project, dry_run=False)
|
|
225
|
+
print(f"{project}: Freed {result.bytes_freed_human}")
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## 🛡️ Security
|
|
229
|
+
|
|
230
|
+
- **Protected Paths**: System directories (`/`, `C:\Windows`, etc.) cannot be deleted
|
|
231
|
+
- **Symbolic Links**: Not followed to prevent escaping directories
|
|
232
|
+
- **Dry Run**: Always preview with `dry_run=True` first
|
|
233
|
+
- **Confirmation**: Requires confirmation unless `force=True` is used
|
|
234
|
+
|
|
235
|
+
## 🔗 Links
|
|
236
|
+
|
|
237
|
+
- **GitHub**: [https://github.com/BhumaSai/cli-tool-recdelete](https://github.com/BhumaSai/cli-tool-recdelete)
|
|
238
|
+
- **PyPI**: [https://pypi.org/project/recdelete/](https://pypi.org/project/recdelete/)
|
|
239
|
+
|
|
240
|
+
## ☕ Support
|
|
241
|
+
|
|
242
|
+
[Buy Me a Coffee](https://buymeacoffee.com/bhumasai)
|
|
243
|
+
|
|
244
|
+
## 📜 License
|
|
245
|
+
|
|
246
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# 🗑️ RecDelete for Python
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/recdelete/)
|
|
4
|
+
[](https://pypi.org/project/recdelete/)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
7
|
+
> **Fast, secure, cross-platform recursive file/folder deletion tool for Python**
|
|
8
|
+
|
|
9
|
+
## 📥 Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install recdelete
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The binary is automatically downloaded for your platform during installation.
|
|
16
|
+
|
|
17
|
+
## 🚀 Quick Start
|
|
18
|
+
|
|
19
|
+
### CLI
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Dry run (preview only)
|
|
23
|
+
recdelete ./projects node_modules --dry-run
|
|
24
|
+
|
|
25
|
+
# Actually delete
|
|
26
|
+
recdelete ./projects node_modules --force
|
|
27
|
+
|
|
28
|
+
# Delete log files
|
|
29
|
+
recdelete ./logs "*.log" --only-files
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Python API
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from recdelete import delete, clean_node_modules, RecDelete
|
|
36
|
+
|
|
37
|
+
# Simple delete
|
|
38
|
+
result = delete("./projects", "node_modules", dry_run=True, only_dirs=True)
|
|
39
|
+
print(f"Would delete {result.total_deleted} items")
|
|
40
|
+
print(f"Would free {result.bytes_freed_human}")
|
|
41
|
+
|
|
42
|
+
# Clean node_modules
|
|
43
|
+
result = clean_node_modules("./projects", dry_run=True)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 📖 API Reference
|
|
47
|
+
|
|
48
|
+
### RecDelete Class
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from recdelete import RecDelete
|
|
52
|
+
|
|
53
|
+
rd = RecDelete()
|
|
54
|
+
|
|
55
|
+
# Main delete method
|
|
56
|
+
result = rd.delete(
|
|
57
|
+
start_path="./projects",
|
|
58
|
+
target_name="node_modules",
|
|
59
|
+
dry_run=True, # Preview only
|
|
60
|
+
only_dirs=True, # Only directories
|
|
61
|
+
only_files=False, # Only files
|
|
62
|
+
force=True, # Skip confirmation
|
|
63
|
+
max_depth=None, # None for unlimited
|
|
64
|
+
parallel=4, # Worker count
|
|
65
|
+
include=["*.cache"], # Include patterns
|
|
66
|
+
exclude=["*important*"], # Exclude patterns
|
|
67
|
+
verbose=False, # Detailed output
|
|
68
|
+
log_file="./log.txt" # Log to file
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Convenience Functions
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
from recdelete import (
|
|
76
|
+
delete,
|
|
77
|
+
scan,
|
|
78
|
+
clean_node_modules,
|
|
79
|
+
clean_python_cache,
|
|
80
|
+
clean_build_artifacts
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Scan (dry run)
|
|
84
|
+
result = scan("./projects", "*.tmp")
|
|
85
|
+
|
|
86
|
+
# Clean node_modules
|
|
87
|
+
result = clean_node_modules("./projects", dry_run=True)
|
|
88
|
+
|
|
89
|
+
# Clean Python cache (__pycache__, .pytest_cache, *.pyc)
|
|
90
|
+
result = clean_python_cache("./projects")
|
|
91
|
+
|
|
92
|
+
# Clean build artifacts (dist, build, .next, etc.)
|
|
93
|
+
result = clean_build_artifacts("./projects")
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### DeleteResult Class
|
|
97
|
+
|
|
98
|
+
```python
|
|
99
|
+
@dataclass
|
|
100
|
+
class DeleteResult:
|
|
101
|
+
files_deleted: int # Files deleted
|
|
102
|
+
dirs_deleted: int # Directories deleted
|
|
103
|
+
files_matched: int # Files matched
|
|
104
|
+
dirs_matched: int # Directories matched
|
|
105
|
+
bytes_freed: int # Bytes freed
|
|
106
|
+
bytes_freed_human: str # Human-readable size (e.g., "1.5 GB")
|
|
107
|
+
items_scanned: int # Total items scanned
|
|
108
|
+
errors: int # Error count
|
|
109
|
+
deleted_paths: list # List of deleted paths
|
|
110
|
+
error_messages: list # List of error messages
|
|
111
|
+
start_path: str # Start path
|
|
112
|
+
target_name: str # Target pattern
|
|
113
|
+
dry_run: bool # Was this a dry run
|
|
114
|
+
elapsed_ms: int # Elapsed milliseconds
|
|
115
|
+
success: bool # Success status
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def total_deleted(self) -> int:
|
|
119
|
+
"""Total deleted items (files + directories)."""
|
|
120
|
+
return self.files_deleted + self.dirs_deleted
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## 💡 Examples
|
|
124
|
+
|
|
125
|
+
### Clean Up Node.js Projects
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from recdelete import clean_node_modules
|
|
129
|
+
|
|
130
|
+
# Preview what would be deleted
|
|
131
|
+
preview = clean_node_modules("./projects", dry_run=True)
|
|
132
|
+
print(f"Would free {preview.bytes_freed_human}")
|
|
133
|
+
|
|
134
|
+
# Actually delete
|
|
135
|
+
result = clean_node_modules("./projects")
|
|
136
|
+
print(f"Freed {result.bytes_freed_human}!")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Delete Log Files
|
|
140
|
+
|
|
141
|
+
```python
|
|
142
|
+
from recdelete import delete
|
|
143
|
+
|
|
144
|
+
result = delete(
|
|
145
|
+
"./logs",
|
|
146
|
+
"*.log",
|
|
147
|
+
only_files=True,
|
|
148
|
+
exclude=["*important*", "*backup*"],
|
|
149
|
+
dry_run=True
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
print(f"Found {result.files_matched} log files")
|
|
153
|
+
for path in result.deleted_paths:
|
|
154
|
+
print(f" - {path}")
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Clean Python Project
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
from recdelete import clean_python_cache, clean_build_artifacts
|
|
161
|
+
|
|
162
|
+
# Clean all Python cache
|
|
163
|
+
result = clean_python_cache("./my_project")
|
|
164
|
+
print(f"Cleaned {result.total_deleted} cache items")
|
|
165
|
+
|
|
166
|
+
# Clean build artifacts
|
|
167
|
+
result = clean_build_artifacts("./my_project")
|
|
168
|
+
print(f"Removed {result.dirs_deleted} build directories")
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Using with Context
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from recdelete import RecDelete
|
|
175
|
+
|
|
176
|
+
# Create instance once, reuse
|
|
177
|
+
rd = RecDelete()
|
|
178
|
+
|
|
179
|
+
# Multiple operations
|
|
180
|
+
for project in ["./project1", "./project2", "./project3"]:
|
|
181
|
+
result = rd.clean_node_modules(project, dry_run=False)
|
|
182
|
+
print(f"{project}: Freed {result.bytes_freed_human}")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 🛡️ Security
|
|
186
|
+
|
|
187
|
+
- **Protected Paths**: System directories (`/`, `C:\Windows`, etc.) cannot be deleted
|
|
188
|
+
- **Symbolic Links**: Not followed to prevent escaping directories
|
|
189
|
+
- **Dry Run**: Always preview with `dry_run=True` first
|
|
190
|
+
- **Confirmation**: Requires confirmation unless `force=True` is used
|
|
191
|
+
|
|
192
|
+
## 🔗 Links
|
|
193
|
+
|
|
194
|
+
- **GitHub**: [https://github.com/BhumaSai/cli-tool-recdelete](https://github.com/BhumaSai/cli-tool-recdelete)
|
|
195
|
+
- **PyPI**: [https://pypi.org/project/recdelete/](https://pypi.org/project/recdelete/)
|
|
196
|
+
|
|
197
|
+
## ☕ Support
|
|
198
|
+
|
|
199
|
+
[Buy Me a Coffee](https://buymeacoffee.com/bhumasai)
|
|
200
|
+
|
|
201
|
+
## 📜 License
|
|
202
|
+
|
|
203
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "recdelete"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Fast, secure, cross-platform recursive file/folder deletion tool"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "BSR", email = "bhumasairam123@gmail.com"}
|
|
13
|
+
]
|
|
14
|
+
maintainers = [
|
|
15
|
+
{name = "BSR", email = "bhumasairam123@gmail.com"}
|
|
16
|
+
]
|
|
17
|
+
keywords = [
|
|
18
|
+
"cli",
|
|
19
|
+
"delete",
|
|
20
|
+
"recursive",
|
|
21
|
+
"file-management",
|
|
22
|
+
"cleanup",
|
|
23
|
+
"node_modules",
|
|
24
|
+
"cache",
|
|
25
|
+
"cross-platform",
|
|
26
|
+
"fast",
|
|
27
|
+
"secure"
|
|
28
|
+
]
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Development Status :: 5 - Production/Stable",
|
|
31
|
+
"Environment :: Console",
|
|
32
|
+
"Intended Audience :: Developers",
|
|
33
|
+
"Intended Audience :: System Administrators",
|
|
34
|
+
"License :: OSI Approved :: MIT License",
|
|
35
|
+
"Operating System :: OS Independent",
|
|
36
|
+
"Operating System :: Microsoft :: Windows",
|
|
37
|
+
"Operating System :: POSIX :: Linux",
|
|
38
|
+
"Operating System :: MacOS",
|
|
39
|
+
"Programming Language :: Python :: 3",
|
|
40
|
+
"Programming Language :: Python :: 3.8",
|
|
41
|
+
"Programming Language :: Python :: 3.9",
|
|
42
|
+
"Programming Language :: Python :: 3.10",
|
|
43
|
+
"Programming Language :: Python :: 3.11",
|
|
44
|
+
"Programming Language :: Python :: 3.12",
|
|
45
|
+
"Topic :: System :: Filesystems",
|
|
46
|
+
"Topic :: Utilities",
|
|
47
|
+
"Typing :: Typed"
|
|
48
|
+
]
|
|
49
|
+
requires-python = ">=3.8"
|
|
50
|
+
dependencies = []
|
|
51
|
+
|
|
52
|
+
[project.optional-dependencies]
|
|
53
|
+
dev = [
|
|
54
|
+
"pytest>=7.0",
|
|
55
|
+
"pytest-cov>=4.0",
|
|
56
|
+
"black>=23.0",
|
|
57
|
+
"mypy>=1.0",
|
|
58
|
+
"ruff>=0.1.0"
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[project.urls]
|
|
62
|
+
Homepage = "https://github.com/BhumaSai/cli-tool-recdelete"
|
|
63
|
+
Documentation = "https://github.com/BhumaSai/cli-tool-recdelete#readme"
|
|
64
|
+
Repository = "https://github.com/BhumaSai/cli-tool-recdelete.git"
|
|
65
|
+
Issues = "https://github.com/BhumaSai/cli-tool-recdelete/issues"
|
|
66
|
+
Changelog = "https://github.com/BhumaSai/cli-tool-recdelete/blob/main/CHANGELOG.md"
|
|
67
|
+
Funding = "https://buymeacoffee.com/bhumasai"
|
|
68
|
+
|
|
69
|
+
[project.scripts]
|
|
70
|
+
recdelete = "recdelete.cli:main"
|
|
71
|
+
|
|
72
|
+
[tool.setuptools]
|
|
73
|
+
package-dir = {"" = "src"}
|
|
74
|
+
include-package-data = true
|
|
75
|
+
|
|
76
|
+
[tool.setuptools.packages.find]
|
|
77
|
+
where = ["src"]
|
|
78
|
+
|
|
79
|
+
[tool.setuptools.package-data]
|
|
80
|
+
recdelete = ["bin/*", "py.typed"]
|
|
81
|
+
|
|
82
|
+
[tool.black]
|
|
83
|
+
line-length = 100
|
|
84
|
+
target-version = ["py38", "py39", "py310", "py311", "py312"]
|
|
85
|
+
|
|
86
|
+
[tool.ruff]
|
|
87
|
+
line-length = 100
|
|
88
|
+
target-version = "py38"
|
|
89
|
+
select = ["E", "F", "W", "I", "N", "UP", "B", "C4"]
|
|
90
|
+
|
|
91
|
+
[tool.mypy]
|
|
92
|
+
python_version = "3.8"
|
|
93
|
+
strict = true
|
|
94
|
+
warn_return_any = true
|
|
95
|
+
warn_unused_ignores = true
|
|
96
|
+
|
|
97
|
+
[tool.pytest.ini_options]
|
|
98
|
+
testpaths = ["tests"]
|
|
99
|
+
python_files = ["test_*.py"]
|
|
100
|
+
addopts = "-v --cov=recdelete --cov-report=term-missing"
|
recdelete-1.0.0/setup.py
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Setup script for recdelete Python package.
|
|
3
|
+
Handles post-install binary download.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from setuptools import setup
|
|
10
|
+
from setuptools.command.install import install
|
|
11
|
+
from setuptools.command.develop import develop
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PostInstallCommand(install):
|
|
15
|
+
"""Post-installation: download binary."""
|
|
16
|
+
def run(self):
|
|
17
|
+
install.run(self)
|
|
18
|
+
self._post_install()
|
|
19
|
+
|
|
20
|
+
def _post_install(self):
|
|
21
|
+
"""Download the binary after installation."""
|
|
22
|
+
try:
|
|
23
|
+
script_path = Path(__file__).parent / "scripts" / "postinstall.py"
|
|
24
|
+
if script_path.exists():
|
|
25
|
+
subprocess.run([sys.executable, str(script_path)], check=False)
|
|
26
|
+
except Exception as e:
|
|
27
|
+
print(f"Note: Could not run postinstall script: {e}")
|
|
28
|
+
print("You may need to manually download the binary.")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class PostDevelopCommand(develop):
|
|
32
|
+
"""Post-development install: download binary."""
|
|
33
|
+
def run(self):
|
|
34
|
+
develop.run(self)
|
|
35
|
+
self._post_install()
|
|
36
|
+
|
|
37
|
+
def _post_install(self):
|
|
38
|
+
"""Download the binary after installation."""
|
|
39
|
+
try:
|
|
40
|
+
script_path = Path(__file__).parent / "scripts" / "postinstall.py"
|
|
41
|
+
if script_path.exists():
|
|
42
|
+
subprocess.run([sys.executable, str(script_path)], check=False)
|
|
43
|
+
except Exception as e:
|
|
44
|
+
print(f"Note: Could not run postinstall script: {e}")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# This setup.py is minimal - most config is in pyproject.toml
|
|
48
|
+
# It exists only to provide custom install commands
|
|
49
|
+
setup(
|
|
50
|
+
cmdclass={
|
|
51
|
+
'install': PostInstallCommand,
|
|
52
|
+
'develop': PostDevelopCommand,
|
|
53
|
+
},
|
|
54
|
+
)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RecDelete - Fast, secure, cross-platform recursive file/folder deletion tool.
|
|
3
|
+
|
|
4
|
+
A Python wrapper for the recdelete Go binary, providing both CLI and
|
|
5
|
+
programmatic access to powerful file deletion capabilities.
|
|
6
|
+
|
|
7
|
+
Installation:
|
|
8
|
+
pip install recdelete
|
|
9
|
+
|
|
10
|
+
Quick Start:
|
|
11
|
+
>>> from recdelete import delete, clean_node_modules
|
|
12
|
+
>>>
|
|
13
|
+
>>> # Dry run first (safe - doesn't delete anything)
|
|
14
|
+
>>> result = delete("./projects", "node_modules", dry_run=True)
|
|
15
|
+
>>> print(f"Would delete {result.total_deleted} items, freeing {result.bytes_freed_human}")
|
|
16
|
+
>>>
|
|
17
|
+
>>> # Clean up node_modules in all projects
|
|
18
|
+
>>> result = clean_node_modules("./projects", dry_run=False)
|
|
19
|
+
|
|
20
|
+
CLI Usage:
|
|
21
|
+
recdelete ./projects node_modules --dry-run
|
|
22
|
+
recdelete ./projects "*.log" --only-files --force
|
|
23
|
+
|
|
24
|
+
Links:
|
|
25
|
+
- GitHub: https://github.com/BhumaSai/cli-tool-recdelete
|
|
26
|
+
- PyPI: https://pypi.org/project/recdelete/
|
|
27
|
+
- Buy Me a Coffee: https://buymeacoffee.com/bhumasai
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
__version__ = "1.0.0"
|
|
31
|
+
__author__ = "BSR"
|
|
32
|
+
__email__ = "bhumasairam123@gmail.com"
|
|
33
|
+
__license__ = "MIT"
|
|
34
|
+
|
|
35
|
+
from recdelete.api import (
|
|
36
|
+
RecDelete,
|
|
37
|
+
DeleteResult,
|
|
38
|
+
delete,
|
|
39
|
+
scan,
|
|
40
|
+
clean_node_modules,
|
|
41
|
+
clean_python_cache,
|
|
42
|
+
clean_build_artifacts,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
# Main class
|
|
47
|
+
"RecDelete",
|
|
48
|
+
# Result type
|
|
49
|
+
"DeleteResult",
|
|
50
|
+
# Convenience functions
|
|
51
|
+
"delete",
|
|
52
|
+
"scan",
|
|
53
|
+
"clean_node_modules",
|
|
54
|
+
"clean_python_cache",
|
|
55
|
+
"clean_build_artifacts",
|
|
56
|
+
# Metadata
|
|
57
|
+
"__version__",
|
|
58
|
+
"__author__",
|
|
59
|
+
"__email__",
|
|
60
|
+
"__license__",
|
|
61
|
+
]
|