Add missing documentation and tune code a bit

This commit is contained in:
Jakub Stasiak 2013-02-19 10:16:56 +00:00
parent 3de2f605fc
commit ea74f93be5
2 changed files with 52 additions and 6 deletions

View File

@ -312,6 +312,46 @@ More information on this topic:
* `"How to use Google Guice to create objects that require parameters?" on Stack Overflow <http://stackoverflow.com/questions/996300/how-to-use-google-guice-to-create-objects-that-require-parameters>`_
* `Google Guice assisted injection <http://code.google.com/p/google-guice/wiki/AssistedInject>`_
Child injectors
---------------
Concept similar to Guice's child injectors is supported by ``Injector``. This way you can
have one injector that inherits bindings from other injector (parent) but these bindings
can be overriden in it and it doesn't affect parent injector bindings::
>>> def configure_parent(binder):
... binder.bind(str, to='asd')
... binder.bind(int, to=42)
...
>>> def configure_child(binder):
... binder.bind(str, to='qwe')
...
>>> parent = Injector(configure_parent)
>>> child = parent.create_child_injector(configure_child)
>>> parent.get(str), parent.get(int)
('asd', 42)
>>> child.get(str), child.get(int)
('qwe', 42)
**Note**: Default scopes are bound only to root injector. Binding them manually to child
injectors will result in unexpected behaviour.
**Note 2**: Once a binding key is present in parent injector scope (like ``singleton``
scope), provider saved there takes predecence when binding is overridden in child injector in
the same scope. This behaviour is subject to change::
>>> def configure_parent(binder):
... binder.bind(str, to='asd', scope=singleton)
...
>>> def configure_child(binder):
... binder.bind(str, to='qwe', scope=singleton)
...
>>> parent = Injector(configure_parent)
>>> child = parent.create_child_injector(configure_child)
>>> child.get(str) # this behaves as expected
'qwe'
>>> parent.get(str) # wat
'qwe'
Scopes
======

View File

@ -196,11 +196,13 @@ class Binder(object):
"""Create a new Binder.
:param injector: Injector we are binding for.
:param auto_bind: Whether to automatically bind missing types.
:param parent: Parent binder.
"""
self.injector = injector
self._auto_bind = auto_bind
self._bindings = {}
self.parent = parent or _EmptyBinder()
self.parent = parent
def bind(self, interface, to=None, annotation=None, scope=None):
"""Bind an interface to an implementation.
@ -284,7 +286,14 @@ class Binder(object):
(interface, to))
def _get_binding(self, key):
return self._bindings.get(key) or self.parent._get_binding(key)
binding = self._bindings.get(key)
if not binding and self.parent:
binding = self.parent._get_binding(key)
if not binding:
raise KeyError
return binding
def get_binding(self, cls, key):
try:
@ -297,10 +306,6 @@ class Binder(object):
return binding
raise UnsatisfiedRequirement(cls, key)
class _EmptyBinder(object):
def _get_binding(self, key):
raise KeyError
class Scope(object):
"""A Scope looks up the Provider for a binding.
@ -439,6 +444,7 @@ class Injector(object):
Signature is ``configure(binder)``.
:param auto_bind: Whether to automatically bind missing types.
:param parent: Parent injector.
"""
# Stack of keys currently being injected. Used to detect circular
# dependencies.