Skip to content

Commit 5b509d3

Browse files
committed
remove redundant field, add new max_bitrate option to video api
1 parent 642401d commit 5b509d3

File tree

18 files changed

+71
-454
lines changed

18 files changed

+71
-454
lines changed

http_client/CHANGES.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
- Updated dependency versions
1+
# 1.5.1
2+
- Remove unnecessary `Content-Type` check on error
3+
24
# 1.5.0
35
- Add new `HttpClient.download_file_stream` method
46
- Add new `FileStreamingError` exception type
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.5.0'
1+
__version__ = '1.5.1'

http_client/src/vonage_http_client/errors.py

Lines changed: 26 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from json import JSONDecodeError, dumps
2+
from typing import Optional
23

34
from requests import Response
45
from vonage_utils.errors import VonageError
@@ -21,32 +22,32 @@ class HttpRequestError(VonageError):
2122
2223
Args:
2324
response (requests.Response): The HTTP response object.
24-
content_type (str): The response content type.
2525
2626
Attributes:
2727
response (requests.Response): The HTTP response object.
2828
message (str): The returned error message.
2929
"""
3030

31-
def __init__(self, response: Response, content_type: str):
31+
def __init__(self, response: Response):
3232
self.response = response
33-
self.set_error_message(self.response, content_type)
33+
self.message = self._format_error_message()
3434
super().__init__(self.message)
3535

36-
def set_error_message(self, response: Response, content_type: str):
37-
body = None
38-
if content_type == 'application/json':
39-
try:
40-
body = dumps(response.json(), indent=4)
41-
except JSONDecodeError:
42-
pass
43-
else:
44-
body = response.text
36+
def _format_error_message(self) -> str:
37+
body = self._get_response_body()
38+
base_message = f'{self.response.status_code} response from {self.response.url}'
4539

4640
if body:
47-
self.message = f'{response.status_code} response from {response.url}. Error response body: \n{body}'
48-
else:
49-
self.message = f'{response.status_code} response from {response.url}.'
41+
return f'{base_message}. Error response body: \n{body}'
42+
return base_message
43+
44+
def _get_response_body(self) -> Optional[str]:
45+
if not self.response.content:
46+
return None
47+
try:
48+
return dumps(self.response.json(), indent=4)
49+
except JSONDecodeError:
50+
return self.response.text
5051

5152

5253
class AuthenticationError(HttpRequestError):
@@ -56,15 +57,14 @@ class AuthenticationError(HttpRequestError):
5657
5758
Args:
5859
response (requests.Response): The HTTP response object.
59-
content_type (str): The response content type.
6060
6161
Attributes (inherited from HttpRequestError parent exception):
6262
response (requests.Response): The HTTP response object.
6363
message (str): The returned error message.
6464
"""
6565

66-
def __init__(self, response: Response, content_type: str):
67-
super().__init__(response, content_type)
66+
def __init__(self, response: Response):
67+
super().__init__(response)
6868

6969

7070
class ForbiddenError(HttpRequestError):
@@ -74,15 +74,14 @@ class ForbiddenError(HttpRequestError):
7474
7575
Args:
7676
response (requests.Response): The HTTP response object.
77-
content_type (str): The response content type.
7877
7978
Attributes (inherited from HttpRequestError parent exception):
8079
response (requests.Response): The HTTP response object.
8180
message (str): The returned error message.
8281
"""
8382

84-
def __init__(self, response: Response, content_type: str):
85-
super().__init__(response, content_type)
83+
def __init__(self, response: Response):
84+
super().__init__(response)
8685

8786

8887
class NotFoundError(HttpRequestError):
@@ -92,15 +91,14 @@ class NotFoundError(HttpRequestError):
9291
9392
Args:
9493
response (requests.Response): The HTTP response object.
95-
content_type (str): The response content type.
9694
9795
Attributes (inherited from HttpRequestError parent exception):
9896
response (requests.Response): The HTTP response object.
9997
message (str): The returned error message.
10098
"""
10199

102-
def __init__(self, response: Response, content_type: str):
103-
super().__init__(response, content_type)
100+
def __init__(self, response: Response):
101+
super().__init__(response)
104102

105103

106104
class RateLimitedError(HttpRequestError):
@@ -111,15 +109,14 @@ class RateLimitedError(HttpRequestError):
111109
112110
Args:
113111
response (requests.Response): The HTTP response object.
114-
content_type (str): The response content type.
115112
116113
Attributes (inherited from HttpRequestError parent exception):
117114
response (requests.Response): The HTTP response object.
118115
message (str): The returned error message.
119116
"""
120117

121-
def __init__(self, response: Response, content_type: str):
122-
super().__init__(response, content_type)
118+
def __init__(self, response: Response):
119+
super().__init__(response)
123120

124121

125122
class ServerError(HttpRequestError):
@@ -130,15 +127,14 @@ class ServerError(HttpRequestError):
130127
131128
Args:
132129
response (requests.Response): The HTTP response object.
133-
content_type (str): The response content type.
134130
135131
Attributes (inherited from HttpRequestError parent exception):
136132
response (requests.Response): The HTTP response object.
137133
message (str): The returned error message.
138134
"""
139135

140-
def __init__(self, response: Response, content_type: str):
141-
super().__init__(response, content_type)
136+
def __init__(self, response: Response):
137+
super().__init__(response)
142138

143139

144140
class FileStreamingError(VonageError):

