fastapi-file-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 (36) hide show
  1. fastapi_file_storage-0.1.1/.gitignore +16 -0
  2. fastapi_file_storage-0.1.1/PKG-INFO +400 -0
  3. fastapi_file_storage-0.1.1/README.md +371 -0
  4. fastapi_file_storage-0.1.1/RELEASE.md +121 -0
  5. fastapi_file_storage-0.1.1/pyproject.toml +50 -0
  6. fastapi_file_storage-0.1.1/src/fastapi_storage/__init__.py +5 -0
  7. fastapi_file_storage-0.1.1/src/fastapi_storage/adapters/__init__.py +14 -0
  8. fastapi_file_storage-0.1.1/src/fastapi_storage/adapters/base.py +113 -0
  9. fastapi_file_storage-0.1.1/src/fastapi_storage/adapters/local.py +67 -0
  10. fastapi_file_storage-0.1.1/src/fastapi_storage/adapters/minio.py +101 -0
  11. fastapi_file_storage-0.1.1/src/fastapi_storage/adapters/obs.py +85 -0
  12. fastapi_file_storage-0.1.1/src/fastapi_storage/adapters/oss.py +78 -0
  13. fastapi_file_storage-0.1.1/src/fastapi_storage/cli.py +84 -0
  14. fastapi_file_storage-0.1.1/src/fastapi_storage/config/__init__.py +23 -0
  15. fastapi_file_storage-0.1.1/src/fastapi_storage/config/filesystems.py +53 -0
  16. fastapi_file_storage-0.1.1/src/fastapi_storage/config/loader.py +37 -0
  17. fastapi_file_storage-0.1.1/src/fastapi_storage/config/models.py +68 -0
  18. fastapi_file_storage-0.1.1/src/fastapi_storage/exceptions.py +22 -0
  19. fastapi_file_storage-0.1.1/src/fastapi_storage/facade.py +55 -0
  20. fastapi_file_storage-0.1.1/src/fastapi_storage/integrations/__init__.py +0 -0
  21. fastapi_file_storage-0.1.1/src/fastapi_storage/integrations/fastapi.py +23 -0
  22. fastapi_file_storage-0.1.1/src/fastapi_storage/manager.py +91 -0
  23. fastapi_file_storage-0.1.1/src/fastapi_storage/registry.py +28 -0
  24. fastapi_file_storage-0.1.1/src/fastapi_storage/scaffold/__init__.py +16 -0
  25. fastapi_file_storage-0.1.1/src/fastapi_storage/scaffold/generator.py +77 -0
  26. fastapi_file_storage-0.1.1/src/fastapi_storage/scaffold/templates.py +93 -0
  27. fastapi_file_storage-0.1.1/src/fastapi_storage/types.py +19 -0
  28. fastapi_file_storage-0.1.1/tests/contract/test_local_adapter_contract.py +29 -0
  29. fastapi_file_storage-0.1.1/tests/integration/test_storage_local_integration.py +19 -0
  30. fastapi_file_storage-0.1.1/tests/unit/test_adapter_async.py +44 -0
  31. fastapi_file_storage-0.1.1/tests/unit/test_cli.py +149 -0
  32. fastapi_file_storage-0.1.1/tests/unit/test_config_models.py +47 -0
  33. fastapi_file_storage-0.1.1/tests/unit/test_filesystems_config.py +9 -0
  34. fastapi_file_storage-0.1.1/tests/unit/test_manager.py +82 -0
  35. fastapi_file_storage-0.1.1/tests/unit/test_path_prefixer.py +18 -0
  36. fastapi_file_storage-0.1.1/tests/unit/test_scaffold_generator.py +126 -0
