Correct globals for shared function types.
authorRobert Bradshaw <robertwb@gmail.com>
Thu, 15 Aug 2013 06:44:40 +0000 (23:44 -0700)
committerRobert Bradshaw <robertwb@gmail.com>
Thu, 15 Aug 2013 09:04:51 +0000 (02:04 -0700)
Cython/Compiler/ExprNodes.py
Cython/Utility/CythonFunction.c
tests/run/common_utility_types.srctree

index 7f1fdcb..4488888 100755 (executable)
@@ -7236,7 +7236,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
             flags = '0'
 
         code.putln(
-            '%s = %s(&%s, %s, %s, %s, %s, %s); %s' % (
+            '%s = %s(&%s, %s, %s, %s, %s, %s, %s); %s' % (
                 self.result(),
                 constructor,
                 self.pymethdef_cname,
@@ -7244,6 +7244,7 @@ class PyCFunctionNode(ExprNode, ModuleNameMixin):
                 self.get_py_qualified_name(code),
                 self.self_result_code(),
                 self.get_py_mod_name(code),
+                "PyModule_GetDict(%s)" % Naming.module_cname,
                 code_object_result,
                 code.error_goto_if_null(self.result(), self.pos)))
 
index 0b6d975..7378b91 100644 (file)
@@ -27,6 +27,7 @@ typedef struct {
     PyObject *func_name;
     PyObject *func_qualname;
     PyObject *func_doc;
+    PyObject *func_globals;
     PyObject *func_code;
     PyObject *func_closure;
     PyObject *func_classobj; /* No-args super() class cell */
@@ -44,12 +45,13 @@ typedef struct {
 
 static PyTypeObject *__pyx_CyFunctionType = 0;
 
-#define __Pyx_CyFunction_NewEx(ml, flags, qualname, self, module, code) \
-    __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, flags, qualname, self, module, code)
+#define __Pyx_CyFunction_NewEx(ml, flags, qualname, self, module, globals, code) \
+    __Pyx_CyFunction_New(__pyx_CyFunctionType, ml, flags, qualname, self, module, globals, code)
 
 static PyObject *__Pyx_CyFunction_New(PyTypeObject *, PyMethodDef *ml,
                                       int flags, PyObject* qualname,
-                                      PyObject *self, PyObject *module,
+                                      PyObject *self,
+                                      PyObject *module, PyObject *globals,
                                       PyObject* code);
 
 static CYTHON_INLINE void *__Pyx_CyFunction_InitDefaults(PyObject *m,
@@ -213,18 +215,11 @@ __Pyx_CyFunction_set_dict(__pyx_CyFunctionObject *op, PyObject *value)
     return 0;
 }
 
-//  TODO: we implicitly use the global module to get func_globals.  This
-//  will need to be passed into __Pyx_CyFunction_NewEx() if we share
-//  this type across modules.  We currently avoid doing this to reduce
-//  the overhead of creating a function object, and to avoid keeping a
-//  reference to the module dict as long as we don't need to.
-
 static PyObject *
-__Pyx_CyFunction_get_globals(CYTHON_UNUSED __pyx_CyFunctionObject *op)
+__Pyx_CyFunction_get_globals(__pyx_CyFunctionObject *op)
 {
-    PyObject* dict = PyModule_GetDict(${module_cname});
-    Py_XINCREF(dict);
-    return dict;
+    Py_INCREF(op->func_globals);
+    return op->func_globals;
 }
 
 static PyObject *
@@ -400,7 +395,7 @@ static PyMethodDef __pyx_CyFunction_methods[] = {
 
 
 static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml, int flags, PyObject* qualname,
-                                      PyObject *closure, PyObject *module, PyObject* code) {
+                                      PyObject *closure, PyObject *module, PyObject* globals, PyObject* code) {
     __pyx_CyFunctionObject *op = PyObject_GC_New(__pyx_CyFunctionObject, type);
     if (op == NULL)
         return NULL;
@@ -418,6 +413,8 @@ static PyObject *__Pyx_CyFunction_New(PyTypeObject *type, PyMethodDef *ml, int f
     op->func_qualname = qualname;
     op->func_doc = NULL;
     op->func_classobj = NULL;
+    op->func_globals = globals;
+    Py_INCREF(op->func_globals);
     Py_XINCREF(code);
     op->func_code = code;
     /* Dynamic Default args */
@@ -440,6 +437,7 @@ __Pyx_CyFunction_clear(__pyx_CyFunctionObject *m)
     Py_CLEAR(m->func_name);
     Py_CLEAR(m->func_qualname);
     Py_CLEAR(m->func_doc);
+    Py_CLEAR(m->func_globals);
     Py_CLEAR(m->func_code);
     Py_CLEAR(m->func_classobj);
     Py_CLEAR(m->defaults_tuple);
@@ -477,6 +475,7 @@ static int __Pyx_CyFunction_traverse(__pyx_CyFunctionObject *m, visitproc visit,
     Py_VISIT(m->func_name);
     Py_VISIT(m->func_qualname);
     Py_VISIT(m->func_doc);
+    Py_VISIT(m->func_globals);
     Py_VISIT(m->func_code);
     Py_VISIT(m->func_classobj);
     Py_VISIT(m->defaults_tuple);
@@ -708,11 +707,12 @@ typedef struct {
     PyObject *self;
 } __pyx_FusedFunctionObject;
 
-#define __pyx_FusedFunction_NewEx(ml, flags, qualname, self, module, code)         \
-        __pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, flags, qualname, self, module, code)
+#define __pyx_FusedFunction_NewEx(ml, flags, qualname, self, module, globals, code)         \
+        __pyx_FusedFunction_New(__pyx_FusedFunctionType, ml, flags, qualname, self, module, globals, code)
 static PyObject *__pyx_FusedFunction_New(PyTypeObject *type,
                                          PyMethodDef *ml, int flags,
-                                         PyObject *qualname, PyObject *self, PyObject *module,
+                                         PyObject *qualname, PyObject *self,
+                                         PyObject *module, PyObject *globals,
                                          PyObject *code);
 
 static int __pyx_FusedFunction_clear(__pyx_FusedFunctionObject *self);
@@ -727,11 +727,12 @@ static int __pyx_FusedFunction_init(void);
 static PyObject *
 __pyx_FusedFunction_New(PyTypeObject *type, PyMethodDef *ml, int flags,
                         PyObject *qualname, PyObject *self,
-                        PyObject *module, PyObject *code)
+                        PyObject *module, PyObject *globals,
+                        PyObject *code)
 {
     __pyx_FusedFunctionObject *fusedfunc =
         (__pyx_FusedFunctionObject *) __Pyx_CyFunction_New(type, ml, flags, qualname,
-                                                           self, module, code);
+                                                           self, module, globals, code);
     if (!fusedfunc)
         return NULL;
 
@@ -789,6 +790,7 @@ __pyx_FusedFunction_descr_get(PyObject *self, PyObject *obj, PyObject *type)
                     ((__pyx_CyFunctionObject *) func)->func_qualname,
                     ((__pyx_CyFunctionObject *) func)->func_closure,
                     ((PyCFunctionObject *) func)->m_module,
+                    ((__pyx_CyFunctionObject *) func)->func_globals,
                     ((__pyx_CyFunctionObject *) func)->func_code);
     if (!meth)
         return NULL;
index c5ea807..1f3d2ae 100644 (file)
@@ -30,5 +30,9 @@ def funcB():
 print("importing...")
 import a, b
 print(type(a.funcA))
+
 assert type(a.funcA).__name__ == 'cython_function_or_method'
 assert type(a.funcA) is type(b.funcB)
+
+assert a.funcA.func_globals is a.__dict__
+assert b.funcB.func_globals is b.__dict__