http_client/src/vonage_http_client/http_client.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -343,18 +343,17 @@ def _parse_response(self, response: Response) -> Union[dict, None]:
343343
except JSONDecodeError:
344344
return None
345345
if response.status_code >= 400:
346-
content_type = response.headers['Content-Type'].split(';', 1)[0]
347346
logger.warning(
348347
f'Http Response Error! Status code: {response.status_code}; content: {repr(response.text)}; from url: {response.url}'
349348
)
350349
if response.status_code == 401:
351-
raise AuthenticationError(response, content_type)
350+
raise AuthenticationError(response)
352351
if response.status_code == 403:
353-
raise ForbiddenError(response, content_type)
352+
raise ForbiddenError(response)
354353
elif response.status_code == 404:
355-
raise NotFoundError(response, content_type)
354+
raise NotFoundError(response)
356355
elif response.status_code == 429:
357-
raise RateLimitedError(response, content_type)
356+
raise RateLimitedError(response)
358357
elif response.status_code == 500:
359-
raise ServerError(response, content_type)
360-
raise HttpRequestError(response, content_type)
358+
raise ServerError(response)
359+
raise HttpRequestError(response)

sms/tests/test_sms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def test_submit_sms_conversion_402():
170170
try:
171171
sms.submit_sms_conversion('3295d748-4e14-4681-af78-166dca3c5aab')
172172
except HttpRequestError as err:
173-
assert err.message == '402 response from https://api.nexmo.com/conversions/sms.'
173+
assert '402 response from https://api.nexmo.com/conversions/sms.' in err.message
174174

175175

176176
def test_http_client_property():

video/CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# 1.1.0
2+
- Add new `max_bitrate` field for archives
3+
14
# 1.0.4
25
- Updated dependency versions
36

video/src/vonage_video/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '1.0.4'
1+
__version__ = '1.1.0'

video/src/vonage_video/models/archive.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ class Archive(BaseModel):
6969
url (str, Optional): The download URL of the available archive file.
7070
This is only set for an archive with the status set to `available`.
7171
transcription (Transcription, Optional): Transcription options for the archive.
72+
max_bitrate (int, Optional): The maximum video bitrate of the archive, in bits per
73+
second. This is only valid for composed archives.
7274
"""
7375

7476
id: Optional[str] = None
@@ -94,6 +96,7 @@ class Archive(BaseModel):
9496
streams: Optional[list[VideoStream]] = None
9597
url: Optional[str] = None
9698
transcription: Optional[Transcription] = None
99+
max_bitrate: Optional[int] = Field(None, validation_alias='maxBitrate')
97100

98101

99102
class CreateArchiveRequest(BaseModel):
@@ -114,7 +117,8 @@ class CreateArchiveRequest(BaseModel):
114117
resolution (VideoResolution, Optional): The resolution of the archive.
115118
stream_mode (StreamMode, Optional): Whether streams included in the archive are selected
116119
automatically ("auto", the default) or manually ("manual").
117-
120+
max_bitrate (int, Optional): The maximum video bitrate of the archive, in bits per
121+
second. This is only valid for composed archives.
118122
Raises:
119123
NoAudioOrVideoError: If neither `has_audio` nor `has_video` is set.
120124
IndividualArchivePropertyError: If `resolution` or `layout` is set for individual archives
@@ -133,6 +137,9 @@ class CreateArchiveRequest(BaseModel):
133137
output_mode: Optional[OutputMode] = Field(None, serialization_alias='outputMode')
134138
resolution: Optional[VideoResolution] = None
135139
stream_mode: Optional[StreamMode] = Field(None, serialization_alias='streamMode')
140+
max_bitrate: Optional[int] = Field(
141+
None, ge=100_000, le=6_000_000, serialization_alias='maxBitrate'
142+
)
136143

137144
@model_validator(mode='after')
138145
def validate_audio_or_video(self):

video/tests/data/archive.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
"multiArchiveTag": "my-multi-archive",
2020
"event": "archive",
2121
"resolution": "1280x720",
22-
"url": null
22+
"url": null,
23+
"maxBitrate": 2000000
2324
}

video/tests/data/list_archives.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
"multiArchiveTag": "my-multi-archive",
4646
"event": "archive",
4747
"resolution": "1280x720",
48-
"url": "https://example.com/archive.mp4"
48+
"url": "https://example.com/archive.mp4",
49+
"maxBitrate": 2000000
4950
}
5051
]
5152
}

video/tests/test_archive.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ def test_list_archives():
127127
assert archives[1].duration == 134
128128
assert archives[1].sha256_sum == 'test_sha256_sum'
129129
assert archives[1].url == 'https://example.com/archive.mp4'
130+
assert archives[1].max_bitrate == 2_000_000
130131

131132

132133
@responses.activate
@@ -150,6 +151,7 @@ def test_start_archive():
150151
output_mode=OutputMode.COMPOSED,
151152
resolution=VideoResolution.RES_1280x720,
152153
stream_mode=StreamMode.MANUAL,
154+
max_bitrate=2_000_000,
153155
)
154156

155157
archive = video.start_archive(archive_options)
@@ -162,6 +164,7 @@ def test_start_archive():
162164
assert archive.status == 'started'
163165
assert archive.name == 'first archive test'
164166
assert archive.resolution == '1280x720'
167+
assert archive.max_bitrate == 2_000_000
165168

166169

167170
@responses.activate

0 commit comments

Comments
 (0)