@@ -0,0 +1,16 @@
1
+ # Python cache
2
+ __pycache__/
3
+ *.py[cod]
4
+
5
+ # Build artifacts
6
+ build/
7
+ dist/
8
+ *.egg-info/
9
+
10
+ # Test cache
11
+ .pytest_cache/
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ .env
@@ -0,0 +1,400 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-file-storage
3
+ Version: 0.1.1
4
+ Summary: Laravel-inspired filesystem storage manager for FastAPI
5
+ Author: xjaqil
6
+ Keywords: fastapi,filesystem,minio,obs,oss,storage
7
+ Classifier: Framework :: FastAPI
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.10
12
+ Requires-Dist: anyio>=4.4.0
13
+ Requires-Dist: pydantic-settings>=2.3.0
14
+ Requires-Dist: pydantic>=2.8.0
15
+ Provides-Extra: all
16
+ Requires-Dist: esdk-obs-python>=3.24.0; extra == 'all'
17
+ Requires-Dist: minio>=7.2.0; extra == 'all'
18
+ Requires-Dist: oss2>=2.18.0; extra == 'all'
19
+ Provides-Extra: minio
20
+ Requires-Dist: minio>=7.2.0; extra == 'minio'
21
+ Provides-Extra: obs
22
+ Requires-Dist: esdk-obs-python>=3.24.0; extra == 'obs'
23
+ Provides-Extra: oss
24
+ Requires-Dist: oss2>=2.18.0; extra == 'oss'
25
+ Provides-Extra: test
26
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'test'
27
+ Requires-Dist: pytest>=8.2.0; extra == 'test'
28
+ Description-Content-Type: text/markdown
29
+
30
+ # fastapi-storage
31
+
32
+ Laravel 风格的 FastAPI 文件存储扩展包,支持多磁盘(disk)管理、统一文件操作接口,以及可扩展自定义驱动。
33
+
34
+ ## 特性
35
+
36
+ - Laravel 风格 API:`Storage.disk("public").put(...)`
37
+ - 多驱动支持:`local`、`minio`、`oss`、`obs`
38
+ - 可配置默认磁盘和云磁盘:`default` / `cloud`
39
+ - 支持自定义驱动:`Storage.extend(...)`
40
+ - 支持自定义驱动配置模型:`Storage.register_config_model(...)`
41
+ - FastAPI 集成:`init_storage` + `get_storage`
42
+ - 安装后 30 秒可用:`fastapi-storage init` + `init_storage(app, filesystems)`
43
+ - 同步 + 异步方法(如 `put/aput`)
44
+
45
+ ## 安装
46
+
47
+ ### 基础安装
48
+
49
+ ```bash
50
+ pip install fastapi-file-storage
51
+ ```
52
+
53
+ ### 按需安装驱动依赖
54
+
55
+ ```bash
56
+ pip install "fastapi-file-storage[minio]"
57
+ pip install "fastapi-file-storage[oss]"
58
+ pip install "fastapi-file-storage[obs]"
59
+ pip install "fastapi-file-storage[all]"
60
+ ```
61
+
62
+ ### 开发与测试依赖
63
+
64
+ ```bash
65
+ pip install "fastapi-file-storage[test]"
66
+ ```
67
+
68
+ ## 30 秒上手(最短路径)
69
+
70
+ ```bash
71
+ pip install fastapi-file-storage
72
+ fastapi-storage init
73
+ fastapi-storage storage:link
74
+ ```
75
+
76
+ ```python
77
+ from fastapi import FastAPI
78
+ from fastapi_storage.config.filesystems import filesystems
79
+ from fastapi_storage.integrations.fastapi import init_storage
80
+
81
+ app = FastAPI()
82
+ init_storage(app, filesystems)
83
+
84
+ # 现在即可使用 local 磁盘
85
+ # storage.disk("local").put("demo.txt", "hello")
86
+ ```
87
+
88
+ 如果你希望完全手写配置,可使用下面的方式:
89
+
90
+ ```python
91
+ from fastapi_storage import Storage
92
+
93
+ Storage.configure(
94
+ {
95
+ "default": "local",
96
+ "cloud": "minio",
97
+ "disks": {
98
+ "local": {
99
+ "driver": "local",
100
+ "root": "storage/app",
101
+ "url": "/storage",
102
+ },
103
+ "minio": {
104
+ "driver": "minio",
105
+ "endpoint": "127.0.0.1:9000",
106
+ "access_key": "minioadmin",
107
+ "secret_key": "minioadmin",
108
+ "bucket": "app-bucket",
109
+ "secure": False,
110
+ },
111
+ },
112
+ }
113
+ )
114
+
115
+ Storage.disk("local").put("avatars/a.txt", "hello")
116
+ content = Storage.disk("local").get("avatars/a.txt")
117
+ print(content.decode())
118
+ ```
119
+
120
+ ## Laravel 风格 filesystems(安装后即用)
121
+
122
+ 安装后可直接使用包内默认配置:
123
+
124
+ ```python
125
+ from fastapi_storage.config.filesystems import filesystems
126
+ ```
127
+
128
+ `init_storage` 支持直接传 `StorageSettings`(即 `filesystems`)、`dict` 或 `None`。
129
+
130
+ ## 初始化脚手架(生成配置文件)
131
+
132
+ 在业务项目根目录执行:
133
+
134
+ ```bash
135
+ fastapi-storage init
136
+ ```
137
+
138
+ 默认生成:
139
+
140
+ - `src/config/filesystems.py`
141
+ - `.env.example`
142
+
143
+ 常用命令:
144
+
145
+ ```bash
146
+ # 已存在时覆盖
147
+ fastapi-storage init --force
148
+
149
+ # 只生成 .env.example
150
+ fastapi-storage init --skip-config
151
+
152
+ # 自定义生成路径
153
+ fastapi-storage init --config-path src/config/filesystems.py --env-path .env.example
154
+ ```
155
+
156
+ ## storage:link(创建公开软链接)
157
+
158
+ Laravel 风格软链接命令:
159
+
160
+ ```bash
161
+ fastapi-storage storage:link
162
+ # 等价别名
163
+ fastapi-storage link
164
+ ```
165
+
166
+ 默认行为:
167
+
168
+ - 创建 `public/storage` -> `storage/app/public`
169
+ - 若链接已存在则跳过(`skipped`)
170
+ - `--force` 可覆盖已存在的文件或符号链接
171
+ - 若 `public/storage` 已是目录,返回冲突提示(避免误删目录)
172
+
173
+ 可选参数:
174
+
175
+ ```bash
176
+ fastapi-storage storage:link --force
177
+ fastapi-storage storage:link --link public/storage --target storage/app/public
178
+ ```
179
+
180
+ ## 配置结构
181
+
182
+ `Storage.configure(...)` 或 `FilesystemManager(settings=...)` 接收如下结构:
183
+
184
+ ```python
185
+ {
186
+ "default": "local",
187
+ "cloud": "minio", # 可选,不填时回退 default
188
+ "disks": {
189
+ "local": {"driver": "local", "root": "storage/app", "url": "/storage"},
190
+ "public": {"driver": "local", "root": "storage/app/public", "url": "/storage"},
191
+ "minio": {
192
+ "driver": "minio",
193
+ "endpoint": "127.0.0.1:9000",
194
+ "access_key": "...",
195
+ "secret_key": "...",
196
+ "bucket": "...",
197
+ "secure": False,
198
+ },
199
+ "oss": {
200
+ "driver": "oss",
201
+ "endpoint": "oss-cn-hangzhou.aliyuncs.com",
202
+ "access_key": "...",
203
+ "secret_key": "...",
204
+ "bucket": "...",
205
+ "is_cname": False,
206
+ },
207
+ "obs": {
208
+ "driver": "obs",
209
+ "server": "obs.cn-east-3.myhuaweicloud.com",
210
+ "access_key_id": "...",
211
+ "secret_access_key": "...",
212
+ "bucket": "...",
213
+ },
214
+ },
215
+ }
216
+ ```
217
+
218
+ ## 环境变量配置(Pydantic Settings)
219
+
220
+ 支持 `STORAGE_` 前缀与双下划线嵌套。`fastapi-storage init` 生成的 `.env.example` 已包含 local/public/minio/oss/obs 示例,可直接复制修改。
221
+
222
+ 最小可用 local 示例:
223
+
224
+ ```bash
225
+ STORAGE_DEFAULT=local
226
+ STORAGE_DISKS__LOCAL__DRIVER=local
227
+ STORAGE_DISKS__LOCAL__ROOT=storage/app
228
+ STORAGE_DISKS__LOCAL__URL=/storage
229
+ ```
230
+
231
+ MinIO / OSS / OBS 示例字段(节选):
232
+
233
+ ```bash
234
+ STORAGE_DISKS__MINIO__DRIVER=minio
235
+ STORAGE_DISKS__MINIO__ENDPOINT=127.0.0.1:9000
236
+ STORAGE_DISKS__MINIO__ACCESS_KEY=minioadmin
237
+ STORAGE_DISKS__MINIO__SECRET_KEY=minioadmin
238
+ STORAGE_DISKS__MINIO__BUCKET=app-bucket
239
+
240
+ STORAGE_DISKS__OSS__DRIVER=oss
241
+ STORAGE_DISKS__OSS__ENDPOINT=oss-cn-hangzhou.aliyuncs.com
242
+ STORAGE_DISKS__OSS__ACCESS_KEY=your-access-key
243
+ STORAGE_DISKS__OSS__SECRET_KEY=your-secret-key
244
+ STORAGE_DISKS__OSS__BUCKET=your-bucket
245
+
246
+ STORAGE_DISKS__OBS__DRIVER=obs
247
+ STORAGE_DISKS__OBS__SERVER=obs.cn-east-3.myhuaweicloud.com
248
+ STORAGE_DISKS__OBS__ACCESS_KEY_ID=your-access-key-id
249
+ STORAGE_DISKS__OBS__SECRET_ACCESS_KEY=your-secret-access-key
250
+ STORAGE_DISKS__OBS__BUCKET=your-bucket
251
+ ```
252
+
253
+ ## API 概览
254
+
255
+ ### 门面 API
256
+
257
+ - `Storage.configure(settings | manager)`
258
+ - `Storage.disk(name=None)`
259
+ - `Storage.drive(name=None)`
260
+ - `Storage.cloud()`
261
+ - `Storage.extend(driver, factory)`
262
+ - `Storage.register_config_model(driver, model)`
263
+ - `Storage.build(config)`(构建临时磁盘)
264
+
265
+ ### 适配器通用方法
266
+
267
+ - `put(path, content)` / `aput(...)`
268
+ - `get(path)` / `aget(...)`
269
+ - `exists(path)` / `aexists(...)`
270
+ - `delete(path | [paths])` / `adelete(...)`
271
+ - `url(path)`
272
+ - `size(path)` / `asize(...)`
273
+ - `copy(src, dst)` / `acopy(...)`
274
+ - `move(src, dst)` / `amove(...)`
275
+
276
+ ## FastAPI 集成
277
+
278
+ ```python
279
+ from fastapi import Depends, FastAPI
280
+ from fastapi_storage.config.filesystems import filesystems
281
+ from fastapi_storage.integrations.fastapi import get_storage, init_storage
282
+ from fastapi_storage.manager import FilesystemManager
283
+
284
+ app = FastAPI()
285
+
286
+ # 支持 StorageSettings / dict / None
287
+ init_storage(app, filesystems)
288
+
289
+ @app.post("/upload")
290
+ def upload(storage: FilesystemManager = Depends(get_storage)):
291
+ storage.disk("local").put("demo.txt", "hello")
292
+ return {"ok": True}
293
+ ```
294
+
295
+ ## FastAPI 高并发推荐用法(async)
296
+
297
+ 在高并发场景下,建议在 `async def` 路由中使用异步方法(`aput/aget/...`),避免阻塞事件循环:
298
+
299
+ ```python
300
+ from fastapi import Depends, FastAPI
301
+ from fastapi_storage.integrations.fastapi import get_storage, init_storage
302
+ from fastapi_storage.manager import FilesystemManager
303
+
304
+ app = FastAPI()
305
+ init_storage(app)
306
+
307
+
308
+ @app.post("/upload-async")
309
+ async def upload_async(storage: FilesystemManager = Depends(get_storage)):
310
+ disk = storage.disk("local")
311
+ await disk.aput("demo.txt", "hello", content_type="text/plain")
312
+ data = await disk.aget("demo.txt")
313
+ exists = await disk.aexists("demo.txt")
314
+ return {
315
+ "ok": True,
316
+ "exists": exists,
317
+ "content": data.decode("utf-8"),
318
+ }
319
+ ```
320
+
321
+ 说明:
322
+
323
+ - 同步方法:`put/get/exists/delete/...`
324
+ - 异步方法:`aput/aget/aexists/adelete/...`
325
+ - 异步方法适合 FastAPI 并发接口;同步方法适合同步脚本或后台任务。
326
+
327
+ ## 自定义驱动示例
328
+
329
+ ```python
330
+ from pydantic import BaseModel
331
+ from fastapi_storage import Storage
332
+
333
+
334
+ class MemoryDiskConfig(BaseModel):
335
+ driver: str = "memory"
336
+
337
+
338
+ class MemoryAdapter:
339
+ def __init__(self, config: MemoryDiskConfig):
340
+ self.config = config
341
+ self.data = {}
342
+
343
+ def put(self, path, content, **kwargs):
344
+ self.data[path] = content if isinstance(content, bytes) else str(content).encode()
345
+ return True
346
+
347
+ def get(self, path):
348
+ return self.data[path]
349
+
350
+ def exists(self, path):
351
+ return path in self.data
352
+
353
+ def delete(self, paths):
354
+ targets = [paths] if isinstance(paths, str) else paths
355
+ for p in targets:
356
+ self.data.pop(p, None)
357
+ return True
358
+
359
+ def url(self, path):
360
+ return f"memory://{path}"
361
+
362
+ def size(self, path):
363
+ return len(self.data[path])
364
+
365
+ def copy(self, src, dst):
366
+ self.data[dst] = self.data[src]
367
+ return True
368
+
369
+ def move(self, src, dst):
370
+ self.data[dst] = self.data[src]
371
+ del self.data[src]
372
+ return True
373
+
374
+
375
+ Storage.configure(
376
+ {
377
+ "default": "memory_disk",
378
+ "disks": {
379
+ "memory_disk": {"driver": "memory"},
380
+ },
381
+ }
382
+ )
383
+
384
+ Storage.register_config_model("memory", MemoryDiskConfig)
385
+ Storage.extend("memory", lambda config: MemoryAdapter(config))
386
+
387
+ Storage.disk("memory_disk").put("a.txt", "hello")
388
+ print(Storage.disk("memory_disk").get("a.txt"))
389
+ ```
390
+
391
+ ## 本地开发
392
+
393
+ ```bash
394
+ pip install -e ".[test]"
395
+ python3 -m pytest tests
396
+ ```
397
+
398
+ ## 发布流程
399
+
400
+ 完整发布步骤见 [RELEASE.md](./RELEASE.md)。