From 31fc9917f464d0a2251e108d6c8321c8ac7d7978 Mon Sep 17 00:00:00 2001 From: Martin Sivak Date: Thu, 6 Dec 2012 14:31:00 +0100 Subject: Support accessing (class)attributes of the object decorated by @inject --- di/core.py | 32 ++++++++++++++++++++++---------- di/core_test.py | 27 +++++++++++++++++++++++++++ python-di.spec | 5 ++++- setup.py | 2 +- 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/di/core.py b/di/core.py index f41d601..0156262 100644 --- a/di/core.py +++ b/di/core.py @@ -55,11 +55,14 @@ class DiRegistry(object): It records the injected objects, handles the execution and cleanup tasks associated with the DI mechanisms. """ + def __init__(self, obj): - self._obj = obj - self._used_objects = {} - self._obj._di_ = self._used_objects + object.__setattr__(self, "_DiRegistry__obj", obj) + object.__setattr__(self, "_DiRegistry__used_objects", {}) + for name in ["__name__", "__module__", "__doc__"]: + object.__setattr__(self, name, getattr(obj, name, getattr(self, name))) + self.__obj._di_ = self.__used_objects def __get__(self, obj, objtype): """Support instance methods.""" @@ -68,23 +71,32 @@ class DiRegistry(object): def register(self, *args, **kwargs): """Add registered injections to the instance of DiRegistry """ - self._used_objects.update(kwargs) + self.__used_objects.update(kwargs) for used_object in args: if hasattr(used_object, "__name__"): - self._used_objects[used_object.__name__] = used_object + self.__used_objects[used_object.__name__] = used_object elif isinstance(used_object, basestring): pass # it is already global, so this is just an annotation else: raise ValueError("%s is not a string or object with __name__" % used_object) def __call__(self, *args, **kwargs): - if not issubclass(type(self._obj), FunctionType): + if not issubclass(type(self.__obj), FunctionType): # call constructor or callable class # (which use @usesclassinject if needed) - return self._obj(*args, **kwargs) + return self.__obj(*args, **kwargs) + else: + return di_call(self.__used_objects, self.__obj, + *args, **kwargs) + + def __getattr__(self, name): + return getattr(self.__obj, name) + + def __setattr__(self, name, value): + if name in self.__dict__: + object.__setattr__(self, name, value) else: - return di_call(self._used_objects, self._obj, - *args, **kwargs) + setattr(self.__obj, name, value) def func_globals(func): """Helper method that allows access to globals @@ -133,7 +145,7 @@ def inject(*args, **kwargs): return obj if not isinstance(obj, DiRegistry): - obj = wraps(obj)(DiRegistry(obj)) + obj = DiRegistry(obj) obj.register(*args, **kwargs) return obj diff --git a/di/core_test.py b/di/core_test.py index 17d88fa..7cbc6bd 100644 --- a/di/core_test.py +++ b/di/core_test.py @@ -1,6 +1,29 @@ +# Tests for the dependency injection core +# +# Copyright (C) 2012 Red Hat, Inc. +# +# This copyrighted material is made available to anyone wishing to use, +# modify, copy, or redistribute it subject to the terms and conditions of +# the GNU General Public License v.2, or (at your option) any later version. +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY expressed or implied, including the implied warranties of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General +# Public License for more details. You should have received a copy of the +# GNU General Public License along with this program; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the +# source code or documentation are not subject to the GNU General Public +# License and may only be used or replicated with the express permission of +# Red Hat, Inc. +# +# Red Hat Author(s): Martin Sivak +# + from .core import * import unittest +def method_to_inject(): + pass class BareFuncEnableTestCase(unittest.TestCase): @inject(injected_func = str.lower) @@ -70,6 +93,10 @@ class ClassDITestCase(unittest.TestCase): obj = Test() self.assertEqual("a", obj.method("A")) + def test_named_register(self): + """Test injection to instance method.""" + Test.register(method_to_inject) + def test_class_init_inject(self): """Test injection to class constructor.""" obj = TestInit("A") diff --git a/python-di.spec b/python-di.spec index 1d91d9c..7b05af8 100644 --- a/python-di.spec +++ b/python-di.spec @@ -4,7 +4,7 @@ %endif Name: python-di -Version: 0.1 +Version: 0.2 Release: 1%{?dist} Summary: Python library for dependency injection support @@ -58,6 +58,9 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Thu Dec 6 2012 Martin Sivak - 0.2-1 +- DiRegistry support for accessing attributes of the decorated object + * Fri Nov 23 2012 Martin Sivak - 0.1-1 - Inital release diff --git a/setup.py b/setup.py index 4008561..e946513 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ def read(fname): setup( name = "di", - version = "0.1", + version = "0.2", author = "Martin Sivak", author_email = "msivak@redhat.com", description = ("Python module which provides decorators to make " -- cgit