Author: Matti Picus <matti.pi...@gmail.com>
Branch: py3.6
Changeset: r96097:805c1a75f5f0
Date: 2019-02-19 21:06 +0200
http://bitbucket.org/pypy/pypy/changeset/805c1a75f5f0/

Log:    merge default into branch

diff --git a/pypy/module/_cffi_backend/ctypeprim.py 
b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -175,7 +175,7 @@
         value = misc.read_raw_ulong_data(cdata, self.size)   # r_uint
         try:
             utf8 = rutf8.unichr_as_utf8(value, allow_surrogates=True)
-        except ValueError:
+        except rutf8.OutOfRange:
             if self.is_signed_wchar:
                 s = hex(intmask(value))
             else:
diff --git a/pypy/module/_cffi_backend/wchar_helper.py 
b/pypy/module/_cffi_backend/wchar_helper.py
--- a/pypy/module/_cffi_backend/wchar_helper.py
+++ b/pypy/module/_cffi_backend/wchar_helper.py
@@ -24,7 +24,7 @@
         j += 1
         try:
             rutf8.unichr_as_utf8_append(u, ch, allow_surrogates=True)
-        except ValueError:
+        except rutf8.OutOfRange:
             raise OutOfRange(ch)
     return u.build(), length
 
diff --git a/pypy/module/cpyext/dictobject.py b/pypy/module/cpyext/dictobject.py
--- a/pypy/module/cpyext/dictobject.py
+++ b/pypy/module/cpyext/dictobject.py
@@ -2,6 +2,7 @@
 from rpython.rlib.objectmodel import specialize
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.classdict import ClassDictStrategy
+from pypy.objspace.std.dictmultiobject import W_DictMultiObject
 from pypy.interpreter.typedef import GetSetProperty
 from pypy.module.cpyext.api import (
     cpython_api, CANNOT_FAIL, build_type_checkers_flags, Py_ssize_t, cts,
@@ -71,68 +72,59 @@
 @cpython_api([PyObject, PyObject], PyObject, error=CANNOT_FAIL,
              result_borrowed=True)
 def PyDict_GetItem(space, w_dict, w_key):
-    try:
-        w_res = space.getitem(w_dict, w_key)
-    except:
-        return None
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise PyErr_BadInternalCall(space)
     # NOTE: this works so far because all our dict strategies store
     # *values* as full objects, which stay alive as long as the dict is
     # alive and not modified.  So we can return a borrowed ref.
     # XXX this is wrong with IntMutableCell.  Hope it works...
-    return w_res
+    return w_dict.getitem(w_key)
 
 @cpython_api([PyObject, PyObject, PyObject], rffi.INT_real, error=-1)
 def PyDict_SetItem(space, w_dict, w_key, w_obj):
-    if PyDict_Check(space, w_dict):
-        space.setitem(w_dict, w_key, w_obj)
-        return 0
-    else:
-        PyErr_BadInternalCall(space)
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise PyErr_BadInternalCall(space)
+    w_dict.setitem(w_key, w_obj)
+    return 0
 
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-1)
 def PyDict_DelItem(space, w_dict, w_key):
-    if PyDict_Check(space, w_dict):
-        space.delitem(w_dict, w_key)
-        return 0
-    else:
-        PyErr_BadInternalCall(space)
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise PyErr_BadInternalCall(space)
+    w_dict.descr_delitem(space, w_key)
+    return 0
 
 @cpython_api([PyObject, CONST_STRING, PyObject], rffi.INT_real, error=-1)
 def PyDict_SetItemString(space, w_dict, key_ptr, w_obj):
