From ae6fad090a0c40995cbc545afdebab191efca704 Mon Sep 17 00:00:00 2001 From: Kai Groner Date: Fri, 22 Jan 2016 09:34:41 -0500 Subject: [PATCH 1/3] Remove provide_self. --- README.rst | 4 ++-- jeni.py | 9 ++------- test_jeni.py | 16 ++++------------ 3 files changed, 8 insertions(+), 21 deletions(-) diff --git a/README.rst b/README.rst index 24c07ed..7710685 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)`` +--------------------------- A subclass could take arguments, but should pass keywords to super. diff --git a/jeni.py b/jeni.py index 113a767..e9d7213 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): """A subclass could take arguments, but should pass keywords to super. An Injector subclass inherits the provider registry of its base @@ -417,11 +416,7 @@ 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')) + self.values['injector'] = self @classmethod def provider(cls, note, provider=None, name=False): diff --git a/test_jeni.py b/test_jeni.py index a75601b..84ce39b 100644 --- a/test_jeni.py +++ b/test_jeni.py @@ -153,21 +153,13 @@ 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')) From c3877c374bcc436bcbe60e6aaf27dca5767379ab Mon Sep 17 00:00:00 2001 From: Kai Groner Date: Fri, 22 Jan 2016 10:17:50 -0500 Subject: [PATCH 2/3] Allow local values when constructing the injector. Injector.sub() has used this form for a while, but it is useful when a sub injector is not needed. --- README.rst | 9 +++++++-- jeni.py | 14 +++++++++++--- test_jeni.py | 27 +++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 7710685..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)`` ---------------------------- +``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 e9d7213..5ee0439 100644 --- a/jeni.py +++ b/jeni.py @@ -365,7 +365,7 @@ class Injector(object): generator_provider = GeneratorProvider re_note = re.compile(r'^(.*?)(?::(.*))?$') # annotation is 'object:name' - def __init__(self): + 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 @@ -398,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() @@ -405,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 = [] @@ -416,8 +426,6 @@ class Injector(BaseInjector): #: This allows for dependency cycle checks. self.instantiating = [] - self.values['injector'] = self - @classmethod def provider(cls, note, provider=None, name=False): """Register a provider, either a Provider class or a generator. diff --git a/test_jeni.py b/test_jeni.py index 84ce39b..e598911 100644 --- a/test_jeni.py +++ b/test_jeni.py @@ -164,6 +164,33 @@ def test_injector_is_local(self): 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() From e83d53badc57e4699186a36ae1d806936cd45f7e Mon Sep 17 00:00:00 2001 From: Kai Groner Date: Fri, 22 Jan 2016 10:27:40 -0500 Subject: [PATCH 3/3] Simplify Injector.sub(). --- jeni.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/jeni.py b/jeni.py index 5ee0439..a0c5997 100644 --- a/jeni.py +++ b/jeni.py @@ -805,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):