Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-injector for openSUSE:Factory 
checked in at 2022-01-03 10:49:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-injector (Old)
 and      /work/SRC/openSUSE:Factory/.python-injector.new.1896 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-injector"

Mon Jan  3 10:49:24 2022 rev:7 rq:943322 version:0.19.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-injector/python-injector.changes  
2021-03-08 15:18:22.981988154 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-injector.new.1896/python-injector.changes    
    2022-01-03 10:49:55.123591918 +0100
@@ -1,0 +2,17 @@
+Fri Dec 31 13:01:20 UTC 2021 - Matej Cepl <mc...@suse.com>
+
+- Update to 0.19.0:
+  - Added the license to the source distribution, thanks to
+    Joshua Adelman
+  - Added Python 3.9 and 3.10 support, this includes fixing
+    Python 3.10 compatibility, thanks to Torge Matthies
+  - Improved the documentation, thanks to Takahiro Kojima
+  - Improved the source distribution so that it can be used to
+    build and install wheels, thanks to Janusz Skonieczny
+  - Added requirements files for easier development, thanks to
+    Greg Eremeev
+  - Removed Python 3.5 support
+  - Fixed a bug where only one of multiple NoInject annotations
+    was interpreted
+
+-------------------------------------------------------------------

Old:
----
  0.18.3.tar.gz

New:
----
  0.19.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-injector.spec ++++++
--- /var/tmp/diff_new_pack.jPPdmI/_old  2022-01-03 10:49:56.199592330 +0100
+++ /var/tmp/diff_new_pack.jPPdmI/_new  2022-01-03 10:49:56.203592332 +0100
@@ -19,7 +19,7 @@
 %define skip_python2 1
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-injector
-Version:        0.18.3
+Version:        0.19.0
 Release:        0
 Summary:        Python dependency injection framework, inspired by Guice
 License:        BSD-3-Clause
@@ -33,7 +33,7 @@
 BuildRequires:  python-rpm-macros
 BuildRequires:  ((python3-dataclasses and python3-base < 3.7) or 
(python36-dataclasses and python36-base))
 Requires:       python
-Requires:       python-typing_extensions >= 3.7.4
+Requires:       (python-typing_extensions if python-base < 3.8)
 BuildArch:      noarch
 %python_subpackages
 

++++++ 0.18.3.tar.gz -> 0.19.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/.github/workflows/ci.yml 
new/injector-0.19.0/.github/workflows/ci.yml
--- old/injector-0.18.3/.github/workflows/ci.yml        1970-01-01 
01:00:00.000000000 +0100
+++ new/injector-0.19.0/.github/workflows/ci.yml        2021-12-20 
23:18:57.000000000 +0100
@@ -0,0 +1,29 @@
+name: CI
+
+on: [push, pull_request]
+
+jobs:
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-latest]
+        python-version: [3.6, 3.7, 3.8, 3.9, "3.10", pypy3]
+    steps:
+    - uses: actions/checkout@v2
+    - name: Set up Python ${{ matrix.python-version }}
+      uses: actions/setup-python@v2
+      with:
+        python-version: ${{ matrix.python-version }}
+    - name: Install dependencies
+      run: |
+        pip install --upgrade -r requirements.txt -r requirements-dev.txt
+        pip install .
+    - name: Run tests
+      run: |
+        py.test -vv --cov=injector --cov-branch --cov-report html --cov-report 
term
+        if which mypy; then mypy injector ; fi
+        if which black; then black --check . ; fi
+        check-manifest
+    - name: Report coverage to Codecov
+      uses: codecov/codecov-action@v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/.gitignore 
new/injector-0.19.0/.gitignore
--- old/injector-0.18.3/.gitignore      2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/.gitignore      2021-12-20 23:18:57.000000000 +0100
@@ -7,3 +7,6 @@
 .mypy_cache/
 .pytest_cache/
 coverage.xml
+/dist/
+/injector.egg-info/
+/.coverage
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/.travis.yml 
new/injector-0.19.0/.travis.yml
--- old/injector-0.18.3/.travis.yml     2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/.travis.yml     1970-01-01 01:00:00.000000000 +0100
@@ -1,29 +0,0 @@
-sudo: false
-language: python
-cache: pip
-python:
-  # There were significant typing-related changes in Python 3.5.4, let's make 
sure we test with the
-  # older versions as well
-  - "3.5.3"
-  - "3.5"
-  - "3.6"
-  - "3.7"
-  - "3.8"
-  - "nightly"
-  - "pypy3.5"
-  - "pypy3"
-matrix:
-  allow_failures:
-    - python: "nightly"
-install:
-  - pip install --upgrade coveralls pytest "pytest-cov>=2.5.1" dataclasses 
typing_extensions
-  # mypy can't be installed on pypy
-  - if [[ "${TRAVIS_PYTHON_VERSION}" != "pypy"* ]] ; then pip install mypy ; fi
-  # Black is Python 3.6+-only
-  - if [[ "${TRAVIS_PYTHON_VERSION}" != "pypy"* &&  "${TRAVIS_PYTHON_VERSION}" 
!= "3.5"* ]] ; then pip install black ; fi
-script:
-  - py.test -vv --cov=injector --cov-branch --cov-report html --cov-report term
-  - if [[ "${TRAVIS_PYTHON_VERSION}" != "pypy"* ]] ; then mypy injector ; fi
-  - if [[ "${TRAVIS_PYTHON_VERSION}" != "pypy"* && "${TRAVIS_PYTHON_VERSION}" 
!= "3.5"* ]] ; then black --check . ; fi
-after_success:
-  - coveralls
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/CHANGES new/injector-0.19.0/CHANGES
--- old/injector-0.18.3/CHANGES 2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/CHANGES 2021-12-20 23:18:57.000000000 +0100
@@ -1,6 +1,24 @@
 Injector Change Log
 ===================
 
+0.19.0
+------
+
+- Added the license to the source distribution, thanks to Joshua Adelman
+- Added Python 3.9 and 3.10 support, this includes fixing Python 3.10 
compatibility, thanks to Torge Matthies
+- Improved the documentation, thanks to Takahiro Kojima
+- Improved the source distribution so that it can be used to build and install 
wheels, thanks to Janusz Skonieczny
+- Added requirements files for easier development, thanks to Greg Eremeev
+
+Backwards incompatible:
+
+- Removed Python 3.5 support
+
+0.18.4
+------
+
+- Fixed a bug where only one of multiple NoInject annotations was interpreted
+
 0.18.3
 ------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/MANIFEST.in 
