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

Commit

Permalink
Addes default __eq__() to BindingSpec, so that DAG binding spec depen…
Browse files Browse the repository at this point in the history
…dencies can have equal but not identical dependencies.
  • Loading branch information
KurtSteinkraus committed Aug 2, 2013
1 parent d7fdc0a commit 93797da
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 3 deletions.
25 changes: 25 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,30 @@ binding spec A can be a dependency of B and of C, and binding spec D can have
dependencies on B and C. Even though there are multiple dependency paths from
D to A, the bindings in binding spec A will only be evaluated once.

The binding spec instance of A that is a dependency of B is considered the
same as the instance that is a dependency of C if the two instances are equal
(via ``__eq__()``). The default implementation of ``__eq__()`` in
``BindingSpec`` says that two binding specs are equal if they are of exactly
the same python type. You will need to override ``__eq__()`` (as well as
``__hash__()``) if your binding spec is parameterized, i.e., if it takes one
or more initializer args so that two instances of the binding spec may behave
differently.

.. code-block:: python
>>> class SomeBindingSpec(pinject.BindingSpec):
... def __init__(self, the_instance):
... self._the_instance = the_instance
... def configure(self, bind):
... bind('foo', to_instance=self._the_instance)
... def __eq__(self, other):
... return (type(self) == type(other) and
... self._the_instance == other._the_instance)
... def __hash__(self):
... return hash(type(self)) ^ hash(self._the_instance)
...
>>>
Provider methods
----------------

Expand Down Expand Up @@ -1218,6 +1242,7 @@ Changelog

v0.10:

* Added default ``__eq__()`` to ``BindingSpec``, so that DAG binding spec dependencies can have equal but not identical dependencies.
* Allowed customizing ``configure()`` and ``dependencies()`` binding spec method names.
* Deprecated ``@injectable`` in favor of ``@inject``.
* Added partial injection.
Expand Down
6 changes: 6 additions & 0 deletions pinject/bindings.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,12 @@ def configure(self, bind):
def dependencies(self):
return []

def __eq__(self, other):
return type(self) == type(other)

def __hash__(self):
return hash(type(self))


def get_provider_fn_bindings(provider_fn, default_arg_names):
provider_decorations = decorators.get_provider_fn_decorations(
Expand Down
27 changes: 27 additions & 0 deletions pinject/bindings_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,33 @@ def test_binding_to_non_class_raises_error(self):
to_class='not-a-class')


class BindingSpecTest(unittest.TestCase):

def test_equal_if_same_type(self):
class SomeBindingSpec(bindings_lib.BindingSpec):
pass
self.assertEqual(SomeBindingSpec(), SomeBindingSpec())

def test_not_equal_if_not_same_type(self):
class BindingSpecOne(bindings_lib.BindingSpec):
pass
class BindingSpecTwo(bindings_lib.BindingSpec):
pass
self.assertNotEqual(BindingSpecOne(), BindingSpecTwo())

def test_hash_equal_if_same_type(self):
class SomeBindingSpec(bindings_lib.BindingSpec):
pass
self.assertEqual(hash(SomeBindingSpec()), hash(SomeBindingSpec()))

def test_hash_not_equal_if_not_same_type(self):
class BindingSpecOne(bindings_lib.BindingSpec):
pass
class BindingSpecTwo(bindings_lib.BindingSpec):
pass
self.assertNotEqual(hash(BindingSpecOne()), hash(BindingSpecTwo()))


class GetProviderFnBindingsTest(unittest.TestCase):

def test_proviser_calls_provider_fn(self):
Expand Down
5 changes: 2 additions & 3 deletions pinject/object_graph_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,12 @@ def test_allows_dag_binding_spec_dependencies(self):
class CommonBindingSpec(bindings.BindingSpec):
def configure(self, bind):
bind('foo', to_instance='a-foo')
a_common_binding_spec = CommonBindingSpec()
class BindingSpecOne(bindings.BindingSpec):
def dependencies(self):
return [a_common_binding_spec]
return [CommonBindingSpec()]
class BindingSpecTwo(bindings.BindingSpec):
def dependencies(self):
return [a_common_binding_spec]
return [CommonBindingSpec()]
class RootBindingSpec(bindings.BindingSpec):
def dependencies(self):
return [BindingSpecOne(), BindingSpecTwo()]
Expand Down

0 comments on commit 93797da

Please sign in to comment.