diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2016-05-16 10:40:38 +0200 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2016-07-15 08:13:23 +0200 |
commit | 31a4969fed691f27805e37122fb3f7b85dfe8d9d (patch) | |
tree | ac08fa429b56492974f16d7768d86833e0b1528d | |
parent | 93c2d0846b99d84128ae47c0b406213e05505848 (diff) | |
download | cython-31a4969fed691f27805e37122fb3f7b85dfe8d9d.tar.gz |
add "__module__" attribute to coroutines and generators
-rw-r--r-- | Cython/Compiler/Nodes.py | 5 | ||||
-rw-r--r-- | Cython/Utility/Coroutine.c | 22 | ||||
-rw-r--r-- | tests/run/test_coroutines_pep492.pyx | 9 |
3 files changed, 26 insertions, 10 deletions
diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py index f0cab52b5..7e5db033e 100644 --- a/Cython/Compiler/Nodes.py +++ b/Cython/Compiler/Nodes.py @@ -3969,12 +3969,13 @@ class GeneratorDefNode(DefNode): body_cname = self.gbody.entry.func_cname name = code.intern_identifier(self.name) qualname = code.intern_identifier(self.qualname) + module_name = code.intern_identifier(self.module_name) code.putln('{') code.putln('__pyx_CoroutineObject *gen = __Pyx_%s_New(' - '(__pyx_coroutine_body_t) %s, (PyObject *) %s, %s, %s); %s' % ( + '(__pyx_coroutine_body_t) %s, (PyObject *) %s, %s, %s, %s); %s' % ( 'Coroutine' if self.is_coroutine else 'Generator', - body_cname, Naming.cur_scope_cname, name, qualname, + body_cname, Naming.cur_scope_cname, name, qualname, module_name, code.error_goto_if_null('gen', self.pos))) code.put_decref(Naming.cur_scope_cname, py_object_type) if self.requires_classobj: diff --git a/Cython/Utility/Coroutine.c b/Cython/Utility/Coroutine.c index d8ea87783..717cc458e 100644 --- a/Cython/Utility/Coroutine.c +++ b/Cython/Utility/Coroutine.c @@ -341,13 +341,15 @@ typedef struct { PyObject *yieldfrom; PyObject *gi_name; PyObject *gi_qualname; + PyObject *gi_modulename; int resume_label; // using T_BOOL for property below requires char value char is_running; } __pyx_CoroutineObject; -static __pyx_CoroutineObject *__Pyx__Coroutine_New(PyTypeObject *type, __pyx_coroutine_body_t body, - PyObject *closure, PyObject *name, PyObject *qualname); /*proto*/ +static __pyx_CoroutineObject *__Pyx__Coroutine_New( + PyTypeObject *type, __pyx_coroutine_body_t body, PyObject *closure, + PyObject *name, PyObject *qualname, PyObject *module_name); /*proto*/ static int __Pyx_Coroutine_clear(PyObject *self); /*proto*/ #if 1 || PY_VERSION_HEX < 0x030300B0 @@ -364,8 +366,8 @@ static PyTypeObject *__pyx_CoroutineType = 0; static PyTypeObject *__pyx_CoroutineAwaitType = 0; #define __Pyx_Coroutine_CheckExact(obj) (Py_TYPE(obj) == __pyx_CoroutineType) -#define __Pyx_Coroutine_New(body, closure, name, qualname) \ - __Pyx__Coroutine_New(__pyx_CoroutineType, body, closure, name, qualname) +#define __Pyx_Coroutine_New(body, closure, name, qualname, module_name) \ + __Pyx__Coroutine_New(__pyx_CoroutineType, body, closure, name, qualname, module_name) static int __pyx_Coroutine_init(void); /*proto*/ static PyObject *__Pyx__Coroutine_await(PyObject *coroutine); /*proto*/ @@ -377,8 +379,8 @@ static PyObject *__Pyx__Coroutine_await(PyObject *coroutine); /*proto*/ static PyTypeObject *__pyx_GeneratorType = 0; #define __Pyx_Generator_CheckExact(obj) (Py_TYPE(obj) == __pyx_GeneratorType) -#define __Pyx_Generator_New(body, closure, name, qualname) \ - __Pyx__Coroutine_New(__pyx_GeneratorType, body, closure, name, qualname) +#define __Pyx_Generator_New(body, closure, name, qualname, module_name) \ + __Pyx__Coroutine_New(__pyx_GeneratorType, body, closure, name, qualname, module_name) static PyObject *__Pyx_Generator_Next(PyObject *self); static int __pyx_Generator_init(void); /*proto*/ @@ -998,8 +1000,9 @@ __Pyx_Coroutine_set_qualname(__pyx_CoroutineObject *self, PyObject *value) return 0; } -static __pyx_CoroutineObject *__Pyx__Coroutine_New(PyTypeObject* type, __pyx_coroutine_body_t body, - PyObject *closure, PyObject *name, PyObject *qualname) { +static __pyx_CoroutineObject *__Pyx__Coroutine_New( + PyTypeObject* type, __pyx_coroutine_body_t body, PyObject *closure, + PyObject *name, PyObject *qualname, PyObject *module_name) { __pyx_CoroutineObject *gen = PyObject_GC_New(__pyx_CoroutineObject, type); if (gen == NULL) @@ -1020,6 +1023,8 @@ static __pyx_CoroutineObject *__Pyx__Coroutine_New(PyTypeObject* type, __pyx_cor gen->gi_qualname = qualname; Py_XINCREF(name); gen->gi_name = name; + Py_XINCREF(module_name); + gen->gi_modulename = module_name; PyObject_GC_Track(gen); return gen; @@ -1260,6 +1265,7 @@ static PyMemberDef __pyx_Coroutine_memberlist[] = { {(char *) "cr_running", T_BOOL, offsetof(__pyx_CoroutineObject, is_running), READONLY, NULL}, {(char*) "cr_await", T_OBJECT, offsetof(__pyx_CoroutineObject, yieldfrom), READONLY, (char*) PyDoc_STR("object being awaited, or None")}, + {(char *) "__module__", T_OBJECT, offsetof(__pyx_CoroutineObject, gi_modulename), PY_WRITE_RESTRICTED, 0}, {0, 0, 0, 0, 0} }; diff --git a/tests/run/test_coroutines_pep492.pyx b/tests/run/test_coroutines_pep492.pyx index 07b6f8011..032c6820d 100644 --- a/tests/run/test_coroutines_pep492.pyx +++ b/tests/run/test_coroutines_pep492.pyx @@ -488,6 +488,15 @@ class CoroutineTest(unittest.TestCase): def gen(): yield self.assertFalse(hasattr(gen, '__await__')) + def test_func_attributes(self): + async def foo(): + return 10 + + f = foo() + self.assertEqual(f.__name__, 'foo') + self.assertEqual(f.__qualname__, 'CoroutineTest.test_func_attributes.<locals>.foo') + self.assertEqual(f.__module__, 'test_coroutines_pep492') + def test_func_1(self): async def foo(): return 10 |