Skip to content
This repository has been archived by the owner on Feb 21, 2020. It is now read-only.

Commit

Permalink
Merge #14.
Browse files Browse the repository at this point in the history
  • Loading branch information
groner committed Jan 22, 2016
2 parents 06a769c + 837d951 commit feca12c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 20 deletions.
24 changes: 15 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,8 @@ method, annotate ``__init__`` and access the value via `self`.
Collects dependencies and reads annotations to inject them.


``Injector.__init__(self, provide_self=False)``
-----------------------------------------------
``Injector.__init__(self, provide_self=True)``
----------------------------------------------

A subclass could take arguments, but should pass keywords to super.

Expand All @@ -155,17 +155,23 @@ or providing alternative dependencies in a different runtime::
class Injector(BaseInjector):
"Subclass provides namespace when registering providers."

By default, the injector does not provide itself, but will when asked::
Injector instances may be used as a context manager::

injector = Injector(provide_self=True)
injector.get('injector')
with Injector() as injector:
injector.apply(annotated_fn)

This is useful in a context manager::
The injector lifecycle can also be managed asynchronously using the
`enter()` and `exit()` methods::

with Injector(provide_self=True) as injector:
injector.get('injector')
injector = Injector().enter()
injector.apply(annotated_fn)
...
injector.exit()

Annotate with note 'injector' to inject the injector.
The injector provides itself as the `'injector'` service::

with Injector() as injector:
injector.get('injector')


``Injector.sub(cls, *mixins_and_dicts, **values)``
Expand Down
31 changes: 21 additions & 10 deletions jeni.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import functools
import inspect
import re
import warnings
import sys

import six
Expand Down Expand Up @@ -365,7 +366,7 @@ class Injector(object):
generator_provider = GeneratorProvider
re_note = re.compile(r'^(.*?)(?::(.*))?$') # annotation is 'object:name'

def __init__(self, provide_self=False):
def __init__(self, provide_self=True):
"""A subclass could take arguments, but should pass keywords to super.
An Injector subclass inherits the provider registry of its base
Expand All @@ -381,20 +382,24 @@ def __init__(self, provide_self=False):
class Injector(BaseInjector):
"Subclass provides namespace when registering providers."
By default, the injector does not provide itself, but will when asked::
Injector instances may be used as a context manager::
injector = Injector(provide_self=True)
injector.get('injector')
with Injector() as injector:
injector.apply(annotated_fn)
This is useful in a context manager::
The injector lifecycle can also be managed asynchronously using the
`enter()` and `exit()` methods::
with Injector(provide_self=True) as injector:
injector.get('injector')
injector = Injector().enter()
injector.apply(annotated_fn)
...
injector.exit()
The injector provides itself as the `'injector'` service::
Annotate with note 'injector' to inject the injector.
with Injector() as injector:
injector.get('injector')
"""
if provide_self:
self.value('injector', self)

self.annotator = self.annotator_class()

Expand All @@ -412,6 +417,12 @@ class Injector(BaseInjector):
#: This allows for dependency cycle checks.
self.instantiating = []

if provide_self:
self.values['injector'] = self
else:
warnings.warn(
DeprecationWarning('provide_self=False is not supported'))

@classmethod
def provider(cls, note, provider=None, name=False):
"""Register a provider, either a Provider class or a generator.
Expand Down
12 changes: 11 additions & 1 deletion test_jeni.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class SubInjector(BasicInjector):
class InjectSelfTestCase(unittest.TestCase):
def test_provide_self_default(self):
self.injector = jeni.Injector()
self.assertRaises(LookupError, self.injector.get, 'injector')
self.assertEqual(self.injector, self.injector.get('injector'))

def test_provide_self_true(self):
self.injector = jeni.Injector(provide_self=True)
Expand All @@ -165,6 +165,12 @@ def test_provide_self_false(self):
self.injector = jeni.Injector(provide_self=False)
self.assertRaises(LookupError, self.injector.get, 'injector')

def test_provide_self_is_self(self):
injector1 = jeni.Injector(provide_self=True)
injector2 = jeni.Injector(provide_self=True)
self.assertEqual(injector1, injector1.get('injector'))
self.assertEqual(injector2, injector2.get('injector'))


class SubInjectorTestCase(BasicInjectorTestCase):
def setUp(self):
Expand Down Expand Up @@ -221,6 +227,10 @@ def test_subinjector_mixins(self):
self.assertIsInstance(subinjector, WithOrderedSpace)
self.assertIsInstance(subinjector.get('space'), odict)

def test_subinjector_provides_injector(self):
subinjector = self.injector.sub()
self.assertEqual(subinjector, subinjector.get('injector'))


class BasicInjectorAnnotationTestCase(unittest.TestCase):
def setUp(self):
Expand Down

0 comments on commit feca12c

Please sign in to comment.