Skip to content

Commit

Permalink
Rework invocation of requests
Browse files Browse the repository at this point in the history
  • Loading branch information
seba-aln committed Dec 11, 2024
1 parent defccec commit 4a4872c
Show file tree
Hide file tree
Showing 36 changed files with 390 additions and 2,572 deletions.
26 changes: 10 additions & 16 deletions .pubnub.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,6 @@ sdks:
- x86
- x86-64
requires:
- name: requests
min-version: "2.4"
location: https://pypi.org/project/requests/
license: Apache Software License (Apache 2.0)
license-url: https://github.com/psf/requests/blob/master/LICENSE
is-required: Required
- name: pycryptodomex
min-version: "3.3"
location: https://pypi.org/project/pycryptodomex/
Expand All @@ -79,11 +73,11 @@ sdks:
license: MIT License (MIT)
license-url: https://github.com/agronholm/cbor2/blob/master/LICENSE.txt
is-required: Required
- name: aiohttp
min-version: "2.3.10"
location: https://pypi.org/project/aiohttp/
license: Apache Software License (Apache 2)
license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt
- name: httpx
min-version: "0.28.0"
location: https://pypi.org/project/httpx/
license: BSD License (BSD-3-Clause)
license-url: https://github.com/encode/httpx/blob/master/LICENSE.md
is-required: Required
-
language: python
Expand Down Expand Up @@ -162,11 +156,11 @@ sdks:
license-url: https://github.com/agronholm/cbor2/blob/master/LICENSE.txt
is-required: Required
-
name: aiohttp
min-version: "2.3.10"
location: https://pypi.org/project/aiohttp/
license: Apache Software License (Apache 2)
license-url: https://github.com/aio-libs/aiohttp/blob/master/LICENSE.txt
name: httpx
min-version: "0.28.0"
location: https://pypi.org/project/httpx/
license: BSD License (BSD-3-Clause)
license-url: https://github.com/encode/httpx/blob/master/LICENSE.md
is-required: Required
changelog:
- date: 2024-11-19
Expand Down
7 changes: 3 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You will need the publish and subscribe keys to authenticate your app. Get your
## Configure PubNub

1. Integrate the Python SDK into your project using `pip`:

```bash
pip install pubnub
```
Expand Down Expand Up @@ -83,9 +83,8 @@ pubnub.subscribe().channels('my_channel').execute()
## Documentation
* [Build your first realtime Python app with PubNub](https://www.pubnub.com/docs/platform/quickstarts/python)
* [API reference for Python](https://www.pubnub.com/docs/python/pubnub-python-sdk)
* [API reference for Python (asyncio)](https://www.pubnub.com/docs/python-aiohttp/pubnub-python-sdk)
* [Build your first realtime Python app with PubNub](https://www.pubnub.com/docs/general/basics/set-up-your-account)
* [API reference for Python](https://www.pubnub.com/docs/sdks/python)
## Support
Expand Down
2 changes: 2 additions & 0 deletions pubnub/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ def decrypt(self, key, file, use_random_iv=True):
cipher = AES.new(bytes(secret[0:32], "utf-8"), self.mode, initialization_vector)
result = unpad(cipher.decrypt(extracted_file), 16)
except ValueError:
if not self.fallback_mode: # No fallback mode so we return the original content
return file
cipher = AES.new(bytes(secret[0:32], "utf-8"), self.fallback_mode, initialization_vector)
result = unpad(cipher.decrypt(extracted_file), 16)

Expand Down
4 changes: 3 additions & 1 deletion pubnub/endpoints/file_operations/download_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from pubnub.request_handlers.requests_handler import RequestsRequestHandler
from pubnub.endpoints.file_operations.get_file_url import GetFileDownloadUrl
from warnings import warn
from urllib.parse import urlparse, parse_qs


class DownloadFileNative(FileOperationEndpoint):
Expand Down Expand Up @@ -69,7 +70,8 @@ def use_base_path(self):
return False

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

def name(self):
return "Downloading file"
Expand Down
32 changes: 15 additions & 17 deletions pubnub/endpoints/file_operations/send_file_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,25 @@


class AsyncioSendFile(SendFileNative):
def options(self):
request_options = super(SendFileNative, self).options()
request_options.data = request_options.files
return request_options

async def future(self):
self._file_upload_envelope = await FetchFileUploadS3Data(self._pubnub).\
channel(self._channel).\
file_name(self._file_name).future()
self._file_upload_envelope = await FetchFileUploadS3Data(self._pubnub) \
.channel(self._channel) \
.file_name(self._file_name).future()

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

publish_file_response = await PublishFileMessage(self._pubnub).\
channel(self._channel).\
meta(self._meta).\
message(self._message).\
file_id(response_envelope.result.file_id).\
file_name(response_envelope.result.name).\
should_store(self._should_store).\
ttl(self._ttl).\
cipher_key(self._cipher_key).future()
publish_file_response = await PublishFileMessage(self._pubnub) \
.channel(self._channel) \
.meta(self._meta) \
.message(self._message) \
.file_id(response_envelope.result.file_id) \
.file_name(response_envelope.result.name) \
.should_store(self._should_store) \
.ttl(self._ttl) \
.replicate(self._replicate) \
.ptto(self._ptto) \
.custom_message_type(self._custom_message_type) \
.cipher_key(self._cipher_key).future()

response_envelope.result.timestamp = publish_file_response.result.timestamp
return response_envelope
Expand Down
23 changes: 14 additions & 9 deletions pubnub/pubnub_asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import urllib

from asyncio import Event, Queue, Semaphore
from yarl import URL
from httpx import AsyncHTTPTransport
from pubnub.event_engine.containers import PresenceStateContainer
from pubnub.event_engine.models import events, states
Expand Down Expand Up @@ -180,26 +179,32 @@ async def _request_helper(self, options_func, cancellation_event):
else:
url = utils.build_url(scheme="", origin="", path=options.path, params=options.query_string)

url = str(URL(url, encoded=True))
full_url = httpx.URL(url, query=options.query_string.encode('utf-8'))

logger.debug("%s %s %s" % (options.method_string, url, options.data))

if options.request_headers:
request_headers = {**self.headers, **options.request_headers}
else:
request_headers = self.headers

request_arguments = {
'method': options.method_string,
'headers': request_headers,
'url': full_url,
'follow_redirects': options.allow_redirects,
'timeout': (options.connect_timeout, options.request_timeout),
}
if options.is_post() or options.is_patch():
request_arguments['content'] = options.data
request_arguments['files'] = options.files

try:
if not self._session:
await self.create_session()
start_timestamp = time.time()
response = await asyncio.wait_for(
self._session.request(
options.method_string,
url,
headers=request_headers,
data=options.data if options.data else None,
follow_redirects=options.allow_redirects
),
self._session.request(**request_arguments),
options.request_timeout
)
except (asyncio.TimeoutError, asyncio.CancelledError):
Expand Down
4 changes: 2 additions & 2 deletions pubnub/pubnub_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ def publish(self, channel: str = None, message: any = None, should_store: Option

def grant(self):
""" Deprecated. Use grant_token instead """
warn("This method will stop working on 31th December 2024. We recommend that you use grant_token() instead.",
warn("Access management v2 is being deprecated. We recommend switching to grant_token().",
DeprecationWarning, stacklevel=2)
return Grant(self)

Expand All @@ -240,7 +240,7 @@ def revoke_token(self, token: str) -> RevokeToken:

def audit(self):
""" Deprecated """
warn("This method will stop working on 31th December 2024.", DeprecationWarning, stacklevel=2)
warn("Access management v2 is being deprecated.", DeprecationWarning, stacklevel=2)
return Audit(self)

# Push Related methods
Expand Down
25 changes: 12 additions & 13 deletions pubnub/request_handlers/requests_handler.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import logging
import threading
import requests
import httpx
import json # noqa # pylint: disable=W0611
import urllib
Expand Down Expand Up @@ -237,14 +236,13 @@ def _invoke_request(self, p_options, e_options, base_origin):
args = {
"method": e_options.method_string,
"headers": request_headers,
"url": url,
"params": e_options.query_string,
"url": httpx.URL(url, query=e_options.query_string.encode("utf-8")),
"timeout": (e_options.connect_timeout, e_options.request_timeout),
"follow_redirects": e_options.allow_redirects
}

if e_options.is_post() or e_options.is_patch():
args["data"] = e_options.data
args["content"] = e_options.data
args["files"] = e_options.files
logger.debug("%s %s %s" % (
e_options.method_string,
Expand All @@ -265,32 +263,33 @@ def _invoke_request(self, p_options, e_options, base_origin):
try:
res = self.session.request(**args)
logger.debug("GOT %s" % res.text)
except requests.exceptions.ConnectionError as e:

except httpx.ConnectError as e:
raise PubNubException(
pn_error=PNERR_CONNECTION_ERROR,
errormsg=str(e)
)
except requests.exceptions.HTTPError as e:
raise PubNubException(
pn_error=PNERR_HTTP_ERROR,
errormsg=str(e)
)
except requests.exceptions.Timeout as e:
except httpx.TimeoutException as e:
raise PubNubException(
pn_error=PNERR_CLIENT_TIMEOUT,
errormsg=str(e)
)
except requests.exceptions.TooManyRedirects as e:
except httpx.TooManyRedirects as e:
raise PubNubException(
pn_error=PNERR_TOO_MANY_REDIRECTS_ERROR,
errormsg=str(e)
)
except httpx.HTTPStatusError as e:
raise PubNubException(
pn_error=PNERR_HTTP_ERROR,
errormsg=str(e),
status_code=e.response.status_code
)
except Exception as e:
raise PubNubException(
pn_error=PNERR_UNKNOWN_ERROR,
errormsg=str(e)
)

return res


Expand Down
9 changes: 5 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: Implementation :: CPython',
'License :: Other/Proprietary License',
'Operating System :: OS Independent',
Expand All @@ -30,10 +33,8 @@
python_requires='>=3.7',
install_requires=[
'pycryptodomex>=3.3',
'requests>=2.4',
'httpx>=0.18',
'cbor2',
'aiohttp'
'httpx>=0.28',
'cbor2>=5.6'
],
zip_safe=False,
)
4 changes: 2 additions & 2 deletions tests/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ def pnconf_pam_copy():
return deepcopy(pnconf_pam)


def pnconf_pam_stub_copy():
return deepcopy(pnconf_pam_stub)
def pnconf_pam_stub_copy(**kwargs):
return copy_and_update(pnconf_pam_stub, **kwargs)


def pnconf_pam_acceptance_copy():
Expand Down
25 changes: 13 additions & 12 deletions tests/integrational/asyncio/test_file_upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ async def test_list_files():
await pubnub.stop()


@pn_vcr.use_cassette(
"tests/integrational/fixtures/asyncio/file_upload/send_and_download_file.json", serializer="pn_json",
filter_query_parameters=['uuid', 'l_file', 'pnsdk']
)
# @pn_vcr.use_cassette(
# "tests/integrational/fixtures/asyncio/file_upload/send_and_download_file.json", serializer="pn_json",
# filter_query_parameters=['uuid', 'l_file', 'pnsdk']
# )
@pytest.mark.asyncio(loop_scope="module")
async def test_send_and_download_file(file_for_upload):
pubnub = PubNubAsyncio(pnconf_env_copy())
Expand All @@ -83,11 +83,12 @@ async def test_send_and_download_file(file_for_upload):
await pubnub.stop()


@pn_vcr.use_cassette(
"tests/integrational/fixtures/asyncio/file_upload/send_and_download_encrypted_file_cipher_key.json",
filter_query_parameters=['uuid', 'l_file', 'pnsdk'], serializer='pn_json'
)
# @pn_vcr.use_cassette(
# "tests/integrational/fixtures/asyncio/file_upload/send_and_download_encrypted_file_cipher_key.json",
# filter_query_parameters=['uuid', 'l_file', 'pnsdk'], serializer='pn_json'
# )
@pytest.mark.asyncio(loop_scope="module")
@pytest.mark.filterwarnings("ignore:.*Usage of local cipher_keys is discouraged.*:DeprecationWarning")
async def test_send_and_download_file_encrypted_cipher_key(file_for_upload, file_upload_test_data):
pubnub = PubNubAsyncio(pnconf_enc_env_copy())

Expand All @@ -105,10 +106,10 @@ async def test_send_and_download_file_encrypted_cipher_key(file_for_upload, file
await pubnub.stop()


@pn_vcr.use_cassette(
"tests/integrational/fixtures/asyncio/file_upload/send_and_download_encrypted_file_crypto_module.json",
filter_query_parameters=['uuid', 'l_file', 'pnsdk'], serializer='pn_json'
)
# @pn_vcr.use_cassette(
# "tests/integrational/fixtures/asyncio/file_upload/send_and_download_encrypted_file_crypto_module.json",
# filter_query_parameters=['uuid', 'l_file', 'pnsdk'], serializer='pn_json'
# )
@pytest.mark.asyncio(loop_scope="module")
async def test_send_and_download_encrypted_file_crypto_module(file_for_upload, file_upload_test_data):
pubnub = PubNubAsyncio(pnconf_enc_env_copy())
Expand Down
Loading

0 comments on commit 4a4872c

Please sign in to comment.