new/injector-0.19.0/MANIFEST.in
--- old/injector-0.18.3/MANIFEST.in     2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/MANIFEST.in     2021-12-20 23:18:57.000000000 +0100
@@ -1 +1,12 @@
+include *.py
+include *.toml
+include *.txt
+include CHANGES
+include COPYING
 include README.md
+include mypy.ini
+include pytest.ini
+recursive-include docs *.html
+recursive-include docs *.py
+recursive-include docs *.rst
+recursive-include docs Makefile
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/README.md 
new/injector-0.19.0/README.md
--- old/injector-0.18.3/README.md       2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/README.md       2021-12-20 23:18:57.000000000 +0100
@@ -1,8 +1,8 @@
 Injector - Python dependency injection framework, inspired by Guice
 ===================================================================
 
-[![image](https://secure.travis-ci.org/alecthomas/injector.svg?branch=master)](https://travis-ci.org/alecthomas/injector)
-[![Coverage 
Status](https://coveralls.io/repos/github/alecthomas/injector/badge.svg?branch=master)](https://coveralls.io/github/alecthomas/injector?branch=master)
+[![image](https://github.com/alecthomas/injector/workflows/CI/badge.svg)](https://github.com/alecthomas/injector/actions?query=workflow%3ACI+branch%3Amaster)
+[![Coverage 
Status](https://codecov.io/gh/alecthomas/injector/branch/master/graph/badge.svg)](https://codecov.io/gh/alecthomas/injector)
 
 Introduction
 ------------
@@ -51,21 +51,28 @@
   is typed such that `injector.get(SomeType)` is statically declared to return 
an instance of
   `SomeType`, therefore making it possible for tools such as 
[mypy](https://github.com/python/mypy) to
   type-check correctly the code using it.
+  
+* The client code only knows about dependency injection to the extent it needs 
?????
+  
[`inject`](https://injector.readthedocs.io/en/latest/api.html#injector.inject),
+  
[`Inject`](https://injector.readthedocs.io/en/latest/api.html#injector.Inject) 
and
+  
[`NoInject`](https://injector.readthedocs.io/en/latest/api.html#injector.NoInject)
 are simple markers
+  that don't really do anything on their own and your code can run just fine 
without Injector
+  orchestrating things.
 
 ### How to get Injector?
 
 * GitHub (code repository, issues): https://github.com/alecthomas/injector
 
-* PyPI (installable, stable distributions): 
https://pypi.python.org/pypi/injector. You can install it using pip:
+* PyPI (installable, stable distributions): 
https://pypi.org/project/injector/. You can install it using pip:
 
   ```bash
   pip install injector
   ```
 
-* Documentation: http://injector.readthedocs.org
-* Change log: http://injector.readthedocs.io/en/latest/changelog.html
+* Documentation: https://injector.readthedocs.org
+* Change log: https://injector.readthedocs.io/en/latest/changelog.html
 
-Injector works with CPython 3.5+ and PyPy 3 implementing Python 3.5+.
+Injector works with CPython 3.6+ and PyPy 3 implementing Python 3.6+.
 
 A Quick Example
 ---------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/docs/_templates/sidebar.html 
new/injector-0.19.0/docs/_templates/sidebar.html
--- old/injector-0.18.3/docs/_templates/sidebar.html    2020-02-03 
15:35:27.000000000 +0100
+++ new/injector-0.19.0/docs/_templates/sidebar.html    2021-12-20 
23:18:57.000000000 +0100
@@ -2,6 +2,6 @@
 <p>Dependency Injection Framework</p>
 <ul>
        <li><a href="https://github.com/alecthomas/injector";>Injector at 
GitHub</a></li>
-       <li><a href="https://pypi.python.org/pypi/injector";>Injector at 
PyPI</a></li>
-       <li><a href="http://injector.readthedocs.org/en/latest/";>Injector 
documentation</a></li>
+       <li><a href="https://pypi.org/project/injector/";>Injector at 
PyPI</a></li>
+       <li><a href="https://injector.readthedocs.org/en/latest/";>Injector 
documentation</a></li>
 </ul>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/docs/index.rst 
new/injector-0.19.0/docs/index.rst
--- old/injector-0.18.3/docs/index.rst  2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/docs/index.rst  2021-12-20 23:18:57.000000000 +0100
@@ -6,13 +6,14 @@
 Welcome to Injector's documentation!
 ====================================
 
-.. image:: https://travis-ci.org/alecthomas/injector.png?branch=master
+.. image:: https://github.com/alecthomas/injector/workflows/CI/badge.svg
    :alt: Build status
-   :target: https://travis-ci.org/alecthomas/injector
+   :target: 
https://github.com/alecthomas/injector/actions?query=workflow%3ACI+branch%3Amaster
    
-.. image:: 
https://coveralls.io/repos/github/alecthomas/injector/badge.svg?branch=master
+.. image:: 
https://codecov.io/gh/alecthomas/injector/branch/master/graph/badge.svg
    :alt: Covergage status
-   :target: https://coveralls.io/github/alecthomas/injector?branch=master
+   :target: https://codecov.io/gh/alecthomas/injector
+
 
 GitHub (code repository, issues): https://github.com/alecthomas/injector
 
@@ -20,7 +21,7 @@
 
     pip install injector
 
-Injector works with CPython 3.5+ and PyPy 3 implementing Python 3.5+.
+Injector works with CPython 3.6+ and PyPy 3 implementing Python 3.6+.
 
 Introduction
 ------------
@@ -51,7 +52,7 @@
 
     class MyClass:
         @inject
-        def __init__(t: SomeType):
+        def __init__(self, t: SomeType):
             # ...
 
     MyClass()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/docs/practices.rst 
new/injector-0.19.0/docs/practices.rst
--- old/injector-0.18.3/docs/practices.rst      2020-02-03 15:35:27.000000000 
+0100
+++ new/injector-0.19.0/docs/practices.rst      2021-12-20 23:18:57.000000000 
+0100
@@ -126,11 +126,11 @@
     from threading import Thread
     from time import sleep
 
-    from injector import inject, Injector, Key, Module, provider
+    from injector import inject, Injector, Module, provider
 
-    SubA = Key('SubA')
-    A = Key('A')
-    B = Key('B')
+    class A: pass
+    class SubA(A): pass
+    class B: pass
 
 
     class BadModule(Module):
@@ -146,11 +146,11 @@
                 sleep(1)
 
             # This never executes
-            return 'suba'
+            return SubA()
 
         @provider
         def provide_b(self) -> B:
-            return 'b'
+            return B()
 
 
     injector = Injector([BadModule])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/docs/terminology.rst 
new/injector-0.19.0/docs/terminology.rst
--- old/injector-0.18.3/docs/terminology.rst    2020-02-03 15:35:27.000000000 
+0100
+++ new/injector-0.19.0/docs/terminology.rst    2021-12-20 23:18:57.000000000 
+0100
@@ -29,15 +29,6 @@
 
 .. seealso:: :ref:`scopes`
 
-Keys
-````
-
-`Key` may be used to create unique types as necessary::
-
-    >>> from injector import Key
-    >>> Name = Key('name')
-    >>> Description = Key('description')
-
 Binding
 ```````
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/injector/__init__.py 
new/injector-0.19.0/injector/__init__.py
--- old/injector-0.18.3/injector/__init__.py    2020-02-03 15:35:27.000000000 
+0100
+++ new/injector-0.19.0/injector/__init__.py    2021-12-20 23:18:57.000000000 
+0100
@@ -33,22 +33,38 @@
     List,
     Optional,
     overload,
+    Set,
     Tuple,
     Type,
     TypeVar,
+    TYPE_CHECKING,
     Union,
 )
 
-from typing_extensions import NoReturn
+try:
+    from typing import NoReturn
+except ImportError:
+    from typing_extensions import NoReturn
 
 HAVE_ANNOTATED = sys.version_info >= (3, 7, 0)
 
-if HAVE_ANNOTATED:
+# This is a messy, type-wise, because we not only have two potentially 
conflicting imports here
+# but we also define our own versions in the else block in case we operate on 
Python 3.6
+# which didn't get Annotated support in get_type_hints(). The easiest way to 
make mypy
+# happy here is to tell it the versions from typing_extensions are canonical. 
Since this
+# typing_extensions import is only for mypy it'll work even without 
typing_extensions actually
+# installed so all's good.
+if TYPE_CHECKING:
+    from typing_extensions import _AnnotatedAlias, Annotated, get_type_hints
+elif HAVE_ANNOTATED:
     # Ignoring errors here as typing_extensions stub doesn't know about those 
things yet
-    from typing_extensions import _AnnotatedAlias, Annotated, get_type_hints  
# type: ignore
+    try:
+        from typing import _AnnotatedAlias, Annotated, get_type_hints
+    except ImportError:
+        from typing_extensions import _AnnotatedAlias, Annotated, 
get_type_hints
 else:
 
-    class Annotated:  # type: ignore
+    class Annotated:
         pass
 
     from typing import get_type_hints as _get_type_hints
@@ -62,11 +78,8 @@
         return _get_type_hints(obj, globalns, localns)
 
 
-TYPING353 = hasattr(Union[str, int], '__origin__')
-
-
 __author__ = 'Alec Thomas <a...@swapoff.org>'
-__version__ = '0.18.3'
+__version__ = '0.19.0'
 __version_tag__ = ''
 
 log = logging.getLogger('injector')
@@ -110,7 +123,7 @@
     InjectT = TypeVar('InjectT')
     Inject = Annotated[InjectT, _inject_marker]
     """An experimental way to declare injectable dependencies utilizing a `PEP 
593`_ implementation
-    in `typing_extensions`.
+    in Python 3.9 and backported to Python 3.7+ in `typing_extensions`.
 
     Those two declarations are equivalent::
 
@@ -150,7 +163,7 @@
 
     NoInject = Annotated[InjectT, _noinject_marker]
     """An experimental way to declare noninjectable dependencies utilizing a 
`PEP 593`_ implementation
-    in `typing_extensions`.
+    in Python 3.9 and backported to Python 3.7+ in `typing_extensions`.
 
     Since :func:`inject` declares all function's parameters to be injectable 
there needs to be a way
     to opt out of it. This has been provided by :func:`noninjectable` but 
`noninjectable` suffers from
@@ -221,15 +234,9 @@
             return self.args[0]
 
         instance, method, args, kwargs, original_error, stack = self.args
-        if hasattr(method, 'im_class'):
-            instance = method.__self__
-            method_name = method.__func__.__name__
-        else:
-            method_name = method.__name__
-
         cls = instance.__class__.__name__ if instance is not None else ''
 
-        full_method = '.'.join((cls, method_name)).strip('.')
+        full_method = '.'.join((cls, method.__name__)).strip('.')
 
         parameters = ', '.join(
             itertools.chain(
@@ -305,7 +312,7 @@
         providing
         providing
         False
-        """
+    """
 
     def __init__(self, callable: Callable[..., T]):
         self._callable = callable
@@ -350,8 +357,10 @@
 class ListOfProviders(Provider, Generic[T]):
     """Provide a list of instances via other Providers."""
 
+    _providers: List[Provider[T]]
+
     def __init__(self) -> None:
-        self._providers = []  # type: List[Provider[T]]
+        self._providers = []
 
     def append(self, provider: Provider[T]) -> None:
         self._providers.append(provider)
@@ -372,7 +381,7 @@
     """A provider for map bindings."""
 
     def get(self, injector: 'Injector') -> Dict[str, T]:
-        map = {}  # type: Dict[str, T]
+        map: Dict[str, T] = {}
         for provider in self._providers:
             map.update(provider.get(injector))
         return map
@@ -399,6 +408,8 @@
         to instantiate it on your own.
     """
 
+    _bindings: Dict[type, Binding]
+
     @private
     def __init__(self, injector: 'Injector', auto_bind: bool = True, parent: 
'Binder' = None) -> None:
         """Create a new Binder.
@@ -409,7 +420,7 @@
         """
         self.injector = injector
         self._auto_bind = auto_bind
-        self._bindings = {}  # type: Dict[type, Binding]
+        self._bindings = {}
         self.parent = parent
 
     def bind(
@@ -507,13 +518,14 @@
         :param scope: Optional Scope in which to bind.
         """
         if interface not in self._bindings:
+            provider: ListOfProviders
             if (
                 isinstance(interface, dict)
                 or isinstance(interface, type)
                 and issubclass(interface, dict)
                 or _get_origin(_punch_through_alias(interface)) is dict
             ):
-                provider = MapBindProvider()  # type: ListOfProviders
+                provider = MapBindProvider()
             else:
                 provider = MultiBindProvider()
             binding = self.create_binding(interface, provider, scope)
@@ -662,47 +674,45 @@
         return any(_is_specialization(interface, cls) for cls in 
[AssistedBuilder, ProviderOf])
 
 
-if TYPING353:
-
-    def _is_specialization(cls: type, generic_class: Any) -> bool:
-        # Starting with typing 3.5.3/Python 3.6 it is no longer necessarily 
true that
-        # issubclass(SomeGeneric[X], SomeGeneric) so we need some other way to
-        # determine whether a particular object is a generic class with type 
parameters
-        # provided. Fortunately there seems to be __origin__ attribute that's 
useful here.
-
-        # We need to special-case Annotated as its __origin__ behaves 
differently than
-        # other typing generic classes. See 
https://github.com/python/typing/pull/635
-        # for some details.
-        if HAVE_ANNOTATED and generic_class is Annotated and isinstance(cls, 
_AnnotatedAlias):
-            return True
-
-        if not hasattr(cls, '__origin__'):
-            return False
-        origin = cast(Any, cls).__origin__
-        if not inspect.isclass(generic_class):
-            generic_class = type(generic_class)
-        if not inspect.isclass(origin):
-            origin = type(origin)
-        # __origin__ is generic_class is a special case to handle Union as
-        # Union cannot be used in issubclass() check (it raises an exception
-        # by design).
-        return origin is generic_class or issubclass(origin, generic_class)
-
-
-else:
-    # To maintain compatibility we fall back to an issubclass check.
-    def _is_specialization(cls: type, generic_class: Any) -> bool:
-        return isinstance(cls, type) and cls is not Any and issubclass(cls, 
generic_class)
+def _is_specialization(cls: type, generic_class: Any) -> bool:
+    # Starting with typing 3.5.3/Python 3.6 it is no longer necessarily true 
that
+    # issubclass(SomeGeneric[X], SomeGeneric) so we need some other way to
+    # determine whether a particular object is a generic class with type 
parameters
+    # provided. Fortunately there seems to be __origin__ attribute that's 
useful here.
+
+    # We need to special-case Annotated as its __origin__ behaves differently 
than
+    # other typing generic classes. See 
https://github.com/python/typing/pull/635
+    # for some details.
+    if HAVE_ANNOTATED and generic_class is Annotated and isinstance(cls, 
_AnnotatedAlias):
+        return True
+
+    if not hasattr(cls, '__origin__'):
+        return False
+    origin = cast(Any, cls).__origin__
+    if not inspect.isclass(generic_class):
+        generic_class = type(generic_class)
+    if not inspect.isclass(origin):
+        origin = type(origin)
+    # __origin__ is generic_class is a special case to handle Union as
+    # Union cannot be used in issubclass() check (it raises an exception
+    # by design).
+    return origin is generic_class or issubclass(origin, generic_class)
 
 
 def _punch_through_alias(type_: Any) -> type:
-    if getattr(type_, '__qualname__', '') == 'NewType.<locals>.new_type':
+    if (
+        sys.version_info < (3, 10)
+        and getattr(type_, '__qualname__', '') == 'NewType.<locals>.new_type'
+        or sys.version_info >= (3, 10)
+        and type(type_).__module__ == 'typing'
+        and type(type_).__name__ == 'NewType'
+    ):
         return type_.__supertype__
     else:
         return type_
 
 
-def _get_origin(type_: type) -> type:
+def _get_origin(type_: type) -> Optional[type]:
     origin = getattr(type_, '__origin__', None)
     # Older typing behaves differently there and stores Dict and List as 
origin, we need to be flexible.
     if origin is List:
@@ -780,8 +790,10 @@
     True
     """
 
+    _context: Dict[type, Provider]
+
     def configure(self) -> None:
-        self._context = {}  # type: Dict[type, Provider]
+        self._context = {}
 
     @synchronized(lock)
     def get(self, key: Type[T], provider: Provider[T]) -> Provider[T]:
@@ -865,6 +877,9 @@
         ``use_annotations`` parameter is removed
     """
 
+    _stack: Tuple[Tuple[object, Callable, Tuple[Tuple[str, type], ...]], ...]
+    binder: Binder
+
     def __init__(
         self,
         modules: Union[_InstallableModuleType, 
Iterable[_InstallableModuleType]] = None,
@@ -873,14 +888,12 @@
     ) -> None:
         # Stack of keys currently being injected. Used to detect circular
         # dependencies.
-        self._stack = ()  # type: Tuple[Tuple[object, Callable, 
Tuple[Tuple[str, type], ...]], ...]
+        self._stack = ()
 
         self.parent = parent
 
         # Binder
-        self.binder = Binder(
-            self, auto_bind=auto_bind, parent=parent.binder if parent is not 
None else None
-        )  # type: Binder
+        self.binder = Binder(self, auto_bind=auto_bind, parent=parent.binder 
if parent is not None else None)
 
         if not modules:
             modules = []
@@ -966,15 +979,13 @@
                 CallError(cls, getattr(cls.__new__, '__func__', cls.__new__), 
(), {}, e, self._stack),
                 maximum_frames=2,
             )
+        init = cls.__init__
         try:
-            # On Python 3.5.3 calling call_with_injection() with 
object.__init__ would fail further
-            # down the line as get_type_hints(object.__init__) raises an 
exception until Python 3.5.4.
-            # And since object.__init__ doesn't do anything useful and can't 
have any injectable
-            # arguments we can skip calling it altogether. See GH-135 for more 
information.
-            if cls.__init__ is not object.__init__:
-                self.call_with_injection(cls.__init__, self_=instance, 
kwargs=additional_kwargs)
+            self.call_with_injection(init, self_=instance, 
kwargs=additional_kwargs)
         except TypeError as e:
-            reraise(e, CallError(instance, instance.__init__.__func__, (), 
additional_kwargs, e, self._stack))
+            # Mypy says "Cannot access "__init__" directly"
+            init_function = instance.__init__.__func__  # type: ignore
+            reraise(e, CallError(instance, init_function, (), 
additional_kwargs, e, self._stack))
         return instance
 
     def call_with_injection(
@@ -1051,7 +1062,7 @@
         try:
             for arg, interface in bindings.items():
                 try:
-                    instance = self.get(interface)  # type: Any
+                    instance: Any = self.get(interface)
                 except UnsatisfiedRequirement as e:
                     if not e.owner:
                         e = UnsatisfiedRequirement(owner_key, e.interface)
@@ -1147,7 +1158,7 @@
         read_and_store_bindings(
             callable, _infer_injected_bindings(callable, 
only_explicit_bindings=look_for_explicit_bindings)
         )
-    noninjectables = getattr(callable, '__noninjectables__', set())
+    noninjectables: Set[str] = getattr(callable, '__noninjectables__', set())
     return {k: v for k, v in cast(Any, callable).__bindings__.items() if k not 
in noninjectables}
 
 
@@ -1188,14 +1199,9 @@
 
         if only_explicit_bindings and _inject_marker not in metadata or 
_noinject_marker in metadata:
             del bindings[k]
-            break
-
-        if _is_specialization(v, Union):
+        elif _is_specialization(v, Union):
             # We don't treat Optional parameters in any special way at the 
moment.
-            if TYPING353:
-                union_members = v.__args__
-            else:
-                union_members = v.__union_params__
+            union_members = v.__args__
             new_members = tuple(set(union_members) - {type(None)})
             # mypy stared complaining about this line for some reason:
             #     error: Variable "new_members" is not valid as a type
@@ -1397,7 +1403,7 @@
             if arg not in argspec.args and arg not in argspec.kwonlyargs:
                 raise UnknownArgument('Unable to mark unknown argument %s ' 
'as non-injectable.' % arg)
 
-        existing = getattr(function, '__noninjectables__', set())
+        existing: Set[str] = getattr(function, '__noninjectables__', set())
         merged = existing | set(args)
         cast(Any, function).__noninjectables__ = merged
         return function
@@ -1481,19 +1487,19 @@
 class ProviderOf(Generic[T]):
     """Can be used to get a provider of an interface, for example:
 
-        >>> def provide_int():
-        ...     print('providing')
-        ...     return 123
-        >>>
-        >>> def configure(binder):
-        ...     binder.bind(int, to=provide_int)
-        >>>
-        >>> injector = Injector(configure)
-        >>> provider = injector.get(ProviderOf[int])
-        >>> value = provider.get()
-        providing
-        >>> value
-        123
+    >>> def provide_int():
+    ...     print('providing')
+    ...     return 123
+    >>>
+    >>> def configure(binder):
+    ...     binder.bind(int, to=provide_int)
+    >>>
+    >>> injector = Injector(configure)
+    >>> provider = injector.get(ProviderOf[int])
+    >>> value = provider.get()
+    providing
+    >>> value
+    123
     """
 
     def __init__(self, injector: Injector, interface: Type[T]):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/injector_test.py 
new/injector-0.19.0/injector_test.py
--- old/injector-0.18.3/injector_test.py        2020-02-03 15:35:27.000000000 
+0100
+++ new/injector-0.19.0/injector_test.py        2021-12-20 23:18:57.000000000 
+0100
@@ -53,17 +53,15 @@
     from injector import Inject, NoInject
 
 
-def prepare_basic_injection():
-    class B:
-        pass
+class EmptyClass:
+    pass
 
-    class A:
-        @inject
-        def __init__(self, b: B):
-            """Construct a new A."""
-            self.b = b
 
-    return A, B
+class DependsOnEmptyClass:
+    @inject
+    def __init__(self, b: EmptyClass):
+        """Construct a new DependsOnEmptyClass."""
+        self.b = b
 
 
 def prepare_nested_injectors():
@@ -130,11 +128,9 @@
 
 
 def test_get_default_injected_instances():
-    A, B = prepare_basic_injection()
-
     def configure(binder):
-        binder.bind(A)
-        binder.bind(B)
+        binder.bind(DependsOnEmptyClass)
+        binder.bind(EmptyClass)
 
     injector = Injector(configure)
     assert injector.get(Injector) is injector
@@ -142,15 +138,13 @@
 
 
 def test_instantiate_injected_method():
-    A, _ = prepare_basic_injection()
-    a = A('Bob')
+    a = DependsOnEmptyClass('Bob')
     assert a.b == 'Bob'
 
 
 def test_method_decorator_is_wrapped():
-    A, _ = prepare_basic_injection()
-    assert A.__init__.__doc__ == 'Construct a new A.'
-    assert A.__init__.__name__ == '__init__'
+    assert DependsOnEmptyClass.__init__.__doc__ == 'Construct a new 
DependsOnEmptyClass.'
+    assert DependsOnEmptyClass.__init__.__name__ == '__init__'
 
 
 def test_decorator_works_for_function_with_no_args():
@@ -178,121 +172,104 @@
 
 
 def test_inject_direct():
-    A, B = prepare_basic_injection()
-
     def configure(binder):
-        binder.bind(A)
-        binder.bind(B)
+        binder.bind(DependsOnEmptyClass)
+        binder.bind(EmptyClass)
 
     injector = Injector(configure)
-    a = injector.get(A)
-    assert isinstance(a, A)
-    assert isinstance(a.b, B)
+    a = injector.get(DependsOnEmptyClass)
+    assert isinstance(a, DependsOnEmptyClass)
+    assert isinstance(a.b, EmptyClass)
 
 
 def test_configure_multiple_modules():
-    A, B = prepare_basic_injection()
-
     def configure_a(binder):
-        binder.bind(A)
+        binder.bind(DependsOnEmptyClass)
 
     def configure_b(binder):
-        binder.bind(B)
+        binder.bind(EmptyClass)
 
     injector = Injector([configure_a, configure_b])
-    a = injector.get(A)
-    assert isinstance(a, A)
-    assert isinstance(a.b, B)
+    a = injector.get(DependsOnEmptyClass)
+    assert isinstance(a, DependsOnEmptyClass)
+    assert isinstance(a.b, EmptyClass)
 
 
 def test_inject_with_missing_dependency():
-    A, _ = prepare_basic_injection()
-
     def configure(binder):
-        binder.bind(A)
+        binder.bind(DependsOnEmptyClass)
 
     injector = Injector(configure, auto_bind=False)
     with pytest.raises(UnsatisfiedRequirement):
-        injector.get(A)
+        injector.get(EmptyClass)
 
 
 def test_inject_named_interface():
-    class B:
-        pass
-
     class A:
         @inject
-        def __init__(self, b: B):
+        def __init__(self, b: EmptyClass):
             self.b = b
 
     def configure(binder):
         binder.bind(A)
-        binder.bind(B)
+        binder.bind(EmptyClass)
 
     injector = Injector(configure)
     a = injector.get(A)
     assert isinstance(a, A)
-    assert isinstance(a.b, B)
+    assert isinstance(a.b, EmptyClass)
 
 
-def prepare_transitive_injection():
-    class C:
-        pass
+class TransitiveC:
+    pass
 
-    class B:
-        @inject
-        def __init__(self, c: C):
-            self.c = c
 
-    class A:
-        @inject
-        def __init__(self, b: B):
-            self.b = b
+class TransitiveB:
+    @inject
+    def __init__(self, c: TransitiveC):
+        self.c = c
 
-    return A, B, C
 
+class TransitiveA:
+    @inject
+    def __init__(self, b: TransitiveB):
+        self.b = b
 
-def test_transitive_injection():
-    A, B, C = prepare_transitive_injection()
 
+def test_transitive_injection():
     def configure(binder):
-        binder.bind(A)
-        binder.bind(B)
-        binder.bind(C)
+        binder.bind(TransitiveA)
+        binder.bind(TransitiveB)
+        binder.bind(TransitiveC)
 
     injector = Injector(configure)
-    a = injector.get(A)
-    assert isinstance(a, A)
-    assert isinstance(a.b, B)
-    assert isinstance(a.b.c, C)
+    a = injector.get(TransitiveA)
+    assert isinstance(a, TransitiveA)
+    assert isinstance(a.b, TransitiveB)
+    assert isinstance(a.b.c, TransitiveC)
 
 
 def test_transitive_injection_with_missing_dependency():
-    A, B, _ = prepare_transitive_injection()
-
     def configure(binder):
-        binder.bind(A)
-        binder.bind(B)
+        binder.bind(TransitiveA)
+        binder.bind(TransitiveB)
 
     injector = Injector(configure, auto_bind=False)
     with pytest.raises(UnsatisfiedRequirement):
-        injector.get(A)
+        injector.get(TransitiveA)
     with pytest.raises(UnsatisfiedRequirement):
-        injector.get(B)
+        injector.get(TransitiveB)
 
 
 def test_inject_singleton():
-    class B:
-        pass
-
     class A:
         @inject
-        def __init__(self, b: B):
+        def __init__(self, b: EmptyClass):
             self.b = b
 
     def configure(binder):
         binder.bind(A)
-        binder.bind(B, scope=SingletonScope)
+        binder.bind(EmptyClass, scope=SingletonScope)
 
     injector1 = Injector(configure)
     a1 = injector1.get(A)
@@ -300,19 +277,20 @@
     assert a1.b is a2.b
 
 
-def test_inject_decorated_singleton_class():
-    @singleton
-    class B:
-        pass
+@singleton
+class SingletonB:
+    pass
+
 
+def test_inject_decorated_singleton_class():
     class A:
         @inject
-        def __init__(self, b: B):
+        def __init__(self, b: SingletonB):
             self.b = b
 
     def configure(binder):
         binder.bind(A)
-        binder.bind(B)
+        binder.bind(SingletonB)
 
     injector1 = Injector(configure)
     a1 = injector1.get(A)
@@ -348,97 +326,105 @@
     assert a2 is not a3[0] and a3[0] is not None
 
 
-def test_injecting_interface_implementation():
-    class Interface:
-        pass
+class Interface2:
+    pass
 
+
+def test_injecting_interface_implementation():
     class Implementation:
         pass
 
     class A:
         @inject
-        def __init__(self, i: Interface):
+        def __init__(self, i: Interface2):
             self.i = i
 
     def configure(binder):
         binder.bind(A)
-        binder.bind(Interface, to=Implementation)
+        binder.bind(Interface2, to=Implementation)
 
     injector = Injector(configure)
     a = injector.get(A)
     assert isinstance(a.i, Implementation)
 
 
-def test_cyclic_dependencies():
-    class Interface:
-        pass
+class CyclicInterface:
+    pass
 
-    class A:
-        @inject
-        def __init__(self, i: Interface):
-            self.i = i
 
-    class B:
-        @inject
-        def __init__(self, a: A):
-            self.a = a
+class CyclicA:
+    @inject
+    def __init__(self, i: CyclicInterface):
+        self.i = i
+
+
+class CyclicB:
+    @inject
+    def __init__(self, a: CyclicA):
+        self.a = a
 
+
+def test_cyclic_dependencies():
     def configure(binder):
-        binder.bind(Interface, to=B)
-        binder.bind(A)
+        binder.bind(CyclicInterface, to=CyclicB)
+        binder.bind(CyclicA)
 
     injector = Injector(configure)
     with pytest.raises(CircularDependency):
-        injector.get(A)
+        injector.get(CyclicA)
 
 
-def test_dependency_cycle_can_be_worked_broken_by_assisted_building():
-    class Interface:
-        pass
+class CyclicInterface2:
+    pass
 
-    class A:
-        @inject
-        def __init__(self, i: Interface):
-            self.i = i
 
-    class B:
-        @inject
-        def __init__(self, a_builder: AssistedBuilder[A]):
-            self.a = a_builder.build(i=self)
+class CyclicA2:
+    @inject
+    def __init__(self, i: CyclicInterface2):
+        self.i = i
 
+
+class CyclicB2:
+    @inject
+    def __init__(self, a_builder: AssistedBuilder[CyclicA2]):
+        self.a = a_builder.build(i=self)
+
+
+def test_dependency_cycle_can_be_worked_broken_by_assisted_building():
     def configure(binder):
-        binder.bind(Interface, to=B)
-        binder.bind(A)
+        binder.bind(CyclicInterface2, to=CyclicB2)
+        binder.bind(CyclicA2)
 
     injector = Injector(configure)
 
     # Previously it'd detect a circular dependency here:
-    # 1. Constructing A requires Interface (bound to B)
-    # 2. Constructing B requires assisted build of A
-    # 3. Constructing A triggers circular dependency check
-    assert isinstance(injector.get(A), A)
+    # 1. Constructing CyclicA2 requires CyclicInterface2 (bound to CyclicB2)
+    # 2. Constructing CyclicB2 requires assisted build of CyclicA2
+    # 3. Constructing CyclicA2 triggers circular dependency check
+    assert isinstance(injector.get(CyclicA2), CyclicA2)
 
 
-def test_that_injection_is_lazy():
-    class Interface:
-        constructed = False
+class Interface5:
+    constructed = False
+
+    def __init__(self):
+        Interface5.constructed = True
 
-        def __init__(self):
-            Interface.constructed = True
 
+def test_that_injection_is_lazy():
     class A:
         @inject
-        def __init__(self, i: Interface):
+        def __init__(self, i: Interface5):
             self.i = i
 
     def configure(binder):
-        binder.bind(Interface)
+        binder.bind(Interface5)
         binder.bind(A)
 
     injector = Injector(configure)
-    assert not (Interface.constructed)
+    assert not (Interface5.constructed)
     injector.get(A)
-    assert Interface.constructed
+    assert Interface5.constructed
 
 
 def test_module_provider():
@@ -482,10 +468,11 @@
     assert Injector(MyModule()).get(str) == 'Bob is 25 and weighs 50.0kg'
 
 
-def test_multibind():
-    Names = NewType('Names', List[str])
-    Passwords = NewType('Ages', Dict[str, str])
+Names = NewType('Names', List[str])
+Passwords = NewType('Ages', Dict[str, str])
 
+
+def test_multibind():
     # First let's have some explicit multibindings
     def configure(binder):
         binder.multibind(List[str], to=['not a name'])
@@ -597,45 +584,51 @@
     assert isinstance(injector.get(AliasOfA), A)
 
 
-def test_custom_scope():
-    class RequestScope(Scope):
-        def configure(self):
-            self.context = None
-
-        @contextmanager
-        def __call__(self, request):
-            assert self.context is None
-            self.context = {}
-            binder = self.injector.get(Binder)
-            binder.bind(Request, to=request, scope=RequestScope)
-            yield
-            self.context = None
-
-        def get(self, key, provider):
-            if self.context is None:
-                raise UnsatisfiedRequirement(None, key)
-            try:
-                return self.context[key]
-            except KeyError:
-                provider = InstanceProvider(provider.get(self.injector))
-                self.context[key] = provider
-                return provider
+class Request:
+    pass
 
-    request = ScopeDecorator(RequestScope)
 
-    class Request:
-        pass
+class RequestScope(Scope):
+    def configure(self):
+        self.context = None
 
-    @request
-    class Handler:
-        def __init__(self, request):
-            self.request = request
+    @contextmanager
+    def __call__(self, request):
+        assert self.context is None
+        self.context = {}
+        binder = self.injector.get(Binder)
+        binder.bind(Request, to=request, scope=RequestScope)
+        yield
+        self.context = None
 
-    class RequestModule(Module):
-        @provider
-        @inject
-        def handler(self, request: Request) -> Handler:
-            return Handler(request)
+    def get(self, key, provider):
+        if self.context is None:
+            raise UnsatisfiedRequirement(None, key)
+        try:
+            return self.context[key]
+        except KeyError:
+            provider = InstanceProvider(provider.get(self.injector))
+            self.context[key] = provider
+            return provider
+
+
+request = ScopeDecorator(RequestScope)
+
+
+@request
+class Handler:
+    def __init__(self, request):
+        self.request = request
+
+
+class RequestModule(Module):
+    @provider
+    @inject
+    def handler(self, request: Request) -> Handler:
+        return Handler(request)
+
+
+def test_custom_scope():
 
     injector = Injector([RequestModule()], auto_bind=False)
 
@@ -716,16 +709,18 @@
     assert isinstance(binder.provider_for(A, None).get(injector), A)
 
 
-def 
test_injecting_undecorated_class_with_missing_dependencies_raises_the_right_error():
-    class ClassA:
-        def __init__(self, parameter):
-            pass
+class ClassA:
+    def __init__(self, parameter):
+        pass
+
+
+class ClassB:
+    @inject
+    def __init__(self, a: ClassA):
+        pass
 
-    class ClassB:
-        @inject
-        def __init__(self, a: ClassA):
-            pass
 
+def 
test_injecting_undecorated_class_with_missing_dependencies_raises_the_right_error():
     injector = Injector()
     try:
         injector.get(ClassB)
@@ -773,10 +768,11 @@
     assert (x.obj.a, x.obj.b) == (str(), 234)
 
 
-def test_assisted_builder_uses_bindings():
-    class Interface:
-        b = 0
+class Interface:
+    b = 0
+
 
+def test_assisted_builder_uses_bindings():
     def configure(binder):
         binder.bind(Interface, to=NeedsAssistance)
 
@@ -884,10 +880,11 @@
     injector.get(X)
 
 
-def test_callable_provider_injection():
-    Name = NewType("Name", str)
-    Message = NewType("Message", str)
+Name = NewType("Name", str)
+Message = NewType("Message", str)
+
 
+def test_callable_provider_injection():
     @inject
     def create_message(name: Name):
         return "Hello, " + name
@@ -991,47 +988,48 @@
     assert injector.get(bytes) == text
 
 
-def test_class_assisted_builder_of_partially_injected_class_old():
-    class A:
-        pass
+class PartialB:
+    @inject
+    def __init__(self, a: EmptyClass, b: str):
+        self.a = a
+        self.b = b
 
-    class B:
-        @inject
-        def __init__(self, a: A, b: str):
-            self.a = a
-            self.b = b
 
+def test_class_assisted_builder_of_partially_injected_class_old():
     class C:
         @inject
-        def __init__(self, a: A, builder: ClassAssistedBuilder[B]):
+        def __init__(self, a: EmptyClass, builder: 
ClassAssistedBuilder[PartialB]):
             self.a = a
             self.b = builder.build(b='C')
 
     c = Injector().get(C)
     assert isinstance(c, C)
-    assert isinstance(c.b, B)
-    assert isinstance(c.b.a, A)
+    assert isinstance(c.b, PartialB)
+    assert isinstance(c.b.a, EmptyClass)
 
 
-def test_implicit_injection_for_python3():
-    class A:
-        pass
+class ImplicitA:
+    pass
 
-    class B:
-        @inject
-        def __init__(self, a: A):
-            self.a = a
 
-    class C:
-        @inject
-        def __init__(self, b: B):
-            self.b = b
+class ImplicitB:
+    @inject
+    def __init__(self, a: ImplicitA):
+        self.a = a
+
+
+class ImplicitC:
+    @inject
+    def __init__(self, b: ImplicitB):
+        self.b = b
 
+
+def test_implicit_injection_for_python3():
     injector = Injector()
-    c = injector.get(C)
-    assert isinstance(c, C)
-    assert isinstance(c.b, B)
-    assert isinstance(c.b.a, A)
+    c = injector.get(ImplicitC)
+    assert isinstance(c, ImplicitC)
+    assert isinstance(c.b, ImplicitB)
+    assert isinstance(c.b.a, ImplicitA)
 
 
 def test_annotation_based_injection_works_in_provider_methods():
@@ -1053,21 +1051,23 @@
     assert injector.get(object) is injector.get(object)
 
 
-def test_assisted_building_is_supported():
-    class Fetcher:
-        def fetch(self, user_id):
-            assert user_id == 333
-            return {'name': 'John'}
-
-    class Processor:
-        @noninjectable('provider_id')
-        @inject
-        @noninjectable('user_id')
-        def __init__(self, fetcher: Fetcher, user_id: int, provider_id: str):
-            assert provider_id == 'not injected'
-            data = fetcher.fetch(user_id)
-            self.name = data['name']
+class Fetcher:
+    def fetch(self, user_id):
+        assert user_id == 333
+        return {'name': 'John'}
+
 
+class Processor:
+    @noninjectable('provider_id')
+    @inject
+    @noninjectable('user_id')
+    def __init__(self, fetcher: Fetcher, user_id: int, provider_id: str):
+        assert provider_id == 'not injected'
+        data = fetcher.fetch(user_id)
+        self.name = data['name']
+
+
+def test_assisted_building_is_supported():
     def configure(binder):
         binder.bind(int, to=897)
         binder.bind(str, to='injected')
@@ -1294,26 +1294,24 @@
         del X
 
 
-def test_class_assisted_builder_of_partially_injected_class():
-    class A:
-        pass
+class AssistedB:
+    @inject
+    def __init__(self, a: EmptyClass, b: str):
+        self.a = a
+        self.b = b
 
-    class B:
-        @inject
-        def __init__(self, a: A, b: str):
-            self.a = a
-            self.b = b
 
+def test_class_assisted_builder_of_partially_injected_class():
     class C:
         @inject
-        def __init__(self, a: A, builder: ClassAssistedBuilder[B]):
+        def __init__(self, a: EmptyClass, builder: 
ClassAssistedBuilder[AssistedB]):
             self.a = a
             self.b = builder.build(b='C')
 
     c = Injector().get(C)
     assert isinstance(c, C)
-    assert isinstance(c.b, B)
-    assert isinstance(c.b.a, A)
+    assert isinstance(c.b, AssistedB)
+    assert isinstance(c.b.a, EmptyClass)
 
 
 # The test taken from Alec Thomas' pull request: 
https://github.com/alecthomas/injector/pull/73
@@ -1380,18 +1378,15 @@
 
 
 def test_using_an_assisted_builder_with_a_provider_raises_an_injector_error():
-    class A:
-        pass
-
     class MyModule(Module):
         @provider
-        def provide_a(self, builder: AssistedBuilder[A]) -> A:
+        def provide_a(self, builder: AssistedBuilder[EmptyClass]) -> 
EmptyClass:
             return builder.build()
 
     injector = Injector(MyModule)
 
     with pytest.raises(Error):
-        injector.get(A)
+        injector.get(EmptyClass)
 
 
 def test_newtype_integration_works():
@@ -1446,6 +1441,14 @@
 
     assert get_bindings(function3) == {'a': int}
 
+    # Let's verify that the inject/noninjectable ordering doesn't matter
+    @noninjectable('b')
+    @inject
+    def function3b(a: int, b: str) -> None:
+        pass
+
+    assert get_bindings(function3b) == {'a': int}
+
     if HAVE_ANNOTATED:
         # The simple case of no @inject but injection requested with 
Inject[...]
         def function4(a: Inject[int], b: str) -> None:
@@ -1472,3 +1475,12 @@
             pass
 
         assert get_bindings(function7) == {}
+
+        # There was a bug where in case of multiple NoInject-decorated 
parameters only the first one was
+        # actually made noninjectable and we tried to inject something we 
couldn't possibly provide
+        # into the second one.
+        @inject
+        def function8(a: NoInject[int], b: NoInject[int]) -> None:
+            pass
+
+        assert get_bindings(function8) == {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/requirements-dev.txt 
new/injector-0.19.0/requirements-dev.txt
--- old/injector-0.18.3/requirements-dev.txt    1970-01-01 01:00:00.000000000 
+0100
+++ new/injector-0.19.0/requirements-dev.txt    2021-12-20 23:18:57.000000000 
+0100
@@ -0,0 +1,6 @@
+pytest
+pytest-cov>=2.5.1
+dataclasses;python_version<"3.7"
+mypy;implementation_name=="cpython"
+black;implementation_name=="cpython"
+check-manifest
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/requirements.txt 
new/injector-0.19.0/requirements.txt
--- old/injector-0.18.3/requirements.txt        1970-01-01 01:00:00.000000000 
+0100
+++ new/injector-0.19.0/requirements.txt        2021-12-20 23:18:57.000000000 
+0100
@@ -0,0 +1 @@
+typing_extensions>=3.7.4;python_version<"3.9"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/injector-0.18.3/setup.py new/injector-0.19.0/setup.py
--- old/injector-0.18.3/setup.py        2020-02-03 15:35:27.000000000 +0100
+++ new/injector-0.19.0/setup.py        2021-12-20 23:18:57.000000000 +0100
@@ -6,6 +6,13 @@
 warnings.filterwarnings("always", module=__name__)
 
 
+def obtain_requirements(file_name):
+    with open(file_name) as fd_in:
+        for line in fd_in:
+            if '#' not in line:
+                yield line.strip()
+
+
 class PyTest(Command):
     user_options = []
 
@@ -34,6 +41,11 @@
 version = read_injector_variable('__version__')
 version_tag = read_injector_variable('__version_tag__')
 
+
+requirements = list(obtain_requirements('requirements.txt'))
+requirements_dev = list(obtain_requirements('requirements-dev.txt'))
+
+
 try:
     import pypandoc
 
@@ -48,8 +60,8 @@
 
 setup(
     name='injector',
-    url='http://github.com/alecthomas/injector',
-    download_url='http://pypi.python.org/pypi/injector',
+    url='https://github.com/alecthomas/injector',
+    download_url='https://pypi.org/project/injector/',
     version=version,
     options=dict(egg_info=dict(tag_build=version_tag)),
     description=description,
@@ -61,6 +73,7 @@
     author='Alec Thomas',
     author_email='a...@swapoff.org',
     cmdclass={'test': PyTest},
+    extras_require={'dev': requirements_dev},
     keywords=[
         'Dependency Injection',
         'DI',
@@ -69,5 +82,5 @@
         'IoC',
         'Inversion of Control container',
     ],
-    install_requires=['typing_extensions>=3.7.4'],
+    install_requires=requirements,
 )

Reply via email to