-    if PyDict_Check(space, w_dict):
-        key = rffi.charp2str(key_ptr)
-        space.setitem_str(w_dict, key, w_obj)
-        return 0
-    else:
-        PyErr_BadInternalCall(space)
+    w_key = space.newtext(rffi.charp2str(key_ptr))
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise PyErr_BadInternalCall(space)
+    w_dict.setitem(w_key, w_obj)
+    return 0
 
 @cpython_api([PyObject, CONST_STRING], PyObject, error=CANNOT_FAIL,
              result_borrowed=True)
 def PyDict_GetItemString(space, w_dict, key):
     """This is the same as PyDict_GetItem(), but key is specified as a
     char*, rather than a PyObject*."""
-    try:
-        w_res = space.finditem_str(w_dict, rffi.charp2str(key))
-    except:
-        w_res = None
+    w_key = space.newtext(rffi.charp2str(key))
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise PyErr_BadInternalCall(space)
     # NOTE: this works so far because all our dict strategies store
     # *values* as full objects, which stay alive as long as the dict is
     # alive and not modified.  So we can return a borrowed ref.
     # XXX this is wrong with IntMutableCell.  Hope it works...
-    return w_res
+    return w_dict.getitem(w_key)
 
 @cpython_api([PyObject, CONST_STRING], rffi.INT_real, error=-1)
 def PyDict_DelItemString(space, w_dict, key_ptr):
     """Remove the entry in dictionary p which has a key specified by the string
     key.  Return 0 on success or -1 on failure."""
