-
Notifications
You must be signed in to change notification settings - Fork 87
different calls to provide() in a singleton scope do not return a singleton #43
Comments
You're instantiating a new >>> graph.provide(A) is graph.provide(A)
False But >>> graph.provide(B) is graph.provide(B)
False
>>> graph.provide(B).a is graph.provide(B).a
True |
As @MrGreenTea said, this is not a bug. However, I'm seeing the same behavior when I: |
This test fails.
|
After further review of the documentation, I think it's working as designed. However, I think the design should change. It is reasonable to expect that if a class is injectable with scope singleton and you ask object_graph to provide an instance of that class multiple times, then you'd always receive the same instance. |
You're not binding |
The provide method expects a type not a string.
The test above yields:
|
use this trick: @loweryjk def test_1():
class TestDependency:
pass
class TestDependencyLocator:
def __init__(self, test_dependency) -> None:
self.item = test_dependency
class TestSpec(pinject.BindingSpec):
def configure(self, bind):
G.a += 1
bind("test_dependency", to_class=TestDependency)
object_graph = pinject.new_object_graph(modules=None, binding_specs=[TestSpec()])
request_one = object_graph.provide(TestDependencyLocator)
request_two = object_graph.provide(TestDependencyLocator)
assert request_two.item is request_one.item |
@loweryjk def resolve_by_name(graph, name: str):
class PowerfulLocator:
def __init__(self, a) -> None:
self.item = a
ctx = {"r": []}
code = """
def fn0(self, {name}):
self.item = {name}
r.append(fn0)
"""
code = code.replace("{name}", name)
exec(code, {}, ctx)
old_ctor = PowerfulLocator.__init__
PowerfulLocator.__init__ = ctx["r"][0]
# to make pinject happy
PowerfulLocator.__init__.__module__ = old_ctor.__module__
locator = graph.provide(PowerfulLocator)
return locator.item
def test_2():
class TestDependency:
pass
class TestSpec(pinject.BindingSpec):
def configure(self, bind):
bind("test_dependency", to_class=TestDependency)
object_graph = pinject.new_object_graph(modules=None, binding_specs=[TestSpec()])
# tests
o1 = resolve_by_name(object_graph, "test_dependency")
o2 = resolve_by_name(object_graph, "test_dependency")
assert o1 is o2
assert isinstance(o1, TestDependency) |
Instead of using def __init__(self, **kwargs):
self.underlying_dependency = kwargs[<dep_name>]
# The signature that pinject sees:
def __init__(self, <dep_name>): Create a dict that maps each bound class to its corresponding wrapper class. Then create a custom provide function that receives a depended class, gets the respective wrapper class from the dict, calls provide on it, then This way, you create wrapper classes once, upfront. The lib |
This test should not fail, i.e.,
a
andb.a
should be the same instance in a singleton scope:The last assertion fails:
The text was updated successfully, but these errors were encountered: