-
Notifications
You must be signed in to change notification settings - Fork 86
Feature request: "Local" bindings without annotating non-binding-spec code #63
Description
Problem
The only way to bind the same name to two different objects depending on where they'll be used seems to be to annotate the "non-binding-spec" code to make the two parameters distinguishable.
But annotations of the non-binding-spec code go against pinject's unique selling point, which is that you can leave your regular code completely untouched. In fact, the very first point of the "Why pinject?" README section says:
[...] Forget having to decorate your code with @inject_this and @annotate_that just to get started. With Pinject, you call new_object_graph(), one line, and you're good to go.
Annotations to avoid name collisions brings back that exact kind of @annotate_that mess people who like pinject want to avoid.
So this is a feature request to come up with and implement an alternative to annotations to avoid name collisions and have certain bindings only apply "locally", e.g. only to one specific class.
Some ideas
Extra parameter to bind
The feature could take the form of e.g. an extra parameter to bind that allows you to choose a specific requesting class for which it is applied:
class SomeBindingSpec:
def configure(bind):
bind("common_name", to_class=SomeBoundClass, local_to=SomeRequestingClass)
class SomeOtherBindingSpec:
def configure(bind):
bind("common_name", to_class=SomeOtherBoundClass, local_to=SomeOtherRequestingClass)Decorated binding specs
Another, perhaps more flexible way to do this would be to instead implement locality on the level of binding specs, e.g.:
@pinject.local_binding_spec(requesters=[SomeRequestingClass])
class SomeBindingSpec:
def configure(bind):
bind("common_name", to_class=SomeBoundClass)
@pinject.local_binding_spec(requesters=[SomeOtherRequestingClass])
class SomeOtherBindingSpec:
def configure(bind):
bind("common_name", to_class=SomeOtherBoundClass)Composable binding specs and object graphs
Another idea that would allow one to more easily work around the issue would be if binding specs and object graphs were more "composable" than they are now, so you could e.g. create a common object graph without collisions and two separate object graphs each consisting of the common one plus the bindings that would otherwise collide, then use those to provide the conflicting requesting classes separately. pinject would however have to ensure that both object graphs return the exact same instances for the common parts, just like it does normally within the same object graph.
Thoughts?