tuspyserver 2.2.0__tar.gz → 2.2.2__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.
- {tuspyserver-2.2.0/tuspyserver.egg-info → tuspyserver-2.2.2}/PKG-INFO +35 -18
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/README.md +33 -3
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/setup.py +1 -1
- {tuspyserver-2.2.0 → tuspyserver-2.2.2/tuspyserver.egg-info}/PKG-INFO +35 -18
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tusserver/tus.py +13 -5
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/LICENSE +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/setup.cfg +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tuspyserver.egg-info/SOURCES.txt +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tuspyserver.egg-info/dependency_links.txt +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tuspyserver.egg-info/requires.txt +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tuspyserver.egg-info/top_level.txt +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tusserver/__init__.py +0 -0
- {tuspyserver-2.2.0 → tuspyserver-2.2.2}/tusserver/metadata.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: tuspyserver
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: TUS py protocol implementation in FastAPI
|
|
5
5
|
Home-page: https://github.com/edihasaj/tuspy-fast-api
|
|
6
6
|
Author: Edi Hasaj
|
|
@@ -15,19 +15,6 @@ Classifier: Programming Language :: Python
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: fastapi>=0.110.0
|
|
19
|
-
Requires-Dist: pydantic>=2.6.2
|
|
20
|
-
Dynamic: author
|
|
21
|
-
Dynamic: author-email
|
|
22
|
-
Dynamic: classifier
|
|
23
|
-
Dynamic: description
|
|
24
|
-
Dynamic: description-content-type
|
|
25
|
-
Dynamic: home-page
|
|
26
|
-
Dynamic: license
|
|
27
|
-
Dynamic: license-file
|
|
28
|
-
Dynamic: platform
|
|
29
|
-
Dynamic: requires-dist
|
|
30
|
-
Dynamic: summary
|
|
31
18
|
|
|
32
19
|
# FastAPI Tus
|
|
33
20
|
|
|
@@ -50,8 +37,8 @@ pip install tuspyserver
|
|
|
50
37
|
Or install directly from source:
|
|
51
38
|
|
|
52
39
|
```bash
|
|
53
|
-
git clone https://github.com/
|
|
54
|
-
cd
|
|
40
|
+
git clone https://github.com/edihasaj/tuspy-fast-api
|
|
41
|
+
cd tuspy-fast-api
|
|
55
42
|
pip install .
|
|
56
43
|
```
|
|
57
44
|
|
|
@@ -74,6 +61,15 @@ app.add_middleware(
|
|
|
74
61
|
allow_origins=["*"],
|
|
75
62
|
allow_methods=["*"],
|
|
76
63
|
allow_headers=["*"],
|
|
64
|
+
expose_headers=[
|
|
65
|
+
"Location",
|
|
66
|
+
"Upload-Offset",
|
|
67
|
+
"Tus-Resumable",
|
|
68
|
+
"Tus-Version",
|
|
69
|
+
"Tus-Extension",
|
|
70
|
+
"Tus-Max-Size",
|
|
71
|
+
"Upload-Expires",
|
|
72
|
+
],
|
|
77
73
|
)
|
|
78
74
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
79
75
|
|
|
@@ -91,6 +87,27 @@ app.include_router(
|
|
|
91
87
|
prefix="files", # OPTIONAL: URL prefix (default: 'files')
|
|
92
88
|
),
|
|
93
89
|
)
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### !Warning If you include your own router then it is necessary that your app allows these Headers:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
app.add_middleware(
|
|
97
|
+
CORSMiddleware, (# OPTIONAL: add CORS middleware if needed)
|
|
98
|
+
allow_origins=["*"], # OPTIONAL: allow all origins
|
|
99
|
+
allow_methods=["*"], # OPTIONAL: allow all methods
|
|
100
|
+
allow_headers=["*"], # OPTIONAL: allow all headers
|
|
101
|
+
expose_headers=[ # REQUIRED: expose these headers to the client
|
|
102
|
+
"Location",
|
|
103
|
+
"Upload-Offset",
|
|
104
|
+
"Tus-Resumable",
|
|
105
|
+
"Tus-Version",
|
|
106
|
+
"Tus-Extension",
|
|
107
|
+
"Tus-Max-Size",
|
|
108
|
+
"Upload-Expires",
|
|
109
|
+
],
|
|
110
|
+
)
|
|
94
111
|
```
|
|
95
112
|
|
|
96
113
|
### Dependency‑Injected Hook (Advanced)
|
|
@@ -161,6 +178,6 @@ scheduler.start()
|
|
|
161
178
|
|
|
162
179
|
## Contributing
|
|
163
180
|
|
|
164
|
-
Contributions welcome! Please open issues or PRs on [GitHub](https://github.com/
|
|
181
|
+
Contributions welcome! Please open issues or PRs on [GitHub](https://github.com/edihasaj/tuspy-fast-api).
|
|
165
182
|
|
|
166
183
|
*© 2025 Edi Hasaj [X](https://x.com/hasajedi)*
|
|
@@ -19,8 +19,8 @@ pip install tuspyserver
|
|
|
19
19
|
Or install directly from source:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
git clone https://github.com/
|
|
23
|
-
cd
|
|
22
|
+
git clone https://github.com/edihasaj/tuspy-fast-api
|
|
23
|
+
cd tuspy-fast-api
|
|
24
24
|
pip install .
|
|
25
25
|
```
|
|
26
26
|
|
|
@@ -43,6 +43,15 @@ app.add_middleware(
|
|
|
43
43
|
allow_origins=["*"],
|
|
44
44
|
allow_methods=["*"],
|
|
45
45
|
allow_headers=["*"],
|
|
46
|
+
expose_headers=[
|
|
47
|
+
"Location",
|
|
48
|
+
"Upload-Offset",
|
|
49
|
+
"Tus-Resumable",
|
|
50
|
+
"Tus-Version",
|
|
51
|
+
"Tus-Extension",
|
|
52
|
+
"Tus-Max-Size",
|
|
53
|
+
"Upload-Expires",
|
|
54
|
+
],
|
|
46
55
|
)
|
|
47
56
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
48
57
|
|
|
@@ -60,6 +69,27 @@ app.include_router(
|
|
|
60
69
|
prefix="files", # OPTIONAL: URL prefix (default: 'files')
|
|
61
70
|
),
|
|
62
71
|
)
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### !Warning If you include your own router then it is necessary that your app allows these Headers:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
app.add_middleware(
|
|
79
|
+
CORSMiddleware, (# OPTIONAL: add CORS middleware if needed)
|
|
80
|
+
allow_origins=["*"], # OPTIONAL: allow all origins
|
|
81
|
+
allow_methods=["*"], # OPTIONAL: allow all methods
|
|
82
|
+
allow_headers=["*"], # OPTIONAL: allow all headers
|
|
83
|
+
expose_headers=[ # REQUIRED: expose these headers to the client
|
|
84
|
+
"Location",
|
|
85
|
+
"Upload-Offset",
|
|
86
|
+
"Tus-Resumable",
|
|
87
|
+
"Tus-Version",
|
|
88
|
+
"Tus-Extension",
|
|
89
|
+
"Tus-Max-Size",
|
|
90
|
+
"Upload-Expires",
|
|
91
|
+
],
|
|
92
|
+
)
|
|
63
93
|
```
|
|
64
94
|
|
|
65
95
|
### Dependency‑Injected Hook (Advanced)
|
|
@@ -130,6 +160,6 @@ scheduler.start()
|
|
|
130
160
|
|
|
131
161
|
## Contributing
|
|
132
162
|
|
|
133
|
-
Contributions welcome! Please open issues or PRs on [GitHub](https://github.com/
|
|
163
|
+
Contributions welcome! Please open issues or PRs on [GitHub](https://github.com/edihasaj/tuspy-fast-api).
|
|
134
164
|
|
|
135
165
|
*© 2025 Edi Hasaj [X](https://x.com/hasajedi)*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: tuspyserver
|
|
3
|
-
Version: 2.2.
|
|
3
|
+
Version: 2.2.2
|
|
4
4
|
Summary: TUS py protocol implementation in FastAPI
|
|
5
5
|
Home-page: https://github.com/edihasaj/tuspy-fast-api
|
|
6
6
|
Author: Edi Hasaj
|
|
@@ -15,19 +15,6 @@ Classifier: Programming Language :: Python
|
|
|
15
15
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
License-File: LICENSE
|
|
18
|
-
Requires-Dist: fastapi>=0.110.0
|
|
19
|
-
Requires-Dist: pydantic>=2.6.2
|
|
20
|
-
Dynamic: author
|
|
21
|
-
Dynamic: author-email
|
|
22
|
-
Dynamic: classifier
|
|
23
|
-
Dynamic: description
|
|
24
|
-
Dynamic: description-content-type
|
|
25
|
-
Dynamic: home-page
|
|
26
|
-
Dynamic: license
|
|
27
|
-
Dynamic: license-file
|
|
28
|
-
Dynamic: platform
|
|
29
|
-
Dynamic: requires-dist
|
|
30
|
-
Dynamic: summary
|
|
31
18
|
|
|
32
19
|
# FastAPI Tus
|
|
33
20
|
|
|
@@ -50,8 +37,8 @@ pip install tuspyserver
|
|
|
50
37
|
Or install directly from source:
|
|
51
38
|
|
|
52
39
|
```bash
|
|
53
|
-
git clone https://github.com/
|
|
54
|
-
cd
|
|
40
|
+
git clone https://github.com/edihasaj/tuspy-fast-api
|
|
41
|
+
cd tuspy-fast-api
|
|
55
42
|
pip install .
|
|
56
43
|
```
|
|
57
44
|
|
|
@@ -74,6 +61,15 @@ app.add_middleware(
|
|
|
74
61
|
allow_origins=["*"],
|
|
75
62
|
allow_methods=["*"],
|
|
76
63
|
allow_headers=["*"],
|
|
64
|
+
expose_headers=[
|
|
65
|
+
"Location",
|
|
66
|
+
"Upload-Offset",
|
|
67
|
+
"Tus-Resumable",
|
|
68
|
+
"Tus-Version",
|
|
69
|
+
"Tus-Extension",
|
|
70
|
+
"Tus-Max-Size",
|
|
71
|
+
"Upload-Expires",
|
|
72
|
+
],
|
|
77
73
|
)
|
|
78
74
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
79
75
|
|
|
@@ -91,6 +87,27 @@ app.include_router(
|
|
|
91
87
|
prefix="files", # OPTIONAL: URL prefix (default: 'files')
|
|
92
88
|
),
|
|
93
89
|
)
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### !Warning If you include your own router then it is necessary that your app allows these Headers:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
app.add_middleware(
|
|
97
|
+
CORSMiddleware, (# OPTIONAL: add CORS middleware if needed)
|
|
98
|
+
allow_origins=["*"], # OPTIONAL: allow all origins
|
|
99
|
+
allow_methods=["*"], # OPTIONAL: allow all methods
|
|
100
|
+
allow_headers=["*"], # OPTIONAL: allow all headers
|
|
101
|
+
expose_headers=[ # REQUIRED: expose these headers to the client
|
|
102
|
+
"Location",
|
|
103
|
+
"Upload-Offset",
|
|
104
|
+
"Tus-Resumable",
|
|
105
|
+
"Tus-Version",
|
|
106
|
+
"Tus-Extension",
|
|
107
|
+
"Tus-Max-Size",
|
|
108
|
+
"Upload-Expires",
|
|
109
|
+
],
|
|
110
|
+
)
|
|
94
111
|
```
|
|
95
112
|
|
|
96
113
|
### Dependency‑Injected Hook (Advanced)
|
|
@@ -161,6 +178,6 @@ scheduler.start()
|
|
|
161
178
|
|
|
162
179
|
## Contributing
|
|
163
180
|
|
|
164
|
-
Contributions welcome! Please open issues or PRs on [GitHub](https://github.com/
|
|
181
|
+
Contributions welcome! Please open issues or PRs on [GitHub](https://github.com/edihasaj/tuspy-fast-api).
|
|
165
182
|
|
|
166
183
|
*© 2025 Edi Hasaj [X](https://x.com/hasajedi)*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import base64
|
|
2
|
+
import inspect
|
|
2
3
|
import json
|
|
3
4
|
import os
|
|
4
5
|
from datetime import datetime, timedelta
|
|
@@ -20,7 +21,7 @@ from starlette.responses import FileResponse
|
|
|
20
21
|
from tusserver.metadata import FileMetadata
|
|
21
22
|
|
|
22
23
|
|
|
23
|
-
def default_auth():
|
|
24
|
+
async def default_auth():
|
|
24
25
|
pass
|
|
25
26
|
|
|
26
27
|
|
|
@@ -35,7 +36,7 @@ def create_api_router(
|
|
|
35
36
|
):
|
|
36
37
|
if prefix and prefix[0] == "/":
|
|
37
38
|
prefix = prefix[1:]
|
|
38
|
-
router = APIRouter(prefix=f"/{prefix}")
|
|
39
|
+
router = APIRouter(prefix=f"/{prefix}", redirect_slashes=True)
|
|
39
40
|
|
|
40
41
|
tus_version = "1.0.0"
|
|
41
42
|
tus_extension = (
|
|
@@ -107,7 +108,7 @@ def create_api_router(
|
|
|
107
108
|
return response
|
|
108
109
|
|
|
109
110
|
@router.patch("/{uuid}", status_code=status.HTTP_204_NO_CONTENT)
|
|
110
|
-
def upload_chunk(
|
|
111
|
+
async def upload_chunk(
|
|
111
112
|
response: Response,
|
|
112
113
|
uuid: str,
|
|
113
114
|
content_length: int = Header(None),
|
|
@@ -126,7 +127,10 @@ def create_api_router(
|
|
|
126
127
|
meta = _read_metadata(uuid)
|
|
127
128
|
if meta and meta.size == meta.offset:
|
|
128
129
|
file_path = os.path.join(files_dir, uuid)
|
|
129
|
-
on_complete(file_path, meta.metadata)
|
|
130
|
+
result = on_complete(file_path, meta.metadata)
|
|
131
|
+
# if the callback returned a coroutine, await it
|
|
132
|
+
if inspect.isawaitable(result):
|
|
133
|
+
await result
|
|
130
134
|
|
|
131
135
|
return headers
|
|
132
136
|
|
|
@@ -140,6 +144,7 @@ def create_api_router(
|
|
|
140
144
|
response.status_code = status.HTTP_204_NO_CONTENT
|
|
141
145
|
return response
|
|
142
146
|
|
|
147
|
+
@router.post("", status_code=status.HTTP_201_CREATED)
|
|
143
148
|
@router.post("/", status_code=status.HTTP_201_CREATED)
|
|
144
149
|
async def create_upload(
|
|
145
150
|
request: Request,
|
|
@@ -186,7 +191,10 @@ def create_api_router(
|
|
|
186
191
|
meta = _read_metadata(uuid)
|
|
187
192
|
if meta and meta.size == 0:
|
|
188
193
|
file_path = os.path.join(files_dir, uuid)
|
|
189
|
-
on_complete(file_path, meta.metadata)
|
|
194
|
+
result = on_complete(file_path, meta.metadata)
|
|
195
|
+
# if the callback returned a coroutine, await it
|
|
196
|
+
if inspect.isawaitable(result):
|
|
197
|
+
await result
|
|
190
198
|
|
|
191
199
|
return response
|
|
192
200
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|