0
# Exception Handling
1
2
Custom exceptions for tus protocol communication errors and upload failures. TusPy provides specific exception types to help applications handle different error conditions appropriately.
3
4
## Capabilities
5
6
### TusCommunicationError
7
8
Base exception for tus server communication errors.
9
10
```python { .api }
11
class TusCommunicationError(Exception):
12
"""
13
Should be raised when communications with tus-server behaves unexpectedly.
14
15
Attributes:
16
message (str): Main message of the exception
17
status_code (int): Status code of response indicating an error
18
response_content (str): Content of response indicating an error
19
"""
20
21
def __init__(self, message: str, status_code: Optional[int] = None,
22
response_content: Optional[str] = None):
23
"""
24
Initialize TusCommunicationError.
25
26
Parameters:
27
- message (str): Error message. Can be None to generate default message using status_code
28
- status_code (Optional[int]): HTTP status code from server response
29
- response_content (Optional[str]): Content body from server response
30
"""
31
```
32
33
### TusUploadFailed
34
35
Exception for failed upload attempts, inheriting from TusCommunicationError.
36
37
```python { .api }
38
class TusUploadFailed(TusCommunicationError):
39
"""
40
Should be raised when an attempted upload fails.
41
42
Inherits all attributes and functionality from TusCommunicationError.
43
Used specifically for upload operation failures.
44
"""
45
```
46
47
### Request Error Decorator
48
49
Decorator function for converting requests library exceptions to TusCommunicationError.
50
51
```python { .api }
52
def catch_requests_error(func):
53
"""
54
Decorator to catch requests exceptions and convert to TusCommunicationError.
55
56
Wraps functions that make HTTP requests and converts any
57
requests.exceptions.RequestException to TusCommunicationError.
58
59
Parameters:
60
- func: Function to wrap
61
62
Returns:
63
Wrapped function that converts request exceptions
64
"""
65
```
66
67
## Usage Examples
68
69
### Basic Exception Handling
70
71
```python
72
from tusclient import client
73
from tusclient.exceptions import TusCommunicationError, TusUploadFailed
74
75
my_client = client.TusClient('http://tusd.tusdemo.net/files/')
76
uploader = my_client.uploader('/path/to/file.ext', chunk_size=1024*1024)
77
78
try:
79
uploader.upload()
80
print("Upload completed successfully")
81
except TusUploadFailed as e:
82
print(f"Upload failed: {e}")
83
if e.status_code:
84
print(f"Server returned status code: {e.status_code}")
85
if e.response_content:
86
print(f"Server response: {e.response_content}")
87
except TusCommunicationError as e:
88
print(f"Communication error: {e}")
89
if e.status_code:
90
print(f"Status code: {e.status_code}")
91
```
92
93
### Detailed Error Information
94
95
```python
96
from tusclient import client
97
from tusclient.exceptions import TusCommunicationError, TusUploadFailed
98
99
def handle_upload_with_details(file_path: str, server_url: str):
100
my_client = client.TusClient(server_url)
101
uploader = my_client.uploader(file_path, chunk_size=1024*1024)
102
103
try:
104
uploader.upload()
105
return True, "Upload successful"
106
107
except TusUploadFailed as e:
108
error_details = {
109
'type': 'upload_failed',
110
'message': str(e),
111
'status_code': e.status_code,
112
'response_content': e.response_content
113
}
114
115
# Handle specific HTTP status codes
116
if e.status_code == 413:
117
error_details['user_message'] = "File too large for server"
118
elif e.status_code == 403:
119
error_details['user_message'] = "Upload not authorized"
120
elif e.status_code == 404:
121
error_details['user_message'] = "Upload URL not found - may have expired"
122
else:
123
error_details['user_message'] = f"Upload failed with status {e.status_code}"
124
125
return False, error_details
126
127
except TusCommunicationError as e:
128
error_details = {
129
'type': 'communication_error',
130
'message': str(e),
131
'status_code': e.status_code,
132
'user_message': "Server communication error"
133
}
134
135
return False, error_details
136
137
# Use the function
138
success, result = handle_upload_with_details('/path/to/file.ext', 'http://tusd.tusdemo.net/files/')
139
if success:
140
print(result)
141
else:
142
print(f"Error: {result['user_message']}")
143
print(f"Details: {result['message']}")
144
```
145
146
### Retry Logic with Exception Handling
147
148
```python
149
import time
150
from tusclient import client
151
from tusclient.exceptions import TusCommunicationError, TusUploadFailed
152
153
def upload_with_custom_retry(file_path: str, server_url: str, max_retries: int = 3):
154
my_client = client.TusClient(server_url)
155
156
for attempt in range(max_retries + 1):
157
try:
158
uploader = my_client.uploader(file_path, chunk_size=1024*1024)
159
uploader.upload()
160
print(f"Upload successful on attempt {attempt + 1}")
161
return True
162
163
except TusUploadFailed as e:
164
# Don't retry on client errors (4xx)
165
if e.status_code and 400 <= e.status_code < 500:
166
print(f"Client error {e.status_code}: {e}")
167
return False
168
169
# Retry on server errors (5xx) or network issues
170
if attempt < max_retries:
171
wait_time = 2 ** attempt # Exponential backoff
172
print(f"Upload failed (attempt {attempt + 1}/{max_retries + 1}), retrying in {wait_time}s...")
173
time.sleep(wait_time)
174
else:
175
print(f"Upload failed after {max_retries + 1} attempts: {e}")
176
return False
177
178
except TusCommunicationError as e:
179
if attempt < max_retries:
180
wait_time = 2 ** attempt
181
print(f"Communication error (attempt {attempt + 1}/{max_retries + 1}), retrying in {wait_time}s...")
182
time.sleep(wait_time)
183
else:
184
print(f"Communication failed after {max_retries + 1} attempts: {e}")
185
return False
186
187
return False
188
189
# Use custom retry logic
190
success = upload_with_custom_retry('/path/to/file.ext', 'http://tusd.tusdemo.net/files/', max_retries=3)
191
```
192
193
### Async Exception Handling
194
195
```python
196
import asyncio
197
from tusclient import client
198
from tusclient.exceptions import TusCommunicationError, TusUploadFailed
199
200
async def async_upload_with_error_handling(file_path: str, server_url: str):
201
my_client = client.TusClient(server_url)
202
uploader = my_client.async_uploader(file_path, chunk_size=1024*1024)
203
204
try:
205
await uploader.upload()
206
print("Async upload completed successfully")
207
return True
208
209
except TusUploadFailed as e:
210
print(f"Async upload failed: {e}")
211
if e.status_code:
212
print(f"Status code: {e.status_code}")
213
return False
214
215
except TusCommunicationError as e:
216
print(f"Async communication error: {e}")
217
return False
218
219
# Run async upload
220
async def main():
221
success = await async_upload_with_error_handling('/path/to/file.ext', 'http://tusd.tusdemo.net/files/')
222
if success:
223
print("Upload operation completed")
224
else:
225
print("Upload operation failed")
226
227
asyncio.run(main())
228
```
229
230
### Logging Exception Details
231
232
```python
233
import logging
234
from tusclient import client
235
from tusclient.exceptions import TusCommunicationError, TusUploadFailed
236
237
# Setup logging
238
logging.basicConfig(level=logging.INFO)
239
logger = logging.getLogger(__name__)
240
241
def upload_with_logging(file_path: str, server_url: str):
242
my_client = client.TusClient(server_url)
243
uploader = my_client.uploader(file_path, chunk_size=1024*1024)
244
245
try:
246
logger.info(f"Starting upload of {file_path}")
247
uploader.upload()
248
logger.info("Upload completed successfully")
249
return True
250
251
except TusUploadFailed as e:
252
logger.error(f"Upload failed: {e}")
253
logger.error(f"Status code: {e.status_code}")
254
logger.error(f"Response content: {e.response_content}")
255
return False
256
257
except TusCommunicationError as e:
258
logger.error(f"Communication error: {e}")
259
if e.status_code:
260
logger.error(f"Status code: {e.status_code}")
261
return False
262
263
except Exception as e:
264
logger.error(f"Unexpected error: {e}")
265
return False
266
267
# Use with logging
268
success = upload_with_logging('/path/to/file.ext', 'http://tusd.tusdemo.net/files/')
269
```