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

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

@sh-at-cs

Description

@sh-at-cs

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions