From 7a4b3dba3e280805b2ffff1243dcb90ea5ddc3b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=BChl?= Date: Thu, 26 Jun 2025 11:02:32 +0200 Subject: [PATCH 1/3] fix: DeprecationWarning: pkg_resources is deprecated as an API --- mode/utils/imports.py | 15 ++++++++++----- tests/unit/utils/test_imports.py | 26 +++++++++++++++----------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/mode/utils/imports.py b/mode/utils/imports.py index afb00681..463321c3 100644 --- a/mode/utils/imports.py +++ b/mode/utils/imports.py @@ -368,14 +368,19 @@ def load_extension_class_names( ``` """ try: - from pkg_resources import iter_entry_points + from importlib.metadata import entry_points except ImportError: return - for ep in iter_entry_points(namespace): - yield RawEntrypointExtension( - ep.name, ":".join([ep.module_name, ep.attrs[0]]) - ) + eps = entry_points() + # For Python 3.10+, entry_points() returns an object with .select() + if hasattr(eps, "select"): + for ep in eps.select(group=namespace): + yield RawEntrypointExtension(ep.name, f"{ep.module}:{ep.attr}") + else: + # For Python 3.8/3.9, entry_points is a dict + for ep in eps.get(namespace, []): + yield RawEntrypointExtension(ep.name, f"{ep.module}:{ep.attr}") @contextmanager diff --git a/tests/unit/utils/test_imports.py b/tests/unit/utils/test_imports.py index 658fef78..39edcc6d 100644 --- a/tests/unit/utils/test_imports.py +++ b/tests/unit/utils/test_imports.py @@ -92,7 +92,7 @@ def test__maybe_finalize(self, *, map): def test__finalize(self, *, map): map.namespaces = {"foo"} - with patch_iter_entry_points(): + with patch_importlib_metadata_entry_points(): map._finalize() assert map.aliases["ep1"] == "foo:a" assert map.aliases["ep2"] == "bar:c" @@ -158,7 +158,7 @@ def test_smart_import(): def test_load_extension_classes(): - with patch_iter_entry_points(): + with patch_importlib_metadata_entry_points(): with patch("mode.utils.imports.symbol_by_name") as sbn: assert list(load_extension_classes("foo")) == [ EntrypointExtension("ep1", sbn.return_value), @@ -169,7 +169,7 @@ def test_load_extension_classes(): def test_load_extension_classes_syntax_error(): - with patch_iter_entry_points(): + with patch_importlib_metadata_entry_points(): with patch("mode.utils.imports.symbol_by_name") as sbn: sbn.side_effect = SyntaxError() with pytest.warns(UserWarning): @@ -177,7 +177,7 @@ def test_load_extension_classes_syntax_error(): def test_load_extension_class_names(): - with patch_iter_entry_points(): + with patch_importlib_metadata_entry_points(): assert list(load_extension_class_names("foo")) == [ RawEntrypointExtension("ep1", "foo:a"), RawEntrypointExtension("ep2", "bar:c"), @@ -185,17 +185,21 @@ def test_load_extension_class_names(): @contextmanager -def patch_iter_entry_points(): - with patch("pkg_resources.iter_entry_points") as iter_entry_points: +def patch_importlib_metadata_entry_points(): + with patch( + "importlib.metadata.entry_points" + ) as importlib_metadata_entry_points: ep1 = Mock(name="ep1") ep1.name = "ep1" - ep1.module_name = "foo" - ep1.attrs = ["a", "b"] + ep1.module = "foo" + ep1.attr = "a" ep2 = Mock(name="ep2") ep2.name = "ep2" - ep2.module_name = "bar" - ep2.attrs = ["c", "d"] - iter_entry_points.return_value = [ep1, ep2] + ep2.module = "bar" + ep2.attr = "c" + mock_entry_points = Mock() + mock_entry_points.select.return_value = [ep1, ep2] + importlib_metadata_entry_points.return_value = mock_entry_points yield From 944fc73cc3e8d06b3df5d043be0c1c4a6692ccda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=BChl?= Date: Fri, 27 Jun 2025 08:25:35 +0200 Subject: [PATCH 2/3] style: fix all linter code style warnings --- mode/__init__.py | 24 +++++----- mode/locals.py | 56 +++++++++++----------- mode/loop/eventlet.py | 2 +- mode/loop/gevent.py | 4 +- mode/services.py | 4 +- mode/supervisors.py | 4 +- mode/threads.py | 4 +- mode/types/__init__.py | 4 +- mode/types/signals.py | 2 +- mode/utils/collections.py | 12 ++--- mode/utils/compat.py | 2 +- mode/utils/cron.py | 2 +- mode/utils/futures.py | 2 +- mode/utils/imports.py | 8 ++-- mode/utils/loops.py | 2 +- mode/utils/objects.py | 20 ++++---- mode/utils/text.py | 22 ++++----- mode/utils/times.py | 4 +- mode/utils/types/graphs.py | 2 +- tests/conftest.py | 2 +- tests/functional/test_proxy.py | 6 +-- tests/functional/test_signals.py | 2 +- tests/functional/test_timers.py | 8 ++-- tests/functional/utils/test_collections.py | 14 +++--- tests/functional/utils/test_tracebacks.py | 4 +- tests/unit/test_debug.py | 2 +- tests/unit/test_locals.py | 42 ++++++++-------- tests/unit/test_services.py | 6 +-- tests/unit/test_supervisors.py | 12 ++--- tests/unit/test_threads.py | 14 +++--- tests/unit/test_worker.py | 2 +- tests/unit/utils/test_imports.py | 6 +-- tests/unit/utils/test_logging.py | 16 +++---- tests/unit/utils/test_objects.py | 4 +- 34 files changed, 160 insertions(+), 160 deletions(-) diff --git a/mode/__init__.py b/mode/__init__.py index 13631e48..d8ee11d3 100644 --- a/mode/__init__.py +++ b/mode/__init__.py @@ -35,29 +35,29 @@ __all__ = [ "BaseSignal", "BaseSignalT", - "Service", - "Signal", - "SignalT", - "SyncSignal", - "SyncSignalT", + "CrashingSupervisor", "ForfeitOneForAllSupervisor", "ForfeitOneForOneSupervisor", "OneForAllSupervisor", "OneForOneSupervisor", - "SupervisorStrategy", - "CrashingSupervisor", + "Seconds", + "Service", "ServiceT", + "Signal", + "SignalT", + "SupervisorStrategy", "SupervisorStrategyT", - "Seconds", - "want_seconds", + "SyncSignal", + "SyncSignalT", + "Worker", + "flight_recorder", "get_logger", - "setup_logging", "label", + "setup_logging", "shortlabel", - "Worker", "task", "timer", - "flight_recorder", + "want_seconds", ] diff --git a/mode/locals.py b/mode/locals.py index 30fe87ad..b2a8a826 100644 --- a/mode/locals.py +++ b/mode/locals.py @@ -113,36 +113,36 @@ class XProxy(MutableMappingRole, AsyncContextManagerRole): from .utils.locals import LocalStack # XXX compat __all__ = [ - "LocalStack", - "Proxy", - "AwaitableRole", - "AwaitableProxy", - "CoroutineRole", - "CoroutineProxy", - "AsyncIterableRole", + "AsyncContextManagerProxy", + "AsyncContextManagerRole", + "AsyncGeneratorProxy", + "AsyncGeneratorRole", "AsyncIterableProxy", - "AsyncIteratorRole", + "AsyncIterableRole", "AsyncIteratorProxy", - "AsyncGeneratorRole", - "AsyncGeneratorProxy", - "SequenceRole", - "SequenceProxy", - "MutableSequenceRole", - "MutableSequenceProxy", - "SetRole", - "SetProxy", - "MutableSetRole", - "MutableSetProxy", - "ContextManagerRole", + "AsyncIteratorRole", + "AwaitableProxy", + "AwaitableRole", + "CallableProxy", + "CallableRole", "ContextManagerProxy", - "AsyncContextManagerRole", - "AsyncContextManagerProxy", - "MappingRole", + "ContextManagerRole", + "CoroutineProxy", + "CoroutineRole", + "LocalStack", "MappingProxy", - "MutableMappingRole", + "MappingRole", "MutableMappingProxy", - "CallableRole", - "CallableProxy", + "MutableMappingRole", + "MutableSequenceProxy", + "MutableSequenceRole", + "MutableSetProxy", + "MutableSetRole", + "Proxy", + "SequenceProxy", + "SequenceRole", + "SetProxy", + "SetRole", "maybe_evaluate", ] @@ -188,11 +188,11 @@ class Proxy(Generic[T]): # Code initially stolen from werkzeug.local.Proxy. if not SLOTS_ISSUE_PRESENT and not PYPY: # pragma: no cover __slots__ = ( - "__local", "__args", - "__kwargs", - "__finalizers", "__dict__", + "__finalizers", + "__kwargs", + "__local", ) def __init_subclass__(self, source: Optional[Type[T]] = None) -> None: diff --git a/mode/loop/eventlet.py b/mode/loop/eventlet.py index 38575a81..7904804d 100644 --- a/mode/loop/eventlet.py +++ b/mode/loop/eventlet.py @@ -8,7 +8,7 @@ import eventlet except ImportError: raise ImportError( - "Eventlet loop requires the eventlet library: " "pip install eventlet" + "Eventlet loop requires the eventlet library: pip install eventlet" ) from None eventlet.monkey_patch() diff --git a/mode/loop/gevent.py b/mode/loop/gevent.py index 057a4da6..7025a1bd 100644 --- a/mode/loop/gevent.py +++ b/mode/loop/gevent.py @@ -11,7 +11,7 @@ import gevent.monkey except ImportError: raise ImportError( - "Gevent loop requires the gevent library: " "pip install gevent" + "Gevent loop requires the gevent library: pip install gevent" ) from None gevent.monkey.patch_all() @@ -35,7 +35,7 @@ except ImportError: raise raise ImportError( - "Gevent loop requires the aiogevent library: " "pip install aiogevent" + "Gevent loop requires the aiogevent library: pip install aiogevent" ) from None diff --git a/mode/services.py b/mode/services.py index 228e1184..eacd7187 100644 --- a/mode/services.py +++ b/mode/services.py @@ -43,7 +43,7 @@ from .utils.trees import Node from .utils.types.trees import NodeT -__all__ = ["ServiceBase", "Service", "Diag", "task", "timer", "crontab"] +__all__ = ["Diag", "Service", "ServiceBase", "crontab", "task", "timer"] ClockArg = Callable[[], float] @@ -111,7 +111,7 @@ def __init__( def _format_log( self, severity: int, msg: str, *args: Any, **kwargs: Any ) -> str: - return f'[^{"-" * (self.beacon.depth - 1)}{self.shortlabel}]: {msg}' + return f"[^{'-' * (self.beacon.depth - 1)}{self.shortlabel}]: {msg}" async def __aenter__(self) -> ServiceT: await self.start() diff --git a/mode/supervisors.py b/mode/supervisors.py index 89a8846b..58b8a02b 100644 --- a/mode/supervisors.py +++ b/mode/supervisors.py @@ -20,9 +20,9 @@ __all__ = [ "ForfeitOneForAllSupervisor", "ForfeitOneForOneSupervisor", - "SupervisorStrategy", - "OneForOneSupervisor", "OneForAllSupervisor", + "OneForOneSupervisor", + "SupervisorStrategy", ] logger = get_logger(__name__) diff --git a/mode/threads.py b/mode/threads.py index 2dd0aeb7..429740fa 100644 --- a/mode/threads.py +++ b/mode/threads.py @@ -35,10 +35,10 @@ from .utils.locks import Event __all__ = [ + "QueueServiceThread", "QueuedMethod", - "WorkerThread", "ServiceThread", - "QueueServiceThread", + "WorkerThread", ] diff --git a/mode/types/__init__.py b/mode/types/__init__.py index f0bbb91b..ac84ceeb 100644 --- a/mode/types/__init__.py +++ b/mode/types/__init__.py @@ -3,11 +3,11 @@ from .supervisors import SupervisorStrategyT __all__ = [ + "BaseSignalT", "DiagT", "ServiceT", - "BaseSignalT", "SignalHandlerT", "SignalT", - "SyncSignalT", "SupervisorStrategyT", + "SyncSignalT", ] diff --git a/mode/types/signals.py b/mode/types/signals.py index 0fc43cd3..40446cb9 100644 --- a/mode/types/signals.py +++ b/mode/types/signals.py @@ -21,8 +21,8 @@ __all__ = [ "BaseSignalT", "FilterReceiverMapping", - "SignalHandlerT", "SignalHandlerRefT", + "SignalHandlerT", "SignalT", "SyncSignalT", "T", diff --git a/mode/utils/collections.py b/mode/utils/collections.py index 2ebfc909..01ecc25f 100644 --- a/mode/utils/collections.py +++ b/mode/utils/collections.py @@ -55,16 +55,16 @@ class LazySettings: ... __all__ = [ - "Heap", + "AttributeDict", + "AttributeDictMixin", + "DictAttribute", "FastUserDict", - "FastUserSet", "FastUserList", + "FastUserSet", + "Heap", "LRUCache", "ManagedUserDict", "ManagedUserSet", - "AttributeDict", - "AttributeDictMixin", - "DictAttribute", "force_mapping", ] @@ -193,7 +193,7 @@ def fromkeys( cls, iterable: Iterable[KT], value: VT = None ) -> "FastUserDict": d = cls() - d.update({k: value for k in iterable}) + d.update(dict.fromkeys(iterable, value)) return d def __getitem__(self, key: KT) -> VT: diff --git a/mode/utils/compat.py b/mode/utils/compat.py index 80252774..3d098d72 100644 --- a/mode/utils/compat.py +++ b/mode/utils/compat.py @@ -2,7 +2,7 @@ from typing import IO, AnyStr -__all__ = ["want_bytes", "want_str", "isatty"] +__all__ = ["isatty", "want_bytes", "want_str"] def want_bytes(s: AnyStr) -> bytes: diff --git a/mode/utils/cron.py b/mode/utils/cron.py index a4b6bcd4..15d52ae5 100644 --- a/mode/utils/cron.py +++ b/mode/utils/cron.py @@ -14,6 +14,6 @@ def secs_for_next(cron_format: str, tz: Optional[tzinfo] = None) -> float: # if not will set now to be the current timestamp (tz # unaware) # If we have tz, now will be a datetime, if not an integer - now = tz and datetime.now(tz) or now_ts + now = (tz and datetime.now(tz)) or now_ts cron_it = croniter(cron_format, start_time=now) return cast(float, cron_it.get_next(float)) - now_ts diff --git a/mode/utils/futures.py b/mode/utils/futures.py index 0776c14c..0888e351 100644 --- a/mode/utils/futures.py +++ b/mode/utils/futures.py @@ -28,8 +28,8 @@ def all_tasks(loop: asyncio.AbstractEventLoop) -> Set[asyncio.Task]: "maybe_cancel", "maybe_set_exception", "maybe_set_result", - "stampede", "notify", + "stampede", ] diff --git a/mode/utils/imports.py b/mode/utils/imports.py index 463321c3..5a0bd5b5 100644 --- a/mode/utils/imports.py +++ b/mode/utils/imports.py @@ -47,12 +47,12 @@ def __init__(self, url: str) -> None: __all__ = [ "FactoryMapping", "SymbolArg", - "symbol_by_name", - "load_extension_class_names", - "load_extension_classes", "cwd_in_path", "import_from_cwd", + "load_extension_class_names", + "load_extension_classes", "smart_import", + "symbol_by_name", ] _T = TypeVar("_T") @@ -113,7 +113,7 @@ def by_name(self, name: SymbolArg[_T]) -> _T: alt = didyoumean( self.aliases, name_, - fmt_none=f'Available choices: {", ".join(self.aliases)}', + fmt_none=f"Available choices: {', '.join(self.aliases)}", ) raise ModuleNotFoundError( f"{name!r} is not a valid name. {alt}" diff --git a/mode/utils/loops.py b/mode/utils/loops.py index 79e6265d..8617d45a 100644 --- a/mode/utils/loops.py +++ b/mode/utils/loops.py @@ -3,7 +3,7 @@ import asyncio from typing import Any, Callable, Optional -__all__ = ["clone_loop", "call_asap"] +__all__ = ["call_asap", "clone_loop"] def _is_unix_loop(loop: asyncio.AbstractEventLoop) -> bool: diff --git a/mode/utils/objects.py b/mode/utils/objects.py index 8c197dc2..70c73c35 100644 --- a/mode/utils/objects.py +++ b/mode/utils/objects.py @@ -64,23 +64,23 @@ def _is_class_var(x: Any) -> bool: __all__ = [ - "FieldMapping", "DefaultsMapping", - "Unordered", - "KeywordReduce", + "FieldMapping", "InvalidAnnotation", + "KeywordReduce", + "Unordered", "abc_compatible_with_init_subclass", - "qualname", - "shortname", + "annotations", + "cached_property", "canoname", "canonshortname", - "annotations", "eval_type", - "iter_mro_reversed", "guess_polymorphic_type", - "cached_property", + "iter_mro_reversed", "label", + "qualname", "shortlabel", + "shortname", ] # Workaround for https://bugs.python.org/issue29581 @@ -230,7 +230,7 @@ def canoname(obj: Any, *, main_name: Optional[str] = None) -> str: name = qualname(obj) parts = name.split(".") if parts[0] == "__main__": - return ".".join([main_name or _detect_main_name()] + parts[1:]) + return ".".join([main_name or _detect_main_name(), *parts[1:]]) return name @@ -239,7 +239,7 @@ def canonshortname(obj: Any, *, main_name: Optional[str] = None) -> str: name = shortname(obj) parts = name.split(".") if parts[0] == "__main__": - return ".".join([main_name or _detect_main_name()] + parts[1:]) + return ".".join([main_name or _detect_main_name(), *parts[1:]]) return name diff --git a/mode/utils/text.py b/mode/utils/text.py index 3605c3c1..41c04541 100644 --- a/mode/utils/text.py +++ b/mode/utils/text.py @@ -5,20 +5,20 @@ __all__ = [ "FuzzyMatch", - "want_bytes", - "want_str", - "isatty", - "title", - "didyoumean", - "fuzzymatch_choices", - "fuzzymatch_iter", - "fuzzymatch_best", "abbr", "abbr_fqdn", + "didyoumean", "enumeration", - "shorten_fqdn", - "pluralize", + "fuzzymatch_best", + "fuzzymatch_choices", + "fuzzymatch_iter", + "isatty", "maybecat", + "pluralize", + "shorten_fqdn", + "title", + "want_bytes", + "want_str", ] @@ -199,7 +199,7 @@ def _abbr_word_boundary(s: str, max: int, suffix: str) -> str: # Do not cut-off any words, but means the limit is even harder # and we won't include any partial words. if len(s) > max: - return suffix and (s[: max - len(suffix)] + suffix) or s[:max] + return (suffix and (s[: max - len(suffix)] + suffix)) or s[:max] return s diff --git a/mode/utils/times.py b/mode/utils/times.py index fce228f9..f92d8420 100644 --- a/mode/utils/times.py +++ b/mode/utils/times.py @@ -24,11 +24,11 @@ "Bucket", "Seconds", "TokenBucket", + "humanize_seconds", + "humanize_seconds_ago", "rate", "rate_limit", "want_seconds", - "humanize_seconds", - "humanize_seconds_ago", ] TIME_MONOTONIC: Callable[[], float] diff --git a/mode/utils/types/graphs.py b/mode/utils/types/graphs.py index a1aec760..6ebc64e0 100644 --- a/mode/utils/types/graphs.py +++ b/mode/utils/types/graphs.py @@ -13,7 +13,7 @@ TypeVar, ) -__all__ = ["GraphFormatterT", "DependencyGraphT"] +__all__ = ["DependencyGraphT", "GraphFormatterT"] _T = TypeVar("_T") diff --git a/tests/conftest.py b/tests/conftest.py index 1f6eaace..9a43bc04 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ import pytest -@pytest.fixture() +@pytest.fixture def loop(event_loop): return event_loop diff --git a/tests/functional/test_proxy.py b/tests/functional/test_proxy.py index 2ce7653e..4c146c3c 100644 --- a/tests/functional/test_proxy.py +++ b/tests/functional/test_proxy.py @@ -17,7 +17,7 @@ def _service(self): class test_Proxy: - @pytest.fixture() + @pytest.fixture def service(self): s = Mock( name="service", @@ -33,11 +33,11 @@ def service(self): ) return s - @pytest.fixture() + @pytest.fixture def subservice(self): return Mock(name="subservice") - @pytest.fixture() + @pytest.fixture def proxy(self, *, service): return Proxy(service) diff --git a/tests/functional/test_signals.py b/tests/functional/test_signals.py index a9e1c672..8925d2a7 100644 --- a/tests/functional/test_signals.py +++ b/tests/functional/test_signals.py @@ -166,7 +166,7 @@ class X: class test_BaseSignal: - @pytest.fixture() + @pytest.fixture def sig(self): return Signal() diff --git a/tests/functional/test_timers.py b/tests/functional/test_timers.py index 02319489..a7fac2e3 100644 --- a/tests/functional/test_timers.py +++ b/tests/functional/test_timers.py @@ -46,21 +46,21 @@ class test_Timer: # time could be long in some cases. default_yield_s = 0.01 - @pytest.fixture() + @pytest.fixture def clock(self): clock = Mock() clock.return_value = self.epoch return clock - @pytest.fixture() + @pytest.fixture def sleep(self): return AsyncMock() - @pytest.fixture() + @pytest.fixture def timer(self, *, clock, sleep) -> Timer: return Timer(self.interval, name="test", clock=clock, sleep=sleep) - @pytest.fixture() + @pytest.fixture def first_interval(self): return self.new_interval() diff --git a/tests/functional/utils/test_collections.py b/tests/functional/utils/test_collections.py index a8012ac2..9073bf17 100644 --- a/tests/functional/utils/test_collections.py +++ b/tests/functional/utils/test_collections.py @@ -18,7 +18,7 @@ class test_FastUserDict: - @pytest.fixture() + @pytest.fixture def d(self): class X(FastUserDict): def __init__(self): @@ -129,7 +129,7 @@ class X(FastUserSet): def __init__(self): self.data = set() - @pytest.fixture() + @pytest.fixture def d(self): return self.X() @@ -337,7 +337,7 @@ def test_interface_on_key_del(self): def test_interface_on_clear(self): ManagedUserDict().on_clear() - @pytest.fixture() + @pytest.fixture def d(self): class X(ManagedUserDict): def __init__(self): @@ -429,7 +429,7 @@ def on_change(self, added, removed): def on_clear(self): self.on_clear_mock() - @pytest.fixture() + @pytest.fixture def s(self): return self.ManagedSet() @@ -523,7 +523,7 @@ def test_update(self, *, s): class test_LRUCache: - @pytest.fixture() + @pytest.fixture def d(self): return LRUCache(limit=10) @@ -571,7 +571,7 @@ def test_pickle(self, d): class test_AttributeDictMixin: - @pytest.fixture() + @pytest.fixture def d(self): class X(dict, AttributeDictMixin): ... @@ -586,7 +586,7 @@ def test_set_get(self, *, d): class test_DictAttribute: - @pytest.fixture() + @pytest.fixture def d(self): class Object: def __init__(self, name): diff --git a/tests/functional/utils/test_tracebacks.py b/tests/functional/utils/test_tracebacks.py index 7222f4eb..0e5d50e7 100644 --- a/tests/functional/utils/test_tracebacks.py +++ b/tests/functional/utils/test_tracebacks.py @@ -57,11 +57,11 @@ async def moo(): class test_Traceback: - @pytest.fixture() + @pytest.fixture def frame(self): return Mock(name="frame") - @pytest.fixture() + @pytest.fixture def tb(self, *, frame): return Traceback(frame) diff --git a/tests/unit/test_debug.py b/tests/unit/test_debug.py index 26b63874..dcb7ada2 100644 --- a/tests/unit/test_debug.py +++ b/tests/unit/test_debug.py @@ -9,7 +9,7 @@ @pytest.mark.skipif(sys.platform == "win32", reason="win32: no SIGALRM") class test_BlockingDetector: - @pytest.fixture() + @pytest.fixture def block(self): return BlockingDetector(timeout=10.0) diff --git a/tests/unit/test_locals.py b/tests/unit/test_locals.py index b22d90da..c7bd4bd3 100644 --- a/tests/unit/test_locals.py +++ b/tests/unit/test_locals.py @@ -61,7 +61,7 @@ def real(): assert x.__doc__ == "real function" - assert x.__class__ == type(real) + assert x.__class__ is type(real) assert x.__dict__ == real.__dict__ assert repr(x) == repr(real) assert x.__module__ @@ -254,11 +254,11 @@ def test_maybe_evaluate(self): class test_MappingProxy: - @pytest.fixture() + @pytest.fixture def orig(self): return {0: 1, 2: 3, 4: 5, 6: 7, 8: 9} - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return MappingProxy(lambda: orig) @@ -298,7 +298,7 @@ def test_len(self, *, s, orig): class test_MutableMappingProxy(test_MappingProxy): # Note: Inherits all test cases from test_MappingProxy - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return MutableMappingProxy(lambda: orig) @@ -361,11 +361,11 @@ def test_update__iterable(self, *, s, orig): class test_SequenceProxy: - @pytest.fixture() + @pytest.fixture def orig(self): return [1, 2, 3, 4, 5, 6, 7] - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return SequenceProxy(lambda: orig) @@ -405,7 +405,7 @@ def test_len(self, *, s, orig): class test_MutableSequenceProxy(test_SequenceProxy): # Note: Inherits all test cases from test_SequenceProxy - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return MutableSequenceProxy(lambda: orig) @@ -458,11 +458,11 @@ def test_iadd(self, *, s, orig): class test_SetProxy: - @pytest.fixture() + @pytest.fixture def orig(self): return {1, 2, 3, 4, 5, 6, 7} - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return SetProxy(lambda: orig) @@ -511,7 +511,7 @@ def test_xor(self, *, s): class test_MutableSetProxy(test_SetProxy): # Note: Inerhits all test cases from test_SetProxy - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return MutableSetProxy(lambda: orig) @@ -563,7 +563,7 @@ class test_AwaitableProxy: async def asynfun(self): return 10 - @pytest.fixture() + @pytest.fixture def s(self): return AwaitableProxy(lambda: self.asynfun(), cache=True) @@ -582,11 +582,11 @@ async def aiter(self): for i in range(10): yield i - @pytest.fixture() + @pytest.fixture def orig(self): return self.aiter() - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return AsyncIterableProxy(lambda: orig) @@ -604,7 +604,7 @@ async def test_async_for(self, *, s): class test_AsyncIteratorProxy(test_AsyncIterableProxy): # Note: Inherits all test cases from test_AsyncIterableProxy - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return AsyncIteratorProxy(lambda: orig) @@ -623,7 +623,7 @@ class test_AsyncGeneratorProxy(test_AsyncIteratorProxy): class Double(Exception): ... # tells coro to double multiplier - @pytest.fixture() + @pytest.fixture def s(self, *, orig): return AsyncGeneratorProxy(lambda: orig) @@ -640,11 +640,11 @@ async def corogen(self): except self.Double: multiplier *= 2 - @pytest.fixture() - def _coro(self): # noqa: PT005 + @pytest.fixture + def _coro(self): return self.corogen() - @pytest.fixture() + @pytest.fixture def coro(self, *, _coro): return AsyncGeneratorProxy(lambda: _coro) @@ -676,11 +676,11 @@ def corogen(self): except self.Double: multiplier *= 2 - @pytest.fixture() - def _coro(self): # noqa: PT005 + @pytest.fixture + def _coro(self): return self.corogen() - @pytest.fixture() + @pytest.fixture def coro(self, *, _coro): return CoroutineProxy(lambda: _coro) diff --git a/tests/unit/test_services.py b/tests/unit/test_services.py index 23c478b4..1122a39f 100644 --- a/tests/unit/test_services.py +++ b/tests/unit/test_services.py @@ -27,7 +27,7 @@ async def on_shutdown(self): class test_Diag: - @pytest.fixture() + @pytest.fixture def diag(self): service = Mock() return Diag(service) @@ -41,7 +41,7 @@ def test_set_unset_flag(self, *, diag): class test_ServiceTask: - @pytest.fixture() + @pytest.fixture def task(self): fun = AsyncMock() return ServiceTask(fun) @@ -133,7 +133,7 @@ async def _background_task(self): class test_Service: - @pytest.fixture() + @pytest.fixture def service(self): return S() diff --git a/tests/unit/test_supervisors.py b/tests/unit/test_supervisors.py index 17f105a9..959134cf 100644 --- a/tests/unit/test_supervisors.py +++ b/tests/unit/test_supervisors.py @@ -14,11 +14,11 @@ class test_SupervisorStrategy: - @pytest.fixture() + @pytest.fixture def service(self): return Mock(stop=AsyncMock()) - @pytest.fixture() + @pytest.fixture def sup(self, *, service): return SupervisorStrategy(service) @@ -133,7 +133,7 @@ async def test_restart_service__replacement(self, *, sup): class test_OneForAllSupervisor: - @pytest.fixture() + @pytest.fixture def sup(self): return OneForAllSupervisor(Mock()) @@ -143,7 +143,7 @@ async def test_restart_services__empty(self, *, sup): class test_ForfeitOneForOneSupervisor: - @pytest.fixture() + @pytest.fixture def sup(self): return ForfeitOneForOneSupervisor(Mock()) @@ -153,7 +153,7 @@ async def test_restart_services__empty(self, *, sup): class test_ForfeitOneForAllSupervisor: - @pytest.fixture() + @pytest.fixture def sup(self): return ForfeitOneForAllSupervisor(Mock()) @@ -163,7 +163,7 @@ async def test_restart_services__empty(self, *, sup): class test_CrashingSupervisor: - @pytest.fixture() + @pytest.fixture def sup(self): return CrashingSupervisor(Mock()) diff --git a/tests/unit/test_threads.py b/tests/unit/test_threads.py index f66bf44d..caf385dd 100644 --- a/tests/unit/test_threads.py +++ b/tests/unit/test_threads.py @@ -15,11 +15,11 @@ class test_WorkerThread: - @pytest.fixture() + @pytest.fixture def service(self): return Mock(name="service") - @pytest.fixture() + @pytest.fixture def thread(self, *, service): return WorkerThread(service) @@ -48,19 +48,19 @@ def test_stop__not_alive(self, *, thread): class test_ServiceThread: - @pytest.fixture() + @pytest.fixture def loop(self, *, event_loop): return event_loop - @pytest.fixture() + @pytest.fixture def thread_loop(self): return Mock(name="thread_loop") - @pytest.fixture() + @pytest.fixture def Worker(self): return Mock(spec=WorkerThread, name="Worker") - @pytest.fixture() + @pytest.fixture def thread(self, *, Worker, loop, thread_loop): return ServiceThread(Worker=Worker, loop=loop, thread_loop=thread_loop) @@ -373,7 +373,7 @@ async def myfun(x, y): class test_QueueServiceThread: - @pytest.fixture() + @pytest.fixture def s(self): return QueueServiceThread() diff --git a/tests/unit/test_worker.py b/tests/unit/test_worker.py index 83648909..56b1d553 100644 --- a/tests/unit/test_worker.py +++ b/tests/unit/test_worker.py @@ -23,7 +23,7 @@ def test_exiting(): class test_Worker: - @pytest.fixture() + @pytest.fixture def worker(self): return Worker(loglevel="INFO", logfile=None) diff --git a/tests/unit/utils/test_imports.py b/tests/unit/utils/test_imports.py index 39edcc6d..0162d790 100644 --- a/tests/unit/utils/test_imports.py +++ b/tests/unit/utils/test_imports.py @@ -21,7 +21,7 @@ class test_FactoryMapping: - @pytest.fixture() + @pytest.fixture def map(self): return FactoryMapping( { @@ -107,7 +107,7 @@ def test__ensure_identifier(): class test_symbol_by_name: - @pytest.fixture() + @pytest.fixture def imp(self): return Mock(name="imp") @@ -172,7 +172,7 @@ def test_load_extension_classes_syntax_error(): with patch_importlib_metadata_entry_points(): with patch("mode.utils.imports.symbol_by_name") as sbn: sbn.side_effect = SyntaxError() - with pytest.warns(UserWarning): + with pytest.warns(UserWarning, match="Cannot load (.*) extension"): assert list(load_extension_classes("foo")) == [] diff --git a/tests/unit/utils/test_logging.py b/tests/unit/utils/test_logging.py index e20a56c1..2cb721fe 100644 --- a/tests/unit/utils/test_logging.py +++ b/tests/unit/utils/test_logging.py @@ -50,15 +50,15 @@ def formatter_called_with(formatter, *args, stacklevel, **kwargs): class test_CompositeLogger: - @pytest.fixture() + @pytest.fixture def logger(self): return Mock(name="logger") - @pytest.fixture() + @pytest.fixture def formatter(self): return Mock(name="formatter") - @pytest.fixture() + @pytest.fixture def log(self, *, logger, formatter): return CompositeLogger(logger=logger, formatter=formatter) @@ -278,15 +278,15 @@ def test_setup_logging_helper_no_merge_config(self): class test_Logwrapped: - @pytest.fixture() + @pytest.fixture def obj(self): return Mock(name="obj") - @pytest.fixture() + @pytest.fixture def logger(self): return Mock(name="logger") - @pytest.fixture() + @pytest.fixture def wrapped(self, *, obj, logger): return Logwrapped(obj, logger, severity="INFO", ident="ident") @@ -341,11 +341,11 @@ def test_print_task_name(): class test_flight_recorder: - @pytest.fixture() + @pytest.fixture def logger(self): return Mock(name="logger") - @pytest.fixture() + @pytest.fixture def bb(self, *, logger): return flight_recorder(logger, timeout=30.0) diff --git a/tests/unit/utils/test_objects.py b/tests/unit/utils/test_objects.py index 4ae4081c..0e384af3 100644 --- a/tests/unit/utils/test_objects.py +++ b/tests/unit/utils/test_objects.py @@ -187,8 +187,8 @@ class Y: ... @pytest.mark.skip(reason="Needs fixing, typing.List eval does not work") def test_eval_type(): - assert eval_type("list") == list - assert eval_type("typing.List") == typing.List + assert eval_type("list") is list + assert eval_type("typing.List") is typing.List def test_annotations(): From c4f1787502acc7392cbea92588de04bae813162b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20B=C3=BChl?= Date: Fri, 27 Jun 2025 09:04:41 +0200 Subject: [PATCH 3/3] fix: use same ruff version in pre-commit hook and venv --- .pre-commit-config.yaml | 4 ++-- requirements-tests.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 42c8326d..0c1cf53d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,10 +14,10 @@ repos: hooks: - id: commitizen - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.3.0 + rev: v0.12.1 hooks: # Run the linter - - id: ruff + - id: ruff-check args: - --fix # Run the formatter diff --git a/requirements-tests.txt b/requirements-tests.txt index 370fe4d2..dbed0d42 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -11,7 +11,7 @@ pytest-random-order>=1.1.1 pytest-sugar>=1.0.0 # TODO: check the need pytest>=8.0.2 pytz -ruff>=0.3.0 +ruff>=0.12.1 vulture yarl