Skip to content

Commit 7494aaa

Browse files
Sebastian Molendatechwritermatpubnub-release-bot
authored
Feat/replace transport with httpx (#201)
Co-authored-by: Mateusz Wiktor <[email protected]> Co-authored-by: Mateusz Wiktor <[email protected]> * PubNub SDK 10.0.0 release. --------- Co-authored-by: Mateusz Wiktor <[email protected]> Co-authored-by: PubNub Release Bot <[email protected]>
1 parent ba33368 commit 7494aaa

File tree

94 files changed

+3782
-4726
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+3782
-4726
lines changed

.pubnub.yml

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: python
2-
version: 9.1.0
2+
version: 10.0.0
33
schema: 1
44
scm: github.com/pubnub/python
55
sdks:
@@ -18,7 +18,7 @@ sdks:
1818
distributions:
1919
- distribution-type: library
2020
distribution-repository: package
21-
package-name: pubnub-9.1.0
21+
package-name: pubnub-10.0.0
2222
location: https://pypi.org/project/pubnub/
2323
supported-platforms:
2424
supported-operating-systems:
@@ -61,12 +61,6 @@ sdks:
6161
- x86
6262
- x86-64
6363
requires:
64-
- name: requests
65-
min-version: "2.4"
66-
location: https://pypi.org/project/requests/
67-
license: Apache Software License (Apache 2.0)
68-
license-url: https://github.com/psf/requests/blob/master/LICENSE
69-
is-required: Required
7064
- name: pycryptodomex
7165
min-version: "3.3"
7266
location: https://pypi.org/project/pycryptodomex/
@@ -79,11 +73,11 @@ sdks:
7973
license: MIT License (MIT)
8074
license-url: https://github.com/agronholm/cbor2/blob/master/LICENSE.txt
8175
is-required: Required
82-
- name: aiohttp
83-
min-version: "2.3.10"
84-
location: https://pypi.org/project/aiohttp/
85-
license: Apache Software License (Apache 2)
86-
license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt
76+
- name: httpx
77+
min-version: "0.28.0"
78+
location: https://pypi.org/project/httpx/
79+
license: BSD License (BSD-3-Clause)
80+
license-url: https://github.com/encode/httpx/blob/master/LICENSE.md
8781
is-required: Required
8882
-
8983
language: python
@@ -97,8 +91,8 @@ sdks:
9791
-
9892
distribution-type: library
9993
distribution-repository: git release
100-
package-name: pubnub-9.1.0
101-
location: https://github.com/pubnub/python/releases/download/v9.1.0/pubnub-9.1.0.tar.gz
94+
package-name: pubnub-10.0.0
95+
location: https://github.com/pubnub/python/releases/download/10.0.0/pubnub-10.0.0.tar.gz
10296
supported-platforms:
10397
supported-operating-systems:
10498
Linux:
@@ -162,13 +156,18 @@ sdks:
162156
license-url: https://github.com/agronholm/cbor2/blob/master/LICENSE.txt
163157
is-required: Required
164158
-
165-
name: aiohttp
166-
min-version: "2.3.10"
167-
location: https://pypi.org/project/aiohttp/
168-
license: Apache Software License (Apache 2)
169-
license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt
159+
name: httpx
160+
min-version: "0.28.0"
161+
location: https://pypi.org/project/httpx/
162+
license: BSD License (BSD-3-Clause)
163+
license-url: https://github.com/encode/httpx/blob/master/LICENSE.md
170164
is-required: Required
171165
changelog:
166+
- date: 2025-01-13
167+
version: 10.0.0
168+
changes:
169+
- type: feature
170+
text: "Introduced configurable request handler with HTTP/2 support."
172171
- date: 2024-11-19
173172
version: v9.1.0
174173
changes:

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 10.0.0
2+
January 13 2025
3+
4+
#### Added
5+
- Introduced configurable request handler with HTTP/2 support.
6+
17
## v9.1.0
28
November 19 2024
39

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ You will need the publish and subscribe keys to authenticate your app. Get your
1818
## Configure PubNub
1919

2020
1. Integrate the Python SDK into your project using `pip`:
21-
21+
2222
```bash
2323
pip install pubnub
2424
```
@@ -83,9 +83,8 @@ pubnub.subscribe().channels('my_channel').execute()
8383
8484
## Documentation
8585
86-
* [Build your first realtime Python app with PubNub](https://www.pubnub.com/docs/platform/quickstarts/python)
87-
* [API reference for Python](https://www.pubnub.com/docs/python/pubnub-python-sdk)
88-
* [API reference for Python (asyncio)](https://www.pubnub.com/docs/python-aiohttp/pubnub-python-sdk)
86+
* [Build your first realtime Python app with PubNub](https://www.pubnub.com/docs/general/basics/set-up-your-account)
87+
* [API reference for Python](https://www.pubnub.com/docs/sdks/python)
8988
9089
## Support
9190

pubnub/crypto.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ def decrypt(self, key, file, use_random_iv=True):
104104
cipher = AES.new(bytes(secret[0:32], "utf-8"), self.mode, initialization_vector)
105105
result = unpad(cipher.decrypt(extracted_file), 16)
106106
except ValueError:
107+
if not self.fallback_mode: # No fallback mode so we return the original content
108+
return file
107109
cipher = AES.new(bytes(secret[0:32], "utf-8"), self.fallback_mode, initialization_vector)
108110
result = unpad(cipher.decrypt(extracted_file), 16)
109111

pubnub/endpoints/file_operations/download_file.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
from pubnub.enums import HttpMethod, PNOperationType
33
from pubnub.crypto import PubNubFileCrypto
44
from pubnub.models.consumer.file import PNDownloadFileResult
5-
from pubnub.request_handlers.requests_handler import RequestsRequestHandler
65
from pubnub.endpoints.file_operations.get_file_url import GetFileDownloadUrl
76
from warnings import warn
7+
from urllib.parse import urlparse, parse_qs
88

99

1010
class DownloadFileNative(FileOperationEndpoint):
@@ -69,7 +69,8 @@ def use_base_path(self):
6969
return False
7070

7171
def build_params_callback(self):
72-
return lambda a: {}
72+
params = parse_qs(urlparse(self._download_data.result.file_url).query)
73+
return lambda a: {key: str(params[key][0]) for key in params.keys()}
7374

7475
def name(self):
7576
return "Downloading file"
@@ -84,4 +85,4 @@ def sync(self):
8485
return super(DownloadFileNative, self).sync()
8586

8687
def pn_async(self, callback):
87-
return RequestsRequestHandler(self._pubnub).async_file_based_operation(self.sync, callback, "File Download")
88+
self._pubnub.get_request_handler().async_file_based_operation(self.sync, callback, "File Download")

pubnub/endpoints/file_operations/send_file.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
from pubnub.models.consumer.file import PNSendFileResult
66
from pubnub.endpoints.file_operations.publish_file_message import PublishFileMessage
77
from pubnub.endpoints.file_operations.fetch_upload_details import FetchFileUploadS3Data
8-
from pubnub.request_handlers.requests_handler import RequestsRequestHandler
98
from pubnub.endpoints.mixins import TimeTokenOverrideMixin
109
from warnings import warn
1110

@@ -152,4 +151,4 @@ def sync(self):
152151
return response_envelope
153152

154153
def pn_async(self, callback):
155-
return RequestsRequestHandler(self._pubnub).async_file_based_operation(self.sync, callback, "File Download")
154+
self._pubnub.get_request_handler().async_file_based_operation(self.sync, callback, "File Download")

pubnub/endpoints/file_operations/send_file_asyncio.py

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,28 @@
1-
import aiohttp
2-
31
from pubnub.endpoints.file_operations.send_file import SendFileNative
42
from pubnub.endpoints.file_operations.publish_file_message import PublishFileMessage
53
from pubnub.endpoints.file_operations.fetch_upload_details import FetchFileUploadS3Data
64

75

86
class AsyncioSendFile(SendFileNative):
9-
def build_file_upload_request(self):
10-
file = self.encrypt_payload()
11-
form_data = aiohttp.FormData()
12-
for form_field in self._file_upload_envelope.result.data["form_fields"]:
13-
form_data.add_field(form_field["key"], form_field["value"], content_type="multipart/form-data")
14-
form_data.add_field("file", file, filename=self._file_name, content_type="application/octet-stream")
15-
16-
return form_data
17-
18-
def options(self):
19-
request_options = super(SendFileNative, self).options()
20-
request_options.data = request_options.files
21-
return request_options
22-
237
async def future(self):
24-
self._file_upload_envelope = await FetchFileUploadS3Data(self._pubnub).\
25-
channel(self._channel).\
26-
file_name(self._file_name).future()
8+
self._file_upload_envelope = await FetchFileUploadS3Data(self._pubnub) \
9+
.channel(self._channel) \
10+
.file_name(self._file_name).future()
2711

2812
response_envelope = await super(SendFileNative, self).future()
2913

30-
publish_file_response = await PublishFileMessage(self._pubnub).\
31-
channel(self._channel).\
32-
meta(self._meta).\
33-
message(self._message).\
34-
file_id(response_envelope.result.file_id).\
35-
file_name(response_envelope.result.name).\
36-
should_store(self._should_store).\
37-
ttl(self._ttl).\
38-
cipher_key(self._cipher_key).future()
14+
publish_file_response = await PublishFileMessage(self._pubnub) \
15+
.channel(self._channel) \
16+
.meta(self._meta) \
17+
.message(self._message) \
18+
.file_id(response_envelope.result.file_id) \
19+
.file_name(response_envelope.result.name) \
20+
.should_store(self._should_store) \
21+
.ttl(self._ttl) \
22+
.replicate(self._replicate) \
23+
.ptto(self._ptto) \
24+
.custom_message_type(self._custom_message_type) \
25+
.cipher_key(self._cipher_key).future()
3926

4027
response_envelope.result.timestamp = publish_file_response.result.timestamp
4128
return response_envelope

pubnub/event_engine/effects.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,15 @@ async def delayed_reconnect_async(self, delay, attempt):
218218
elif response.status.error:
219219
self.logger.warning(f'Reconnect failed: {response.status.error_data.__dict__}')
220220
self.failure(response.status.error_data, attempt, self.get_timetoken())
221-
else:
221+
elif 't' in response.result:
222222
cursor = response.result['t']
223223
timetoken = int(self.invocation.timetoken) if self.invocation.timetoken else cursor['t']
224224
region = cursor['r']
225225
messages = response.result['m']
226226
self.success(timetoken=timetoken, region=region, messages=messages)
227+
else:
228+
self.logger.warning(f'Reconnect failed: Invalid response {str(response)}')
229+
self.failure(str(response), attempt, self.get_timetoken())
227230

228231
def stop(self):
229232
self.logger.debug(f'stop called on {self.__class__.__name__}')

pubnub/exceptions.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,19 @@ def __init__(self, errormsg="", status_code=0, pn_error=None, status=None):
1818
def _status(self):
1919
raise DeprecationWarning
2020
return self.status
21+
22+
23+
class PubNubAsyncioException(Exception):
24+
def __init__(self, result, status):
25+
self.result = result
26+
self.status = status
27+
28+
def __str__(self):
29+
return str(self.status.error_data.exception)
30+
31+
@staticmethod
32+
def is_error():
33+
return True
34+
35+
def value(self):
36+
return self.status.error_data.exception

pubnub/models/envelopes.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class AsyncioEnvelope:
2+
def __init__(self, result, status):
3+
self.result = result
4+
self.status = status
5+
6+
@staticmethod
7+
def is_error():
8+
return False

0 commit comments

Comments
 (0)