From 6e4794bab18fef3ffbc6a11bee526fe24688286f Mon Sep 17 00:00:00 2001 From: ZipFile Date: Sun, 2 Mar 2025 14:33:31 +0200 Subject: [PATCH] Remove code for EOL Python versions (#864) --- src/dependency_injector/containers.pyx | 29 ++--------- src/dependency_injector/providers.pxd | 14 ++---- src/dependency_injector/providers.pyx | 69 ++++++-------------------- src/dependency_injector/wiring.py | 24 +-------- tests/.configs/pytest-py27.ini | 10 ---- tests/.configs/pytest-py35.ini | 10 ---- 6 files changed, 25 insertions(+), 131 deletions(-) delete mode 100644 tests/.configs/pytest-py27.ini delete mode 100644 tests/.configs/pytest-py35.ini diff --git a/src/dependency_injector/containers.pyx b/src/dependency_injector/containers.pyx index 7e922773..2f4c4af5 100644 --- a/src/dependency_injector/containers.pyx +++ b/src/dependency_injector/containers.pyx @@ -1,17 +1,11 @@ """Containers module.""" +import asyncio import contextlib import copy as copy_module import json -import sys import importlib import inspect -import warnings - -try: - import asyncio -except ImportError: - asyncio = None try: import yaml @@ -20,24 +14,7 @@ except ImportError: from . import providers, errors from .providers cimport __is_future_or_coroutine - - -if sys.version_info[:2] >= (3, 6): - from .wiring import wire, unwire -else: - def wire(*args, **kwargs): - raise NotImplementedError("Wiring requires Python 3.6 or above") - - def unwire(*args, **kwargs): - raise NotImplementedError("Wiring requires Python 3.6 or above") - -if sys.version_info[:2] == (3, 5): - warnings.warn( - "Dependency Injector will drop support of Python 3.5 after Jan 1st of 2022. " - "This does not mean that there will be any immediate breaking changes, " - "but tests will no longer be executed on Python 3.5, and bugs will not be addressed.", - category=DeprecationWarning, - ) +from .wiring import wire, unwire class WiringConfiguration: @@ -53,7 +30,7 @@ class WiringConfiguration: return self.__class__(self.modules, self.packages, self.from_package, self.auto_wire) -class Container(object): +class Container: """Abstract container.""" diff --git a/src/dependency_injector/providers.pxd b/src/dependency_injector/providers.pxd index 4a733d80..b4eb471d 100644 --- a/src/dependency_injector/providers.pxd +++ b/src/dependency_injector/providers.pxd @@ -1,10 +1,6 @@ """Providers module.""" -try: - import asyncio -except ImportError: - asyncio = None - +import asyncio import functools cimport cython @@ -19,7 +15,7 @@ cdef tuple __COROUTINE_TYPES # Base providers -cdef class Provider(object): +cdef class Provider: cdef tuple _overridden cdef Provider _last_overriding cdef tuple _overrides @@ -291,7 +287,7 @@ cdef class MethodCaller(Provider): # Injections -cdef class Injection(object): +cdef class Injection: cdef object _value cdef int _is_provider cdef int _is_delegated @@ -313,12 +309,12 @@ cpdef tuple parse_named_injections(dict kwargs) # Utils -cdef class OverridingContext(object): +cdef class OverridingContext: cdef Provider _overridden cdef Provider _overriding -cdef class BaseSingletonResetContext(object): +cdef class BaseSingletonResetContext: cdef object _singleton diff --git a/src/dependency_injector/providers.pyx b/src/dependency_injector/providers.pyx index a3620350..73c5cbe1 100644 --- a/src/dependency_injector/providers.pyx +++ b/src/dependency_injector/providers.pyx @@ -3,6 +3,8 @@ from __future__ import absolute_import import asyncio +import builtins +import contextvars import copy import errno import functools @@ -13,21 +15,9 @@ import os import re import sys import threading -import types import warnings from configparser import ConfigParser as IniConfigParser -try: - import contextvars -except ImportError: - contextvars = None - -try: - import builtins -except ImportError: - # Python 2.7 - import __builtin__ as builtins - try: from inspect import _is_coroutine_mark as _is_coroutine_marker except ImportError: @@ -76,24 +66,6 @@ from .errors import ( cimport cython -if sys.version_info[0] == 3: # pragma: no cover - CLASS_TYPES = (type,) -else: # pragma: no cover - CLASS_TYPES = (type, types.ClassType) - - copy._deepcopy_dispatch[types.MethodType] = \ - lambda obj, memo: type(obj)(obj.im_func, - copy.deepcopy(obj.im_self, memo), - obj.im_class) - -if sys.version_info[:2] == (3, 5): - warnings.warn( - "Dependency Injector will drop support of Python 3.5 after Jan 1st of 2022. " - "This does not mean that there will be any immediate breaking changes, " - "but tests will no longer be executed on Python 3.5, and bugs will not be addressed.", - category=DeprecationWarning, - ) - config_env_marker_pattern = re.compile( r"\${(?P[^}^{:]+)(?P:?)(?P.*?)}", ) @@ -153,7 +125,7 @@ cdef int ASYNC_MODE_ENABLED = 1 cdef int ASYNC_MODE_DISABLED = 2 cdef set __iscoroutine_typecache = set() -cdef tuple __COROUTINE_TYPES = asyncio.coroutines._COROUTINE_TYPES if asyncio else tuple() +cdef tuple __COROUTINE_TYPES = asyncio.coroutines._COROUTINE_TYPES cdef dict pydantic_settings_to_dict(settings, dict kwargs): if not has_pydantic_settings: @@ -163,7 +135,7 @@ cdef dict pydantic_settings_to_dict(settings, dict kwargs): f"\"pip install dependency-injector[{pydantic_extra}]\"" ) - if isinstance(settings, CLASS_TYPES) and issubclass(settings, PydanticSettings): + if isinstance(settings, type) and issubclass(settings, PydanticSettings): raise Error( "Got settings class, but expect instance: " "instead \"{0}\" use \"{0}()\"".format(settings.__name__) @@ -181,7 +153,7 @@ cdef dict pydantic_settings_to_dict(settings, dict kwargs): return settings.model_dump(mode="python", **kwargs) -cdef class Provider(object): +cdef class Provider: """Base provider class. :py:class:`Provider` is callable (implements ``__call__`` method). Every @@ -903,12 +875,9 @@ cdef class Dependency(Provider): def set_instance_of(self, instance_of): """Set type.""" - if not isinstance(instance_of, CLASS_TYPES): + if not isinstance(instance_of, type): raise TypeError( - "\"instance_of\" has incorrect type (expected {0}, got {1}))".format( - CLASS_TYPES, - instance_of, - ), + f"\"instance_of\" is not a class (got {instance_of!r}))", ) self._instance_of = instance_of return self @@ -1470,8 +1439,6 @@ cdef class Coroutine(Callable): def set_provides(self, provides): """Set provider provides.""" - if not asyncio: - raise Error("Package asyncio is not available") provides = _resolve_string_import(provides) if provides and not asyncio.iscoroutinefunction(provides): raise Error(f"Provider {_class_qualname(self)} expected to get coroutine function, " @@ -3970,18 +3937,14 @@ cdef class Resource(Provider): @staticmethod def _is_resource_subclass(instance): - if sys.version_info < (3, 5): - return False - if not isinstance(instance, CLASS_TYPES): + if not isinstance(instance, type): return from . import resources return issubclass(instance, resources.Resource) @staticmethod def _is_async_resource_subclass(instance): - if sys.version_info < (3, 5): - return False - if not isinstance(instance, CLASS_TYPES): + if not isinstance(instance, type): return from . import resources return issubclass(instance, resources.AsyncResource) @@ -4639,7 +4602,7 @@ cdef class MethodCaller(Provider): future_result.set_result(result) -cdef class Injection(object): +cdef class Injection: """Abstract injection class.""" @@ -4766,7 +4729,7 @@ cpdef tuple parse_named_injections(dict kwargs): return tuple(injections) -cdef class OverridingContext(object): +cdef class OverridingContext: """Provider overriding context. :py:class:`OverridingContext` is used by :py:meth:`Provider.override` for @@ -4802,7 +4765,7 @@ cdef class OverridingContext(object): self._overridden.reset_last_overriding() -cdef class BaseSingletonResetContext(object): +cdef class BaseSingletonResetContext: def __init__(self, Provider provider): self._singleton = provider @@ -4838,7 +4801,7 @@ cpdef bint is_provider(object instance): :rtype: bool """ - return (not isinstance(instance, CLASS_TYPES) and + return (not isinstance(instance, type) and getattr(instance, "__IS_PROVIDER__", False) is True) @@ -4866,7 +4829,7 @@ cpdef bint is_delegated(object instance): :rtype: bool """ - return (not isinstance(instance, CLASS_TYPES) and + return (not isinstance(instance, type) and getattr(instance, "__IS_DELEGATED__", False) is True) @@ -4897,7 +4860,7 @@ cpdef bint is_container_instance(object instance): :rtype: bool """ - return (not isinstance(instance, CLASS_TYPES) and + return (not isinstance(instance, type) and getattr(instance, "__IS_CONTAINER__", False) is True) @@ -4909,7 +4872,7 @@ cpdef bint is_container_class(object instance): :rtype: bool """ - return (isinstance(instance, CLASS_TYPES) and + return (isinstance(instance, type) and getattr(instance, "__IS_CONTAINER__", False) is True) diff --git a/src/dependency_injector/wiring.py b/src/dependency_injector/wiring.py index 5cded9f5..9de6f823 100644 --- a/src/dependency_injector/wiring.py +++ b/src/dependency_injector/wiring.py @@ -6,7 +6,6 @@ import importlib.machinery import inspect import pkgutil import sys -import warnings from types import ModuleType from typing import ( Any, @@ -24,12 +23,6 @@ from typing import ( cast, ) -if sys.version_info < (3, 7): - from typing import GenericMeta -else: - - class GenericMeta(type): ... - # Hotfix, see: https://github.com/ets-labs/python-dependency-injector/issues/362 if sys.version_info >= (3, 9): @@ -73,13 +66,6 @@ except ImportError: from . import providers -if sys.version_info[:2] == (3, 5): - warnings.warn( - "Dependency Injector will drop support of Python 3.5 after Jan 1st of 2022. " - "This does not mean that there will be any immediate breaking changes, " - "but tests will no longer be executed on Python 3.5, and bugs will not be addressed.", - category=DeprecationWarning, - ) __all__ = ( "wire", @@ -888,15 +874,7 @@ def provided() -> ProvidedInstance: return ProvidedInstance() -class ClassGetItemMeta(GenericMeta): - def __getitem__(cls, item): - # Spike for Python 3.6 - if isinstance(item, tuple): - return cls(*item) - return cls(item) - - -class _Marker(Generic[T], metaclass=ClassGetItemMeta): +class _Marker(Generic[T]): __IS_MARKER__ = True diff --git a/tests/.configs/pytest-py27.ini b/tests/.configs/pytest-py27.ini deleted file mode 100644 index 8901a901..00000000 --- a/tests/.configs/pytest-py27.ini +++ /dev/null @@ -1,10 +0,0 @@ -[pytest] -testpaths = tests/unit/ -python_files = test_*_py2_py3.py -asyncio_mode = auto -filterwarnings = - ignore:Module \"dependency_injector.ext.aiohttp\" is deprecated since version 4\.0\.0:DeprecationWarning - ignore:Module \"dependency_injector.ext.flask\" is deprecated since version 4\.0\.0:DeprecationWarning - ignore:Please use \`.*?\` from the \`scipy.*?\`(.*?)namespace is deprecated\.:DeprecationWarning - ignore:The \`scipy(.*?)\` namespace is deprecated(.*):DeprecationWarning - ignore:ssl\.PROTOCOL_TLS is deprecated:DeprecationWarning:botocore.* diff --git a/tests/.configs/pytest-py35.ini b/tests/.configs/pytest-py35.ini deleted file mode 100644 index 3c682e9a..00000000 --- a/tests/.configs/pytest-py35.ini +++ /dev/null @@ -1,10 +0,0 @@ -[pytest] -testpaths = tests/unit/ -python_files = test_*_py3.py -asyncio_mode = auto -filterwarnings = - ignore:Module \"dependency_injector.ext.aiohttp\" is deprecated since version 4\.0\.0:DeprecationWarning - ignore:Module \"dependency_injector.ext.flask\" is deprecated since version 4\.0\.0:DeprecationWarning - ignore:Please use \`.*?\` from the \`scipy.*?\`(.*?)namespace is deprecated\.:DeprecationWarning - ignore:The \`scipy(.*?)\` namespace is deprecated(.*):DeprecationWarning - ignore:ssl\.PROTOCOL_TLS is deprecated:DeprecationWarning:botocore.*