putplace 0.4.1__py3-none-any.whl
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.
Potentially problematic release.
This version of putplace might be problematic. Click here for more details.
- putplace/__init__.py +5 -0
- putplace/auth.py +279 -0
- putplace/config.py +167 -0
- putplace/database.py +387 -0
- putplace/main.py +3048 -0
- putplace/models.py +179 -0
- putplace/ppclient.py +586 -0
- putplace/ppserver.py +453 -0
- putplace/scripts/__init__.py +1 -0
- putplace/scripts/create_api_key.py +119 -0
- putplace/storage.py +456 -0
- putplace/user_auth.py +52 -0
- putplace/version.py +6 -0
- putplace-0.4.1.dist-info/METADATA +346 -0
- putplace-0.4.1.dist-info/RECORD +17 -0
- putplace-0.4.1.dist-info/WHEEL +4 -0
- putplace-0.4.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: putplace
|
|
3
|
+
Version: 0.4.1
|
|
4
|
+
Summary: A Python project built with uv
|
|
5
|
+
Classifier: Development Status :: 4 - Beta
|
|
6
|
+
Classifier: Framework :: FastAPI
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Intended Audience :: System Administrators
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: System :: Archiving
|
|
17
|
+
Classifier: Topic :: System :: Filesystems
|
|
18
|
+
Classifier: Topic :: System :: Systems Administration
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Requires-Dist: argon2-cffi>=23.1.0
|
|
21
|
+
Requires-Dist: configargparse>=1.7.0
|
|
22
|
+
Requires-Dist: fastapi>=0.110.0
|
|
23
|
+
Requires-Dist: httpx>=0.26.0
|
|
24
|
+
Requires-Dist: pydantic-settings>=2.1.0
|
|
25
|
+
Requires-Dist: pydantic>=2.6.0
|
|
26
|
+
Requires-Dist: pymongo>=4.10.0
|
|
27
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
28
|
+
Requires-Dist: python-jose[cryptography]>=3.3.0
|
|
29
|
+
Requires-Dist: python-multipart>=0.0.6
|
|
30
|
+
Requires-Dist: rich>=13.7.0
|
|
31
|
+
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
32
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: invoke>=2.2.0; extra == 'dev'
|
|
35
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest-xdist>=3.5.0; extra == 'dev'
|
|
39
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
40
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
41
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
42
|
+
Provides-Extra: s3
|
|
43
|
+
Requires-Dist: aioboto3>=12.0.0; extra == 's3'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# PutPlace
|
|
47
|
+
|
|
48
|
+
[](https://putplace.readthedocs.io/en/latest/?badge=latest)
|
|
49
|
+
[](https://www.python.org/downloads/)
|
|
50
|
+
[](https://fastapi.tiangolo.com/)
|
|
51
|
+
[](https://www.mongodb.com/)
|
|
52
|
+
|
|
53
|
+
A distributed file metadata storage and content deduplication system with SHA256-based clone detection, epoch file tracking, and multiple storage backends.
|
|
54
|
+
|
|
55
|
+
## Tech Stack
|
|
56
|
+
|
|
57
|
+
- **FastAPI** - Modern async web framework
|
|
58
|
+
- **MongoDB (PyMongo Async)** - Native async MongoDB driver (PyMongo 4.10+)
|
|
59
|
+
- **Argon2** - Modern password hashing algorithm
|
|
60
|
+
- **JWT** - JSON Web Tokens for authentication
|
|
61
|
+
- **uv** - Fast Python package manager
|
|
62
|
+
- **pytest** - Comprehensive test suite with 125+ tests
|
|
63
|
+
|
|
64
|
+
**Note:** This project uses PyMongo's native async support (introduced in PyMongo 4.9+) which provides better performance than the deprecated Motor library through direct asyncio implementation.
|
|
65
|
+
|
|
66
|
+
## Features
|
|
67
|
+
|
|
68
|
+
- 📁 **File Metadata Tracking** - Store file metadata with SHA256 hashes across your infrastructure
|
|
69
|
+
- 🔄 **Content Deduplication** - Upload files only once, deduplicated by SHA256
|
|
70
|
+
- 👥 **Clone Detection** - Track duplicate files across all users with epoch file identification
|
|
71
|
+
- 💾 **Multiple Storage Backends** - Local filesystem or AWS S3 for file content
|
|
72
|
+
- 🔐 **Dual Authentication** - API key (for clients) and JWT (for web UI)
|
|
73
|
+
- 🌐 **Interactive Web UI** - Tree-based file browser with clone visualization
|
|
74
|
+
- 🚀 **Production Ready** - Comprehensive tests, TOML configuration, graceful interrupt handling
|
|
75
|
+
|
|
76
|
+
## Documentation
|
|
77
|
+
|
|
78
|
+
**📖 Full documentation:** https://putplace.readthedocs.io/
|
|
79
|
+
|
|
80
|
+
- [Installation Guide](https://putplace.readthedocs.io/en/latest/installation.html)
|
|
81
|
+
- [Quick Start Guide](https://putplace.readthedocs.io/en/latest/quickstart.html)
|
|
82
|
+
- [Client Usage Guide](https://putplace.readthedocs.io/en/latest/client-guide.html)
|
|
83
|
+
- [API Reference](https://putplace.readthedocs.io/en/latest/api-reference.html)
|
|
84
|
+
- [Deployment Guide](https://putplace.readthedocs.io/en/latest/deployment.html)
|
|
85
|
+
- [Architecture Overview](https://putplace.readthedocs.io/en/latest/architecture.html)
|
|
86
|
+
|
|
87
|
+
## Quick Start
|
|
88
|
+
|
|
89
|
+
### Prerequisites
|
|
90
|
+
|
|
91
|
+
- Python 3.10 - 3.14
|
|
92
|
+
- [uv](https://github.com/astral-sh/uv) - Fast Python package installer
|
|
93
|
+
- Docker (for MongoDB container)
|
|
94
|
+
|
|
95
|
+
### Installation
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Install uv
|
|
99
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
100
|
+
|
|
101
|
+
# Clone repository
|
|
102
|
+
git clone https://github.com/jdrumgoole/putplace.git
|
|
103
|
+
cd putplace
|
|
104
|
+
|
|
105
|
+
# Complete setup (venv + dependencies + MongoDB)
|
|
106
|
+
invoke setup
|
|
107
|
+
source .venv/bin/activate
|
|
108
|
+
|
|
109
|
+
# Start MongoDB and server
|
|
110
|
+
invoke quickstart
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The server will be available at http://localhost:8000
|
|
114
|
+
|
|
115
|
+
### Using the Client
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Scan a directory and upload metadata
|
|
119
|
+
ppclient --path /var/log
|
|
120
|
+
|
|
121
|
+
# Dry run (no upload)
|
|
122
|
+
ppclient --path /var/log --dry-run
|
|
123
|
+
|
|
124
|
+
# With API key
|
|
125
|
+
ppclient --path /var/log --api-key your-api-key-here
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
See the [Client Guide](https://putplace.readthedocs.io/en/latest/client-guide.html) for more details.
|
|
129
|
+
|
|
130
|
+
## Development
|
|
131
|
+
|
|
132
|
+
### Project Structure
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
putplace/
|
|
136
|
+
├── src/putplace/ # Main application code
|
|
137
|
+
│ ├── main.py # FastAPI application
|
|
138
|
+
│ ├── models.py # Pydantic models
|
|
139
|
+
│ ├── database.py # MongoDB operations
|
|
140
|
+
│ ├── storage.py # Storage backends (local/S3)
|
|
141
|
+
│ ├── auth.py # API key authentication
|
|
142
|
+
│ ├── ppclient.py # Client tool
|
|
143
|
+
│ └── ppserver.py # Server manager
|
|
144
|
+
├── tests/ # Test suite (125+ tests, parallel execution)
|
|
145
|
+
├── docs/ # Documentation (Sphinx)
|
|
146
|
+
├── tasks.py # Invoke task automation
|
|
147
|
+
└── pyproject.toml # Project configuration
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Development Tasks
|
|
151
|
+
|
|
152
|
+
This project uses [invoke](https://www.pyinvoke.org/) for task automation:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
# Setup
|
|
156
|
+
invoke setup # Complete project setup
|
|
157
|
+
invoke setup-venv # Create virtual environment only
|
|
158
|
+
invoke install # Install dependencies
|
|
159
|
+
|
|
160
|
+
# MongoDB
|
|
161
|
+
invoke mongo-start # Start MongoDB in Docker
|
|
162
|
+
invoke mongo-stop # Stop MongoDB
|
|
163
|
+
invoke mongo-status # Check MongoDB status
|
|
164
|
+
|
|
165
|
+
# Running
|
|
166
|
+
invoke serve # Development server (auto-reload)
|
|
167
|
+
invoke serve-prod # Production server (4 workers)
|
|
168
|
+
invoke quickstart # Start MongoDB + dev server
|
|
169
|
+
|
|
170
|
+
# Testing
|
|
171
|
+
invoke test-all # Run all tests (parallel, 4 workers, ~40% faster)
|
|
172
|
+
invoke test-all --parallel=False # Run serially (most stable)
|
|
173
|
+
invoke test # Run tests with coverage
|
|
174
|
+
invoke test-one tests/test_api.py # Run specific test file
|
|
175
|
+
pytest -m "not integration" # Skip integration tests
|
|
176
|
+
pytest -m integration # Run only integration tests
|
|
177
|
+
|
|
178
|
+
# Code Quality
|
|
179
|
+
invoke lint # Run ruff linter
|
|
180
|
+
invoke lint --fix # Auto-fix linting issues
|
|
181
|
+
invoke format # Format code with black
|
|
182
|
+
invoke typecheck # Run mypy type checker
|
|
183
|
+
invoke check # Run all checks (format, lint, typecheck, test)
|
|
184
|
+
|
|
185
|
+
# Other
|
|
186
|
+
invoke build # Build package
|
|
187
|
+
invoke clean # Clean build artifacts
|
|
188
|
+
invoke --list # List all tasks
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Testing
|
|
192
|
+
|
|
193
|
+
The project includes 125+ comprehensive tests covering:
|
|
194
|
+
- Unit tests for models, API endpoints, database operations
|
|
195
|
+
- Integration tests with real server and MongoDB
|
|
196
|
+
- End-to-end tests including file upload and deduplication
|
|
197
|
+
- Console script installation tests
|
|
198
|
+
- Parallel test execution with isolated databases (4 workers, ~40% faster)
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
# Run all tests with coverage (parallel by default, ~40% faster)
|
|
202
|
+
invoke test-all
|
|
203
|
+
|
|
204
|
+
# Run tests serially (most stable)
|
|
205
|
+
invoke test-all --parallel=False
|
|
206
|
+
|
|
207
|
+
# Run with more workers
|
|
208
|
+
invoke test-all --workers=8
|
|
209
|
+
|
|
210
|
+
# Run specific test file
|
|
211
|
+
invoke test-one tests/test_models.py
|
|
212
|
+
|
|
213
|
+
# Run specific test function
|
|
214
|
+
invoke test-one tests/test_api.py::test_put_file_valid
|
|
215
|
+
|
|
216
|
+
# Skip integration tests (faster, no MongoDB required)
|
|
217
|
+
pytest -m "not integration"
|
|
218
|
+
|
|
219
|
+
# View coverage report
|
|
220
|
+
open htmlcov/index.html
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Parallel Testing:** Tests run in parallel by default using pytest-xdist with isolated databases per worker, preventing race conditions while providing significant speed improvements.
|
|
224
|
+
|
|
225
|
+
See [tests/README.md](tests/README.md) for detailed testing documentation.
|
|
226
|
+
|
|
227
|
+
### Server Manager (ppserver)
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
ppserver start # Start server
|
|
231
|
+
ppserver start --port 8080 # Custom port
|
|
232
|
+
ppserver status # Check status
|
|
233
|
+
ppserver stop # Stop server
|
|
234
|
+
ppserver restart # Restart server
|
|
235
|
+
ppserver logs # View logs
|
|
236
|
+
ppserver logs --follow # Follow logs
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Files are stored in `~/.putplace/`:
|
|
240
|
+
- `ppserver.pid` - Process ID
|
|
241
|
+
- `ppserver.log` - Server logs
|
|
242
|
+
|
|
243
|
+
## Configuration
|
|
244
|
+
|
|
245
|
+
PutPlace uses TOML configuration files. Copy the example and customize:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
cp ppserver.toml.example ppserver.toml
|
|
249
|
+
nano ppserver.toml
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
The server looks for `ppserver.toml` in:
|
|
253
|
+
1. `./ppserver.toml` (current directory)
|
|
254
|
+
2. `~/.config/putplace/ppserver.toml` (user config)
|
|
255
|
+
3. `/etc/putplace/ppserver.toml` (system config)
|
|
256
|
+
|
|
257
|
+
Environment variables override all settings. See [Configuration Guide](https://putplace.readthedocs.io/en/latest/configuration.html) for details.
|
|
258
|
+
|
|
259
|
+
## API Endpoints
|
|
260
|
+
|
|
261
|
+
Once the server is running:
|
|
262
|
+
|
|
263
|
+
- **Home**: http://localhost:8000
|
|
264
|
+
- **API Docs**: http://localhost:8000/docs (Swagger UI)
|
|
265
|
+
- **Alternative Docs**: http://localhost:8000/redoc (ReDoc)
|
|
266
|
+
- **Health Check**: http://localhost:8000/health
|
|
267
|
+
|
|
268
|
+
### Key Endpoints
|
|
269
|
+
|
|
270
|
+
**File Operations:**
|
|
271
|
+
- `POST /put_file` - Store file metadata (requires API key)
|
|
272
|
+
- `GET /get_file/{sha256}` - Retrieve file by SHA256 (requires API key)
|
|
273
|
+
- `POST /upload_file/{sha256}` - Upload file content (requires API key)
|
|
274
|
+
- `GET /api/clones/{sha256}` - Get all file clones (requires JWT)
|
|
275
|
+
- `GET /api/my_files` - Get user's files (requires JWT)
|
|
276
|
+
|
|
277
|
+
**Authentication:**
|
|
278
|
+
- `POST /api/register` - Register new user
|
|
279
|
+
- `POST /api/login` - Login and get JWT token
|
|
280
|
+
- `POST /api_keys` - Create API key (requires JWT)
|
|
281
|
+
- `GET /api_keys` - List API keys (requires JWT)
|
|
282
|
+
|
|
283
|
+
See [API Reference](https://putplace.readthedocs.io/en/latest/api-reference.html) for complete endpoint documentation.
|
|
284
|
+
|
|
285
|
+
## Architecture
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
289
|
+
│ Client │ │ Client │ │ Client │
|
|
290
|
+
│ (Server A) │ │ (Server B) │ │ (Server C) │
|
|
291
|
+
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
|
292
|
+
│ X-API-Key Auth │ │
|
|
293
|
+
└───────────┬───────────┴────────────────────────┘
|
|
294
|
+
│
|
|
295
|
+
▼
|
|
296
|
+
┌─────────────────┐
|
|
297
|
+
│ PutPlace API │
|
|
298
|
+
│ (FastAPI) │
|
|
299
|
+
└────────┬────────┘
|
|
300
|
+
│
|
|
301
|
+
┌───────┴────────┐
|
|
302
|
+
│ │
|
|
303
|
+
▼ ▼
|
|
304
|
+
┌────────────┐ ┌────────────┐
|
|
305
|
+
│ MongoDB │ │ Storage │
|
|
306
|
+
│ (Metadata) │ │ Backend │
|
|
307
|
+
└────────────┘ └────────────┘
|
|
308
|
+
│
|
|
309
|
+
┌─────┴─────┐
|
|
310
|
+
│ │
|
|
311
|
+
▼ ▼
|
|
312
|
+
┌──────────┐ ┌──────────┐
|
|
313
|
+
│ Local │ │ AWS │
|
|
314
|
+
│ FS │ │ S3 │
|
|
315
|
+
└──────────┘ └──────────┘
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
See [Architecture Guide](https://putplace.readthedocs.io/en/latest/architecture.html) for detailed design documentation.
|
|
319
|
+
|
|
320
|
+
## Contributing
|
|
321
|
+
|
|
322
|
+
Contributions are welcome! Please:
|
|
323
|
+
|
|
324
|
+
1. Fork the repository
|
|
325
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
326
|
+
3. Make your changes
|
|
327
|
+
4. Run tests and linting (`invoke check`)
|
|
328
|
+
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
329
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
330
|
+
7. Open a Pull Request
|
|
331
|
+
|
|
332
|
+
See [Development Guide](https://putplace.readthedocs.io/en/latest/development.html) for more details.
|
|
333
|
+
|
|
334
|
+
## License
|
|
335
|
+
|
|
336
|
+
See [LICENSE](LICENSE) file for details.
|
|
337
|
+
|
|
338
|
+
## Support
|
|
339
|
+
|
|
340
|
+
- **Documentation**: https://putplace.readthedocs.io/
|
|
341
|
+
- **Issues**: https://github.com/jdrumgoole/putplace/issues
|
|
342
|
+
- **Source**: https://github.com/jdrumgoole/putplace
|
|
343
|
+
|
|
344
|
+
## Changelog
|
|
345
|
+
|
|
346
|
+
See [CHANGELOG.md](CHANGELOG.md) for version history and release notes.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
putplace/__init__.py,sha256=T0e_B4Okh4Oidh2veEpxz_htu64NgY-s7mxVrui3UK0,96
|
|
2
|
+
putplace/auth.py,sha256=F400hR0mBAi9Bu3-bRDdUvq00RpqVIn3Rfq1cTZ-Cdk,7658
|
|
3
|
+
putplace/config.py,sha256=ubrcfqZoaPD3OdxXVgv0VmemBl7JK1KqRgnJJbZviyQ,5563
|
|
4
|
+
putplace/database.py,sha256=Pg0RWaR3RyFlJQ3bRJWOJMrVAyEWIiFcykmorogTvNk,14149
|
|
5
|
+
putplace/main.py,sha256=b8yX9B6q-KKQPGumXpf2D5KWvbPlW86m-HMcSCNkHpI,109384
|
|
6
|
+
putplace/models.py,sha256=06vKdU1aW3JytR8lk5fNgjddVJ1navU98wGmjwN97rg,6706
|
|
7
|
+
putplace/ppclient.py,sha256=NvKgcfVSclDrYjxZCviEvqinYo9SZMruOMXmj7E3qH8,18025
|
|
8
|
+
putplace/ppserver.py,sha256=xsymXQf_vIhKqyF007M9UTP8zmggH9YcAgLFc-O1UR4,12197
|
|
9
|
+
putplace/storage.py,sha256=AOubCR7KiDIopS5C66Ema30T6ktNB-XEOXCG1MISHNM,14434
|
|
10
|
+
putplace/user_auth.py,sha256=OoNAGRg1p_NM_uj6VPE7C2eodg4ZZwT8kMXSA4_qDkE,1537
|
|
11
|
+
putplace/version.py,sha256=PShUX8iVLxxmtzq2jqUYXZlbKcvHdWmky-q6_vruuDo,123
|
|
12
|
+
putplace/scripts/__init__.py,sha256=tfvdbwiMTwE7K6AhDLJGW68U-eATY0LAYz-OGeqixO4,45
|
|
13
|
+
putplace/scripts/create_api_key.py,sha256=-b0uG2iGciOXJ_ZNuCf9eXT89kDfI3V4P-gnkMVE_cc,3510
|
|
14
|
+
putplace-0.4.1.dist-info/METADATA,sha256=-YV81sKdUQnUyfjTQ-nhOeKF_1X_KHrDukcrS1nPARU,12826
|
|
15
|
+
putplace-0.4.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
16
|
+
putplace-0.4.1.dist-info/entry_points.txt,sha256=cUl4VG-YFUpZZmCJNnbdH3eIGOkgLFPU5U0yHk2K7Oo,86
|
|
17
|
+
putplace-0.4.1.dist-info/RECORD,,
|