Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r66252:51c5cb0ddc92 Date: 2013-08-20 13:48 +0200 http://bitbucket.org/pypy/pypy/changeset/51c5cb0ddc92/
Log: A first version of import_from_mixin(), which really copies the content of the source class into the target, completely before translation. diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py --- a/rpython/annotator/test/test_annrpython.py +++ b/rpython/annotator/test/test_annrpython.py @@ -2539,6 +2539,27 @@ s = a.build_types(f, []) assert s.const == 2 + def test_import_from_mixin(self): + class M(object): + def f(self): + return self.a + class I(object): + objectmodel.import_from_mixin(M) + def __init__(self, i): + self.a = i + class S(object): + objectmodel.import_from_mixin(M) + def __init__(self, s): + self.a = s + def f(n): + return (I(n).f(), S("a" * n).f()) + + assert f(3) == (3, "aaa") + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert isinstance(s.items[0], annmodel.SomeInteger) + assert isinstance(s.items[1], annmodel.SomeString) + def test___class___attribute(self): class Base(object): pass class A(Base): pass diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -9,7 +9,7 @@ import types import math import inspect -from rpython.tool.sourcetools import rpython_wrapper +from rpython.tool.sourcetools import rpython_wrapper, func_with_new_name # specialize is a decorator factory for attaching _annspecialcase_ # attributes to functions: for example @@ -720,3 +720,32 @@ self.dic = dic self.key = key self.hash = hash + +# ____________________________________________________________ + +def import_from_mixin(M): + flatten = {} + for base in inspect.getmro(M): + for key, value in base.__dict__.items(): + if key in ('__module__', '__name__', '__dict__', + '__doc__', '__weakref__'): + continue + if key in flatten: + continue + if isinstance(value, types.FunctionType): + value = func_with_new_name(value, value.__name__) + elif isinstance(value, staticmethod): + func = value.__get__(42) + func = func_with_new_name(func, func.__name__) + value = staticmethod(func) + elif isinstance(value, classmethod): + raise AssertionError("classmethods not supported " + "in 'import_from_mixin'") + flatten[key] = value + # + target = sys._getframe(1).f_locals + for key, value in flatten.items(): + if key in target: + raise Exception("import_from_mixin: would overwrite the value " + "already defined locally for %r" % (key,)) + target[key] = value diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py --- a/rpython/rlib/test/test_objectmodel.py +++ b/rpython/rlib/test/test_objectmodel.py @@ -548,3 +548,57 @@ r = interpret(f, [29]) assert r == 1 + +def test_import_from_mixin(): + class M: # old-style + def f(self): pass + class A: # old-style + import_from_mixin(M) + assert A.f.im_func is not M.f.im_func + + class M(object): + def f(self): pass + class A: # old-style + import_from_mixin(M) + assert A.f.im_func is not M.f.im_func + + class M: # old-style + def f(self): pass + class A(object): + import_from_mixin(M) + assert A.f.im_func is not M.f.im_func + + class M(object): + def f(self): pass + class A(object): + import_from_mixin(M) + assert A.f.im_func is not M.f.im_func + + class MBase(object): + a = 42; b = 43; c = 1000 + def f(self): return "hi" + def g(self): return self.c - 1 + class M(MBase): + a = 84 + def f(self): return "there" + class A(object): + import_from_mixin(M) + c = 88 + assert A.f.im_func is not M.f.im_func + assert A.f.im_func is not MBase.f.im_func + assert A.g.im_func is not MBase.g.im_func + assert A().f() == "there" + assert A.a == 84 + assert A.b == 43 + assert A.c == 88 + assert A().g() == 87 + + try: + class B(object): + a = 63 + import_from_mixin(M) + except Exception, e: + assert ("would overwrite the value already defined locally for 'a'" + in str(e)) + else: + raise AssertionError("failed to detect overwritten attribute") _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit