Compare commits

..

No commits in common. "master" and "4.46.0" have entirely different histories.

6 changed files with 131 additions and 25 deletions

View File

@ -1,11 +1,17 @@
"""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
@ -14,7 +20,24 @@ except ImportError:
from . import providers, errors
from .providers cimport __is_future_or_coroutine
from .wiring import wire, unwire
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,
)
class WiringConfiguration:
@ -30,7 +53,7 @@ class WiringConfiguration:
return self.__class__(self.modules, self.packages, self.from_package, self.auto_wire)
class Container:
class Container(object):
"""Abstract container."""

View File

@ -1,6 +1,10 @@
"""Providers module."""
import asyncio
try:
import asyncio
except ImportError:
asyncio = None
import functools
cimport cython
@ -15,7 +19,7 @@ cdef tuple __COROUTINE_TYPES
# Base providers
cdef class Provider:
cdef class Provider(object):
cdef tuple _overridden
cdef Provider _last_overriding
cdef tuple _overrides
@ -287,7 +291,7 @@ cdef class MethodCaller(Provider):
# Injections
cdef class Injection:
cdef class Injection(object):
cdef object _value
cdef int _is_provider
cdef int _is_delegated
@ -309,12 +313,12 @@ cpdef tuple parse_named_injections(dict kwargs)
# Utils
cdef class OverridingContext:
cdef class OverridingContext(object):
cdef Provider _overridden
cdef Provider _overriding
cdef class BaseSingletonResetContext:
cdef class BaseSingletonResetContext(object):
cdef object _singleton

View File

@ -3,8 +3,6 @@
from __future__ import absolute_import
import asyncio
import builtins
import contextvars
import copy
import errno
import functools
@ -15,9 +13,21 @@ 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:
@ -66,6 +76,24 @@ 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<name>[^}^{:]+)(?P<separator>:?)(?P<default>.*?)}",
)
@ -125,7 +153,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
cdef tuple __COROUTINE_TYPES = asyncio.coroutines._COROUTINE_TYPES if asyncio else tuple()
cdef dict pydantic_settings_to_dict(settings, dict kwargs):
if not has_pydantic_settings:
@ -135,7 +163,7 @@ cdef dict pydantic_settings_to_dict(settings, dict kwargs):
f"\"pip install dependency-injector[{pydantic_extra}]\""
)
if isinstance(settings, type) and issubclass(settings, PydanticSettings):
if isinstance(settings, CLASS_TYPES) and issubclass(settings, PydanticSettings):
raise Error(
"Got settings class, but expect instance: "
"instead \"{0}\" use \"{0}()\"".format(settings.__name__)
@ -153,7 +181,7 @@ cdef dict pydantic_settings_to_dict(settings, dict kwargs):
return settings.model_dump(mode="python", **kwargs)
cdef class Provider:
cdef class Provider(object):
"""Base provider class.
:py:class:`Provider` is callable (implements ``__call__`` method). Every
@ -875,9 +903,12 @@ cdef class Dependency(Provider):
def set_instance_of(self, instance_of):
"""Set type."""
if not isinstance(instance_of, type):
if not isinstance(instance_of, CLASS_TYPES):
raise TypeError(
f"\"instance_of\" is not a class (got {instance_of!r}))",
"\"instance_of\" has incorrect type (expected {0}, got {1}))".format(
CLASS_TYPES,
instance_of,
),
)
self._instance_of = instance_of
return self
@ -1439,6 +1470,8 @@ 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, "
@ -3937,14 +3970,18 @@ cdef class Resource(Provider):
@staticmethod
def _is_resource_subclass(instance):
if not isinstance(instance, type):
if sys.version_info < (3, 5):
return False
if not isinstance(instance, CLASS_TYPES):
return
from . import resources
return issubclass(instance, resources.Resource)
@staticmethod
def _is_async_resource_subclass(instance):
if not isinstance(instance, type):
if sys.version_info < (3, 5):
return False
if not isinstance(instance, CLASS_TYPES):
return
from . import resources
return issubclass(instance, resources.AsyncResource)
@ -4602,7 +4639,7 @@ cdef class MethodCaller(Provider):
future_result.set_result(result)
cdef class Injection:
cdef class Injection(object):
"""Abstract injection class."""
@ -4729,7 +4766,7 @@ cpdef tuple parse_named_injections(dict kwargs):
return tuple(injections)
cdef class OverridingContext:
cdef class OverridingContext(object):
"""Provider overriding context.
:py:class:`OverridingContext` is used by :py:meth:`Provider.override` for
@ -4765,7 +4802,7 @@ cdef class OverridingContext:
self._overridden.reset_last_overriding()
cdef class BaseSingletonResetContext:
cdef class BaseSingletonResetContext(object):
def __init__(self, Provider provider):
self._singleton = provider
@ -4801,7 +4838,7 @@ cpdef bint is_provider(object instance):
:rtype: bool
"""
return (not isinstance(instance, type) and
return (not isinstance(instance, CLASS_TYPES) and
getattr(instance, "__IS_PROVIDER__", False) is True)
@ -4829,7 +4866,7 @@ cpdef bint is_delegated(object instance):
:rtype: bool
"""
return (not isinstance(instance, type) and
return (not isinstance(instance, CLASS_TYPES) and
getattr(instance, "__IS_DELEGATED__", False) is True)
@ -4860,7 +4897,7 @@ cpdef bint is_container_instance(object instance):
:rtype: bool
"""
return (not isinstance(instance, type) and
return (not isinstance(instance, CLASS_TYPES) and
getattr(instance, "__IS_CONTAINER__", False) is True)
@ -4872,7 +4909,7 @@ cpdef bint is_container_class(object instance):
:rtype: bool
"""
return (isinstance(instance, type) and
return (isinstance(instance, CLASS_TYPES) and
getattr(instance, "__IS_CONTAINER__", False) is True)

View File

@ -6,6 +6,7 @@ import importlib.machinery
import inspect
import pkgutil
import sys
import warnings
from types import ModuleType
from typing import (
Any,
@ -23,6 +24,12 @@ 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):
@ -66,6 +73,13 @@ 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",
@ -874,7 +888,15 @@ def provided() -> ProvidedInstance:
return ProvidedInstance()
class _Marker(Generic[T]):
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):
__IS_MARKER__ = True

View File

@ -0,0 +1,10 @@
[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.*

View File

@ -0,0 +1,10 @@
[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.*