We're assigning to an attribute Mypy doesn't know about. The error it
raised:
injector/__init__.py:862: error: "FunctionType" has no attribute "__binding__" [attr-defined]
Found 1 error in 1 file (checked 1 source file)
This change introduces consistency to how instances for unbound
classes decorated with a `@singleton` are shared among parent/child
injectors, when auto-binding is enabled.
Classes decorated with `@singleton`, that have not been explicitly
bound, are now created by and bound to the parent injector closest
to the root where all dependencies are fulfilled.
The behavior was like this before, but only when the parent injector
had created the singleton instance (and its implicit binding) before
the child injector. This allows sharing singletons between child
injectors without creating them on the parent injector first.
One of the thread safety tests has been failing on various PyPy
versions[1]:
_____________ TestThreadSafety.test_singleton_scope_is_thread_safe _____________
Traceback (most recent call last):
File "/home/runner/work/injector/injector/injector_test.py", line 863, in test_singleton_scope_is_thread_safe
assert a is b
AssertionError: assert <injector_test.TestThreadSafety.setup.<locals>.XXX object at 0x0000000006b80d08> is <injector_test.TestThreadSafety.setup.<locals>.XXX object at 0x0000000006b810c0>
SingletonScope's get() was protected with a lock already but Injector.get()
wasn't and there are things in there that are totally likely to produce
invalid results if executed from multiple contexts concurrently.
Rather than try to nail down the exact issue that caused this, figure
out why it's been failing only on PyPy etc. I figured it's ok to go for
the big hammer here and protect the whole method with the lock. This way
we don't have to wonder about the details that can be *really* difficult
to figure out.
I don't think this is gonna make anything meaningfully slower –
ClassProvider and CallableProvider are already locked (indirecty,
through Injector.args_to_inject() being synchronized) and I expect
these to be involved in vast majority of the injection work.
[1] https://github.com/python-injector/injector/actions/runs/4156039132/jobs/7189544034
Explicit optional type hints
This is the default in recent `mypy` versions. It is fully backwards
compatible, but the previous typing did not work with explicit
optional type hints.
Declare classes as generic
To fix the following `mypy` error:
> A function returning TypeVar should receive at least one argument
> containing the same TypeVar [type-var]
Highlight that the code snippet will not work. Users most of the time will
skim read the docs trying to spot snippets on how to use the code.
Since this is the only snippet on the welcome page, we might want to
highlight that it's an example that won't work.
Only check the current binder for bindings when resolving
`AssistedBuilder` instances, since any injected argument to the built
class should use the active injector when creating the `AssistedBuilder`
and not one of its parents.
Fixes#186.
NoInject[T] = None has the runtime typehint NoInject[T] | None,
instead of the expected NoInject[T | None].
NoInject[str] = 'blarb' works as expected
Resolves#192
There are a few changes that need to happen together with this one,
namely we need to specify explicit 3.7+ PyPy3 versions and in order
to do that we have to upgrade the setup-python GH action.
Tests started failing like
________________________ test_newtype_integration_works ________________________
Traceback (most recent call last):
File "/home/runner/work/injector/injector/injector_test.py", line 1398, in test_newtype_integration_works
injector = Injector([configure])
File "/home/runner/work/injector/injector/injector/__init__.py", line 904, in __init__
self.binder.install(module)
File "/home/runner/work/injector/injector/injector/__init__.py", line 573, in install
instance(self)
File "/home/runner/work/injector/injector/injector_test.py", line 1396, in configure
binder.bind(UserID, to=123)
File "/home/runner/work/injector/injector/injector/__init__.py", line 474, in bind
self._bindings[interface] = self.create_binding(interface, to, scope)
File "/home/runner/work/injector/injector/injector/__init__.py", line 578, in create_binding
provider = self.provider_for(interface, to)
File "/home/runner/work/injector/injector/injector/__init__.py", line 640, in provider_for
raise UnknownProvider('couldn\'t determine provider for %r to %r' % (interface, to))
injector.UnknownProvider: couldn't determine provider for <function NewType.<locals>.new_type at 0x7f64edc69d90> to 123
when I merged d7f6f396eb.
Makes GreenWithEnvy work again.
Fixes errors like
Traceback (most recent call last):
File "/Users/user/projects/injector/injector_test.py", line 1398, in test_newtype_integration_works
injector = Injector([configure])
File "/Users/user/projects/injector/injector/__init__.py", line 904, in __init__
self.binder.install(module)
File "/Users/user/projects/injector/injector/__init__.py", line 573, in install
instance(self)
File "/Users/user/projects/injector/injector_test.py", line 1396, in configure
binder.bind(UserID, to=123)
File "/Users/user/projects/injector/injector/__init__.py", line 474, in bind
self._bindings[interface] = self.create_binding(interface, to, scope)
File "/Users/user/projects/injector/injector/__init__.py", line 578, in create_binding
provider = self.provider_for(interface, to)
File "/Users/user/projects/injector/injector/__init__.py", line 640, in provider_for
raise UnknownProvider('couldn\'t determine provider for %r to %r' % (interface, to))
injector.UnknownProvider: couldn't determine provider for injector_test.UserID to 123
Fixes GH-192
from __future__ annotations are the default on Python 3.10 so the tricks
we used to keep the test suite nice can no longer be applied.
CI addition to make sure it stays compatible.
Free Travis CI is shutting down and since I already have Codecov set up
in other projects instead of Coveralls I'm switching that too for
consistency.
There's no nightly so I left it out for now.