Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Feature request: "Local" bindings without annotating non-binding-spec code #63

Open
sh-at-cs opened this issue Sep 21, 2022 · 0 comments

Comments

@sh-at-cs
Copy link

sh-at-cs commented Sep 21, 2022

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?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant