Skip to content

Commit

Permalink
Fix a false positive issue with dependency cycle detection
Browse files Browse the repository at this point in the history
See the test code for details.
  • Loading branch information
Jakub Stasiak committed Sep 30, 2016
1 parent 435ddaa commit 56d0fc1
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 3 deletions.
6 changes: 6 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Injector Change Log
===================

0.10.1
------

- Fixed a false positive bug in dependency cycle detection (AssistedBuilder can be
used to break dependency cycles now)

0.10.0
------

Expand Down
8 changes: 5 additions & 3 deletions injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def emit(self, record):
pass

__author__ = 'Alec Thomas <alec@swapoff.org>'
__version__ = '0.10.0'
__version__ = '0.10.1'
__version_tag__ = ''

log = logging.getLogger('injector')
Expand Down Expand Up @@ -862,10 +862,12 @@ def args_to_inject(self, function, bindings, owner_key):
:returns: Dictionary of resolved arguments.
"""
dependencies = {}
key = (owner_key, function)

key = (owner_key, function, tuple(sorted(bindings.items())))

def repr_key(k):
return '%s.%s()' % tuple(map(_describe, k))
owner_key, function, bindings = k
return '%s.%s(injecting %s)' % (tuple(map(_describe, k[:2])) + (dict(k[2]),))

log.debug('%sProviding %r for %r', self._log_prefix, bindings, function)

Expand Down
27 changes: 27 additions & 0 deletions injector_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,33 @@ def configure(binder):
injector.get(A)


def test_dependency_cycle_can_be_worked_broken_by_assisted_building():
class Interface(object):
pass

class A(object):
@inject(i=Interface)
def __init__(self, i):
self.i = i

class B(object):
@inject(a_builder=AssistedBuilder(A))
def __init__(self, a_builder):
self.a = a_builder.build(i=self)

def configure(binder):
binder.bind(Interface, to=B)
binder.bind(A)

injector = Injector(configure)

# Previously it'd detect a circular dependency here:
# 1. Constructing A requires Interface (bound to B)
# 2. Constructing B requires assisted build of A
# 3. Constructing A triggers circular dependency check
assert isinstance(injector.get(A), A)


def test_avoid_circular_dependency_with_method_injection():
class Interface(object):
pass
Expand Down

0 comments on commit 56d0fc1

Please sign in to comment.