From 5065687ad7c6ee99aee868e4da0bbbea5009efa8 Mon Sep 17 00:00:00 2001 From: Dylan Lukes Date: Mon, 26 Aug 2024 17:09:05 -0700 Subject: [PATCH] all ruff checks green --- pyproject.toml | 14 +++- src/renkon/_internal/logger.py | 2 + src/renkon/_internal/singleton.py | 107 ---------------------------- src/renkon/core/model/type/base.py | 77 +++++++++++++------- src/renkon/core/trait/base.py | 6 +- src/renkon/core/trait/refinement.py | 4 +- 6 files changed, 72 insertions(+), 138 deletions(-) delete mode 100644 src/renkon/_internal/singleton.py diff --git a/pyproject.toml b/pyproject.toml index f8d932e..2e0f469 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,7 +34,7 @@ dependencies = [ "scikit-learn", # Machine learning "scipy", # Scientific computing "polars", # Data frames -# "pandas", # Data frames (not used, but needed for stubs in typings to not be Unknown) + # "pandas", # Data frames (not used, but needed for stubs in typings to not be Unknown) "pandera", # Data validation "pyarrow", # Columnar data format @@ -166,6 +166,18 @@ pythonVersion = "3.12" extend = "ruff_defaults.toml" exclude = [".hatch", "scripts", "typings", "notebooks"] +[tool.ruff.lint.pylint] +allow-dunder-method-names = [ + "__get_pydantic_core_schema__", + "__get_pydantic_json_schema__" +] + +[tool.ruff.lint.per-file-ignores] +"tests/**/*.py" = ["S", "PLC1901", "PLC2701", "PLR2004", "PLR6301", "TID252"] + +[tool.ruff.lint.isort] +known-first-party = ["renkon"] + # Coverage # -------- diff --git a/src/renkon/_internal/logger.py b/src/renkon/_internal/logger.py index 05f254c..ac629eb 100644 --- a/src/renkon/_internal/logger.py +++ b/src/renkon/_internal/logger.py @@ -5,6 +5,7 @@ import logging import os import sys +from typing import override from loguru import logger @@ -48,6 +49,7 @@ def configure_logging( class InterceptHandler(logging.Handler): + @override def emit(self, record: logging.LogRecord) -> None: # Get corresponding Loguru level if it exists. level: str | int diff --git a/src/renkon/_internal/singleton.py b/src/renkon/_internal/singleton.py deleted file mode 100644 index 7548a51..0000000 --- a/src/renkon/_internal/singleton.py +++ /dev/null @@ -1,107 +0,0 @@ -# SPDX-FileCopyrightText: 2024-present Dylan Lukes -# -# SPDX-License-Identifier: BSD-3-Clause -from __future__ import annotations - -import functools -from abc import ABCMeta -from typing import TYPE_CHECKING, Any, ClassVar, Concatenate - -if TYPE_CHECKING: - from collections.abc import Callable - - -class _SingletonMeta(ABCMeta): - _instances: ClassVar[dict[type, Any]] = {} - - def __call__(cls, *args: Any, **kwargs: Any): - if cls not in cls._instances: - cls._instances[cls] = super().__call__(*args, **kwargs) - return cls._instances[cls] - - -class Singleton(metaclass=_SingletonMeta): - @classmethod - def get_instance(cls: type[Singleton]) -> Singleton: - return cls() - - -# if TYPE_CHECKING: -# def singletonmethod[**P, R](_method: Callable[P, R]) -> Callable[P, R]: -# ... -# else: -class singletonmethod[T: Singleton, **P, R]: # noqa: N801 - """Descriptor for a method which when called on the class, delegates to the singleton instance.""" - - method: Callable[Concatenate[T, P], R] - instance: T | None - - def __init__(self, method: Callable[Concatenate[T, P], R], instance: T | None = None): - if not callable(method) and not hasattr(method, "__get__"): - msg = f"{method!r} is not callable or a descriptor" - raise TypeError(msg) - self.method = method - self.instance = instance - - def __get__(self, instance: T | None, owner: type[T]) -> Callable[P, R]: - instance = instance or owner.get_instance() - descriptor = self.__class__(self.method, instance) - functools.update_wrapper(descriptor, self.method) - return descriptor - - def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: - if self.instance is None: - msg = "singletonmethod instance is not set" - raise TypeError(msg) - return self.method(self.instance, *args, **kwargs) - - @property - def __isabstractmethod__(self): - return getattr(self.method, "__isabstractmethod__", False) - - -class instancemethod[T, **P, R]: # noqa: N801 - method: Callable[Concatenate[T, P], R] - instance: T | None - - def __init__(self, method: Callable[Concatenate[T, P], R], instance: T | None = None): - self.method = method - self.instance = instance - - def __get__(self, instance: T | None, owner: type[T]) -> Callable[P, R]: - descriptor = self.__class__(self.method, instance) - functools.update_wrapper(descriptor, self.method) - return descriptor - - def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: - if self.instance is None: - msg = "instancemethod called directly, not on instance" - raise TypeError(msg) - return self.method(self.instance, *args, **kwargs) - - -# class Base(ABC): -# # foo: Callable[[], str] -# def foo(self) -> str: -# return "foo" -# -# -# class DerivedNormal(Base): -# def _foo(self) -> str: -# return "foo" -# foo = instancemethod(_foo) -# -# class DerivedSingleton2(Base, Singleton): -# @singletonmethod -# def foo(self) -> str: -# return "foo" -# -# class DerivedSingleton(Base, Singleton): -# def _foo(self) -> str: -# return "foo" -# foo = singletonmethod(_foo) -# -# -# def test_singleton(): -# assert "foo" == DerivedNormal.foo() -# assert "foo" == DerivedSingleton.foo() == DerivedSingleton().foo() diff --git a/src/renkon/core/model/type/base.py b/src/renkon/core/model/type/base.py index e06eda0..4cb7e18 100644 --- a/src/renkon/core/model/type/base.py +++ b/src/renkon/core/model/type/base.py @@ -187,63 +187,79 @@ def __get_pydantic_core_schema__(cls, source: type[BaseModel], handler: GetCoreS class TopType(RenkonType): + def __init__(self, /, **data: Any) -> None: + if not data: + return + super().__init__(**data) + + @override def is_equal(self, other: RenkonType) -> bool: return isinstance(other, TopType) + @override def is_equivalent(self, other: RenkonType) -> bool: return self.is_equal(other) - def is_subtype(self, other: RenkonType) -> bool: # noqa: ARG002 + @override + def is_subtype(self, other: RenkonType) -> bool: return False + @override def is_supertype(self, other: RenkonType) -> bool: return self.is_equal(other) + @override def canonicalize(self) -> Self: return self + @override def normalize(self) -> RenkonType: return self + @override def dump_string(self) -> str: return "any" - def __init__(self, /, **data: Any) -> None: - if not data: - return - super().__init__(**data) - + @override def __hash__(self) -> int: return hash(TopType) class BottomType(RenkonType): + def __init__(self, /, **data: Any) -> None: + if not data: + return + super().__init__(**data) + + @override def is_equal(self, other: RenkonType) -> bool: return isinstance(other, BottomType) + @override def is_equivalent(self, other: RenkonType) -> bool: return self.is_equal(other) - def is_subtype(self, other: RenkonType) -> bool: # noqa: ARG002 + @override + def is_subtype(self, other: RenkonType) -> bool: return True + @override def is_supertype(self, other: RenkonType) -> bool: return self.is_equal(other) + @override def canonicalize(self) -> Self: return self + @override def normalize(self) -> RenkonType: return self + @override def dump_string(self) -> str: return "none" - def __init__(self, /, **data: Any) -> None: - if not data: - return - super().__init__(**data) - + @override def __hash__(self) -> int: return hash(BottomType) @@ -422,42 +438,55 @@ def __and__(self, other: UnionType) -> UnionType: # region + # noinspection PyMethodMayBeStatic class TreeToTypeTransformer(Transformer[RenkonType]): - def type(self, type_: list[RenkonType]): + @staticmethod + def type(type_: list[RenkonType]): return type_[0] - def int(self, _) -> IntType: + @staticmethod + def int(_) -> IntType: return int_() - def float(self, _) -> FloatType: + @staticmethod + def float(_) -> FloatType: return float_() - def string(self, _) -> StringType: + @staticmethod + def string(_) -> StringType: return str_() - def bool(self, _) -> BoolType: + @staticmethod + def bool(_) -> BoolType: return bool_() - def top(self, _) -> RenkonType: + @staticmethod + def top(_) -> RenkonType: return any_() - def bottom(self, _) -> BottomType: + @staticmethod + def bottom(_) -> BottomType: return none() - def union(self, types: list[RenkonType]) -> UnionType: + @staticmethod + def union(types: list[RenkonType]) -> UnionType: return union(*types) - def equatable(self, _) -> UnionType: + @staticmethod + def equatable(_) -> UnionType: return equatable() - def comparable(self, _) -> UnionType: + @staticmethod + def comparable(_) -> UnionType: return comparable() - def numeric(self, _) -> UnionType: + @staticmethod + def numeric(_) -> UnionType: return numeric() - def paren(self, type_: list[RenkonType]) -> RenkonType: + @staticmethod + def paren(type_: list[RenkonType]) -> RenkonType: return type_[0] diff --git a/src/renkon/core/trait/base.py b/src/renkon/core/trait/base.py index 845afdd..19e537c 100644 --- a/src/renkon/core/trait/base.py +++ b/src/renkon/core/trait/base.py @@ -4,7 +4,7 @@ from typing import ClassVar, Protocol, final import renkon.core.model.type as rk_type -from renkon.core.model import Schema, TraitId, TraitKind, TraitPattern, TraitSketch, TraitSpec +from renkon.core.model import TraitId, TraitKind, TraitPattern, TraitSketch, TraitSpec from renkon.core.model.type import RenkonType @@ -47,8 +47,8 @@ def typevars(self) -> dict[str, RenkonType]: def typings(self) -> dict[str, RenkonType | str]: return self.spec.typings - def can_sketch(self, _schema: Schema, _bindings: dict[str, str]) -> bool: - return False # TODO: implement + # def can_sketch(self, _schema: Schema, _bindings: dict[str, str]) -> bool: + # return False # TODO: implement def sketch(self, **kwargs: RenkonType) -> TraitSketch: return TraitSketch.model_validate( diff --git a/src/renkon/core/trait/refinement.py b/src/renkon/core/trait/refinement.py index 0ec0965..6e797d4 100644 --- a/src/renkon/core/trait/refinement.py +++ b/src/renkon/core/trait/refinement.py @@ -13,7 +13,7 @@ from abc import ABC from typing import ClassVar, final -from renkon.core.model import RenkonType, TraitPattern, TraitSpec +from renkon.core.model import RenkonType, TraitKind, TraitPattern, TraitSpec from renkon.core.trait.base import Trait @@ -25,8 +25,6 @@ def __init_subclass__(cls, *, base_type: RenkonType | str, **kwargs: None): if not isinstance(base_type, RenkonType): base_type = RenkonType.model_validate(base_type) - from renkon.core.model import TraitKind - cls.spec = TraitSpec( id=f"{cls.__qualname__}", name=f"{cls.__name__}",