[pypy-commit] pypy stdlib-2.7.12: tighten type's arg checking

pjenvey pypy.commits at gmail.com
Sat Oct 8 18:40:13 EDT 2016


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: stdlib-2.7.12
Changeset: r87637:9dacf5a3b331
Date: 2016-10-08 15:36 -0700
http://bitbucket.org/pypy/pypy/changeset/9dacf5a3b331/

Log:	tighten type's arg checking

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
@@ -886,10 +886,11 @@
         Abc.__name__ = 'Def'
         assert Abc.__name__ == 'Def'
         raises(TypeError, "Abc.__name__ = 42")
+        raises(TypeError, "Abc.__name__ = u'A'")
         try:
             Abc.__name__ = 'G\x00hi'
         except ValueError as e:
-            assert str(e) == "__name__ must not contain null bytes"
+            assert str(e) == "type name must not contain null characters"
         else:
             assert False
 
@@ -1112,6 +1113,14 @@
             __bases__ = (int,)
         assert int.__subclasscheck__(AbstractClass()) is True
 
+    def test_bad_args(self):
+        import UserDict
+        raises(TypeError, type, 'A', (), dict={})
+        raises(TypeError, type, 'A', [], {})
+        raises(TypeError, type, 'A', (), UserDict.UserDict())
+        raises(ValueError, type, 'A\x00B', (), {})
+        raises(TypeError, type, u'A', (), {})
+
 
 class AppTestWithMethodCacheCounter:
     spaceconfig = {"objspace.std.withmethodcachecounter": True}
@@ -1200,7 +1209,7 @@
         assert w_B.w_new_function is not None
         w_b = space.call_function(w_B)
 
-        w_m = space.call_function(w_M, space.wrap('C'), space.newlist([]),
+        w_m = space.call_function(w_M, space.wrap('C'), space.newtuple([]),
                                   space.newdict())
         assert w_M.w_new_function is not None
 
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
@@ -672,25 +672,34 @@
 
 
 def descr__new__(space, w_typetype, w_name, w_bases=None, w_dict=None):
-    "This is used to create user-defined classes only."
-    # XXX check types
-
+    """This is used to create user-defined classes only."""
     w_typetype = _precheck_for_new(space, w_typetype)
 
     # special case for type(x)
-    if (space.is_w(space.type(w_typetype), space.w_type) and w_bases is None and
-        w_dict is None):
+    if (space.is_w(space.type(w_typetype), space.w_type) and
+        w_bases is None and w_dict is None):
         return space.type(w_name)
-    else:
-        return _create_new_type(space, w_typetype, w_name, w_bases, w_dict)
+    return _create_new_type(space, w_typetype, w_name, w_bases, w_dict)
+
+
+def _check_new_args(space, w_name, w_bases, w_dict):
+    if w_bases is None or w_dict is None:
+        raise oefmt(space.w_TypeError, "type() takes 1 or 3 arguments")
+    if not space.isinstance_w(w_name, space.w_str):
+        raise oefmt(space.w_TypeError,
+                    "type() argument 1 must be string, not %T", w_name)
+    if not space.isinstance_w(w_bases, space.w_tuple):
+        raise oefmt(space.w_TypeError,
+                    "type() argument 2 must be tuple, not %T", w_bases)
+    if not space.isinstance_w(w_dict, space.w_dict):
+        raise oefmt(space.w_TypeError,
+                    "type() argument 3 must be dict, not %T", w_dict)
 
 
 def _create_new_type(space, w_typetype, w_name, w_bases, w_dict):
     # this is in its own function because we want the special case 'type(x)'
     # above to be seen by the jit.
-    if w_bases is None or w_dict is None:
-        raise oefmt(space.w_TypeError, "type() takes 1 or 3 arguments")
-
+    _check_new_args(space, w_name, w_bases, w_dict)
     bases_w = space.fixedview(w_bases)
 
     w_winner = w_typetype
@@ -716,6 +725,8 @@
 
     name = space.str_w(w_name)
     assert isinstance(name, str)
+    if '\x00' in name:
+        raise oefmt(space.w_ValueError, "type name must not contain null characters")
     dict_w = {}
     dictkeys_w = space.listview(w_dict)
     for w_key in dictkeys_w:
@@ -732,6 +743,16 @@
         raise oefmt(space.w_TypeError, "X is not a type object (%T)", w_type)
     return w_type
 
+
+def descr__init__(space, w_type, __args__):
+    if __args__.keywords:
+        raise oefmt(space.w_TypeError,
+                    "type.__init__() takes no keyword arguments")
+    if len(__args__.arguments_w) not in (1, 3):
+        raise oefmt(space.w_TypeError,
+                    "type.__init__() takes 1 or 3 arguments")
+
+
 # ____________________________________________________________
 
 def _check(space, w_type, msg="descriptor is for 'type'"):
@@ -748,9 +769,13 @@
     w_type = _check(space, w_type)
     if not w_type.is_heaptype():
         raise oefmt(space.w_TypeError, "can't set %N.__name__", w_type)
+    if not space.isinstance_w(w_value, space.w_str):
+        raise oefmt(space.w_TypeError,
+                    "can only assign string to %N.__name__, not '%T'",
+                    w_type, w_value)
     name = space.str_w(w_value)
     if '\x00' in name:
-        raise oefmt(space.w_ValueError, "__name__ must not contain null bytes")
+        raise oefmt(space.w_ValueError, "type name must not contain null characters")
     w_type.name = name
 
 def descr_get__mro__(space, w_type):
@@ -920,6 +945,7 @@
 
 W_TypeObject.typedef = TypeDef("type",
     __new__ = gateway.interp2app(descr__new__),
+    __init__ = gateway.interp2app(descr__init__),
     __name__ = GetSetProperty(descr_get__name__, descr_set__name__),
     __bases__ = GetSetProperty(descr_get__bases__, descr_set__bases__),
     __base__ = GetSetProperty(descr__base),


More information about the pypy-commit mailing list