-    if PyDict_Check(space, w_dict):
-        key = rffi.charp2str(key_ptr)
-        # our dicts dont have a standardized interface, so we need
-        # to go through the space
-        space.delitem(w_dict, space.newtext(key))
-        return 0
-    else:
-        PyErr_BadInternalCall(space)
+    w_key = space.newtext(rffi.charp2str(key_ptr))
+    if not isinstance(w_dict, W_DictMultiObject):
+        raise PyErr_BadInternalCall(space)
+    w_dict.descr_delitem(space, w_key)
+    return 0
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PyDict_Size(space, w_obj):
@@ -191,7 +183,7 @@
     """
     override = rffi.cast(lltype.Signed, override)
     w_keys = space.call_method(w_b, "keys")
-    for w_key  in space.iteriterable(w_keys):
+    for w_key in space.iteriterable(w_keys):
         if not _has_val(space, w_a, w_key) or override != 0:
             space.setitem(w_a, w_key, space.getitem(w_b, w_key))
     return 0
diff --git a/pypy/module/cpyext/test/test_dictobject.py 
b/pypy/module/cpyext/test/test_dictobject.py
--- a/pypy/module/cpyext/test/test_dictobject.py
+++ b/pypy/module/cpyext/test/test_dictobject.py
@@ -332,3 +332,67 @@
         assert module.dict_delitem(d, 'a') == 0
         r = module.dict_next({'a': 1, 'b': 2})
         assert r == 2
+
+    def test_subclassing(self):
+        module = self.import_extension('foo', [
+            ("dict_setitem", "METH_VARARGS",
+             """
+             PyObject *d, *key, *value;
+             if (!PyArg_ParseTuple(args, "OOO", &d, &key, &value)) {
+                return NULL;
+             }
+             if (PyDict_SetItem(d, key, value) < 0) {
+                return NULL;
+             }
+             Py_RETURN_NONE;
+             """),
+            ("dict_delitem", "METH_VARARGS",
+             """
+             PyObject *d, *key;
+             if (!PyArg_ParseTuple(args, "OO", &d, &key)) {
+                return NULL;
+             }
+             if (PyDict_DelItem(d, key) < 0) {
+                return NULL;
+             }
+             Py_RETURN_NONE;
+             """),
+            ("dict_getitem", "METH_VARARGS",
+             """
+             PyObject *d, *key, *result;
+             if (!PyArg_ParseTuple(args, "OO", &d, &key)) {
+                return NULL;
+             }
+             result = PyDict_GetItem(d, key);
+             Py_XINCREF(result);
+             return result;
+             """),
+        ])
+
+        class mydict(dict):
+            def __setitem__(self, key, value):
+                dict.__setitem__(self, key, 42)
+
+            def __delitem__(self, key):
+                dict.__setitem__(self, key, None)
+        d = {}
+        module.dict_setitem(d, 1, 2)
+        assert d[1] == 2
+        d = mydict()
+        d[1] = 2
+        assert d[1] == 42
+        module.dict_setitem(d, 2, 3)
+        assert d[2] == 3
+        del d[2]
+        assert d[2] is None
+        module.dict_delitem(d, 2)
+        assert 2 not in d
+
+        class mydict2(dict):
+            def __getitem__(self, key):
+                return 42
+
+        d = mydict2()
+        d[1] = 2
+        assert d[1] == 42
+        assert module.dict_getitem(d, 1) == 2
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -479,7 +479,7 @@
                 if do_unicode:
                     try:
                         c = rutf8.unichr_as_utf8(r_uint(n))
-                    except ValueError:
+                    except rutf8.OutOfRange:
                         raise oefmt(space.w_OverflowError,
                                     "unicode character code out of range")
                     self.std_wp(c, False)
diff --git a/rpython/rlib/rutf8.py b/rpython/rlib/rutf8.py
--- a/rpython/rlib/rutf8.py
+++ b/rpython/rlib/rutf8.py
@@ -30,6 +30,11 @@
 MAXUNICODE = 0x10ffff
 allow_surrogate_by_default = False
 
+
+class OutOfRange(Exception):
+    def __init__(self, code):
+        self.code = code
+
 # we need a way to accept both r_uint and int(nonneg=True)
 #@signature(types.int_nonneg(), types.bool(), returns=types.str())
 def unichr_as_utf8(code, allow_surrogates=False):
@@ -44,7 +49,7 @@
         return chr((0xc0 | (code >> 6))) + chr((0x80 | (code & 0x3f)))
     if code <= r_uint(0xFFFF):
         if not allow_surrogates and 0xD800 <= code <= 0xDfff:
-            raise ValueError
+            raise OutOfRange(code)
         return (chr((0xe0 | (code >> 12))) +
                 chr((0x80 | ((code >> 6) & 0x3f))) +
                 chr((0x80 | (code & 0x3f))))
@@ -53,7 +58,7 @@
                 chr((0x80 | ((code >> 12) & 0x3f))) +
                 chr((0x80 | ((code >> 6) & 0x3f))) +
                 chr((0x80 | (code & 0x3f))))
-    raise ValueError
+    raise OutOfRange(code)
 
 @try_inline
 def unichr_as_utf8_append(builder, code, allow_surrogates=False):
@@ -89,7 +94,7 @@
         builder.append(chr((0x80 | ((code >> 6) & 0x3f))))
         builder.append(chr((0x80 | (code & 0x3f))))
         return
-    raise ValueError('character U+%x is not in range [U+0000; U+10ffff]' % 
code)
+    raise OutOfRange(code)
 
 @dont_inline
 def _nonascii_unichr_as_utf8_append_nosurrogates(builder, code):
@@ -110,7 +115,7 @@
         builder.append(chr((0x80 | ((code >> 6) & 0x3f))))
         builder.append(chr((0x80 | (code & 0x3f))))
         return
-    raise ValueError
+    raise OutOfRange(code)
 
 
 # note - table lookups are really slow. Measured on various elements of obama
diff --git a/rpython/rlib/test/test_rutf8.py b/rpython/rlib/test/test_rutf8.py
--- a/rpython/rlib/test/test_rutf8.py
+++ b/rpython/rlib/test/test_rutf8.py
@@ -9,7 +9,7 @@
 def test_unichr_as_utf8(c, allow_surrogates):
     i = ord(c)
     if not allow_surrogates and 0xD800 <= i <= 0xDFFF:
-        with pytest.raises(ValueError):
+        with pytest.raises(rutf8.OutOfRange):
             rutf8.unichr_as_utf8(i, allow_surrogates)
     else:
         u = rutf8.unichr_as_utf8(i, allow_surrogates)
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to