tiny-object-storage 0.1.1__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.
Files changed (40) hide show
  1. tiny_object_storage-0.1.1/LICENSE +21 -0
  2. tiny_object_storage-0.1.1/PKG-INFO +228 -0
  3. tiny_object_storage-0.1.1/README.md +189 -0
  4. tiny_object_storage-0.1.1/pyproject.toml +110 -0
  5. tiny_object_storage-0.1.1/setup.cfg +4 -0
  6. tiny_object_storage-0.1.1/src/tiny_object_storage/__init__.py +8 -0
  7. tiny_object_storage-0.1.1/src/tiny_object_storage/api/__init__.py +0 -0
  8. tiny_object_storage-0.1.1/src/tiny_object_storage/api/buckets.py +114 -0
  9. tiny_object_storage-0.1.1/src/tiny_object_storage/api/health.py +25 -0
  10. tiny_object_storage-0.1.1/src/tiny_object_storage/api/objects.py +196 -0
  11. tiny_object_storage-0.1.1/src/tiny_object_storage/cli.py +128 -0
  12. tiny_object_storage-0.1.1/src/tiny_object_storage/config.py +37 -0
  13. tiny_object_storage-0.1.1/src/tiny_object_storage/core/__init__.py +0 -0
  14. tiny_object_storage-0.1.1/src/tiny_object_storage/core/errors.py +33 -0
  15. tiny_object_storage-0.1.1/src/tiny_object_storage/core/utils.py +209 -0
  16. tiny_object_storage-0.1.1/src/tiny_object_storage/logging_config.py +73 -0
  17. tiny_object_storage-0.1.1/src/tiny_object_storage/main.py +199 -0
  18. tiny_object_storage-0.1.1/src/tiny_object_storage/models/__init__.py +0 -0
  19. tiny_object_storage-0.1.1/src/tiny_object_storage/models/bucket.py +10 -0
  20. tiny_object_storage-0.1.1/src/tiny_object_storage/models/object_info.py +18 -0
  21. tiny_object_storage-0.1.1/src/tiny_object_storage/models/responses.py +48 -0
  22. tiny_object_storage-0.1.1/src/tiny_object_storage/services/__init__.py +0 -0
  23. tiny_object_storage-0.1.1/src/tiny_object_storage/services/bucket_service.py +50 -0
  24. tiny_object_storage-0.1.1/src/tiny_object_storage/services/object_service.py +79 -0
  25. tiny_object_storage-0.1.1/src/tiny_object_storage/storage/__init__.py +0 -0
  26. tiny_object_storage-0.1.1/src/tiny_object_storage/storage/base.py +67 -0
  27. tiny_object_storage-0.1.1/src/tiny_object_storage/storage/filesystem.py +318 -0
  28. tiny_object_storage-0.1.1/src/tiny_object_storage.egg-info/PKG-INFO +228 -0
  29. tiny_object_storage-0.1.1/src/tiny_object_storage.egg-info/SOURCES.txt +38 -0
  30. tiny_object_storage-0.1.1/src/tiny_object_storage.egg-info/dependency_links.txt +1 -0
  31. tiny_object_storage-0.1.1/src/tiny_object_storage.egg-info/entry_points.txt +2 -0
  32. tiny_object_storage-0.1.1/src/tiny_object_storage.egg-info/requires.txt +16 -0
  33. tiny_object_storage-0.1.1/src/tiny_object_storage.egg-info/top_level.txt +1 -0
  34. tiny_object_storage-0.1.1/tests/test_api.py +222 -0
  35. tiny_object_storage-0.1.1/tests/test_cli.py +80 -0
  36. tiny_object_storage-0.1.1/tests/test_core.py +159 -0
  37. tiny_object_storage-0.1.1/tests/test_filesystem_storage.py +162 -0
  38. tiny_object_storage-0.1.1/tests/test_health.py +14 -0
  39. tiny_object_storage-0.1.1/tests/test_models.py +38 -0
  40. tiny_object_storage-0.1.1/tests/test_services.py +163 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ehsan Bitaraf
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,228 @@
1
+ Metadata-Version: 2.4
2
+ Name: tiny-object-storage
3
+ Version: 0.1.1
4
+ Summary: A lightweight S3-compatible object storage server for local development and learning.
5
+ Author: Ehsan Bitaraf
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/EhsanBitaraf/tiny-object-storage
8
+ Project-URL: Repository, https://github.com/EhsanBitaraf/tiny-object-storage
9
+ Project-URL: Bug Tracker, https://github.com/EhsanBitaraf/tiny-object-storage/issues
10
+ Keywords: s3,object-storage,minio,aws-s3,emulator,s3-compatible,mock,testing,fastapi
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Topic :: Software Development :: Testing
14
+ Classifier: Topic :: Internet :: WWW/HTTP
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Operating System :: OS Independent
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: fastapi<1.0.0,>=0.115.0
24
+ Requires-Dist: uvicorn[standard]<1.0.0,>=0.30.0
25
+ Requires-Dist: pydantic<3.0.0,>=2.8.0
26
+ Requires-Dist: pydantic-settings<3.0.0,>=2.4.0
27
+ Requires-Dist: python-dotenv<2.0.0,>=1.0.1
28
+ Requires-Dist: python-multipart<1.0.0,>=0.0.9
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest<9.0.0,>=8.3.0; extra == "dev"
31
+ Requires-Dist: pytest-cov<6.0.0,>=5.0.0; extra == "dev"
32
+ Requires-Dist: httpx<1.0.0,>=0.27.0; extra == "dev"
33
+ Requires-Dist: ruff<1.0.0,>=0.6.0; extra == "dev"
34
+ Requires-Dist: mypy<2.0.0,>=1.11.0; extra == "dev"
35
+ Requires-Dist: bandit<2.0.0,>=1.7.9; extra == "dev"
36
+ Requires-Dist: safety<4.0.0,>=3.2.0; extra == "dev"
37
+ Requires-Dist: pre-commit<4.0.0,>=3.8.0; extra == "dev"
38
+ Dynamic: license-file
39
+
40
+ <div align="center">
41
+ <img src="assets/logo.png" alt="tiny-object-storage logo" width="180" height="auto" />
42
+ <h1>🪣 tiny-object-storage</h1>
43
+ <p><i>A lightweight, S3-compatible object storage server for local development, testing, and learning.</i></p>
44
+
45
+ [![Python](https://img.shields.io/badge/Python-3.11+-blue.svg?logo=python&logoColor=white)](https://www.python.org)
46
+ [![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-009688.svg?logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com)
47
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
48
+ [![Mypy Strict](https://img.shields.io/badge/mypy-strict-success.svg)](https://mypy.readthedocs.io/en/stable/)
49
+ [![Security: Bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
50
+ [![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
51
+ [![Coverage: 91%](https://img.shields.io/badge/Coverage-91%25-brightgreen.svg)](https://pytest-cov.readthedocs.io/en/latest/)
52
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
53
+
54
+ </div>
55
+
56
+ ---
57
+
58
+ ## 📖 Overview
59
+
60
+ `tiny-object-storage` is a fast, minimalistic object storage server written in Python using FastAPI. It acts as a local emulator that mimics the core functionality of Amazon S3, allowing developers to test S3-integrated applications locally without relying on external cloud services or heavy containers like MinIO.
61
+
62
+ ## ✨ Features
63
+
64
+ - **S3 Compatibility**: Supports core S3 XML responses and basic HTTP methods (`GET`, `PUT`, `HEAD`, `DELETE`).
65
+ - **Bucket Management**: Create, list, and delete buckets.
66
+ - **Object Operations**: Upload, download, metadata lookup, listing (`list-type=2`), and deletion.
67
+ - **Persistent Storage**: Filesystem-based persistence with dedicated metadata and data separation.
68
+ - **Developer Experience**: Interactive Swagger UI and OpenAPI schema built-in.
69
+ - **Enterprise Code Quality**: Enforced static typing (Mypy strict), linting (Ruff), and security analysis (Bandit).
70
+ - **Flexible Configuration**: Configurable via CLI arguments, environment variables, or `.env` files.
71
+
72
+ ---
73
+
74
+ ## 🚀 Quick Start
75
+
76
+ ### Installation
77
+
78
+ **From PyPI (Recommended)**
79
+ Install the package globally or in a virtual environment using `pip`:
80
+
81
+ ```bash
82
+ pip install tiny-object-storage
83
+ ```
84
+
85
+ **From Source (Development)**
86
+ Clone the repository and install it in a virtual environment:
87
+
88
+ ```bash
89
+ git clone https://github.com/EhsanBitaraf/tiny-object-storage.git
90
+ cd tiny-object-storage
91
+ python -m venv .venv
92
+
93
+ # On Linux/macOS:
94
+ source .venv/bin/activate
95
+ # On Windows:
96
+ .venv\Scripts\activate
97
+
98
+ # Install the application and development dependencies
99
+ pip install -e ".[dev]"
100
+ ```
101
+
102
+ ### Running the Server
103
+
104
+ Start the server using the built-in CLI:
105
+
106
+ ```bash
107
+ tos-server
108
+ ```
109
+
110
+ Or run it directly with `uvicorn`:
111
+ ```bash
112
+ uvicorn tiny_object_storage.main:app --reload --host 0.0.0.0 --port 9000
113
+ ```
114
+
115
+ ---
116
+
117
+ ## ⚙️ Configuration
118
+
119
+ The server reads configuration in the following priority (highest to lowest):
120
+ 1. **Command-line arguments**
121
+ 2. **Environment variables**
122
+ 3. **`.env` file**
123
+
124
+ ### CLI Usage Examples
125
+
126
+ ```bash
127
+ # View all available options
128
+ tos-server --help
129
+
130
+ # Load from a specific .env file
131
+ tos-server --env-file .env.custom
132
+
133
+ # Override host and port
134
+ tos-server --host 127.0.0.1 --port 9001 --reload
135
+
136
+ # Customize storage directories and log level
137
+ tos-server --data-dir ./storage_data --log-dir ./logs --log-level debug
138
+ ```
139
+
140
+ ---
141
+
142
+ ## 🔌 S3 Client Compatibility
143
+
144
+ `tiny-object-storage` acts as a local emulator and has been successfully verified against the following official SDKs and tools:
145
+
146
+ - **MinIO Python SDK**
147
+ - **Boto3 (AWS SDK for Python)**
148
+ - **AWS CLI**
149
+
150
+ > **Note:** For official SDKs to interact locally, configure them with `secure=False` (or `--no-verify-ssl`) and point the `endpoint_url` to `http://127.0.0.1:9000` with any dummy credentials.
151
+
152
+ Sample scripts for verifying SDK interactions are included in the repository root (e.g., `test_boto3_sdk.py`, `test_minio_sdk.py`).
153
+
154
+ ---
155
+
156
+ ## 🛠 Testing & Code Quality
157
+
158
+ The project includes an extensive test suite built with `pytest` achieving **100% test pass rate** over 63 edge-case scenarios.
159
+
160
+ ### Running Tests
161
+
162
+ ```bash
163
+ pytest
164
+ ```
165
+ *(Optionally, use `pytest --cov=src` to generate a coverage report).*
166
+
167
+ ### Code Quality Tools
168
+
169
+ We use `pre-commit` to maintain our code quality. The suite includes:
170
+ - **Ruff**: For ultra-fast linting and code formatting.
171
+ - **Mypy**: For strict static type checking.
172
+ - **Bandit**: For security vulnerability scanning.
173
+
174
+ To run checks manually on all files:
175
+ ```bash
176
+ pre-commit run --all-files
177
+ ```
178
+
179
+ ---
180
+
181
+ ## 🌐 API Endpoints (Examples)
182
+
183
+ After starting the server, visit `/docs` for the interactive Swagger UI. Below are standard `curl` examples targeting common S3 actions:
184
+
185
+ **Health check**
186
+ ```bash
187
+ curl http://127.0.0.1:9000/health
188
+ ```
189
+
190
+ **Create a bucket**
191
+ ```bash
192
+ curl -X PUT http://127.0.0.1:9000/photos
193
+ ```
194
+
195
+ **Upload an object**
196
+ ```bash
197
+ curl -X PUT --data-binary @"cat.jpg" http://127.0.0.1:9000/photos/cat.jpg
198
+ ```
199
+
200
+ **Download an object**
201
+ ```bash
202
+ curl http://127.0.0.1:9000/photos/cat.jpg --output cat.jpg
203
+ ```
204
+
205
+ **List objects (S3 Format)**
206
+ ```bash
207
+ curl "http://127.0.0.1:9000/photos?list-type=2"
208
+ ```
209
+
210
+ **Debug endpoints (JSON format)**
211
+ ```bash
212
+ curl http://127.0.0.1:9000/_debug/buckets
213
+ curl http://127.0.0.1:9000/_debug/photos
214
+ ```
215
+
216
+ ---
217
+
218
+ ## 🤝 Contributing
219
+
220
+ Contributions are welcome and highly appreciated! Please review our [Contributing Guidelines](CONTRIBUTING.md) to get started. By participating in this project, you agree to abide by the [Code of Conduct](.github/CODE_OF_CONDUCT.md).
221
+
222
+ ## 🔒 Security
223
+
224
+ For instructions on reporting security vulnerabilities, please refer to our [Security Policy](SECURITY.md).
225
+
226
+ ## 📜 License
227
+
228
+ This project is licensed under the MIT License - see the `LICENSE` file for details.
@@ -0,0 +1,189 @@
1
+ <div align="center">
2
+ <img src="assets/logo.png" alt="tiny-object-storage logo" width="180" height="auto" />
3
+ <h1>🪣 tiny-object-storage</h1>
4
+ <p><i>A lightweight, S3-compatible object storage server for local development, testing, and learning.</i></p>
5
+
6
+ [![Python](https://img.shields.io/badge/Python-3.11+-blue.svg?logo=python&logoColor=white)](https://www.python.org)
7
+ [![FastAPI](https://img.shields.io/badge/FastAPI-0.115+-009688.svg?logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com)
8
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
9
+ [![Mypy Strict](https://img.shields.io/badge/mypy-strict-success.svg)](https://mypy.readthedocs.io/en/stable/)
10
+ [![Security: Bandit](https://img.shields.io/badge/security-bandit-yellow.svg)](https://github.com/PyCQA/bandit)
11
+ [![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
12
+ [![Coverage: 91%](https://img.shields.io/badge/Coverage-91%25-brightgreen.svg)](https://pytest-cov.readthedocs.io/en/latest/)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## 📖 Overview
20
+
21
+ `tiny-object-storage` is a fast, minimalistic object storage server written in Python using FastAPI. It acts as a local emulator that mimics the core functionality of Amazon S3, allowing developers to test S3-integrated applications locally without relying on external cloud services or heavy containers like MinIO.
22
+
23
+ ## ✨ Features
24
+
25
+ - **S3 Compatibility**: Supports core S3 XML responses and basic HTTP methods (`GET`, `PUT`, `HEAD`, `DELETE`).
26
+ - **Bucket Management**: Create, list, and delete buckets.
27
+ - **Object Operations**: Upload, download, metadata lookup, listing (`list-type=2`), and deletion.
28
+ - **Persistent Storage**: Filesystem-based persistence with dedicated metadata and data separation.
29
+ - **Developer Experience**: Interactive Swagger UI and OpenAPI schema built-in.
30
+ - **Enterprise Code Quality**: Enforced static typing (Mypy strict), linting (Ruff), and security analysis (Bandit).
31
+ - **Flexible Configuration**: Configurable via CLI arguments, environment variables, or `.env` files.
32
+
33
+ ---
34
+
35
+ ## 🚀 Quick Start
36
+
37
+ ### Installation
38
+
39
+ **From PyPI (Recommended)**
40
+ Install the package globally or in a virtual environment using `pip`:
41
+
42
+ ```bash
43
+ pip install tiny-object-storage
44
+ ```
45
+
46
+ **From Source (Development)**
47
+ Clone the repository and install it in a virtual environment:
48
+
49
+ ```bash
50
+ git clone https://github.com/EhsanBitaraf/tiny-object-storage.git
51
+ cd tiny-object-storage
52
+ python -m venv .venv
53
+
54
+ # On Linux/macOS:
55
+ source .venv/bin/activate
56
+ # On Windows:
57
+ .venv\Scripts\activate
58
+
59
+ # Install the application and development dependencies
60
+ pip install -e ".[dev]"
61
+ ```
62
+
63
+ ### Running the Server
64
+
65
+ Start the server using the built-in CLI:
66
+
67
+ ```bash
68
+ tos-server
69
+ ```
70
+
71
+ Or run it directly with `uvicorn`:
72
+ ```bash
73
+ uvicorn tiny_object_storage.main:app --reload --host 0.0.0.0 --port 9000
74
+ ```
75
+
76
+ ---
77
+
78
+ ## ⚙️ Configuration
79
+
80
+ The server reads configuration in the following priority (highest to lowest):
81
+ 1. **Command-line arguments**
82
+ 2. **Environment variables**
83
+ 3. **`.env` file**
84
+
85
+ ### CLI Usage Examples
86
+
87
+ ```bash
88
+ # View all available options
89
+ tos-server --help
90
+
91
+ # Load from a specific .env file
92
+ tos-server --env-file .env.custom
93
+
94
+ # Override host and port
95
+ tos-server --host 127.0.0.1 --port 9001 --reload
96
+
97
+ # Customize storage directories and log level
98
+ tos-server --data-dir ./storage_data --log-dir ./logs --log-level debug
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 🔌 S3 Client Compatibility
104
+
105
+ `tiny-object-storage` acts as a local emulator and has been successfully verified against the following official SDKs and tools:
106
+
107
+ - **MinIO Python SDK**
108
+ - **Boto3 (AWS SDK for Python)**
109
+ - **AWS CLI**
110
+
111
+ > **Note:** For official SDKs to interact locally, configure them with `secure=False` (or `--no-verify-ssl`) and point the `endpoint_url` to `http://127.0.0.1:9000` with any dummy credentials.
112
+
113
+ Sample scripts for verifying SDK interactions are included in the repository root (e.g., `test_boto3_sdk.py`, `test_minio_sdk.py`).
114
+
115
+ ---
116
+
117
+ ## 🛠 Testing & Code Quality
118
+
119
+ The project includes an extensive test suite built with `pytest` achieving **100% test pass rate** over 63 edge-case scenarios.
120
+
121
+ ### Running Tests
122
+
123
+ ```bash
124
+ pytest
125
+ ```
126
+ *(Optionally, use `pytest --cov=src` to generate a coverage report).*
127
+
128
+ ### Code Quality Tools
129
+
130
+ We use `pre-commit` to maintain our code quality. The suite includes:
131
+ - **Ruff**: For ultra-fast linting and code formatting.
132
+ - **Mypy**: For strict static type checking.
133
+ - **Bandit**: For security vulnerability scanning.
134
+
135
+ To run checks manually on all files:
136
+ ```bash
137
+ pre-commit run --all-files
138
+ ```
139
+
140
+ ---
141
+
142
+ ## 🌐 API Endpoints (Examples)
143
+
144
+ After starting the server, visit `/docs` for the interactive Swagger UI. Below are standard `curl` examples targeting common S3 actions:
145
+
146
+ **Health check**
147
+ ```bash
148
+ curl http://127.0.0.1:9000/health
149
+ ```
150
+
151
+ **Create a bucket**
152
+ ```bash
153
+ curl -X PUT http://127.0.0.1:9000/photos
154
+ ```
155
+
156
+ **Upload an object**
157
+ ```bash
158
+ curl -X PUT --data-binary @"cat.jpg" http://127.0.0.1:9000/photos/cat.jpg
159
+ ```
160
+
161
+ **Download an object**
162
+ ```bash
163
+ curl http://127.0.0.1:9000/photos/cat.jpg --output cat.jpg
164
+ ```
165
+
166
+ **List objects (S3 Format)**
167
+ ```bash
168
+ curl "http://127.0.0.1:9000/photos?list-type=2"
169
+ ```
170
+
171
+ **Debug endpoints (JSON format)**
172
+ ```bash
173
+ curl http://127.0.0.1:9000/_debug/buckets
174
+ curl http://127.0.0.1:9000/_debug/photos
175
+ ```
176
+
177
+ ---
178
+
179
+ ## 🤝 Contributing
180
+
181
+ Contributions are welcome and highly appreciated! Please review our [Contributing Guidelines](CONTRIBUTING.md) to get started. By participating in this project, you agree to abide by the [Code of Conduct](.github/CODE_OF_CONDUCT.md).
182
+
183
+ ## 🔒 Security
184
+
185
+ For instructions on reporting security vulnerabilities, please refer to our [Security Policy](SECURITY.md).
186
+
187
+ ## 📜 License
188
+
189
+ This project is licensed under the MIT License - see the `LICENSE` file for details.
@@ -0,0 +1,110 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "tiny-object-storage"
7
+ version = "0.1.1"
8
+ description = "A lightweight S3-compatible object storage server for local development and learning."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Ehsan Bitaraf" }
14
+ ]
15
+ keywords = [
16
+ "s3",
17
+ "object-storage",
18
+ "minio",
19
+ "aws-s3",
20
+ "emulator",
21
+ "s3-compatible",
22
+ "mock",
23
+ "testing",
24
+ "fastapi"
25
+ ]
26
+ classifiers = [
27
+ "Development Status :: 4 - Beta",
28
+ "Intended Audience :: Developers",
29
+ "Topic :: Software Development :: Testing",
30
+ "Topic :: Internet :: WWW/HTTP",
31
+ "License :: OSI Approved :: MIT License",
32
+ "Programming Language :: Python :: 3",
33
+ "Programming Language :: Python :: 3.11",
34
+ "Programming Language :: Python :: 3.12",
35
+ "Operating System :: OS Independent",
36
+ ]
37
+ dependencies = [
38
+ "fastapi>=0.115.0,<1.0.0",
39
+ "uvicorn[standard]>=0.30.0,<1.0.0",
40
+ "pydantic>=2.8.0,<3.0.0",
41
+ "pydantic-settings>=2.4.0,<3.0.0",
42
+ "python-dotenv>=1.0.1,<2.0.0",
43
+ "python-multipart>=0.0.9,<1.0.0"
44
+ ]
45
+
46
+ [project.urls]
47
+ Homepage = "https://github.com/EhsanBitaraf/tiny-object-storage"
48
+ Repository = "https://github.com/EhsanBitaraf/tiny-object-storage"
49
+ "Bug Tracker" = "https://github.com/EhsanBitaraf/tiny-object-storage/issues"
50
+
51
+ [project.optional-dependencies]
52
+ dev = [
53
+ "pytest>=8.3.0,<9.0.0",
54
+ "pytest-cov>=5.0.0,<6.0.0",
55
+ "httpx>=0.27.0,<1.0.0",
56
+ "ruff>=0.6.0,<1.0.0",
57
+ "mypy>=1.11.0,<2.0.0",
58
+ "bandit>=1.7.9,<2.0.0",
59
+ "safety>=3.2.0,<4.0.0",
60
+ "pre-commit>=3.8.0,<4.0.0"
61
+ ]
62
+
63
+ [project.scripts]
64
+ tos-server = "tiny_object_storage.cli:main"
65
+
66
+ [tool.setuptools]
67
+ package-dir = {"" = "src"}
68
+
69
+ [tool.setuptools.packages.find]
70
+ where = ["src"]
71
+
72
+ [tool.pytest.ini_options]
73
+ pythonpath = ["src"]
74
+ testpaths = ["tests"]
75
+
76
+ [tool.ruff]
77
+ line-length = 100
78
+ target-version = "py311"
79
+
80
+ [tool.ruff.lint]
81
+ select = [
82
+ "E", # pycodestyle errors
83
+ "W", # pycodestyle warnings
84
+ "F", # pyflakes
85
+ "I", # isort
86
+ "UP", # pyupgrade
87
+ "B", # flake8-bugbear
88
+ "C4", # flake8-comprehensions
89
+ "SIM",# flake8-simplify
90
+ ]
91
+ ignore = []
92
+
93
+ [tool.ruff.format]
94
+ quote-style = "double"
95
+ indent-style = "space"
96
+ skip-magic-trailing-comma = false
97
+ line-ending = "auto"
98
+
99
+ [tool.mypy]
100
+ python_version = "3.11"
101
+ strict = true
102
+ warn_return_any = true
103
+ warn_unused_configs = true
104
+ ignore_missing_imports = true
105
+ disallow_untyped_decorators = false
106
+ exclude = ["venv", ".venv"]
107
+
108
+ [tool.bandit]
109
+ exclude_dirs = ["tests", "venv", ".venv"]
110
+ skips = ["B104", "B405", "B324", "B404", "B603", "B105", "B106"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ import importlib.metadata
2
+
3
+ try:
4
+ __version__ = importlib.metadata.version("tiny-object-storage")
5
+ except importlib.metadata.PackageNotFoundError:
6
+ __version__ = "unknown"
7
+
8
+ __all__ = ["__version__"]
@@ -0,0 +1,114 @@
1
+ from fastapi import APIRouter, Request, Response, status
2
+ from fastapi.responses import Response as FastAPIResponse
3
+
4
+ from tiny_object_storage.core.utils import build_list_buckets_xml
5
+ from tiny_object_storage.models.bucket import BucketInfo
6
+ from tiny_object_storage.models.responses import (
7
+ BucketCreatedResponse,
8
+ BucketsListResponse,
9
+ ErrorResponse,
10
+ )
11
+
12
+ router = APIRouter(tags=["buckets"])
13
+
14
+
15
+ @router.get(
16
+ "/",
17
+ responses={
18
+ 200: {
19
+ "description": "Buckets returned in S3-style XML.",
20
+ "content": {"application/xml": {}},
21
+ },
22
+ 500: {"model": ErrorResponse, "description": "Internal server error."},
23
+ },
24
+ summary="List buckets",
25
+ description="Return all available buckets as a minimal S3-compatible XML response.",
26
+ )
27
+ def list_buckets(request: Request) -> FastAPIResponse:
28
+ # Return all buckets from the service layer as XML.
29
+ bucket_service = request.app.state.bucket_service
30
+ buckets = bucket_service.list_buckets()
31
+ xml_payload = build_list_buckets_xml(buckets)
32
+ return FastAPIResponse(content=xml_payload, media_type="application/xml")
33
+
34
+
35
+ @router.get(
36
+ "/_debug/buckets",
37
+ response_model=BucketsListResponse,
38
+ include_in_schema=True,
39
+ summary="List buckets as JSON",
40
+ description="Return all available buckets in JSON format for debugging and development.",
41
+ responses={
42
+ 500: {"model": ErrorResponse, "description": "Internal server error."},
43
+ },
44
+ )
45
+ def list_buckets_json(request: Request) -> BucketsListResponse:
46
+ # Return all buckets from the service layer as JSON.
47
+ bucket_service = request.app.state.bucket_service
48
+ buckets = bucket_service.list_buckets()
49
+ return BucketsListResponse(buckets=[BucketInfo(**bucket) for bucket in buckets])
50
+
51
+
52
+ @router.put(
53
+ "/{bucket_name}",
54
+ response_model=BucketCreatedResponse,
55
+ status_code=status.HTTP_200_OK,
56
+ summary="Create bucket",
57
+ description="Create a new bucket using an S3-style path.",
58
+ responses={
59
+ 200: {"description": "Bucket created."},
60
+ 400: {"model": ErrorResponse, "description": "Invalid bucket name."},
61
+ 409: {"model": ErrorResponse, "description": "Bucket already exists."},
62
+ 500: {"model": ErrorResponse, "description": "Internal server error."},
63
+ },
64
+ )
65
+ def create_bucket(bucket_name: str, request: Request) -> BucketCreatedResponse:
66
+ # Create a new bucket and return its metadata.
67
+ bucket_service = request.app.state.bucket_service
68
+ bucket = bucket_service.create_bucket(bucket_name=bucket_name)
69
+ return BucketCreatedResponse(
70
+ message="Bucket created successfully.",
71
+ bucket=BucketInfo(**bucket),
72
+ )
73
+
74
+
75
+ @router.delete(
76
+ "/{bucket_name}",
77
+ status_code=status.HTTP_204_NO_CONTENT,
78
+ summary="Delete bucket",
79
+ description="Delete an existing bucket. The bucket must be empty.",
80
+ responses={
81
+ 204: {"description": "Bucket deleted."},
82
+ 400: {"model": ErrorResponse, "description": "Invalid bucket name."},
83
+ 404: {"model": ErrorResponse, "description": "Bucket not found."},
84
+ 409: {"model": ErrorResponse, "description": "Bucket is not empty."},
85
+ 500: {"model": ErrorResponse, "description": "Internal server error."},
86
+ },
87
+ )
88
+ def delete_bucket(bucket_name: str, request: Request) -> Response:
89
+ # Delete the requested bucket.
90
+ bucket_service = request.app.state.bucket_service
91
+ bucket_service.delete_bucket(bucket_name=bucket_name)
92
+ return Response(status_code=status.HTTP_204_NO_CONTENT)
93
+
94
+
95
+ @router.head(
96
+ "/{bucket_name}",
97
+ status_code=status.HTTP_200_OK,
98
+ summary="Head bucket",
99
+ description="Determine if a bucket exists and if you have permission to access it.",
100
+ responses={
101
+ 200: {"description": "Bucket exists."},
102
+ 400: {"model": ErrorResponse, "description": "Invalid bucket name."},
103
+ 404: {"model": ErrorResponse, "description": "Bucket not found."},
104
+ 500: {"model": ErrorResponse, "description": "Internal server error."},
105
+ },
106
+ )
107
+ def head_bucket(bucket_name: str, request: Request) -> Response:
108
+ # Check if a bucket exists. Boto3 relies on this to verify buckets before acting.
109
+ bucket_service = request.app.state.bucket_service
110
+ from tiny_object_storage.core.errors import BucketNotFoundError
111
+
112
+ if not bucket_service.bucket_exists(bucket_name):
113
+ raise BucketNotFoundError(f"Bucket '{bucket_name}' does not exist.")
114
+ return Response(status_code=status.HTTP_200_OK)