[pypy-commit] pypy py3.5: Fix allowed types in __slots__ for CPython compatibility
rlamy
pypy.commits at gmail.com
Wed Dec 7 09:51:44 EST 2016
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r88943:74f6e6f2c9ff
Date: 2016-12-07 14:51 +0000
http://bitbucket.org/pypy/pypy/changeset/74f6e6f2c9ff/
Log: Fix allowed types in __slots__ for CPython compatibility
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -667,6 +667,11 @@
b.abc = "awesomer"
assert b.abc == "awesomer"
+ def test_bad_slots(self):
+ raises(TypeError, type, 'A', (), {'__slots__': b'x'})
+ raises(TypeError, type, 'A', (), {'__slots__': 42})
+ raises(TypeError, type, 'A', (), {'__slots__': '2_x'})
+
def test_base_attr(self):
# check the '__base__'
class A(object):
diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -1057,6 +1057,14 @@
w_self.weakrefable = w_self.weakrefable or w_base.weakrefable
return hasoldstylebase
+def slot_w(space, w_name):
+ from pypy.objspace.std.unicodeobject import _isidentifier
+ if not space.isinstance_w(w_name, space.w_text):
+ raise oefmt(space.w_TypeError,
+ "__slots__ items must be strings, not '%T'", w_name)
+ if not _isidentifier(w_name._value):
+ raise oefmt(space.w_TypeError, "__slots__ must be identifiers")
+ return w_name.identifier_w(space)
def create_all_slots(w_self, hasoldstylebase, w_bestbase, force_new_layout):
from pypy.objspace.std.listobject import StringSort
@@ -1073,13 +1081,12 @@
wantdict = False
wantweakref = False
w_slots = dict_w['__slots__']
- if (space.isinstance_w(w_slots, space.w_str) or
- space.isinstance_w(w_slots, space.w_unicode)):
+ if space.isinstance_w(w_slots, space.w_text):
slot_names_w = [w_slots]
else:
slot_names_w = space.unpackiterable(w_slots)
for w_slot_name in slot_names_w:
- slot_name = space.str_w(w_slot_name)
+ slot_name = slot_w(space, w_slot_name)
if slot_name == '__dict__':
if wantdict or w_bestbase.hasdict:
raise oefmt(space.w_TypeError,
@@ -1124,8 +1131,6 @@
def create_slot(w_self, slot_name, index_next_extra_slot):
space = w_self.space
- if not valid_slot_name(slot_name):
- raise oefmt(space.w_TypeError, "__slots__ must be identifiers")
# create member
slot_name = mangle(slot_name, w_self.name)
if slot_name not in w_self.dict_w:
@@ -1156,14 +1161,6 @@
w_self.space.wrap(weakref_descr))
w_self.weakrefable = True
-def valid_slot_name(slot_name):
- if len(slot_name) == 0 or slot_name[0].isdigit():
- return False
- for c in slot_name:
- if not c.isalnum() and c != '_':
- return False
- return True
-
def setup_user_defined_type(w_self, force_new_layout):
if len(w_self.bases_w) == 0:
w_self.bases_w = [w_self.space.w_object]
More information about the pypy-commit
mailing list