Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions django-stubs/core/cache/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
from collections import OrderedDict
from collections.abc import Callable
from typing import Any

from django.utils.connection import BaseConnectionHandler
from typing_extensions import override

from .backends.base import BaseCache as BaseCache
from .backends.base import CacheKeyWarning as CacheKeyWarning
from .backends.base import InvalidCacheBackendError as InvalidCacheBackendError
from .backends.base import InvalidCacheKey as InvalidCacheKey

DEFAULT_CACHE_ALIAS: str

class CacheHandler:
def __init__(self) -> None: ...
def __getitem__(self, alias: str) -> BaseCache: ...
def all(self) -> Any: ...
class CacheHandler(BaseConnectionHandler[BaseCache]):
settings_name: str
exception_class: type[Exception]
@override
def create_connection(self, alias: str) -> BaseCache: ...
@override
def all(self, initialized_only: bool = False) -> list[BaseCache]: ...

class DefaultCacheProxy:
def __getattr__(self, name: str) -> Callable[..., Any] | dict[str, float] | OrderedDict[Any, Any] | int: ...
def __setattr__(self, name: str, value: Callable[..., Any]) -> None: ...
def __delattr__(self, name: Any) -> Any: ...
def __contains__(self, key: str) -> bool: ...
def close_caches(**kwargs: Any) -> None: ...

cache: BaseCache
caches: CacheHandler
# Actually ConnectionProxy, but quacks exactly like BaseCache, it's not worth distinguishing the two.
cache: BaseCache

__all__ = [
"DEFAULT_CACHE_ALIAS",
"BaseCache",
"CacheKeyWarning",
"InvalidCacheBackendError",
"InvalidCacheKey",
"cache",
"caches",
]
125 changes: 52 additions & 73 deletions django-stubs/core/cache/backends/base.pyi
Original file line number Diff line number Diff line change
@@ -1,93 +1,72 @@
from collections.abc import Callable, Iterable
from collections.abc import Callable, Iterable, Iterator
from re import Pattern
from typing import Any

from django.core.exceptions import ImproperlyConfigured

class InvalidCacheBackendError(ImproperlyConfigured): ...
class CacheKeyWarning(RuntimeWarning): ...
class InvalidCacheKey(ValueError): ...

DEFAULT_TIMEOUT: int
DEFAULT_TIMEOUT: Any
MEMCACHE_MAX_KEY_LENGTH: int

def default_key_func(key: str, key_prefix: str, version: Any) -> str: ...
def get_key_func(key_func: Callable[..., Any] | str | None) -> Callable[..., Any]: ...
def default_key_func(key: Any, key_prefix: str, version: Any) -> str: ...
def get_key_func(key_func: Callable | str | None) -> Callable: ...

class BaseCache:
default_timeout: int = ...
key_prefix: str = ...
version: int = ...
key_func: Callable[..., Any] = ...
_missing_key: object
default_timeout: float | None
_max_entries: int
_cull_frequency: int
key_prefix: str
version: int
key_func: Callable
def __init__(self, params: dict[str, Any]) -> None: ...
def get_backend_timeout(self, timeout: int | None = ...) -> float | None: ...
def make_key(self, key: str, version: int | None = ...) -> str: ...
def add(
self,
key: str,
value: Any,
timeout: int | None = ...,
version: int | None = ...,
) -> bool: ...
async def aadd(
self,
key: str,
value: Any,
timeout: int | None = ...,
version: int | None = ...,
) -> bool: ...
def get(self, key: str, default: Any | None = ..., version: int | None = ...) -> Any: ...
async def aget(self, key: str, default: Any | None = ..., version: int | None = ...) -> Any: ...
def set(
self,
key: str,
value: Any,
timeout: int | None = ...,
version: int | None = ...,
) -> None: ...
async def aset(
self,
key: str,
value: Any,
timeout: int | None = ...,
version: int | None = ...,
) -> None: ...
def touch(self, key: str, timeout: int | None = ..., version: int | None = ...) -> bool: ...
def delete(self, key: str, version: int | None = ...) -> None: ...
def get_many(self, keys: Iterable[str], version: int | None = ...) -> dict[str, int | str]: ...
async def aget_many(self, keys: Iterable[str], version: int | None = ...) -> dict[str, int | str]: ...
def get_backend_timeout(self, timeout: float | None = ...) -> float | None: ...
def make_key(self, key: Any, version: int | None = None) -> str: ...
def validate_key(self, key: Any) -> None: ...
def make_and_validate_key(self, key: Any, version: int | None = None) -> str: ...
def add(self, key: Any, value: Any, timeout: float | None = ..., version: int | None = None) -> bool: ...
async def aadd(self, key: Any, value: Any, timeout: float | None = ..., version: int | None = None) -> bool: ...
def get(self, key: Any, default: Any | None = None, version: int | None = None) -> Any: ...
async def aget(self, key: Any, default: Any | None = None, version: int | None = None) -> Any: ...
def set(self, key: Any, value: Any, timeout: float | None = ..., version: int | None = None) -> None: ...
async def aset(self, key: Any, value: Any, timeout: float | None = ..., version: int | None = None) -> None: ...
def touch(self, key: Any, timeout: float | None = ..., version: int | None = None) -> bool: ...
async def atouch(self, key: Any, timeout: float | None = ..., version: int | None = None) -> bool: ...
def delete(self, key: Any, version: int | None = None) -> bool: ...
async def adelete(self, key: Any, version: int | None = None) -> bool: ...
def get_many(self, keys: Iterable[Any], version: int | None = None) -> dict[Any, Any]: ...
async def aget_many(self, keys: Iterable[Any], version: int | None = None) -> dict[Any, Any]: ...
def get_or_set(
self,
key: str,
default: Any | None,
timeout: int | None = ...,
version: int | None = ...,
self, key: Any, default: Any | None, timeout: float | None = ..., version: int | None = None
) -> Any | None: ...
async def aget_or_set(
self,
key: str,
default: Any | None,
timeout: int | None = ...,
version: int | None = ...,
self, key: Any, default: Any | None, timeout: float | None = ..., version: int | None = None
) -> Any | None: ...
def has_key(self, key: str, version: int | None = ...) -> bool: ...
def incr(self, key: str, delta: int = ..., version: int | None = ...) -> int: ...
def decr(self, key: str, delta: int = ..., version: int | None = ...) -> int: ...
def __contains__(self, key: str) -> bool: ...
def set_many(
self,
data: dict[str, Any],
timeout: int | None = ...,
version: int | None = ...,
) -> list[Any]: ...
def has_key(self, key: Any, version: int | None = None) -> bool: ...
async def ahas_key(self, key: Any, version: int | None = None) -> bool: ...
def incr(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
async def aincr(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
def decr(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
async def adecr(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
def __contains__(self, key: Any) -> bool: ...
def set_many(self, data: dict[Any, Any], timeout: float | None = ..., version: int | None = None) -> list[Any]: ...
async def aset_many(
self,
data: dict[str, Any],
timeout: int | None = ...,
version: int | None = ...,
self, data: dict[Any, Any], timeout: float | None = ..., version: int | None = None
) -> list[Any]: ...
def delete_many(self, keys: Iterable[str], version: int | None = ...) -> None: ...
async def adelete_many(self, keys: Iterable[str], version: int | None = ...) -> None: ...
def delete_many(self, keys: Iterable[Any], version: int | None = None) -> None: ...
async def adelete_many(self, keys: Iterable[Any], version: int | None = None) -> None: ...
def clear(self) -> None: ...
def validate_key(self, key: str) -> None: ...
def incr_version(self, key: str, delta: int = ..., version: int | None = ...) -> int: ...
def decr_version(self, key: str, delta: int = ..., version: int | None = ...) -> int: ...
async def aclear(self) -> None: ...
def incr_version(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
async def aincr_version(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
def decr_version(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
async def adecr_version(self, key: Any, delta: int = 1, version: int | None = None) -> int: ...
def close(self, **kwargs: Any) -> None: ...
async def aclose(self, **kwargs: Any) -> None: ...

memcached_error_chars_re: Pattern[str]

def memcache_key_warnings(key: str) -> Iterator[str]: ...
27 changes: 14 additions & 13 deletions django-stubs/core/cache/backends/db.pyi
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
from typing import Any
from typing import Any, ClassVar

from django.core.cache.backends.base import BaseCache
from django.utils.functional import _StrOrPromise

class Options:
db_table: str = ...
app_label: str = ...
model_name: str = ...
verbose_name: _StrOrPromise = ...
verbose_name_plural: _StrOrPromise = ...
object_name: str = ...
abstract: bool = ...
managed: bool = ...
proxy: bool = ...
swapped: bool = ...
db_table: str
app_label: str
model_name: str
verbose_name: _StrOrPromise
verbose_name_plural: _StrOrPromise
object_name: str
abstract: bool
managed: bool
proxy: bool
swapped: bool
def __init__(self, table: str) -> None: ...

class BaseDatabaseCache(BaseCache):
cache_model_class: Any = ...
cache_model_class: Any
def __init__(self, table: str, params: dict[str, Any]) -> None: ...

class DatabaseCache(BaseDatabaseCache): ...
class DatabaseCache(BaseDatabaseCache):
pickle_protocol: ClassVar[int]
5 changes: 3 additions & 2 deletions django-stubs/core/cache/backends/filebased.pyi
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from typing import Any
from typing import Any, ClassVar

from django.core.cache.backends.base import BaseCache

class FileBasedCache(BaseCache):
cache_suffix: str = ...
cache_suffix: ClassVar[str]
pickle_protocol: ClassVar[int]
def __init__(self, dir: str, params: dict[str, Any]) -> None: ...
4 changes: 3 additions & 1 deletion django-stubs/core/cache/backends/locmem.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Any
from typing import Any, ClassVar

from django.core.cache.backends.base import BaseCache

class LocMemCache(BaseCache):
pickle_protocol: ClassVar[int]

def __init__(self, name: str, params: dict[str, Any]) -> None: ...
24 changes: 19 additions & 5 deletions django-stubs/core/cache/backends/memcached.pyi
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
from collections.abc import Sequence
from types import ModuleType
from typing import Any

from django.core.cache.backends.base import BaseCache
from typing_extensions import override

class BaseMemcachedCache(BaseCache):
def __init__(self, server: Any, params: Any, library: Any, value_not_found_exception: Any) -> None: ...

class MemcachedCache(BaseMemcachedCache):
def __init__(self, server: Any, params: Any) -> None: ...
def __init__(
self,
server: str | Sequence[str],
params: dict[str, Any],
library: ModuleType,
value_not_found_exception: type[BaseException],
) -> None: ...
@property
def client_servers(self) -> Sequence[str]: ...

class PyLibMCCache(BaseMemcachedCache):
def __init__(self, server: Any, params: Any) -> None: ...
def __init__(self, server: str | Sequence[str], params: dict[str, Any]) -> None: ...
@property
@override
def client_servers(self) -> list[str]: ...

class PyMemcacheCache(BaseMemcachedCache):
def __init__(self, server: str | Sequence[str], params: dict[str, Any]) -> None: ...
58 changes: 58 additions & 0 deletions django-stubs/core/cache/backends/redis.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from collections.abc import Callable, Iterable, Mapping
from datetime import timedelta
from typing import Any, Protocol, SupportsInt, TypeAlias, overload, type_check_only

from _typeshed import ReadableBuffer
from django.core.cache.backends.base import BaseCache
from django.utils.functional import cached_property
from redis._parsers import BaseParser
from redis.client import Redis
from redis.connection import ConnectionPool

@type_check_only
class _RedisCacheClientSerializer(Protocol):
def dumps(self, obj: Any) -> bytes: ...
@overload
def loads(self, data: SupportsInt) -> int: ...
@overload
def loads(self, data: ReadableBuffer) -> Any: ...

class RedisSerializer:
def __init__(self, protocol: int | None = None) -> None: ...
def dumps(self, obj: Any) -> bytes: ...
@overload
def loads(self, data: SupportsInt) -> int: ...
@overload
def loads(self, data: ReadableBuffer) -> Any: ...

# Taken from https://github.com/redis/redis-py/blob/6b8978/redis/typing.py
_Key: TypeAlias = str | bytes | memoryview
_Expiry: TypeAlias = int | timedelta

class RedisCacheClient:
def __init__(
self,
servers: list[str],
serializer: str | Callable[[], _RedisCacheClientSerializer] | _RedisCacheClientSerializer | None = None,
pool_class: str | type[ConnectionPool] | None = None,
parser_class: str | type[BaseParser] | None = None,
**options: Any,
) -> None: ...
def get_client(self, key: _Key | None = None, *, write: bool = False) -> Redis: ...
def add(self, key: _Key, value: Any, timeout: _Expiry | None) -> bool: ...
def get(self, key: _Key, default: Any) -> Any: ...
def set(self, key: _Key, value: Any, timeout: _Expiry | None) -> None: ...
def touch(self, key: _Key, timeout: _Expiry) -> bool: ...
def delete(self, key: _Key) -> bool: ...
def get_many(self, keys: Iterable[_Key]) -> dict[_Key, Any]: ...
def has_key(self, key: _Key) -> bool: ...
def incr(self, key: _Key, delta: int) -> Any: ...
def set_many(self, data: Mapping[_Key, Any], timeout: _Expiry) -> None: ...
def delete_many(self, keys: Iterable[_Key]) -> None: ...
def clear(self) -> bool: ...

class RedisCache(BaseCache):
def __init__(self, server: str | list[str], params: dict[str, Any]) -> None: ...
# We need this, because it is the only way to get the Redis connection from cache:
@cached_property
def _cache(self) -> RedisCacheClient: ...
2 changes: 1 addition & 1 deletion django-stubs/core/cache/utils.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ from typing import Any

TEMPLATE_FRAGMENT_KEY_TEMPLATE: str

def make_template_fragment_key(fragment_name: str, vary_on: Iterable[Any] | None = ...) -> str: ...
def make_template_fragment_key(fragment_name: str, vary_on: Iterable[Any] | None = None) -> str: ...
2 changes: 1 addition & 1 deletion django-stubs/utils/connection.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class ConnectionProxy(Generic[_T]):
class ConnectionDoesNotExist(Exception): ...

class BaseConnectionHandler(_SupportsContains[str], Generic[_T]):
settings_name: str | None
settings_name: str
exception_class: type[Exception]
thread_critical: bool
@cached_property
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dev = [
"pyright>=1.1.406",
"ruff>=0.1.0",
"tomlkit>=0.12.1",
"redis>=7.4.0",
]


Expand Down
2 changes: 1 addition & 1 deletion s/sync
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ set -e

DJANGO_STUBS_TARGET_TAG="6.0.5"
git fetch https://github.com/typeddjango/django-stubs.git $DJANGO_STUBS_TARGET_TAG
git checkout $DJANGO_STUBS_TARGET_TAG -- django-stubs/tasks/
git checkout $DJANGO_STUBS_TARGET_TAG -- django-stubs/tasks/ django-stubs/core/cache

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SYNC_FILES="$SCRIPT_DIR/sync-files.txt"
Expand Down
Loading
Loading