Skip to content

Commit

Permalink
Setup mypy config and pre-commit hook
Browse files Browse the repository at this point in the history
  • Loading branch information
unmade committed Sep 20, 2023
1 parent eee4b27 commit 5fe74a7
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 32 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,10 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4

- name: install extras for mypy
run: |
pip install -e ".[redis,diskcache,speedup,dill,lint]"
pip install starlette
- uses: pre-commit/action@v3.0.0
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ build/
*.egg-info
.tox
.hypothesis
.pytest_cache
.mypy_cache
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ repos:
rev: 6.0.0
hooks:
- id: flake8

- repo: local
hooks:
- id: mypy
name: mypy
entry: python3 -m mypy
exclude: (^tests/|^perf/|^examples/|setup.py)
language: system
types: [python]
4 changes: 2 additions & 2 deletions cashews/backends/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ async def scan(self, pattern: str, batch_size: int = 100) -> AsyncIterator[Key]:
yield key

async def incr(self, key: Key, value: int = 1, expire: float | None = None) -> int:
value += int(await self._get(key, 0)) # type: ignore
value += int(await self._get(key, 0))
_expire = None if value != 1 else expire
self._set(key=key, value=value, expire=_expire)
return value
Expand Down Expand Up @@ -158,7 +158,7 @@ async def ping(self, message: bytes | None = None) -> bytes:
return message

async def get_bits(self, key: Key, *indexes: int, size: int = 1) -> tuple[int, ...]:
array: Bitarray = await self._get(key, default=Bitarray("0")) # type: ignore
array: Bitarray = await self._get(key, default=Bitarray("0"))
return tuple(array.get(index, size) for index in indexes)

async def incr_bits(self, key: Key, *indexes: int, size: int = 1, by: int = 1) -> tuple[int, ...]:
Expand Down
24 changes: 12 additions & 12 deletions cashews/backends/redis/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ async def is_locked(
async def unlock(self, key: Key, value: Value) -> bool:
if "UNLOCK" not in self._sha:
self._sha["UNLOCK"] = await self._client.script_load(_UNLOCK.replace("\n", " "))
return await self._client.evalsha(self._sha["UNLOCK"], 1, key, value) # type: ignore
return await self._client.evalsha(self._sha["UNLOCK"], 1, key, value)

async def delete(self, key: Key) -> bool:
try:
Expand Down Expand Up @@ -241,22 +241,24 @@ async def incr(self, key: Key, value: int = 1, expire: float | None = None) -> i
self._sha["INCR_EXPIRE"] = await self._client.script_load(_INCR_EXPIRE.replace("\n", " "))
expire = expire or 0
expire = int(expire * 1000)
return await self._client.evalsha(self._sha["INCR_EXPIRE"], 1, key, value, expire) # type: ignore
return await self._client.evalsha(self._sha["INCR_EXPIRE"], 1, key, value, expire)

async def get_bits(self, key: Key, *indexes: int, size: int = 1) -> tuple[int, ...]:
"""
https://redis.io/commands/bitfield
"""
bitops = self._client.bitfield(key)
for index in indexes:
bitops.get(fmt=f"u{size}", offset=f"#{index}")
return tuple(await bitops.execute() or [])
bitops.get(fmt=f"u{size}", offset=f"#{index}") # type: ignore[attr-defined]
return tuple(await bitops.execute() or []) # type: ignore[attr-defined]

async def incr_bits(self, key: Key, *indexes: int, size: int = 1, by: int = 1) -> tuple[int, ...]:
bitops = self._client.bitfield(key)
for index in indexes:
bitops.incrby(fmt=f"u{size}", offset=f"#{index}", increment=by, overflow="SAT")
return tuple(await bitops.execute())
bitops.incrby( # type: ignore[attr-defined]
fmt=f"u{size}", offset=f"#{index}", increment=by, overflow="SAT"
)
return tuple(await bitops.execute()) # type: ignore[attr-defined]

async def ping(self, message: bytes | None = None) -> bytes:
await self._client.ping()
Expand All @@ -277,24 +279,22 @@ async def slice_incr(
expire = int(expire * 1000)
if "INCR_SLICE" not in self._sha:
self._sha["INCR_SLICE"] = await self._client.script_load(_INCR_SLICE.replace("\n", " "))
return await self._client.evalsha( # type: ignore[misc]
self._sha["INCR_SLICE"], 1, key, start, end, maxvalue, expire # type: ignore[arg-type]
)
return await self._client.evalsha(self._sha["INCR_SLICE"], 1, key, start, end, maxvalue, expire)

async def set_add(self, key: Key, *values: str, expire: float | None = None):
if expire is None:
return await self._client.sadd(key, *values) # type: ignore[misc]
return await self._client.sadd(key, *values)
expire = int(expire * 1000)
async with self._pipeline as pipe:
await pipe.sadd(key, *values)
await pipe.pexpire(key, expire)
await pipe.execute()

async def set_remove(self, key: Key, *values: str):
await self._client.srem(key, *values) # type: ignore[misc]
await self._client.srem(key, *values)

async def set_pop(self, key: Key, count: int = 100) -> Iterable[str]:
return [value.decode() for value in await self._client.spop(key, count)] # type: ignore[misc]
return [value.decode() for value in await self._client.spop(key, count)] # type: ignore[union-attr]

async def get_keys_count(self) -> int:
return await self._client.dbsize()
Expand Down
46 changes: 33 additions & 13 deletions cashews/decorators/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
from cashews.cache_condition import NOT_NONE # noqa
from cashews.cache_condition import NOT_NONE

from .bloom import bloom, dual_bloom # noqa
from .cache.defaults import CacheDetect, context_cache_detect # noqa
from .cache.early import early # noqa
from .cache.fail import failover, fast_condition # noqa
from .cache.hit import hit # noqa
from .cache.iterator import iterator # noqa
from .cache.simple import cache # noqa
from .cache.soft import soft # noqa
from .circuit_breaker import circuit_breaker # noqa
from .locked import locked, thunder_protection # noqa
from .rate import rate_limit # noqa
from .rate_slide import slice_rate_limit # noqa
from .bloom import bloom, dual_bloom
from .cache.defaults import CacheDetect, context_cache_detect
from .cache.early import early
from .cache.fail import failover, fast_condition
from .cache.hit import hit
from .cache.iterator import iterator
from .cache.simple import cache
from .cache.soft import soft
from .circuit_breaker import circuit_breaker
from .locked import locked, thunder_protection
from .rate import rate_limit
from .rate_slide import slice_rate_limit

__all__ = [
"NOT_NONE",
"bloom",
"dual_bloom",
"CacheDetect",
"context_cache_detect",
"early",
"failover",
"fast_condition",
"hit",
"iterator",
"cache",
"soft",
"circuit_breaker",
"locked",
"thunder_protection",
"rate_limit",
"slice_rate_limit",
]
2 changes: 1 addition & 1 deletion cashews/decorators/locked.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ async def _wrap(*args, **kwargs):
yield chunk
return

return _wrap # type: ignore[return-value]
return _wrap


def thunder_protection(key: KeyOrTemplate | None = None) -> Callable[[DecoratedFunc], DecoratedFunc]:
Expand Down
4 changes: 2 additions & 2 deletions cashews/ttl.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ def ttl_to_seconds(ttl: TTL, *args, with_callable: bool = False, result=None, **
return None
_type = type(ttl) # isinstance is slow
if _type == str:
return _ttl_from_str(ttl) # type: ignore[union-attr, arg-type]
return _ttl_from_str(ttl) # type: ignore[arg-type]
if _type == int:
return ttl # type: ignore[union-attr, return-value]
return ttl # type: ignore[return-value]
if _type == timedelta:
return ttl.total_seconds() # type: ignore[union-attr]

Expand Down
6 changes: 6 additions & 0 deletions cashews/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@
from ._bitarray import Bitarray # type: ignore[assignment]
from .object_size import get_obj_size
from .split_hash import get_indexes

__all__ = [
"Bitarray",
"get_obj_size",
"get_indexes",
]
8 changes: 6 additions & 2 deletions cashews/wrapper/__init__.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from cashews.backends.interface import _BackendInterface
from cashews.decorators import context_cache_detect

from .backend_settings import register_backend # noqa
from .backend_settings import register_backend
from .decorators import DecoratorsWrapper
from .disable_control import ControlWrapper
from .tags import CommandsTagsWrapper
from .transaction import TransactionMode, TransactionWrapper

__all__ = ["Cache", "register_backend"]
__all__ = [
"Cache",
"TransactionMode",
"register_backend",
]


class Cache(
Expand Down
9 changes: 9 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
[mypy]
python_version = 3.7

# warn_return_any = True
warn_redundant_casts = True
warn_unused_configs = True
warn_unused_ignores = True
# disallow_any_generics = True
# check_untyped_defs = True
no_implicit_reexport = True
no_implicit_optional = False

[mypy-dill.*]
ignore_missing_imports = True

Expand Down
4 changes: 4 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ speedup =
hiredis
dill =
dill
lint =
mypy >= 1.5.0
types-redis
starlette
tests =
pytest
pytest-asyncio
Expand Down

0 comments on commit 5fe74a7

Please sign in to comment.