Author: Armin Rigo <ar...@tunes.org> Branch: Changeset: r53259:534c2faf1522 Date: 2012-03-07 17:07 +0000 http://bitbucket.org/pypy/pypy/changeset/534c2faf1522/
Log: merge heads diff --git a/pypy/annotation/description.py b/pypy/annotation/description.py --- a/pypy/annotation/description.py +++ b/pypy/annotation/description.py @@ -398,7 +398,6 @@ cls = pyobj base = object baselist = list(cls.__bases__) - baselist.reverse() # special case: skip BaseException in Python 2.5, and pretend # that all exceptions ultimately inherit from Exception instead @@ -408,17 +407,27 @@ elif baselist == [py.builtin.BaseException]: baselist = [Exception] + mixins_before = [] + mixins_after = [] for b1 in baselist: if b1 is object: continue if b1.__dict__.get('_mixin_', False): - self.add_mixin(b1) + if base is object: + mixins_before.append(b1) + else: + mixins_after.append(b1) else: assert base is object, ("multiple inheritance only supported " "with _mixin_: %r" % (cls,)) base = b1 + if mixins_before and mixins_after: + raise Exception("unsupported: class %r has mixin bases both" + " before and after the regular base" % (self,)) + self.add_mixins(mixins_after, check_not_in=base) + self.add_mixins(mixins_before) + self.add_sources_for_class(cls) - self.add_sources_for_class(cls) if base is not object: self.basedesc = bookkeeper.getdesc(base) @@ -480,14 +489,30 @@ return self.classdict[name] = Constant(value) - def add_mixin(self, base): - for subbase in base.__bases__: - if subbase is object: - continue - assert subbase.__dict__.get("_mixin_", False), ("Mixin class %r has non" - "mixin base class %r" % (base, subbase)) - self.add_mixin(subbase) - self.add_sources_for_class(base, mixin=True) + def add_mixins(self, mixins, check_not_in=object): + if not mixins: + return + A = type('tmp', tuple(mixins) + (object,), {}) + mro = A.__mro__ + assert mro[0] is A and mro[-1] is object + mro = mro[1:-1] + # + skip = set() + def add(cls): + if cls is not object: + for base in cls.__bases__: + add(base) + for name in cls.__dict__: + skip.add(name) + add(check_not_in) + # + for base in reversed(mro): + assert base.__dict__.get("_mixin_", False), ("Mixin class %r has non" + "mixin base class %r" % (mixins, base)) + for name, value in base.__dict__.items(): + if name in skip: + continue + self.add_source_attribute(name, value, mixin=True) def add_sources_for_class(self, cls, mixin=False): for name, value in cls.__dict__.items(): diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py --- a/pypy/annotation/test/test_annrpython.py +++ b/pypy/annotation/test/test_annrpython.py @@ -2431,6 +2431,52 @@ assert isinstance(s.items[1], annmodel.SomeChar) assert isinstance(s.items[2], annmodel.SomeChar) + def test_mixin_first(self): + class Mixin(object): + _mixin_ = True + def foo(self): return 4 + class Base(object): + def foo(self): return 5 + class Concrete(Mixin, Base): + pass + def f(): + return Concrete().foo() + + assert f() == 4 + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert s.const == 4 + + def test_mixin_last(self): + class Mixin(object): + _mixin_ = True + def foo(self): return 4 + class Base(object): + def foo(self): return 5 + class Concrete(Base, Mixin): + pass + def f(): + return Concrete().foo() + + assert f() == 5 + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert s.const == 5 + + def test_mixin_concrete(self): + class Mixin(object): + _mixin_ = True + def foo(self): return 4 + class Concrete(Mixin): + def foo(self): return 5 + def f(): + return Concrete().foo() + + assert f() == 5 + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert s.const == 5 + def test_multiple_mixins_mro(self): # an obscure situation, but it occurred in module/micronumpy/types.py class A(object): diff --git a/pypy/jit/backend/x86/codebuf.py b/pypy/jit/backend/x86/codebuf.py --- a/pypy/jit/backend/x86/codebuf.py +++ b/pypy/jit/backend/x86/codebuf.py @@ -19,8 +19,8 @@ class MachineCodeBlockWrapper(BlockBuilderMixin, - codebuilder_cls, - LocationCodeBuilder): + LocationCodeBuilder, + codebuilder_cls): def __init__(self): self.init_block_builder() # a list of relative positions; for each position p, the bytes _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit