-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Register a processor which has injections #50
Comments
thanks @davidbrochart perhaps you could modify this test a bit to make it fail according to your expectations? def test_processors_with_injections() -> None:
"""Test that we can use processors with injections."""
class ThingToProcess:
...
class InjectedDep:
...
dep = InjectedDep()
t2p = ThingToProcess()
mock = Mock()
# this function processes a ThingToProcess, but also requires
# an InjectedDep to be injected before it will work
@ino.register_processor
@ino.inject
def processor_that_has_injections(p0: ThingToProcess, p1: InjectedDep) -> None:
mock(p0, p1)
# "inject processors" of this function...
# meaning: when `return_a_thing ` is called, the t2p return value should be processed
# (as a side effect of calling the function)
@ino.inject_processors
def return_a_thing() -> ThingToProcess:
return t2p
# at the moment, our `processor_that_has_injections` function still doesn't have a
# p1 InjectedDep, so `return_a_thing`'s return value won't be processed successfully
with pytest.warns(UserWarning, match="Processor .* failed to process result"):
return_a_thing()
# but if we register a something that provides an InjectedDep...
@ino.register_provider
def provide_other_thing() -> InjectedDep:
return dep
# then the processor should work as expected ...
return_a_thing()
mock.assert_called_once_with(t2p, dep) |
Sorry, I could probably simplify the example again, but here is a test that fails (the two commented blocks work fine): import in_n_out as ino
def test_processors_with_injections() -> None:
class Dummy:
pass
class Thing:
def __init__(self):
self.list = []
def dummy_provider() -> Dummy:
return Dummy()
@ino.inject
@ino.inject_processors
def thing_provider(dummy: Dummy) -> Thing:
return Thing()
ino.register_provider(dummy_provider)
ino.register_provider(thing_provider)
# def add_item(thing: Thing):
# thing.list.append("item")
@ino.inject
def add_item(dummy: Dummy, thing: Thing):
thing.list.append("item")
# def add_item(thing: Thing):
# @ino.inject
# def inner(dummy: Dummy):
# thing.list.append("item")
# inner()
ino.register_processor(add_item)
ino.register_processor(add_item)
ino.register_processor(add_item)
@ino.inject
def func(thing: Thing):
return thing.list
assert func() == ["item"] * 3 I think it's the normal behavior, because with: @ino.inject
def add_item(dummy: Dummy, thing: Thing):
... One cannot say that |
ahhh, I see! sorry, I missed that. So, to restate the problem slightly, you want to specify that ino.register_processor(add_item, type_hint=Thing) (... this is documented, but it's a bit hard to find at the moment when you use the global in-n-out/src/in_n_out/_store.py Lines 329 to 330 in 204ed24
however! ... doing that in your then reveals a RecursionError in your test. So let me look into that a bit more |
OK, looks like I just didn't prepare for processor functions that process anything other than their first argument: in-n-out/src/in_n_out/_store.py Lines 568 to 572 in 204ed24
I think I could fix this by additionally storing the name of the function parameter that the processor processes ('thing' in your case), and then calling the processor with |
in summary, this boiled down to 2 things:
|
Description
Consider the following code which registers providers and processors:
Now if I want to inject a
Dummy
object inadd_item
:It doesn't work anymore, as
dummy
andthing
can be injected and the signature doesn't match with aThing
. This works:But I was wondering if there could be a better solution?
The text was updated successfully, but these errors were encountered: