[pypy-commit] pypy default: Issue #2820

arigo pypy.commits at gmail.com
Sat May 12 03:14:46 EDT 2018


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r94526:a91492fa1e35
Date: 2018-05-12 09:14 +0200
http://bitbucket.org/pypy/pypy/changeset/a91492fa1e35/

Log:	Issue #2820

	Implement Py_ReprEnter() and Py_ReprLeave()

diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -11,6 +11,7 @@
 from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.executioncontext import ExecutionContext
 import pypy.module.__builtin__.operation as operation
 
 
@@ -411,3 +412,27 @@
 def _PyPyGC_AddMemoryPressure(space, report):
     from rpython.rlib import rgc
     rgc.add_memory_pressure(report)
+
+
+ExecutionContext.cpyext_recursive_repr = None
+
+ at cpython_api([PyObject], rffi.INT_real, error=-1)
+def Py_ReprEnter(space, w_obj):
+    ec = space.getexecutioncontext()
+    d = ec.cpyext_recursive_repr
+    if d is None:
+        d = ec.cpyext_recursive_repr = {}
+    if w_obj in d:
+        return 1
+    d[w_obj] = None
+    return 0
+
+ at cpython_api([PyObject], lltype.Void)
+def Py_ReprLeave(space, w_obj):
+    ec = space.getexecutioncontext()
+    d = ec.cpyext_recursive_repr
+    if d is not None:
+        try:
+            del d[w_obj]
+        except KeyError:
+            pass
diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -403,6 +403,47 @@
         module.foo(35000)
         assert self.cur_memory_pressure() == 65536 + 80000 + 70000
 
+    def test_repr_enter_leave(self):
+        module = self.import_extension('foo', [
+            ("enter", "METH_O",
+            """
+                return PyInt_FromLong(Py_ReprEnter(args));
+            """),
+            ("leave", "METH_O",
+            """
+                Py_ReprLeave(args);
+                Py_INCREF(Py_None);
+                return Py_None;
+            """)])
+        obj1 = [42]
+        obj2 = [42]   # another list
+
+        n = module.enter(obj1)
+        assert n == 0
+        module.leave(obj1)
+
+        n = module.enter(obj1)
+        assert n == 0
+        n = module.enter(obj1)
+        assert n == 1
+        n = module.enter(obj1)
+        assert n == 1
+        module.leave(obj1)
+
+        n = module.enter(obj1)
+        assert n == 0
+        n = module.enter(obj2)
+        assert n == 0
+        n = module.enter(obj1)
+        assert n == 1
+        n = module.enter(obj2)
+        assert n == 1
+        module.leave(obj1)
+        n = module.enter(obj2)
+        assert n == 1
+        module.leave(obj2)
+
+
 class AppTestPyBuffer_FillInfo(AppTestCpythonExtensionBase):
     """
     PyBuffer_FillInfo populates the fields of a Py_buffer from its arguments.


More information about the pypy-commit mailing list