[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