summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Cook <jordan.cook@pioneer.com>2022-04-09 13:33:32 -0500
committerJordan Cook <jordan.cook@pioneer.com>2022-04-09 15:42:39 -0500
commit82e68b9f917ddc78feaa19fb4d63fffe20047089 (patch)
tree8e3b7c0babaa49780639321cdfa01f9d3c4eb473
parent9c2defeba951fc166d1d6b5079f0ae7d73dde361 (diff)
downloadrequests-cache-82e68b9f917ddc78feaa19fb4d63fffe20047089.tar.gz
Add compatibility with cattrs 21.1+, and clean up preconf module a bit
-rw-r--r--poetry.lock52
-rw-r--r--pyproject.toml2
-rw-r--r--requests_cache/__init__.py2
-rw-r--r--requests_cache/serializers/preconf.py89
4 files changed, 84 insertions, 61 deletions
diff --git a/poetry.lock b/poetry.lock
index 5db2e9b..6fe2a64 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -63,11 +63,11 @@ pytz = ">=2015.7"
[[package]]
name = "beautifulsoup4"
-version = "4.10.0"
+version = "4.11.1"
description = "Screen-scraping library"
category = "main"
optional = true
-python-versions = ">3.0.0"
+python-versions = ">=3.6.0"
[package.dependencies]
soupsieve = ">1.2"
@@ -78,14 +78,14 @@ lxml = ["lxml"]
[[package]]
name = "boto3"
-version = "1.21.35"
+version = "1.21.37"
description = "The AWS SDK for Python"
category = "main"
optional = true
python-versions = ">= 3.6"
[package.dependencies]
-botocore = ">=1.24.35,<1.25.0"
+botocore = ">=1.24.37,<1.25.0"
jmespath = ">=0.7.1,<2.0.0"
s3transfer = ">=0.5.0,<0.6.0"
@@ -94,7 +94,7 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
[[package]]
name = "botocore"
-version = "1.24.35"
+version = "1.24.37"
description = "Low-level, data-driven core of boto 3."
category = "main"
optional = true
@@ -122,7 +122,7 @@ six = ">=1.9.0"
[[package]]
name = "cattrs"
-version = "1.10.0"
+version = "22.1.0"
description = "Composable complex class support for attrs and dataclasses."
category = "main"
optional = false
@@ -130,6 +130,7 @@ python-versions = ">=3.7,<4.0"
[package.dependencies]
attrs = ">=20"
+exceptiongroup = {version = "*", markers = "python_version <= \"3.10\""}
typing_extensions = {version = "*", markers = "python_version >= \"3.7\" and python_version < \"3.8\""}
[[package]]
@@ -237,6 +238,17 @@ optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
+name = "exceptiongroup"
+version = "1.0.0rc2"
+description = "Backport of PEP 654 (exception groups)"
+category = "main"
+optional = false
+python-versions = ">=3.7"
+
+[package.extras]
+test = ["pytest (>=6)", "coverage (>=6)"]
+
+[[package]]
name = "execnet"
version = "1.9.0"
description = "execnet: rapid multi-Python deployment"
@@ -261,7 +273,7 @@ testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-co
[[package]]
name = "furo"
-version = "2022.3.4"
+version = "2022.4.7"
description = "A clean customisable Sphinx documentation theme."
category = "main"
optional = true
@@ -1259,7 +1271,7 @@ yaml = ["pyyaml"]
[metadata]
lock-version = "1.1"
python-versions = "^3.7"
-content-hash = "ef51335c82b4ea675988ed97c3f9f67f24a2cad0c6edec0d1695cd68ed686ffe"
+content-hash = "5cb2e245d8e7642d221b6fb33465920b316e2e8e318db4c833a7ba919ee145d3"
[metadata.files]
alabaster = [
@@ -1287,23 +1299,23 @@ babel = [
{file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"},
]
beautifulsoup4 = [
- {file = "beautifulsoup4-4.10.0-py3-none-any.whl", hash = "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf"},
- {file = "beautifulsoup4-4.10.0.tar.gz", hash = "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891"},
+ {file = "beautifulsoup4-4.11.1-py3-none-any.whl", hash = "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30"},
+ {file = "beautifulsoup4-4.11.1.tar.gz", hash = "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693"},
]
boto3 = [
- {file = "boto3-1.21.35-py3-none-any.whl", hash = "sha256:4fb810755bca4696effbeb0c6f792295795fae52e895638038dff53965f3f423"},
- {file = "boto3-1.21.35.tar.gz", hash = "sha256:ab6e001ba9de1db986634424abff6c79d938c15d0d2fa3ef95eb0939c120b4f6"},
+ {file = "boto3-1.21.37-py3-none-any.whl", hash = "sha256:1e845aa92b3ad70b954329b98835135c28b3000e322ff8d3fc46a956bdb6e94b"},
+ {file = "boto3-1.21.37.tar.gz", hash = "sha256:013ba57295f05da141e364191dd46f4086e8fe3eb83a3cd09730eeb684ffbab3"},
]
botocore = [
- {file = "botocore-1.24.35-py3-none-any.whl", hash = "sha256:734aa598af5d6bc0351e6ecce4a91b0b6ccf245febfd8d4de8425211aada5f36"},
- {file = "botocore-1.24.35.tar.gz", hash = "sha256:36b5422d8f0c312983582b8b4b056c98e1fd6121cb0b2ddb1f67e882e1ae6867"},
+ {file = "botocore-1.24.37-py3-none-any.whl", hash = "sha256:21e164a213beca36033c46026bffa62f2ee2cd2600777271f9a551fb34dba006"},
+ {file = "botocore-1.24.37.tar.gz", hash = "sha256:70c48c4ae3c2b9ec0ca025385979d01f4c7dae4d9a61c82758d4cf7caa7082cd"},
]
bson = [
{file = "bson-0.5.10.tar.gz", hash = "sha256:d6511b2ab051139a9123c184de1a04227262173ad593429d21e443d6462d6590"},
]
cattrs = [
- {file = "cattrs-1.10.0-py3-none-any.whl", hash = "sha256:35dd9063244263e63bd0bd24ea61e3015b00272cead084b2c40d788b0f857c46"},
- {file = "cattrs-1.10.0.tar.gz", hash = "sha256:211800f725cdecedcbcf4c753bbd22d248312b37d130f06045434acb7d9b34e1"},
+ {file = "cattrs-22.1.0-py3-none-any.whl", hash = "sha256:d55c477b4672f93606e992049f15d526dc7867e6c756cd6256d4af92e2b1e364"},
+ {file = "cattrs-22.1.0.tar.gz", hash = "sha256:94b67b64cf92c994f8784c40c082177dc916e0489a73a9a36b24eb18a9db40c6"},
]
certifi = [
{file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"},
@@ -1384,6 +1396,10 @@ docutils = [
{file = "docutils-0.17.1-py2.py3-none-any.whl", hash = "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61"},
{file = "docutils-0.17.1.tar.gz", hash = "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125"},
]
+exceptiongroup = [
+ {file = "exceptiongroup-1.0.0rc2-py3-none-any.whl", hash = "sha256:83e465152bd0bc2bc40d9b75686854260f86946bb947c652b5cafc31cdff70e7"},
+ {file = "exceptiongroup-1.0.0rc2.tar.gz", hash = "sha256:4d254b05231bed1d43079bdcfe0f1d66c0ab4783e6777a329355f9b78de3ad83"},
+]
execnet = [
{file = "execnet-1.9.0-py2.py3-none-any.whl", hash = "sha256:a295f7cc774947aac58dde7fdc85f4aa00c42adf5d8f5468fc630c1acf30a142"},
{file = "execnet-1.9.0.tar.gz", hash = "sha256:8f694f3ba9cc92cab508b152dcfe322153975c29bda272e2fd7f3f00f36e47c5"},
@@ -1393,8 +1409,8 @@ filelock = [
{file = "filelock-3.6.0.tar.gz", hash = "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85"},
]
furo = [
- {file = "furo-2022.3.4-py3-none-any.whl", hash = "sha256:6c718293ebf87755f0b9f148b1e697c9e3aabd7af955644d4bcaee5ce75db781"},
- {file = "furo-2022.3.4.tar.gz", hash = "sha256:7660267cc67b2828fd0e17bc07adeb612c47b2eba5a6de07049a1569e6044aa8"},
+ {file = "furo-2022.4.7-py3-none-any.whl", hash = "sha256:7f3e3d2fb977483590f8ecb2c2cd511bd82661b79c18efb24de9558bc9cdf2d7"},
+ {file = "furo-2022.4.7.tar.gz", hash = "sha256:96204ab7cd047e4b6c523996e0279c4c629a8fc31f4f109b2efd470c17f49c80"},
]
identify = [
{file = "identify-2.4.12-py2.py3-none-any.whl", hash = "sha256:5f06b14366bd1facb88b00540a1de05b69b310cbc2654db3c7e07fa3a4339323"},
diff --git a/pyproject.toml b/pyproject.toml
index a39fd4b..ae9fec9 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -32,7 +32,7 @@ python = "^3.7"
requests = "^2.22" # Needs no introduction
urllib3 = ">=1.25.5" # Use a slightly newer version than required by requests (for bugfixes)
attrs = ">=21.2" # For response data models
-cattrs = "^1.8" # For response serialization
+cattrs = ">=22.0" # For response serialization
platformdirs = "^2.5" # For options that use platform-specific user cache dirs
url-normalize = "^1.4" # For improved request matching
diff --git a/requests_cache/__init__.py b/requests_cache/__init__.py
index b752000..81da8e9 100644
--- a/requests_cache/__init__.py
+++ b/requests_cache/__init__.py
@@ -18,4 +18,4 @@ try:
from .settings import *
# Log and ignore ImportErrors, if imported outside a virtualenv (e.g., just to check __version__)
except ImportError as e:
- logger.warning(e)
+ logger.warning(e, exc_info=True)
diff --git a/requests_cache/serializers/preconf.py b/requests_cache/serializers/preconf.py
index ed19fb4..cb099b8 100644
--- a/requests_cache/serializers/preconf.py
+++ b/requests_cache/serializers/preconf.py
@@ -1,3 +1,4 @@
+# flake8: noqa: F841
"""The ``cattrs`` library includes a number of `pre-configured converters
<https://cattrs.readthedocs.io/en/latest/preconf.html>`_ that perform some pre-serialization steps
required for specific serialization formats.
@@ -14,69 +15,75 @@ class that raises an ``ImportError`` at initialization time instead of at import
"""
import pickle
from functools import partial
-
-from cattr.preconf import bson as bson_preconf
-from cattr.preconf import json as json_preconf
-from cattr.preconf import msgpack, orjson, pyyaml, tomlkit, ujson
+from importlib import import_module
from .._utils import get_placeholder_class
from .cattrs import CattrStage
from .pipeline import SerializerPipeline, Stage
-base_stage = (
- CattrStage()
-) #: Base stage for all serializer pipelines (or standalone dict serializer)
+
+def make_stage(preconf_module: str):
+ """Create a preconf serializer stage from a module name, if dependencies are installed"""
+ try:
+ return CattrStage(import_module(preconf_module).make_converter)
+ except ImportError as e:
+ return get_placeholder_class(e)
+
+
+base_stage = CattrStage() #: Base stage for all serializer pipelines
dict_serializer = base_stage #: Partial serializer that unstructures responses into dicts
-bson_preconf_stage = CattrStage(bson_preconf.make_converter) #: Pre-serialization steps for BSON
-json_preconf_stage = CattrStage(json_preconf.make_converter) #: Pre-serialization steps for JSON
-msgpack_preconf_stage = CattrStage(msgpack.make_converter) #: Pre-serialization steps for msgpack
-orjson_preconf_stage = CattrStage(orjson.make_converter) #: Pre-serialization steps for orjson
-yaml_preconf_stage = CattrStage(pyyaml.make_converter) #: Pre-serialization steps for YAML
-toml_preconf_stage = CattrStage(tomlkit.make_converter) #: Pre-serialization steps for TOML
-ujson_preconf_stage = CattrStage(ujson.make_converter) #: Pre-serialization steps for ultrajson
-pickle_serializer = SerializerPipeline(
- [base_stage, pickle], is_binary=True
-) #: Complete pickle serializer
+pickle_serializer = SerializerPipeline([base_stage, pickle], is_binary=True) #: Pickle serializer
utf8_encoder = Stage(dumps=str.encode, loads=lambda x: x.decode()) #: Encode to bytes
+bson_preconf_stage = make_stage('cattr.preconf.bson') #: Pre-serialization steps for BSON
+json_preconf_stage = make_stage('cattr.preconf.json') #: Pre-serialization steps for JSON
+msgpack_preconf_stage = make_stage('cattr.preconf.msgpack') #: Pre-serialization steps for msgpack
+orjson_preconf_stage = make_stage('cattr.preconf.orjson') #: Pre-serialization steps for orjson
+toml_preconf_stage = make_stage('cattr.preconf.tomlkit') #: Pre-serialization steps for TOML
+ujson_preconf_stage = make_stage('cattr.preconf.ujson') #: Pre-serialization steps for ultrajson
+yaml_preconf_stage = make_stage('cattr.preconf.pyyaml') #: Pre-serialization steps for YAML
# Safe pickle serializer
-try:
+def signer_stage(secret_key=None, salt='requests-cache') -> Stage:
+ """Create a stage that uses ``itsdangerous`` to add a signature to responses on write, and
+ validate that signature with a secret key on read. Can be used in a
+ :py:class:`.SerializerPipeline` in combination with any other serialization steps.
+ """
from itsdangerous import Signer
- def signer_stage(secret_key=None, salt='requests-cache') -> Stage:
- """Create a stage that uses ``itsdangerous`` to add a signature to responses on write, and
- validate that signature with a secret key on read. Can be used in a
- :py:class:`.SerializerPipeline` in combination with any other serialization steps.
- """
- return Stage(Signer(secret_key=secret_key, salt=salt), dumps='sign', loads='unsign')
-
- def safe_pickle_serializer(
- secret_key=None, salt='requests-cache', **kwargs
- ) -> SerializerPipeline:
- """Create a serializer that uses ``pickle`` + ``itsdangerous`` to add a signature to
- responses on write, and validate that signature with a secret key on read.
- """
- return SerializerPipeline(
- [base_stage, pickle, signer_stage(secret_key, salt)], is_binary=True
- )
+ return Stage(Signer(secret_key=secret_key, salt=salt), dumps='sign', loads='unsign')
+
+
+def safe_pickle_serializer(secret_key=None, salt='requests-cache', **kwargs) -> SerializerPipeline:
+ """Create a serializer that uses ``pickle`` + ``itsdangerous`` to add a signature to
+ responses on write, and validate that signature with a secret key on read.
+ """
+ return SerializerPipeline([base_stage, pickle, signer_stage(secret_key, salt)], is_binary=True)
+
+try:
+ import itsdangerous # noqa: F401
except ImportError as e:
signer_stage = get_placeholder_class(e)
safe_pickle_serializer = get_placeholder_class(e)
-# BSON serializer
-try:
+def _get_bson_functions():
+ """Handle different function names between pymongo's bson and standalone bson"""
try:
- from bson import decode as _bson_loads
- from bson import encode as _bson_dumps
+ import pymongo # noqa: F401
+
+ return {'dumps': 'encode', 'loads': 'decode'}
except ImportError:
- from bson import dumps as _bson_dumps
- from bson import loads as _bson_loads
+ return {'dumps': 'dumps', 'loads': 'loads'}
+
+
+# BSON serializer
+try:
+ import bson
bson_serializer = SerializerPipeline(
- [bson_preconf_stage, Stage(dumps=_bson_dumps, loads=_bson_loads)], is_binary=True
+ [bson_preconf_stage, Stage(bson, **_get_bson_functions())], is_binary=True
) #: Complete BSON serializer; uses pymongo's ``bson`` if installed, otherwise standalone ``bson`` codec
except ImportError as e:
bson_serializer = get_placeholder_class(e)