[pypy-commit] pypy default: try to see whether it's plausible to forbid moving methods up the class
cfbolz
pypy.commits at gmail.com
Mon May 21 10:03:57 EDT 2018
Author: Carl Friedrich Bolz-Tereick <cfbolz at gmx.de>
Branch:
Changeset: r94626:b51d40dbb01d
Date: 2018-05-17 13:56 +0200
http://bitbucket.org/pypy/pypy/changeset/b51d40dbb01d/
Log: try to see whether it's plausible to forbid moving methods up the
class hierarchy in rpython
diff --git a/rpython/annotator/classdesc.py b/rpython/annotator/classdesc.py
--- a/rpython/annotator/classdesc.py
+++ b/rpython/annotator/classdesc.py
@@ -102,13 +102,20 @@
def validate(self, homedef):
s_newvalue = self.s_value
- # check for after-the-fact method additions
+ homedesc = homedef.classdesc
+ # check for method demotion and after-the-fact method additions
if isinstance(s_newvalue, SomePBC):
attr = self.name
if s_newvalue.getKind() == MethodDesc:
# is method
if homedef.classdesc.read_attribute(attr, None) is None:
- homedef.check_missing_attribute_update(attr)
+ if not homedef.check_missing_attribute_update(attr):
+ for desc in s_newvalue.descriptions:
+ if desc.selfclassdef is None:
+ raise AnnotatorError(
+ "demoting method %s from %s to class "
+ "%s not allowed" % (self.name, desc.originclassdef, homedef)
+ )
# check for attributes forbidden by slots or _attrs_
if homedef.classdesc.all_enforced_attrs is not None:
@@ -489,6 +496,7 @@
knowntype = type
instance_level = False
all_enforced_attrs = None # or a set
+ settled = False
_detect_invalid_attrs = None
def __init__(self, bookkeeper, cls,
@@ -559,6 +567,9 @@
if base is not object:
self.basedesc = bookkeeper.getdesc(base)
+ if '_settled_' in cls.__dict__:
+ self.settled = bool(cls.__dict__['_settled_'])
+
if '__slots__' in cls.__dict__ or '_attrs_' in cls.__dict__:
attrs = {}
for decl in ('__slots__', '_attrs_'):
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
@@ -2374,7 +2374,8 @@
def test_stored_bound_method_2(self):
# issue 129
class H:
- pass
+ def h(self):
+ raise NotImplementedError("abstract method")
class H1(H):
def h(self):
return 42
@@ -3049,6 +3050,7 @@
def test_slots_check(self):
class Base(object):
__slots__ = 'x'
+ def m(self): raise NotImplementedError("abstract")
class A(Base):
__slots__ = 'y'
def m(self):
@@ -3098,6 +3100,7 @@
def test_enforced_attrs_check(self):
class Base(object):
_attrs_ = 'x'
+ def m(self): raise NotImplementedError("abstract")
class A(Base):
_attrs_ = 'y'
def m(self):
@@ -3167,6 +3170,45 @@
a = self.RPythonAnnotator()
a.build_types(f, [bool])
+ def test_enforce_settled(self):
+ class A(object):
+ _settled_ = True
+
+ def m(self):
+ raise NotImplementedError
+
+ class B(A):
+
+ def m(self):
+ return 1
+
+ def n(self):
+ return 1
+
+ def fun(x):
+ if x:
+ a = A()
+ else:
+ a = B()
+
+ return a.m()
+
+ a = self.RPythonAnnotator()
+ s = a.build_types(fun, [bool])
+ assert s.knowntype == int
+
+ def fun(x):
+ if x:
+ a = A()
+ else:
+ a = B()
+
+ return a.n()
+
+ a = self.RPythonAnnotator()
+ with py.test.raises(AnnotatorError):
+ a.build_types(fun, [bool])
+
def test_float_cmp(self):
def fun(x, y):
return (x < y,
diff --git a/rpython/translator/test/snippet.py b/rpython/translator/test/snippet.py
--- a/rpython/translator/test/snippet.py
+++ b/rpython/translator/test/snippet.py
@@ -375,7 +375,9 @@
return _getstuff(d), _getstuff(e)
class F:
- pass
+ def m(self, x):
+ raise NotImplementedError("abstract base")
+
class G(F):
def m(self, x):
return self.m2(x)
More information about the pypy-commit
mailing list