Author: Ronan Lamy <[email protected]>
Branch: py3.5
Changeset: r92453:ce24631719e2
Date: 2017-09-24 19:27 +0100
http://bitbucket.org/pypy/pypy/changeset/ce24631719e2/

Log:    Implement PyGenObject so that C code can recognize @types.coroutine
        old-style generator-coroutines

diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -12,7 +12,8 @@
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.interpreter.astcompiler.consts import (
     CO_OPTIMIZED, CO_NEWLOCALS, CO_VARARGS, CO_VARKEYWORDS, CO_NESTED,
-    CO_GENERATOR, CO_COROUTINE, CO_KILL_DOCSTRING, CO_YIELD_INSIDE_TRY)
+    CO_GENERATOR, CO_COROUTINE, CO_KILL_DOCSTRING, CO_YIELD_INSIDE_TRY,
+    CO_ITERABLE_COROUTINE)
 from pypy.tool import dis3
 from pypy.tool.stdlib_opcode import opcodedesc, HAVE_ARGUMENT
 from rpython.rlib.rarithmetic import intmask
diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -18,6 +18,8 @@
     CO_VARKEYWORDS = 0x0008,
     CO_NESTED      = 0x0010,
     CO_GENERATOR   = 0x0020,
+    CO_COROUTINE=0x0080,
+    CO_ITERABLE_COROUTINE=0x0100,
 )
 ALL_CODE_FLAGS = unrolling_iterable(CODE_FLAGS.items())
 
diff --git a/pypy/module/cpyext/genobject.py b/pypy/module/cpyext/genobject.py
--- a/pypy/module/cpyext/genobject.py
+++ b/pypy/module/cpyext/genobject.py
@@ -1,7 +1,29 @@
 from pypy.interpreter.generator import GeneratorIterator, Coroutine
-from pypy.module.cpyext.api import build_type_checkers
+from pypy.module.cpyext.api import (
+    build_type_checkers, cts, parse_dir, bootstrap_function)
+from pypy.module.cpyext.pyobject import make_typedescr, as_pyobj
+from pypy.module.cpyext.object import _dealloc
+
+cts.parse_header(parse_dir / 'cpyext_genobject.h')
+
+@bootstrap_function
+def init_genobject(space):
+    make_typedescr(GeneratorIterator.typedef,
+                   basestruct=cts.gettype('PyGenObject'),
+                   attach=gi_attach,
+                   dealloc=_dealloc)
 
 
 PyGen_Check, PyGen_CheckExact = build_type_checkers("Gen", GeneratorIterator)
 
 _, PyCoro_CheckExact = build_type_checkers("Coro", Coroutine)
+
+def gi_attach(space, py_obj, w_obj, w_userdata=None):
+    py_obj.c_gi_code = as_pyobj(space, w_obj.pycode)
+
+def gi_realize(space, py_obj):
+    raise NotImplementedError(
+        "PyPy doesn't support creation of generators from the C-API.")
+
+def gi_dealloc(space, py_obj):
+    _dealloc(space, py_obj)
diff --git a/pypy/module/cpyext/include/code.h 
b/pypy/module/cpyext/include/code.h
--- a/pypy/module/cpyext/include/code.h
+++ b/pypy/module/cpyext/include/code.h
@@ -20,6 +20,11 @@
 #define CO_VARKEYWORDS  0x0008
 #define CO_NESTED       0x0010
 #define CO_GENERATOR    0x0020
+  
+/* The CO_COROUTINE flag is set for coroutine functions (defined with
+   ``async def`` keywords) */
+#define CO_COROUTINE            0x0080
+#define CO_ITERABLE_COROUTINE   0x0100
 
 #define CO_FUTURE_DIVISION         0x02000
 #define CO_FUTURE_ABSOLUTE_IMPORT  0x04000
diff --git a/pypy/module/cpyext/test/test_genobject.py 
b/pypy/module/cpyext/test/test_genobject.py
--- a/pypy/module/cpyext/test/test_genobject.py
+++ b/pypy/module/cpyext/test/test_genobject.py
@@ -28,7 +28,28 @@
         assert PyCoro_CheckExact(space, w_coroutine)
 
 class AppTestCoroutine(AppTestCpythonExtensionBase):
-    def test_simple(self):
+    def test_generator_coroutine(self):
+        module = self.import_extension('test_gen', [
+            ('is_coroutine', 'METH_O',
+             '''
+             if (!PyGen_CheckExact(args))
+                Py_RETURN_NONE;
+             PyObject* co = ((PyGenObject*)args)->gi_code;
+             if (((PyCodeObject*)co)->co_flags & CO_ITERABLE_COROUTINE)
+                Py_RETURN_TRUE;
+             else
+                Py_RETURN_FALSE;
+             ''')])
+        def it():
+            yield 42
+
+        print(module.is_coroutine(it()))
+        assert module.is_coroutine(it()) is False
+        from types import coroutine
+        assert module.is_coroutine(coroutine(it)()) is True
+
+
+    def test_await(self):
         """
         module = self.import_extension('test_coroutine', [
             ('await_', 'METH_O',
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to