Skip to content

Commit

Permalink
ci: update ruff rules
Browse files Browse the repository at this point in the history
  • Loading branch information
karlicoss committed Jan 18, 2025
1 parent 06cf9f2 commit 209db16
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 118 deletions.
8 changes: 1 addition & 7 deletions ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ lint.extend-select = [
"PTH", # pathlib migration
# "ARG", # TODO useful, but results in some false positives in pytest fixtures... maybe later
"A", # builtin shadowing
"G", # logging stuff
# "EM", # TODO hmm could be helpful to prevent duplicate err msg in traceback.. but kinda annoying

# "ALL", # uncomment this to check for new rules!
Expand Down Expand Up @@ -64,14 +65,8 @@ lint.ignore = [
# sometimes it's useful to give a variable a name even if we don't use it as a documentation
# on the other hand, often is a sign of error
"F841", # Local variable `count` is assigned to but never used
"F401", # imported but unused
###

### TODO should be fine to use these with from __future__ import annotations?
### there was some issue with cachew though... double check this?
"UP006", # use type instead of Type
"UP007", # use X | Y instead of Union
###
"RUF100", # unused noqa -- handle later
"RUF012", # mutable class attrs should be annotated with ClassVar... ugh pretty annoying for user configs

Expand Down Expand Up @@ -112,7 +107,6 @@ lint.ignore = [
"PLW0603", # global variable update.. we usually know why we are doing this
"PLW2901", # for loop variable overwritten, usually this is intentional

"PT004", # deprecated rule, will be removed later
"PT011", # pytest raises should is too broad
"PT012", # pytest raises should contain a single statement

Expand Down
36 changes: 16 additions & 20 deletions src/cachew/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,16 @@
import stat
import sys
import warnings
from collections.abc import Iterable
from dataclasses import dataclass
from pathlib import Path
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Generic,
Iterable,
List,
Literal,
Optional,
Tuple,
Type,
TypeVar,
Union,
cast,
Expand Down Expand Up @@ -89,7 +85,7 @@ def get_logger() -> logging.Logger:
return make_logger(__name__)


BACKENDS: Dict[Backend, Type[AbstractBackend]] = {
BACKENDS: dict[Backend, type[AbstractBackend]] = {
'file': FileBackend,
'sqlite': SqliteBackend,
}
Expand Down Expand Up @@ -130,7 +126,7 @@ def mtime_hash(path: Path, *args, **kwargs) -> SourceHash:

Failure = str
Kind = Literal['single', 'multiple']
Inferred = Tuple[Kind, Type[Any]]
Inferred = tuple[Kind, type[Any]]


def infer_return_type(func) -> Union[Failure, Inferred]:
Expand Down Expand Up @@ -299,7 +295,7 @@ def cachew_impl(
cache_path: Optional[PathProvider[P]] = use_default_path,
*,
force_file: bool = False,
cls: Optional[Union[Type, Tuple[Kind, Type]]] = None,
cls: Optional[Union[type, tuple[Kind, type]]] = None,
depends_on: HashFunction[P] = default_hash,
logger: Optional[logging.Logger] = None,
chunk_by: int = 100,
Expand Down Expand Up @@ -387,7 +383,7 @@ def process(self, msg, kwargs):
logger.debug(f'no cache_path specified, using the default {cache_path}')

use_kind: Optional[Kind] = None
use_cls: Optional[Type] = None
use_cls: Optional[type] = None
if cls is not None:
# defensive here since typing. objects passed as cls might fail on isinstance
try:
Expand Down Expand Up @@ -475,7 +471,7 @@ def cachew(
cache_path: Optional[PathProvider[P]] = ...,
*,
force_file: bool = ...,
cls: Optional[Union[Type, Tuple[Kind, Type]]] = ...,
cls: Optional[Union[type, tuple[Kind, type]]] = ...,
depends_on: HashFunction[P] = ...,
logger: Optional[logging.Logger] = ...,
chunk_by: int = ...,
Expand All @@ -498,7 +494,7 @@ def callable_module_name(func: Callable) -> Optional[str]:


# could cache this, but might be worth not to, so the user can change it on the fly?
def _parse_disabled_modules(logger: Optional[logging.Logger] = None) -> List[str]:
def _parse_disabled_modules(logger: Optional[logging.Logger] = None) -> list[str]:
# e.g. CACHEW_DISABLE=my.browser:my.reddit
if 'CACHEW_DISABLE' not in os.environ:
return []
Expand Down Expand Up @@ -582,14 +578,14 @@ class Context(Generic[P]):
func : Callable
cache_path : PathProvider[P]
force_file : bool
cls_ : Type
cls_ : type
depends_on : HashFunction[P]
logger : logging.Logger
chunk_by : int
synthetic_key: Optional[str]
backend : Optional[Backend]

def composite_hash(self, *args, **kwargs) -> Dict[str, Any]:
def composite_hash(self, *args, **kwargs) -> dict[str, Any]:
fsig = inspect.signature(self.func)
# defaults wouldn't be passed in kwargs, but they can be an implicit dependency (especially inbetween program runs)
defaults = {
Expand Down Expand Up @@ -693,7 +689,7 @@ def try_use_synthetic_key() -> None:
return
# attempt to use existing cache if possible, as a 'prefix'

old_hash_d: Dict[str, Any] = {}
old_hash_d: dict[str, Any] = {}
if old_hash is not None:
try:
old_hash_d = json.loads(old_hash)
Expand All @@ -711,7 +707,7 @@ def try_use_synthetic_key() -> None:
if not cache_compatible:
return

def missing_keys(cached: List[str], wanted: List[str]) -> Optional[List[str]]:
def missing_keys(cached: list[str], wanted: list[str]) -> Optional[list[str]]:
# FIXME assert both cached and wanted are sorted? since we rely on it
# if not, then the user could use some custom key for caching (e.g. normalise filenames etc)
# although in this case passing it into the function wouldn't make sense?
Expand All @@ -734,8 +730,8 @@ def missing_keys(cached: List[str], wanted: List[str]) -> Optional[List[str]]:
# otherwise too many things are cached, and we seem to wante less
return None

new_values: List[str] = new_hash_d[_SYNTHETIC_KEY_VALUE]
old_values: List[str] = old_hash_d[_SYNTHETIC_KEY_VALUE]
new_values: list[str] = new_hash_d[_SYNTHETIC_KEY_VALUE]
old_values: list[str] = old_hash_d[_SYNTHETIC_KEY_VALUE]
missing = missing_keys(cached=old_values, wanted=new_values)
if missing is not None:
# can reuse cache
Expand All @@ -760,7 +756,7 @@ def written_to_cache():

flush_blobs = backend.flush_blobs

chunk: List[Any] = []
chunk: list[Any] = []

def flush() -> None:
nonlocal chunk
Expand Down Expand Up @@ -849,9 +845,9 @@ def cached_items():


__all__ = [
'cachew',
'CachewException',
'SourceHash',
'HashFunction',
'SourceHash',
'cachew',
'get_logger',
]
3 changes: 1 addition & 2 deletions src/cachew/backend/common.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import logging
from abc import abstractmethod
from collections.abc import Iterator, Sequence
from pathlib import Path
from typing import (
Iterator,
Optional,
Sequence,
)

from ..common import SourceHash
Expand Down
4 changes: 1 addition & 3 deletions src/cachew/backend/file.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import logging
import os
from collections.abc import Iterator, Sequence
from pathlib import Path
from typing import (
BinaryIO,
Iterator,
Optional,
Sequence,
)

from ..common import SourceHash
Expand Down
3 changes: 1 addition & 2 deletions src/cachew/backend/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@
import sqlite3
import time
import warnings
from collections.abc import Iterator, Sequence
from pathlib import Path
from typing import (
Iterator,
Optional,
Sequence,
)

import sqlalchemy
Expand Down
52 changes: 23 additions & 29 deletions src/cachew/legacy.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
import typing
import warnings
from collections.abc import Iterable, Iterator, Sequence
from dataclasses import dataclass
from datetime import date, datetime
from itertools import chain, islice
from pathlib import Path
from typing import (
Any,
Generic,
Iterable,
Iterator,
List,
NamedTuple,
Optional,
Sequence,
Set,
Tuple,
Type,
TypeVar,
Union,
)
Expand All @@ -27,7 +21,7 @@
from .utils import CachewException


def get_union_args(cls) -> Optional[Tuple[Type]]:
def get_union_args(cls) -> Optional[tuple[type]]:
if getattr(cls, '__origin__', None) != Union:
return None

Expand All @@ -42,16 +36,16 @@ def is_union(cls) -> bool:


Types = Union[
Type[str],
Type[int],
Type[float],
Type[bool],
Type[datetime],
Type[date],
Type[dict],
Type[list],
Type[Exception],
Type[NamedTuple],
type[str],
type[int],
type[float],
type[bool],
type[datetime],
type[date],
type[dict],
type[list],
type[Exception],
type[NamedTuple],
]

Values = Union[
Expand Down Expand Up @@ -80,7 +74,7 @@ def is_union(cls) -> bool:
}


def is_primitive(cls: Type) -> bool:
def is_primitive(cls: type) -> bool:
"""
>>> from typing import Dict, Any
>>> is_primitive(int)
Expand Down Expand Up @@ -194,10 +188,10 @@ def python_type(self):
def process_literal_param(self, value, dialect):
raise NotImplementedError() # make pylint happy

def process_bind_param(self, value: Optional[Exception], dialect) -> Optional[List[Any]]:
def process_bind_param(self, value: Optional[Exception], dialect) -> Optional[list[Any]]:
if value is None:
return None
sargs: List[Any] = []
sargs: list[Any] = []
for a in value.args:
if any(isinstance(a, t) for t in jtypes):
sargs.append(a)
Expand Down Expand Up @@ -230,7 +224,7 @@ def process_result_value(self, value: Optional[str], dialect) -> Optional[Except
assert set(PRIMITIVES.keys()) == PRIMITIVE_TYPES


def strip_optional(cls) -> Tuple[Type, bool]:
def strip_optional(cls) -> tuple[type, bool]:
"""
>>> from typing import Optional, NamedTuple
>>> strip_optional(Optional[int])
Expand Down Expand Up @@ -313,14 +307,14 @@ class NTBinder(Generic[NT]):
span: int # not sure if span should include optional col?
primitive: bool
optional: bool
union: Optional[Type] # helper, which isn't None if type is Union
union: Optional[type] # helper, which isn't None if type is Union
fields: Sequence[Any] # mypy can't handle cyclic definition at this point :(

@staticmethod
def make(tp: Type[NT], name: Optional[str] = None) -> 'NTBinder[NT]':
def make(tp: type[NT], name: Optional[str] = None) -> 'NTBinder[NT]':
tp, optional = strip_optional(tp)
union: Optional[Type]
fields: Tuple[Any, ...]
union: Optional[type]
fields: tuple[Any, ...]
primitive: bool

union_args = get_union_args(tp)
Expand Down Expand Up @@ -360,11 +354,11 @@ def make(tp: Type[NT], name: Optional[str] = None) -> 'NTBinder[NT]':
)

@property
def columns(self) -> List[Column]:
def columns(self) -> list[Column]:
return list(self.iter_columns())

# TODO not necessarily namedtuple? could be primitive type
def to_row(self, obj: NT) -> Tuple[Optional[Values], ...]:
def to_row(self, obj: NT) -> tuple[Optional[Values], ...]:
return tuple(self._to_row(obj))

def from_row(self, row: Iterable[Any]) -> NT:
Expand Down Expand Up @@ -425,7 +419,7 @@ def _from_row(self, row_iter):

# TODO not sure if we want to allow optionals on top level?
def iter_columns(self) -> Iterator[Column]:
used_names: Set[str] = set()
used_names: set[str] = set()

def col(name: str, tp) -> Column:
while name in used_names:
Expand Down
Loading

0 comments on commit 209db16

Please sign in to comment.