[pypy-commit] pypy py3.5: Implement PyDict_SetDefault()

rlamy pypy.commits at gmail.com
Sat Sep 16 00:16:11 EDT 2017


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r92409:1a05dfedf02e
Date: 2017-09-16 05:15 +0100
http://bitbucket.org/pypy/pypy/changeset/1a05dfedf02e/

Log:	Implement PyDict_SetDefault()

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
@@ -4,10 +4,10 @@
 from pypy.objspace.std.classdict import ClassDictStrategy
 from pypy.interpreter.typedef import GetSetProperty
 from pypy.module.cpyext.api import (
-    cpython_api, CANNOT_FAIL, build_type_checkers_flags, Py_ssize_t,
+    cpython_api, CANNOT_FAIL, build_type_checkers_flags, Py_ssize_t, cts,
     Py_ssize_tP, CONST_STRING, PyObjectFields, cpython_struct,
     bootstrap_function, slot_function)
-from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, as_pyobj, 
+from pypy.module.cpyext.pyobject import (PyObject, PyObjectP, as_pyobj,
         make_typedescr, track_reference, create_ref, from_ref, decref,
         Py_IncRef)
 from pypy.module.cpyext.object import _dealloc
@@ -155,6 +155,15 @@
     """Empty an existing dictionary of all key-value pairs."""
     space.call_method(space.w_dict, "clear", w_obj)
 
+ at cts.decl("""PyObject *
+    PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *defaultobj)""")
+def PyDict_SetDefault(space, w_dict, w_key, w_defaultobj):
+    if not PyDict_Check(space, w_dict):
+        PyErr_BadInternalCall(space)
+    else:
+        return space.call_method(
+            space.w_dict, "setdefault", w_dict, w_key, w_defaultobj)
+
 @cpython_api([PyObject], PyObject)
 def PyDict_Copy(space, w_obj):
     """Return a new dictionary that contains the same key-value pairs as p.
@@ -258,7 +267,7 @@
     if w_dict is None:
         return 0
     if not space.isinstance_w(w_dict, space.w_dict):
-        return 0 
+        return 0
     pos = ppos[0]
     py_obj = as_pyobj(space, w_dict)
     py_dict = rffi.cast(PyDictObject, py_obj)
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
@@ -174,6 +174,26 @@
             ])
         assert module.dict_proxy({'a': 1, 'b': 2}) == 2
 
+    def test_setdefault(self):
+        module = self.import_extension('foo', [
+            ("setdefault", "METH_VARARGS",
+             '''
+             PyObject *d, *key, *defaultobj, *val;
+             if (!PyArg_ParseTuple(args, "OOO", &d, &key, &defaultobj))
+                 return NULL;
+             val = PyDict_SetDefault(d, key, defaultobj);
+             Py_XINCREF(val);
+             return val;
+             ''')])
+
+        class Dict(dict):
+            def setdefault(self, key, default):
+                return 42
+
+        d = Dict()
+        assert module.setdefault(d, 'x', 1) == 1
+        assert d['x'] == 1
+
     def test_update(self):
         module = self.import_extension('foo', [
             ("update", "METH_VARARGS",


More information about the pypy-commit mailing list