sortmeout 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.
- sortmeout-1.0.0/LICENSE +21 -0
- sortmeout-1.0.0/PKG-INFO +302 -0
- sortmeout-1.0.0/README.md +248 -0
- sortmeout-1.0.0/pyproject.toml +140 -0
- sortmeout-1.0.0/setup.cfg +4 -0
- sortmeout-1.0.0/sortmeout/__init__.py +23 -0
- sortmeout-1.0.0/sortmeout/app.py +618 -0
- sortmeout-1.0.0/sortmeout/cli.py +550 -0
- sortmeout-1.0.0/sortmeout/config/__init__.py +11 -0
- sortmeout-1.0.0/sortmeout/config/manager.py +313 -0
- sortmeout-1.0.0/sortmeout/config/settings.py +201 -0
- sortmeout-1.0.0/sortmeout/core/__init__.py +21 -0
- sortmeout-1.0.0/sortmeout/core/action.py +889 -0
- sortmeout-1.0.0/sortmeout/core/condition.py +672 -0
- sortmeout-1.0.0/sortmeout/core/engine.py +421 -0
- sortmeout-1.0.0/sortmeout/core/rule.py +254 -0
- sortmeout-1.0.0/sortmeout/core/watcher.py +471 -0
- sortmeout-1.0.0/sortmeout/gui/__init__.py +10 -0
- sortmeout-1.0.0/sortmeout/gui/app.py +325 -0
- sortmeout-1.0.0/sortmeout/macos/__init__.py +19 -0
- sortmeout-1.0.0/sortmeout/macos/spotlight.py +337 -0
- sortmeout-1.0.0/sortmeout/macos/tags.py +308 -0
- sortmeout-1.0.0/sortmeout/macos/trash.py +449 -0
- sortmeout-1.0.0/sortmeout/utils/__init__.py +12 -0
- sortmeout-1.0.0/sortmeout/utils/file_info.py +363 -0
- sortmeout-1.0.0/sortmeout/utils/logger.py +214 -0
- sortmeout-1.0.0/sortmeout.egg-info/PKG-INFO +302 -0
- sortmeout-1.0.0/sortmeout.egg-info/SOURCES.txt +35 -0
- sortmeout-1.0.0/sortmeout.egg-info/dependency_links.txt +1 -0
- sortmeout-1.0.0/sortmeout.egg-info/entry_points.txt +3 -0
- sortmeout-1.0.0/sortmeout.egg-info/requires.txt +27 -0
- sortmeout-1.0.0/sortmeout.egg-info/top_level.txt +1 -0
- sortmeout-1.0.0/tests/test_action.py +354 -0
- sortmeout-1.0.0/tests/test_condition.py +376 -0
- sortmeout-1.0.0/tests/test_engine.py +430 -0
- sortmeout-1.0.0/tests/test_rule.py +402 -0
- sortmeout-1.0.0/tests/test_watcher.py +384 -0
sortmeout-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 SortMeOut Contributors
|
|
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.
|
sortmeout-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sortmeout
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Open-source file automation and organization tool for macOS
|
|
5
|
+
Author: SortMeOut Contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://sortmeout.saidborna.com
|
|
8
|
+
Project-URL: Documentation, https://github.com/S-Borna/sortmeout/tree/main/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/S-Borna/sortmeout
|
|
10
|
+
Project-URL: Issues, https://github.com/S-Borna/sortmeout/issues
|
|
11
|
+
Keywords: automation,file-management,macos,organization,rules,workflow
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: MacOS X
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: MacOS :: MacOS X
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Desktop Environment :: File Managers
|
|
23
|
+
Classifier: Topic :: System :: Filesystems
|
|
24
|
+
Classifier: Topic :: Utilities
|
|
25
|
+
Requires-Python: >=3.9
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: watchdog>=3.0.0
|
|
29
|
+
Requires-Dist: pyobjc-core>=9.0
|
|
30
|
+
Requires-Dist: pyobjc-framework-Cocoa>=9.0
|
|
31
|
+
Requires-Dist: pyobjc-framework-FSEvents>=9.0
|
|
32
|
+
Requires-Dist: pyobjc-framework-Quartz>=9.0
|
|
33
|
+
Requires-Dist: pyobjc-framework-ScriptingBridge>=9.0
|
|
34
|
+
Requires-Dist: pyyaml>=6.0
|
|
35
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
36
|
+
Requires-Dist: rich>=13.0.0
|
|
37
|
+
Requires-Dist: click>=8.0.0
|
|
38
|
+
Requires-Dist: appdirs>=1.4.0
|
|
39
|
+
Requires-Dist: humanize>=4.0.0
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
42
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
43
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
44
|
+
Requires-Dist: pytest-mock>=3.0.0; extra == "dev"
|
|
45
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
47
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: isort>=5.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
|
|
50
|
+
Provides-Extra: gui
|
|
51
|
+
Requires-Dist: rumps>=0.4.0; extra == "gui"
|
|
52
|
+
Requires-Dist: pyobjc-framework-Cocoa>=9.0; extra == "gui"
|
|
53
|
+
Dynamic: license-file
|
|
54
|
+
|
|
55
|
+
# SortMeOut 📁✨
|
|
56
|
+
|
|
57
|
+
An open-source file automation and organization tool for macOS, inspired by Noodlesoft Hazel.
|
|
58
|
+
|
|
59
|
+
[](https://opensource.org/licenses/MIT)
|
|
60
|
+
[](https://www.python.org/downloads/)
|
|
61
|
+
[](https://www.apple.com/macos/)
|
|
62
|
+
|
|
63
|
+
## 🎯 Overview
|
|
64
|
+
|
|
65
|
+
SortMeOut watches folders you specify and automatically organizes files according to rules you create. Move, rename, tag, archive, or delete files based on name, date, type, content, and much more.
|
|
66
|
+
|
|
67
|
+
## ✨ Features
|
|
68
|
+
|
|
69
|
+
### Core Features
|
|
70
|
+
|
|
71
|
+
- **Folder Watching**: Monitor multiple folders for file changes in real-time
|
|
72
|
+
- **Rule-Based Organization**: Create powerful rules with conditions and actions
|
|
73
|
+
- **Pattern Matching**: Use glob patterns, regex, and smart matching
|
|
74
|
+
- **File Operations**: Move, copy, rename, delete, archive files
|
|
75
|
+
- **macOS Integration**: Tags, Spotlight metadata, Finder comments
|
|
76
|
+
|
|
77
|
+
### Conditions
|
|
78
|
+
|
|
79
|
+
- File name (contains, starts with, ends with, matches pattern)
|
|
80
|
+
- File extension/type (documents, images, videos, etc.)
|
|
81
|
+
- File size (greater than, less than, between)
|
|
82
|
+
- Date attributes (created, modified, accessed, added)
|
|
83
|
+
- File contents (text search, regex)
|
|
84
|
+
- macOS tags and Finder comments
|
|
85
|
+
- Source URL/application (where downloaded from)
|
|
86
|
+
- Nested conditions (AND, OR, NOT logic)
|
|
87
|
+
|
|
88
|
+
### Actions
|
|
89
|
+
|
|
90
|
+
- Move to folder (with subfolder creation)
|
|
91
|
+
- Copy to folder
|
|
92
|
+
- Rename (with pattern substitution)
|
|
93
|
+
- Add/remove macOS tags
|
|
94
|
+
- Set Finder comments
|
|
95
|
+
- Archive (zip, tar, gzip)
|
|
96
|
+
- Delete / Move to Trash
|
|
97
|
+
- Run shell script
|
|
98
|
+
- Execute AppleScript
|
|
99
|
+
- Open with application
|
|
100
|
+
- Send notification
|
|
101
|
+
- Import to Photos/Music
|
|
102
|
+
|
|
103
|
+
### Advanced Features
|
|
104
|
+
|
|
105
|
+
- **Trash Management**: Auto-clean trash based on age/size
|
|
106
|
+
- **App Sweep**: Detect and remove app support files when uninstalling
|
|
107
|
+
- **Preview Mode**: See what rules would do without executing
|
|
108
|
+
- **Rule Import/Export**: Share rules with others
|
|
109
|
+
- **Logging**: Detailed logs of all operations
|
|
110
|
+
- **Menu Bar App**: Quick access and status
|
|
111
|
+
|
|
112
|
+
## 🚀 Quick Start
|
|
113
|
+
|
|
114
|
+
### Installation
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Clone the repository
|
|
118
|
+
git clone https://github.com/yourusername/sortmeout.git
|
|
119
|
+
cd sortmeout
|
|
120
|
+
|
|
121
|
+
# Create virtual environment
|
|
122
|
+
python3 -m venv venv
|
|
123
|
+
source venv/bin/activate
|
|
124
|
+
|
|
125
|
+
# Install dependencies
|
|
126
|
+
pip install -r requirements.txt
|
|
127
|
+
|
|
128
|
+
# Install the application
|
|
129
|
+
pip install -e .
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Basic Usage
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from sortmeout import SortMeOut, Rule, Condition, Action
|
|
136
|
+
|
|
137
|
+
# Create a new instance
|
|
138
|
+
app = SortMeOut()
|
|
139
|
+
|
|
140
|
+
# Add a folder to watch
|
|
141
|
+
app.add_folder("~/Downloads")
|
|
142
|
+
|
|
143
|
+
# Create a rule to organize PDF files
|
|
144
|
+
rule = Rule(
|
|
145
|
+
name="Organize PDFs",
|
|
146
|
+
conditions=[
|
|
147
|
+
Condition("extension", "equals", "pdf")
|
|
148
|
+
],
|
|
149
|
+
actions=[
|
|
150
|
+
Action("move", destination="~/Documents/PDFs")
|
|
151
|
+
]
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# Add rule to the Downloads folder
|
|
155
|
+
app.add_rule("~/Downloads", rule)
|
|
156
|
+
|
|
157
|
+
# Start watching
|
|
158
|
+
app.start()
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### GUI Application
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
# Launch the GUI
|
|
165
|
+
sortmeout-gui
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## 📖 Documentation
|
|
169
|
+
|
|
170
|
+
- [User Manual](docs/user-manual.md)
|
|
171
|
+
- [Rule Creation Guide](docs/rules-guide.md)
|
|
172
|
+
- [API Reference](docs/api-reference.md)
|
|
173
|
+
- [Contributing Guide](CONTRIBUTING.md)
|
|
174
|
+
- [FAQ](docs/faq.md)
|
|
175
|
+
|
|
176
|
+
## 🗺️ Roadmap
|
|
177
|
+
|
|
178
|
+
### Phase 1: Core Engine (v0.1.0) ✅
|
|
179
|
+
|
|
180
|
+
- [x] Folder monitoring with FSEvents
|
|
181
|
+
- [x] Basic rule engine
|
|
182
|
+
- [x] File conditions (name, extension, size, date)
|
|
183
|
+
- [x] Basic actions (move, copy, rename, delete)
|
|
184
|
+
|
|
185
|
+
### Phase 2: Advanced Conditions (v0.2.0)
|
|
186
|
+
|
|
187
|
+
- [ ] Content-based matching
|
|
188
|
+
- [ ] macOS metadata (tags, comments)
|
|
189
|
+
- [ ] Download source detection
|
|
190
|
+
- [ ] Compound conditions (AND/OR/NOT)
|
|
191
|
+
|
|
192
|
+
### Phase 3: Advanced Actions (v0.3.0)
|
|
193
|
+
|
|
194
|
+
- [ ] Archive creation
|
|
195
|
+
- [ ] Shell script execution
|
|
196
|
+
- [ ] AppleScript integration
|
|
197
|
+
- [ ] Notifications
|
|
198
|
+
|
|
199
|
+
### Phase 4: GUI & UX (v0.4.0)
|
|
200
|
+
|
|
201
|
+
- [ ] Menu bar application
|
|
202
|
+
- [ ] Rule editor interface
|
|
203
|
+
- [ ] Preview mode
|
|
204
|
+
- [ ] Activity log viewer
|
|
205
|
+
|
|
206
|
+
### Phase 5: System Features (v0.5.0)
|
|
207
|
+
|
|
208
|
+
- [ ] Trash management
|
|
209
|
+
- [ ] App Sweep functionality
|
|
210
|
+
- [ ] Spotlight integration
|
|
211
|
+
- [ ] Photos/Music import
|
|
212
|
+
|
|
213
|
+
### Phase 6: Polish & Release (v1.0.0)
|
|
214
|
+
|
|
215
|
+
- [ ] Performance optimization
|
|
216
|
+
- [ ] Comprehensive testing
|
|
217
|
+
- [ ] Documentation complete
|
|
218
|
+
- [ ] Community feedback integration
|
|
219
|
+
|
|
220
|
+
## 🛠️ Development
|
|
221
|
+
|
|
222
|
+
### Prerequisites
|
|
223
|
+
|
|
224
|
+
- macOS 10.15 (Catalina) or later
|
|
225
|
+
- Python 3.9 or later
|
|
226
|
+
- Xcode Command Line Tools
|
|
227
|
+
|
|
228
|
+
### Setup Development Environment
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
# Install development dependencies
|
|
232
|
+
pip install -r requirements-dev.txt
|
|
233
|
+
|
|
234
|
+
# Run tests
|
|
235
|
+
pytest
|
|
236
|
+
|
|
237
|
+
# Run with coverage
|
|
238
|
+
pytest --cov=sortmeout
|
|
239
|
+
|
|
240
|
+
# Type checking
|
|
241
|
+
mypy sortmeout
|
|
242
|
+
|
|
243
|
+
# Linting
|
|
244
|
+
flake8 sortmeout
|
|
245
|
+
black sortmeout
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Project Structure
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
sortmeout/
|
|
252
|
+
├── sortmeout/ # Main package
|
|
253
|
+
│ ├── __init__.py
|
|
254
|
+
│ ├── app.py # Main application class
|
|
255
|
+
│ ├── core/ # Core functionality
|
|
256
|
+
│ │ ├── __init__.py
|
|
257
|
+
│ │ ├── watcher.py # Folder watching (FSEvents)
|
|
258
|
+
│ │ ├── rule.py # Rule definitions
|
|
259
|
+
│ │ ├── condition.py # Condition types
|
|
260
|
+
│ │ └── action.py # Action types
|
|
261
|
+
│ ├── conditions/ # Condition implementations
|
|
262
|
+
│ ├── actions/ # Action implementations
|
|
263
|
+
│ ├── macos/ # macOS-specific integrations
|
|
264
|
+
│ ├── gui/ # GUI components
|
|
265
|
+
│ ├── utils/ # Utility functions
|
|
266
|
+
│ └── config/ # Configuration management
|
|
267
|
+
├── tests/ # Test suite
|
|
268
|
+
├── docs/ # Documentation
|
|
269
|
+
├── examples/ # Example rules and scripts
|
|
270
|
+
└── resources/ # Icons, assets
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## 🤝 Contributing
|
|
274
|
+
|
|
275
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
276
|
+
|
|
277
|
+
### Ways to Contribute
|
|
278
|
+
|
|
279
|
+
- Report bugs and request features via [Issues](https://github.com/yourusername/sortmeout/issues)
|
|
280
|
+
- Submit pull requests for bug fixes or new features
|
|
281
|
+
- Improve documentation
|
|
282
|
+
- Share your custom rules
|
|
283
|
+
- Help translate the application
|
|
284
|
+
|
|
285
|
+
## 📄 License
|
|
286
|
+
|
|
287
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
288
|
+
|
|
289
|
+
## 🙏 Acknowledgments
|
|
290
|
+
|
|
291
|
+
- Inspired by [Noodlesoft Hazel](https://www.noodlesoft.com)
|
|
292
|
+
- Built with [watchdog](https://github.com/gorakhargosh/watchdog) for cross-platform file monitoring
|
|
293
|
+
- Uses [PyObjC](https://pyobjc.readthedocs.io/) for macOS integration
|
|
294
|
+
|
|
295
|
+
## 📬 Contact
|
|
296
|
+
|
|
297
|
+
- GitHub Issues: For bug reports and feature requests
|
|
298
|
+
- Discussions: For questions and community support
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
**Note**: This is an independent open-source project and is not affiliated with Noodlesoft.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# SortMeOut 📁✨
|
|
2
|
+
|
|
3
|
+
An open-source file automation and organization tool for macOS, inspired by Noodlesoft Hazel.
|
|
4
|
+
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://www.python.org/downloads/)
|
|
7
|
+
[](https://www.apple.com/macos/)
|
|
8
|
+
|
|
9
|
+
## 🎯 Overview
|
|
10
|
+
|
|
11
|
+
SortMeOut watches folders you specify and automatically organizes files according to rules you create. Move, rename, tag, archive, or delete files based on name, date, type, content, and much more.
|
|
12
|
+
|
|
13
|
+
## ✨ Features
|
|
14
|
+
|
|
15
|
+
### Core Features
|
|
16
|
+
|
|
17
|
+
- **Folder Watching**: Monitor multiple folders for file changes in real-time
|
|
18
|
+
- **Rule-Based Organization**: Create powerful rules with conditions and actions
|
|
19
|
+
- **Pattern Matching**: Use glob patterns, regex, and smart matching
|
|
20
|
+
- **File Operations**: Move, copy, rename, delete, archive files
|
|
21
|
+
- **macOS Integration**: Tags, Spotlight metadata, Finder comments
|
|
22
|
+
|
|
23
|
+
### Conditions
|
|
24
|
+
|
|
25
|
+
- File name (contains, starts with, ends with, matches pattern)
|
|
26
|
+
- File extension/type (documents, images, videos, etc.)
|
|
27
|
+
- File size (greater than, less than, between)
|
|
28
|
+
- Date attributes (created, modified, accessed, added)
|
|
29
|
+
- File contents (text search, regex)
|
|
30
|
+
- macOS tags and Finder comments
|
|
31
|
+
- Source URL/application (where downloaded from)
|
|
32
|
+
- Nested conditions (AND, OR, NOT logic)
|
|
33
|
+
|
|
34
|
+
### Actions
|
|
35
|
+
|
|
36
|
+
- Move to folder (with subfolder creation)
|
|
37
|
+
- Copy to folder
|
|
38
|
+
- Rename (with pattern substitution)
|
|
39
|
+
- Add/remove macOS tags
|
|
40
|
+
- Set Finder comments
|
|
41
|
+
- Archive (zip, tar, gzip)
|
|
42
|
+
- Delete / Move to Trash
|
|
43
|
+
- Run shell script
|
|
44
|
+
- Execute AppleScript
|
|
45
|
+
- Open with application
|
|
46
|
+
- Send notification
|
|
47
|
+
- Import to Photos/Music
|
|
48
|
+
|
|
49
|
+
### Advanced Features
|
|
50
|
+
|
|
51
|
+
- **Trash Management**: Auto-clean trash based on age/size
|
|
52
|
+
- **App Sweep**: Detect and remove app support files when uninstalling
|
|
53
|
+
- **Preview Mode**: See what rules would do without executing
|
|
54
|
+
- **Rule Import/Export**: Share rules with others
|
|
55
|
+
- **Logging**: Detailed logs of all operations
|
|
56
|
+
- **Menu Bar App**: Quick access and status
|
|
57
|
+
|
|
58
|
+
## 🚀 Quick Start
|
|
59
|
+
|
|
60
|
+
### Installation
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
# Clone the repository
|
|
64
|
+
git clone https://github.com/yourusername/sortmeout.git
|
|
65
|
+
cd sortmeout
|
|
66
|
+
|
|
67
|
+
# Create virtual environment
|
|
68
|
+
python3 -m venv venv
|
|
69
|
+
source venv/bin/activate
|
|
70
|
+
|
|
71
|
+
# Install dependencies
|
|
72
|
+
pip install -r requirements.txt
|
|
73
|
+
|
|
74
|
+
# Install the application
|
|
75
|
+
pip install -e .
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Basic Usage
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from sortmeout import SortMeOut, Rule, Condition, Action
|
|
82
|
+
|
|
83
|
+
# Create a new instance
|
|
84
|
+
app = SortMeOut()
|
|
85
|
+
|
|
86
|
+
# Add a folder to watch
|
|
87
|
+
app.add_folder("~/Downloads")
|
|
88
|
+
|
|
89
|
+
# Create a rule to organize PDF files
|
|
90
|
+
rule = Rule(
|
|
91
|
+
name="Organize PDFs",
|
|
92
|
+
conditions=[
|
|
93
|
+
Condition("extension", "equals", "pdf")
|
|
94
|
+
],
|
|
95
|
+
actions=[
|
|
96
|
+
Action("move", destination="~/Documents/PDFs")
|
|
97
|
+
]
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
# Add rule to the Downloads folder
|
|
101
|
+
app.add_rule("~/Downloads", rule)
|
|
102
|
+
|
|
103
|
+
# Start watching
|
|
104
|
+
app.start()
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### GUI Application
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
# Launch the GUI
|
|
111
|
+
sortmeout-gui
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## 📖 Documentation
|
|
115
|
+
|
|
116
|
+
- [User Manual](docs/user-manual.md)
|
|
117
|
+
- [Rule Creation Guide](docs/rules-guide.md)
|
|
118
|
+
- [API Reference](docs/api-reference.md)
|
|
119
|
+
- [Contributing Guide](CONTRIBUTING.md)
|
|
120
|
+
- [FAQ](docs/faq.md)
|
|
121
|
+
|
|
122
|
+
## 🗺️ Roadmap
|
|
123
|
+
|
|
124
|
+
### Phase 1: Core Engine (v0.1.0) ✅
|
|
125
|
+
|
|
126
|
+
- [x] Folder monitoring with FSEvents
|
|
127
|
+
- [x] Basic rule engine
|
|
128
|
+
- [x] File conditions (name, extension, size, date)
|
|
129
|
+
- [x] Basic actions (move, copy, rename, delete)
|
|
130
|
+
|
|
131
|
+
### Phase 2: Advanced Conditions (v0.2.0)
|
|
132
|
+
|
|
133
|
+
- [ ] Content-based matching
|
|
134
|
+
- [ ] macOS metadata (tags, comments)
|
|
135
|
+
- [ ] Download source detection
|
|
136
|
+
- [ ] Compound conditions (AND/OR/NOT)
|
|
137
|
+
|
|
138
|
+
### Phase 3: Advanced Actions (v0.3.0)
|
|
139
|
+
|
|
140
|
+
- [ ] Archive creation
|
|
141
|
+
- [ ] Shell script execution
|
|
142
|
+
- [ ] AppleScript integration
|
|
143
|
+
- [ ] Notifications
|
|
144
|
+
|
|
145
|
+
### Phase 4: GUI & UX (v0.4.0)
|
|
146
|
+
|
|
147
|
+
- [ ] Menu bar application
|
|
148
|
+
- [ ] Rule editor interface
|
|
149
|
+
- [ ] Preview mode
|
|
150
|
+
- [ ] Activity log viewer
|
|
151
|
+
|
|
152
|
+
### Phase 5: System Features (v0.5.0)
|
|
153
|
+
|
|
154
|
+
- [ ] Trash management
|
|
155
|
+
- [ ] App Sweep functionality
|
|
156
|
+
- [ ] Spotlight integration
|
|
157
|
+
- [ ] Photos/Music import
|
|
158
|
+
|
|
159
|
+
### Phase 6: Polish & Release (v1.0.0)
|
|
160
|
+
|
|
161
|
+
- [ ] Performance optimization
|
|
162
|
+
- [ ] Comprehensive testing
|
|
163
|
+
- [ ] Documentation complete
|
|
164
|
+
- [ ] Community feedback integration
|
|
165
|
+
|
|
166
|
+
## 🛠️ Development
|
|
167
|
+
|
|
168
|
+
### Prerequisites
|
|
169
|
+
|
|
170
|
+
- macOS 10.15 (Catalina) or later
|
|
171
|
+
- Python 3.9 or later
|
|
172
|
+
- Xcode Command Line Tools
|
|
173
|
+
|
|
174
|
+
### Setup Development Environment
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
# Install development dependencies
|
|
178
|
+
pip install -r requirements-dev.txt
|
|
179
|
+
|
|
180
|
+
# Run tests
|
|
181
|
+
pytest
|
|
182
|
+
|
|
183
|
+
# Run with coverage
|
|
184
|
+
pytest --cov=sortmeout
|
|
185
|
+
|
|
186
|
+
# Type checking
|
|
187
|
+
mypy sortmeout
|
|
188
|
+
|
|
189
|
+
# Linting
|
|
190
|
+
flake8 sortmeout
|
|
191
|
+
black sortmeout
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Project Structure
|
|
195
|
+
|
|
196
|
+
```
|
|
197
|
+
sortmeout/
|
|
198
|
+
├── sortmeout/ # Main package
|
|
199
|
+
│ ├── __init__.py
|
|
200
|
+
│ ├── app.py # Main application class
|
|
201
|
+
│ ├── core/ # Core functionality
|
|
202
|
+
│ │ ├── __init__.py
|
|
203
|
+
│ │ ├── watcher.py # Folder watching (FSEvents)
|
|
204
|
+
│ │ ├── rule.py # Rule definitions
|
|
205
|
+
│ │ ├── condition.py # Condition types
|
|
206
|
+
│ │ └── action.py # Action types
|
|
207
|
+
│ ├── conditions/ # Condition implementations
|
|
208
|
+
│ ├── actions/ # Action implementations
|
|
209
|
+
│ ├── macos/ # macOS-specific integrations
|
|
210
|
+
│ ├── gui/ # GUI components
|
|
211
|
+
│ ├── utils/ # Utility functions
|
|
212
|
+
│ └── config/ # Configuration management
|
|
213
|
+
├── tests/ # Test suite
|
|
214
|
+
├── docs/ # Documentation
|
|
215
|
+
├── examples/ # Example rules and scripts
|
|
216
|
+
└── resources/ # Icons, assets
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 🤝 Contributing
|
|
220
|
+
|
|
221
|
+
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
|
|
222
|
+
|
|
223
|
+
### Ways to Contribute
|
|
224
|
+
|
|
225
|
+
- Report bugs and request features via [Issues](https://github.com/yourusername/sortmeout/issues)
|
|
226
|
+
- Submit pull requests for bug fixes or new features
|
|
227
|
+
- Improve documentation
|
|
228
|
+
- Share your custom rules
|
|
229
|
+
- Help translate the application
|
|
230
|
+
|
|
231
|
+
## 📄 License
|
|
232
|
+
|
|
233
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
234
|
+
|
|
235
|
+
## 🙏 Acknowledgments
|
|
236
|
+
|
|
237
|
+
- Inspired by [Noodlesoft Hazel](https://www.noodlesoft.com)
|
|
238
|
+
- Built with [watchdog](https://github.com/gorakhargosh/watchdog) for cross-platform file monitoring
|
|
239
|
+
- Uses [PyObjC](https://pyobjc.readthedocs.io/) for macOS integration
|
|
240
|
+
|
|
241
|
+
## 📬 Contact
|
|
242
|
+
|
|
243
|
+
- GitHub Issues: For bug reports and feature requests
|
|
244
|
+
- Discussions: For questions and community support
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
**Note**: This is an independent open-source project and is not affiliated with Noodlesoft.
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sortmeout"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Open-source file automation and organization tool for macOS"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "SortMeOut Contributors"}
|
|
13
|
+
]
|
|
14
|
+
keywords = [
|
|
15
|
+
"automation",
|
|
16
|
+
"file-management",
|
|
17
|
+
"macos",
|
|
18
|
+
"organization",
|
|
19
|
+
"rules",
|
|
20
|
+
"workflow"
|
|
21
|
+
]
|
|
22
|
+
classifiers = [
|
|
23
|
+
"Development Status :: 3 - Alpha",
|
|
24
|
+
"Environment :: MacOS X",
|
|
25
|
+
"Intended Audience :: End Users/Desktop",
|
|
26
|
+
"License :: OSI Approved :: MIT License",
|
|
27
|
+
"Operating System :: MacOS :: MacOS X",
|
|
28
|
+
"Programming Language :: Python :: 3",
|
|
29
|
+
"Programming Language :: Python :: 3.9",
|
|
30
|
+
"Programming Language :: Python :: 3.10",
|
|
31
|
+
"Programming Language :: Python :: 3.11",
|
|
32
|
+
"Programming Language :: Python :: 3.12",
|
|
33
|
+
"Topic :: Desktop Environment :: File Managers",
|
|
34
|
+
"Topic :: System :: Filesystems",
|
|
35
|
+
"Topic :: Utilities",
|
|
36
|
+
]
|
|
37
|
+
requires-python = ">=3.9"
|
|
38
|
+
dependencies = [
|
|
39
|
+
"watchdog>=3.0.0",
|
|
40
|
+
"pyobjc-core>=9.0",
|
|
41
|
+
"pyobjc-framework-Cocoa>=9.0",
|
|
42
|
+
"pyobjc-framework-FSEvents>=9.0",
|
|
43
|
+
"pyobjc-framework-Quartz>=9.0",
|
|
44
|
+
"pyobjc-framework-ScriptingBridge>=9.0",
|
|
45
|
+
"pyyaml>=6.0",
|
|
46
|
+
"python-dateutil>=2.8.0",
|
|
47
|
+
"rich>=13.0.0",
|
|
48
|
+
"click>=8.0.0",
|
|
49
|
+
"appdirs>=1.4.0",
|
|
50
|
+
"humanize>=4.0.0",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[project.optional-dependencies]
|
|
54
|
+
dev = [
|
|
55
|
+
"pytest>=7.0.0",
|
|
56
|
+
"pytest-cov>=4.0.0",
|
|
57
|
+
"pytest-asyncio>=0.21.0",
|
|
58
|
+
"pytest-mock>=3.0.0",
|
|
59
|
+
"mypy>=1.0.0",
|
|
60
|
+
"black>=23.0.0",
|
|
61
|
+
"flake8>=6.0.0",
|
|
62
|
+
"isort>=5.0.0",
|
|
63
|
+
"pre-commit>=3.0.0",
|
|
64
|
+
]
|
|
65
|
+
gui = [
|
|
66
|
+
"rumps>=0.4.0",
|
|
67
|
+
"pyobjc-framework-Cocoa>=9.0",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[project.scripts]
|
|
71
|
+
sortmeout = "sortmeout.cli:main"
|
|
72
|
+
sortmeout-gui = "sortmeout.gui.app:main"
|
|
73
|
+
|
|
74
|
+
[project.urls]
|
|
75
|
+
Homepage = "https://sortmeout.saidborna.com"
|
|
76
|
+
Documentation = "https://github.com/S-Borna/sortmeout/tree/main/docs"
|
|
77
|
+
Repository = "https://github.com/S-Borna/sortmeout"
|
|
78
|
+
Issues = "https://github.com/S-Borna/sortmeout/issues"
|
|
79
|
+
|
|
80
|
+
[tool.setuptools.packages.find]
|
|
81
|
+
where = ["."]
|
|
82
|
+
include = ["sortmeout*"]
|
|
83
|
+
|
|
84
|
+
[tool.black]
|
|
85
|
+
line-length = 100
|
|
86
|
+
target-version = ["py39", "py310", "py311", "py312"]
|
|
87
|
+
include = '\.pyi?$'
|
|
88
|
+
exclude = '''
|
|
89
|
+
/(
|
|
90
|
+
\.eggs
|
|
91
|
+
| \.git
|
|
92
|
+
| \.hg
|
|
93
|
+
| \.mypy_cache
|
|
94
|
+
| \.tox
|
|
95
|
+
| \.venv
|
|
96
|
+
| _build
|
|
97
|
+
| buck-out
|
|
98
|
+
| build
|
|
99
|
+
| dist
|
|
100
|
+
)/
|
|
101
|
+
'''
|
|
102
|
+
|
|
103
|
+
[tool.isort]
|
|
104
|
+
profile = "black"
|
|
105
|
+
line_length = 100
|
|
106
|
+
skip_gitignore = true
|
|
107
|
+
|
|
108
|
+
[tool.mypy]
|
|
109
|
+
python_version = "3.9"
|
|
110
|
+
warn_return_any = true
|
|
111
|
+
warn_unused_configs = true
|
|
112
|
+
ignore_missing_imports = true
|
|
113
|
+
exclude = [
|
|
114
|
+
"build",
|
|
115
|
+
"dist",
|
|
116
|
+
"venv",
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
[tool.pytest.ini_options]
|
|
120
|
+
testpaths = ["tests"]
|
|
121
|
+
python_files = ["test_*.py", "*_test.py"]
|
|
122
|
+
addopts = "-v --tb=short"
|
|
123
|
+
asyncio_mode = "auto"
|
|
124
|
+
|
|
125
|
+
[tool.coverage.run]
|
|
126
|
+
source = ["sortmeout"]
|
|
127
|
+
branch = true
|
|
128
|
+
omit = [
|
|
129
|
+
"*/tests/*",
|
|
130
|
+
"*/__pycache__/*",
|
|
131
|
+
]
|
|
132
|
+
|
|
133
|
+
[tool.coverage.report]
|
|
134
|
+
exclude_lines = [
|
|
135
|
+
"pragma: no cover",
|
|
136
|
+
"def __repr__",
|
|
137
|
+
"raise AssertionError",
|
|
138
|
+
"raise NotImplementedError",
|
|
139
|
+
"if __name__ == .__main__.:",
|
|
140
|
+
]
|