summaryrefslogtreecommitdiff
path: root/requests_cache
diff options
context:
space:
mode:
authorJordan Cook <jordan.cook.git@proton.me>2022-12-11 22:28:55 -0600
committerJordan Cook <jordan.cook.git@proton.me>2022-12-13 16:27:49 -0600
commitf7281895698f33b9c41239b5be3a961fd1691b99 (patch)
tree233d6439c5f5a9b770a4206aed8fbe26e60d3a94 /requests_cache
parentca26b146592e08ff237cf9b6cccdba56eb2af484 (diff)
downloadrequests-cache-f7281895698f33b9c41239b5be3a961fd1691b99.tar.gz
Update type hints to appease Pylance and stricter mypy settings
Diffstat (limited to 'requests_cache')
-rw-r--r--requests_cache/_utils.py12
-rw-r--r--requests_cache/backends/__init__.py4
-rw-r--r--requests_cache/backends/base.py26
-rw-r--r--requests_cache/backends/dynamodb.py6
-rw-r--r--requests_cache/backends/filesystem.py6
-rw-r--r--requests_cache/backends/mongodb.py2
-rw-r--r--requests_cache/backends/redis.py12
-rw-r--r--requests_cache/backends/sqlite.py14
-rw-r--r--requests_cache/models/raw_response.py8
-rwxr-xr-xrequests_cache/models/response.py8
-rw-r--r--requests_cache/patcher.py2
-rw-r--r--requests_cache/policy/actions.py14
-rw-r--r--requests_cache/policy/expiration.py6
-rw-r--r--requests_cache/serializers/cattrs.py9
-rw-r--r--requests_cache/serializers/pipeline.py4
-rw-r--r--requests_cache/session.py14
16 files changed, 89 insertions, 58 deletions
diff --git a/requests_cache/_utils.py b/requests_cache/_utils.py
index ea6948f..4dbc4ec 100644
--- a/requests_cache/_utils.py
+++ b/requests_cache/_utils.py
@@ -7,9 +7,9 @@ KwargDict = Dict[str, Any]
logger = getLogger('requests_cache')
-def chunkify(iterable: Iterable, max_size: int) -> Iterator[List]:
+def chunkify(iterable: Optional[Iterable], max_size: int) -> Iterator[List]:
"""Split an iterable into chunks of a max size"""
- iterable = list(iterable)
+ iterable = list(iterable or [])
for index in range(0, len(iterable), max_size):
yield iterable[index : index + max_size]
@@ -35,7 +35,7 @@ def encode(value, encoding='utf-8') -> bytes:
return value if isinstance(value, bytes) else str(value).encode(encoding)
-def get_placeholder_class(original_exception: Exception = None):
+def get_placeholder_class(original_exception: Optional[Exception] = None):
"""Create a placeholder type for a class that does not have dependencies installed.
This allows delaying ImportErrors until init time, rather than at import time.
"""
@@ -58,14 +58,16 @@ def get_placeholder_class(original_exception: Exception = None):
return Placeholder
-def get_valid_kwargs(func: Callable, kwargs: Dict, extras: Iterable[str] = None) -> KwargDict:
+def get_valid_kwargs(
+ func: Callable, kwargs: Dict, extras: Optional[Iterable[str]] = None
+) -> KwargDict:
"""Get the subset of non-None ``kwargs`` that are valid arguments for ``func``"""
kwargs, _ = split_kwargs(func, kwargs, extras)
return {k: v for k, v in kwargs.items() if v is not None}
def split_kwargs(
- func: Callable, kwargs: Dict, extras: Iterable[str] = None
+ func: Callable, kwargs: Dict, extras: Optional[Iterable[str]] = None
) -> Tuple[KwargDict, KwargDict]:
"""Split ``kwargs`` into two dicts: those that are valid arguments for ``func``, and those that
are not
diff --git a/requests_cache/backends/__init__.py b/requests_cache/backends/__init__.py
index 9dd206a..d916ab8 100644
--- a/requests_cache/backends/__init__.py
+++ b/requests_cache/backends/__init__.py
@@ -56,7 +56,9 @@ BACKEND_CLASSES = {
}
-def init_backend(cache_name: str, backend: BackendSpecifier = None, **kwargs) -> BaseCache:
+def init_backend(
+ cache_name: str, backend: Optional[BackendSpecifier] = None, **kwargs
+) -> BaseCache:
"""Initialize a backend from a name, class, or instance"""
logger.debug(f'Initializing backend: {backend} {cache_name}')
diff --git a/requests_cache/backends/base.py b/requests_cache/backends/base.py
index efbd214..cca234a 100644
--- a/requests_cache/backends/base.py
+++ b/requests_cache/backends/base.py
@@ -73,7 +73,12 @@ class BaseCache:
except (AttributeError, KeyError):
return default
- def save_response(self, response: Response, cache_key: str = None, expires: datetime = None):
+ def save_response(
+ self,
+ response: Response,
+ cache_key: Optional[str] = None,
+ expires: Optional[datetime] = None,
+ ):
"""Save a response to the cache
Args:
@@ -101,10 +106,13 @@ class BaseCache:
self.redirects.close()
def create_key(
- self, request: AnyRequest = None, match_headers: Iterable[str] = None, **kwargs
+ self,
+ request: AnyRequest,
+ match_headers: Optional[Iterable[str]] = None,
+ **kwargs,
) -> str:
"""Create a normalized cache key from a request object"""
- key_fn = self._settings.key_fn or create_key
+ key_fn = self._settings.key_fn if self._settings.key_fn is not None else create_key
return key_fn(
request=request,
ignored_parameters=self._settings.ignored_parameters,
@@ -118,9 +126,9 @@ class BaseCache:
def contains(
self,
- key: str = None,
- request: AnyRequest = None,
- url: str = None,
+ key: Optional[str] = None,
+ request: Optional[AnyRequest] = None,
+ url: Optional[str] = None,
):
"""Check if the specified request is cached
@@ -141,8 +149,8 @@ class BaseCache:
expired: bool = False,
invalid: bool = False,
older_than: ExpirationTime = None,
- requests: Iterable[AnyRequest] = None,
- urls: Iterable[str] = None,
+ requests: Optional[Iterable[AnyRequest]] = None,
+ urls: Optional[Iterable[str]] = None,
):
"""Remove responses from the cache according one or more conditions.
@@ -355,7 +363,7 @@ class BaseStorage(MutableMapping[KT, VT], ABC):
def __init__(
self,
- serializer: SerializerType = None,
+ serializer: Optional[SerializerType] = None,
no_serializer: bool = False,
decode_content: bool = False,
**kwargs,
diff --git a/requests_cache/backends/dynamodb.py b/requests_cache/backends/dynamodb.py
index e5f0c4b..721e256 100644
--- a/requests_cache/backends/dynamodb.py
+++ b/requests_cache/backends/dynamodb.py
@@ -4,7 +4,7 @@
:classes-only:
:nosignatures:
"""
-from typing import Dict, Iterable
+from typing import Dict, Iterable, Optional
import boto3
from boto3.dynamodb.types import Binary
@@ -33,7 +33,7 @@ class DynamoDbCache(BaseCache):
self,
table_name: str = 'http_cache',
ttl: bool = True,
- connection: ServiceResource = None,
+ connection: Optional[ServiceResource] = None,
decode_content: bool = True,
**kwargs,
):
@@ -75,7 +75,7 @@ class DynamoDbDict(BaseStorage):
table_name: str,
namespace: str,
ttl: bool = True,
- connection: ServiceResource = None,
+ connection: Optional[ServiceResource] = None,
**kwargs,
):
super().__init__(**kwargs)
diff --git a/requests_cache/backends/filesystem.py b/requests_cache/backends/filesystem.py
index a349dae..cc57597 100644
--- a/requests_cache/backends/filesystem.py
+++ b/requests_cache/backends/filesystem.py
@@ -10,7 +10,7 @@ from pathlib import Path
from pickle import PickleError
from shutil import rmtree
from threading import RLock
-from typing import Iterator
+from typing import Iterator, Optional
from ..serializers import SERIALIZERS, json_serializer
from . import BaseCache, BaseStorage
@@ -75,7 +75,7 @@ class FileDict(BaseStorage):
cache_name: AnyPath,
use_temp: bool = False,
use_cache_dir: bool = False,
- extension: str = None,
+ extension: Optional[str] = None,
**kwargs,
):
super().__init__(**kwargs)
@@ -133,7 +133,7 @@ class FileDict(BaseStorage):
return self.cache_dir.glob(f'*{self.extension}')
-def _get_extension(extension: str = None, serializer=None) -> str:
+def _get_extension(extension: Optional[str] = None, serializer=None) -> str:
"""Use either the provided file extension, or get the serializer's default extension"""
if extension:
return f'.{extension}'
diff --git a/requests_cache/backends/mongodb.py b/requests_cache/backends/mongodb.py
index c719aa7..e15e331 100644
--- a/requests_cache/backends/mongodb.py
+++ b/requests_cache/backends/mongodb.py
@@ -83,7 +83,7 @@ class MongoDict(BaseStorage):
self,
db_name: str,
collection_name: str = 'http_cache',
- connection: MongoClient = None,
+ connection: Optional[MongoClient] = None,
**kwargs,
):
super().__init__(**kwargs)
diff --git a/requests_cache/backends/redis.py b/requests_cache/backends/redis.py
index 259b858..fef488c 100644
--- a/requests_cache/backends/redis.py
+++ b/requests_cache/backends/redis.py
@@ -5,7 +5,7 @@
:nosignatures:
"""
from logging import getLogger
-from typing import Iterable
+from typing import Iterable, Optional
from redis import Redis, StrictRedis
@@ -32,7 +32,7 @@ class RedisCache(BaseCache):
def __init__(
self,
namespace='http_cache',
- connection: Redis = None,
+ connection: Optional[Redis] = None,
ttl: bool = True,
ttl_offset: int = DEFAULT_TTL_OFFSET,
**kwargs,
@@ -62,7 +62,7 @@ class RedisDict(BaseStorage):
def __init__(
self,
namespace: str,
- collection_name: str = None,
+ collection_name: Optional[str] = None,
connection=None,
ttl: bool = True,
ttl_offset: int = DEFAULT_TTL_OFFSET,
@@ -144,7 +144,11 @@ class RedisHashDict(BaseStorage):
"""
def __init__(
- self, namespace: str = 'http_cache', collection_name: str = None, connection=None, **kwargs
+ self,
+ namespace: str = 'http_cache',
+ collection_name: Optional[str] = None,
+ connection=None,
+ **kwargs,
):
super().__init__(**kwargs)
connection_kwargs = get_valid_kwargs(Redis, kwargs)
diff --git a/requests_cache/backends/sqlite.py b/requests_cache/backends/sqlite.py
index f936a77..7a99a39 100644
--- a/requests_cache/backends/sqlite.py
+++ b/requests_cache/backends/sqlite.py
@@ -13,7 +13,7 @@ from os.path import getsize, isfile
from pathlib import Path
from tempfile import gettempdir
from time import time
-from typing import Collection, Iterator, List, Tuple, Type, Union
+from typing import Collection, Iterator, List, Optional, Tuple, Type, Union
from platformdirs import user_cache_dir
@@ -143,7 +143,7 @@ class SQLiteCache(BaseCache):
self,
key: str = 'expires',
reversed: bool = False,
- limit: int = None,
+ limit: Optional[int] = None,
expired: bool = True,
) -> Iterator[CachedResponse]:
"""Get cached responses, with sorting and other query options.
@@ -334,7 +334,11 @@ class SQLiteDict(BaseStorage):
return page_count * page_size
def sorted(
- self, key: str = 'expires', reversed: bool = False, limit: int = None, expired: bool = True
+ self,
+ key: str = 'expires',
+ reversed: bool = False,
+ limit: Optional[int] = None,
+ expired: bool = True,
) -> Iterator[CachedResponse]:
"""Get cache values in sorted order; see :py:meth:`.SQLiteCache.sorted` for usage details"""
# Get sort key, direction, and limit
@@ -420,9 +424,9 @@ def get_cache_path(db_path: AnyPath, use_cache_dir: bool = False, use_temp: bool
def sqlite_template(
timeout: float = 5.0,
detect_types: int = 0,
- isolation_level: str = None,
+ isolation_level: Optional[str] = None,
check_same_thread: bool = True,
- factory: Type = None,
+ factory: Optional[Type] = None,
cached_statements: int = 100,
uri: bool = False,
):
diff --git a/requests_cache/models/raw_response.py b/requests_cache/models/raw_response.py
index dfc5591..f95afab 100644
--- a/requests_cache/models/raw_response.py
+++ b/requests_cache/models/raw_response.py
@@ -1,6 +1,6 @@
from io import BytesIO
from logging import getLogger
-from typing import TYPE_CHECKING
+from typing import TYPE_CHECKING, Optional
from attr import define, field, fields_dict
from requests import Response
@@ -37,7 +37,7 @@ class CachedHTTPResponse(RichMixin, HTTPResponse):
strict: int = field(default=0)
version: int = field(default=0)
- def __init__(self, body: bytes = None, **kwargs):
+ def __init__(self, body: Optional[bytes] = None, **kwargs):
"""First initialize via HTTPResponse, then via attrs"""
kwargs = {k: v for k, v in kwargs.items() if v is not None}
super().__init__(body=BytesIO(body or b''), preload_content=False, **kwargs)
@@ -45,7 +45,7 @@ class CachedHTTPResponse(RichMixin, HTTPResponse):
self.__attrs_init__(**kwargs) # type: ignore # False positive in mypy 0.920+?
@classmethod
- def from_response(cls, response: Response):
+ def from_response(cls, response: Response) -> 'CachedHTTPResponse':
"""Create a CachedHTTPResponse based on an original response"""
# Copy basic attributes
raw = response.raw
@@ -94,7 +94,7 @@ class CachedHTTPResponse(RichMixin, HTTPResponse):
self._fp.close()
return data
- def reset(self, body: bytes = None):
+ def reset(self, body: Optional[bytes] = None):
"""Reset raw response file pointer, and optionally update content"""
if body is not None:
self._body = body
diff --git a/requests_cache/models/response.py b/requests_cache/models/response.py
index e704f03..2cd6047 100755
--- a/requests_cache/models/response.py
+++ b/requests_cache/models/response.py
@@ -11,7 +11,7 @@ from requests import PreparedRequest, Response
from requests.cookies import RequestsCookieJar
from requests.structures import CaseInsensitiveDict
-from ..policy.expiration import ExpirationTime, get_expiration_datetime
+from ..policy import ExpirationTime, get_expiration_datetime
from . import CachedHTTPResponse, CachedRequest, RichMixin
if TYPE_CHECKING:
@@ -47,7 +47,7 @@ class OriginalResponse(BaseResponse):
"""Wrapper class for non-cached responses returned by :py:class:`.CachedSession`"""
@classmethod
- def wrap_response(cls, response: Response, actions: 'CacheActions'):
+ def wrap_response(cls, response: Response, actions: 'CacheActions') -> 'OriginalResponse':
"""Modify a response object in-place and add extra cache-related attributes"""
if not isinstance(response, cls):
response.__class__ = cls
@@ -55,7 +55,7 @@ class OriginalResponse(BaseResponse):
response.expires = None if actions.skip_write else actions.expires # type: ignore
response.cache_key = None if actions.skip_write else actions.cache_key # type: ignore
response.created_at = datetime.utcnow() # type: ignore
- return response
+ return response # type: ignore
@define(auto_attribs=False, repr=False, slots=False)
@@ -85,7 +85,7 @@ class CachedResponse(RichMixin, BaseResponse):
self.raw = self.raw or CachedHTTPResponse.from_cached_response(self)
@classmethod
- def from_response(cls, response: Response, **kwargs):
+ def from_response(cls, response: Response, **kwargs) -> 'CachedResponse':
"""Create a CachedResponse based on an original Response or another CachedResponse object"""
if isinstance(response, CachedResponse):
obj = attr.evolve(response, **kwargs)
diff --git a/requests_cache/patcher.py b/requests_cache/patcher.py
index 137e928..406ee45 100644
--- a/requests_cache/patcher.py
+++ b/requests_cache/patcher.py
@@ -22,7 +22,7 @@ logger = getLogger(__name__)
def install_cache(
cache_name: str = 'http_cache',
- backend: BackendSpecifier = None,
+ backend: Optional[BackendSpecifier] = None,
session_factory: Type[OriginalSession] = CachedSession,
**kwargs,
):
diff --git a/requests_cache/policy/actions.py b/requests_cache/policy/actions.py
index bc59c13..50960cb 100644
--- a/requests_cache/policy/actions.py
+++ b/requests_cache/policy/actions.py
@@ -14,11 +14,12 @@ from . import (
NEVER_EXPIRE,
CacheDirectives,
ExpirationTime,
+ KeyCallback,
get_expiration_datetime,
get_expiration_seconds,
get_url_expiration,
)
-from .settings import CacheSettings, KeyCallback
+from .settings import CacheSettings
if TYPE_CHECKING:
from ..models import CachedResponse
@@ -71,7 +72,9 @@ class CacheActions(RichMixin):
_validation_headers: Dict[str, str] = field(factory=dict, repr=False)
@classmethod
- def from_request(cls, cache_key: str, request: PreparedRequest, settings: CacheSettings = None):
+ def from_request(
+ cls, cache_key: str, request: PreparedRequest, settings: Optional[CacheSettings] = None
+ ):
"""Initialize from request info and cache settings.
Note on refreshing: `must-revalidate` isn't a standard request header, but is used here to
@@ -133,7 +136,7 @@ class CacheActions(RichMixin):
"""
return get_expiration_datetime(self.expire_after)
- def is_usable(self, cached_response: 'CachedResponse', error: bool = False):
+ def is_usable(self, cached_response: Optional['CachedResponse'], error: bool = False):
"""Determine whether a given cached response is "fresh enough" to satisfy the request,
based on:
@@ -163,7 +166,10 @@ class CacheActions(RichMixin):
return datetime.utcnow() < cached_response.expires + offset
def update_from_cached_response(
- self, cached_response: 'CachedResponse', create_key: KeyCallback = None, **key_kwargs
+ self,
+ cached_response: Optional['CachedResponse'],
+ create_key: Optional[KeyCallback] = None,
+ **key_kwargs,
):
"""Determine if we can reuse a cached response, or set headers for a conditional request
if possible.
diff --git a/requests_cache/policy/expiration.py b/requests_cache/policy/expiration.py
index 256ab91..18a2593 100644
--- a/requests_cache/policy/expiration.py
+++ b/requests_cache/policy/expiration.py
@@ -18,7 +18,9 @@ logger = getLogger(__name__)
def get_expiration_datetime(
- expire_after: ExpirationTime, start_time: datetime = None, negative_delta: bool = False
+ expire_after: ExpirationTime,
+ start_time: Optional[datetime] = None,
+ negative_delta: bool = False,
) -> Optional[datetime]:
"""Convert an expiration value in any supported format to an absolute datetime"""
# Never expire (or do not cache, in which case expiration won't be used)
@@ -50,7 +52,7 @@ def get_expiration_seconds(expire_after: ExpirationTime) -> int:
def get_url_expiration(
- url: Optional[str], urls_expire_after: ExpirationPatterns = None
+ url: Optional[str], urls_expire_after: Optional[ExpirationPatterns] = None
) -> ExpirationTime:
"""Check for a matching per-URL expiration, if any"""
if not url:
diff --git a/requests_cache/serializers/cattrs.py b/requests_cache/serializers/cattrs.py
index 13d05e6..bf45c2d 100644
--- a/requests_cache/serializers/cattrs.py
+++ b/requests_cache/serializers/cattrs.py
@@ -14,7 +14,7 @@ serialization formats.
from datetime import datetime, timedelta
from decimal import Decimal
from json import JSONDecodeError
-from typing import Callable, Dict, ForwardRef, MutableMapping
+from typing import Callable, Dict, ForwardRef, MutableMapping, Optional
from cattr import Converter
from requests.cookies import RequestsCookieJar, cookiejar_from_dict
@@ -50,7 +50,10 @@ class CattrStage(Stage):
"""
def __init__(
- self, factory: Callable[..., Converter] = None, decode_content: bool = False, **kwargs
+ self,
+ factory: Optional[Callable[..., Converter]] = None,
+ decode_content: bool = False,
+ **kwargs
):
self.converter = init_converter(factory, **kwargs)
self.decode_content = decode_content
@@ -68,7 +71,7 @@ class CattrStage(Stage):
def init_converter(
- factory: Callable[..., Converter] = None,
+ factory: Optional[Callable[..., Converter]] = None,
convert_datetime: bool = True,
convert_timedelta: bool = True,
) -> Converter:
diff --git a/requests_cache/serializers/pipeline.py b/requests_cache/serializers/pipeline.py
index 652c8f5..320e498 100644
--- a/requests_cache/serializers/pipeline.py
+++ b/requests_cache/serializers/pipeline.py
@@ -4,7 +4,7 @@
:classes-only:
:nosignatures:
"""
-from typing import Any, Callable, Sequence, Union
+from typing import Any, Callable, Optional, Sequence, Union
from ..models import CachedResponse
@@ -43,7 +43,7 @@ class SerializerPipeline:
is_binary: Indicates whether the serialized content is binary
"""
- def __init__(self, stages: Sequence, name: str = None, is_binary: bool = False):
+ def __init__(self, stages: Sequence, name: Optional[str] = None, is_binary: bool = False):
self.is_binary = is_binary
self.stages = stages
self.dump_stages = [stage.dumps for stage in stages]
diff --git a/requests_cache/session.py b/requests_cache/session.py
index d94adf8..c0e2563 100644
--- a/requests_cache/session.py
+++ b/requests_cache/session.py
@@ -44,18 +44,18 @@ class CacheMixin(MIXIN_BASE):
def __init__(
self,
cache_name: str = DEFAULT_CACHE_NAME,
- backend: BackendSpecifier = None,
- serializer: SerializerType = None,
+ backend: Optional[BackendSpecifier] = None,
+ serializer: Optional[SerializerType] = None,
expire_after: ExpirationTime = -1,
- urls_expire_after: ExpirationPatterns = None,
+ urls_expire_after: Optional[ExpirationPatterns] = None,
cache_control: bool = False,
allowable_codes: Iterable[int] = DEFAULT_STATUS_CODES,
allowable_methods: Iterable[str] = DEFAULT_METHODS,
always_revalidate: bool = False,
ignored_parameters: Iterable[str] = DEFAULT_IGNORED_PARAMS,
match_headers: Union[Iterable[str], bool] = False,
- filter_fn: FilterCallback = None,
- key_fn: KeyCallback = None,
+ filter_fn: Optional[FilterCallback] = None,
+ key_fn: Optional[KeyCallback] = None,
stale_if_error: Union[bool, int] = False,
**kwargs,
):
@@ -127,7 +127,7 @@ class CacheMixin(MIXIN_BASE):
method: str,
url: str,
*args,
- headers: MutableMapping[str, str] = None,
+ headers: Optional[MutableMapping[str, str]] = None,
expire_after: ExpirationTime = None,
only_if_cached: bool = False,
refresh: bool = False,
@@ -220,7 +220,7 @@ class CacheMixin(MIXIN_BASE):
self,
request: PreparedRequest,
actions: CacheActions,
- cached_response: CachedResponse = None,
+ cached_response: Optional[CachedResponse] = None,
**kwargs,
) -> AnyResponse:
"""Send a request and cache the response, unless disabled by settings or headers.