diff --git a/README.rst b/README.rst index 24c07ed..2ab73f0 100644 --- a/README.rst +++ b/README.rst @@ -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=True)`` ----------------------------------------------- +``Injector.__init__(self, *dicts, **values)`` +--------------------------------------------- A subclass could take arguments, but should pass keywords to super. @@ -173,6 +173,11 @@ The injector provides itself as the `'injector'` service:: with Injector() as injector: injector.get('injector') +Local values can be provided when constructing the injector:: + + with RequestInjector(request=request) as injector: + injector.get('form:username') + ``Injector.sub(cls, *mixins_and_dicts, **values)`` -------------------------------------------------- diff --git a/jeni.py b/jeni.py index 113a767..a0c5997 100644 --- a/jeni.py +++ b/jeni.py @@ -11,7 +11,6 @@ import functools import inspect import re -import warnings import sys import six @@ -366,7 +365,7 @@ class Injector(object): generator_provider = GeneratorProvider re_note = re.compile(r'^(.*?)(?::(.*))?$') # annotation is 'object:name' - def __init__(self, provide_self=True): + def __init__(self, *dicts, **values): """A subclass could take arguments, but should pass keywords to super. An Injector subclass inherits the provider registry of its base @@ -399,6 +398,12 @@ class Injector(BaseInjector): with Injector() as injector: injector.get('injector') + + Local values can be provided when constructing the injector:: + + with RequestInjector(request=request) as injector: + injector.get('form:username') + """ self.annotator = self.annotator_class() @@ -406,6 +411,10 @@ class Injector(BaseInjector): self.closed = False self.instances = {} self.values = {} + for d in dicts: + self.values.update(d) + self.values.update(values) + self.values['injector'] = self self.finalizers = [] @@ -417,12 +426,6 @@ 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. @@ -802,15 +805,8 @@ class SubInjector(cls): SubInjector.__bases__ = tuple(mixins) + SubInjector.__bases__ dicts = [ x for x in mixins_and_dicts if not isinstance(x, type) ] - for d in reversed(dicts): - for k,v in d.items(): - if k not in values: - values[k] = v - - for k,v in values.items(): - SubInjector.value(k, v) - return SubInjector() + return SubInjector(*dicts, **values) class InjectorProxy(object): diff --git a/test_jeni.py b/test_jeni.py index a75601b..e598911 100644 --- a/test_jeni.py +++ b/test_jeni.py @@ -153,25 +153,44 @@ class SubInjector(BasicInjector): class InjectSelfTestCase(unittest.TestCase): - def test_provide_self_default(self): + def test_injector_is_self(self): self.injector = jeni.Injector() self.assertEqual(self.injector, self.injector.get('injector')) - def test_provide_self_true(self): - self.injector = jeni.Injector(provide_self=True) - self.assertEqual(self.injector, self.injector.get('injector')) - - 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) + def test_injector_is_local(self): + injector1 = jeni.Injector() + injector2 = jeni.Injector() self.assertEqual(injector1, injector1.get('injector')) self.assertEqual(injector2, injector2.get('injector')) +class InjectorLocals(unittest.TestCase): + def test_ctor_kwargs(self): + injector = jeni.Injector(flavor='banana') + self.assertEqual('banana', injector.get('flavor')) + + def test_ctor_args(self): + injector = jeni.Injector(dict(flavor='banana')) + self.assertEqual('banana', injector.get('flavor')) + + def test_ctor_overrides(self): + class SubInjector(jeni.Injector): pass + SubInjector.value('flavor', 'banana') + injector = jeni.Injector(flavor='triangle') + self.assertEqual('triangle', injector.get('flavor')) + + def test_ctor_priority(self): + injector = jeni.Injector(dict(flavor='banana'), flavor='triangle') + self.assertEqual('triangle', injector.get('flavor')) + + def test_isolation(self): + injector1 = jeni.Injector(flavor='banana') + injector2 = jeni.Injector() + injector3 = injector1.sub() + self.assertRaises(LookupError, injector2.get, 'flavor') + self.assertRaises(LookupError, injector3.get, 'flavor') + + class SubInjectorTestCase(BasicInjectorTestCase): def setUp(self): self.injector = SubInjector()