Hello,

I've found an issue with class module names, which do not respect the package 
hierarchy.

With foo.py containing:

  class Foo:
      pass

>>> import foo
>>> foo
<module 'foo' from 'foo.py'>
>>> foo.Foo().__module__
'foo'

Now compiled through Cython:

>>> import foo
>>> foo
<module 'foo' from 'foo.pyd'>
>>> foo.Foo().__module__
'foo'

Same behaviour. Perfect.

Now if I move it into a package:

>>> import pkg.foo
>>> pkg.foo
<module 'pkg.foo' from 'pkg\foo.pyc'>
>>> pkg.foo.Foo().__module__
'pkg.foo'

And through Cython:

>>> import pkg.foo
>>> pkg.foo
<module 'pkg.foo' from 'pkg\foo.pyd'>
>>> pkg.foo.Foo().__module__
'foo'    ### ERROR: should have been 'pkg.foo'


To solve it, I patch the generated code to get the module name through the 
module:

static PyObject *__Pyx_CreateClass(
    PyObject *bases, PyObject *dict, PyObject *name, char *modname) {
    PyObject *py_modname;
    PyObject *result = 0;

    #if PY_MAJOR_VERSION < 3
    //SD py_modname = PyString_FromString(modname)
    py_modname = PyObject_GetAttrString(__pyx_m, "__name__");
    #else
    py_modname = PyUnicode_FromString(modname);
    #endif
    if (!py_modname)
        goto bad;
    if (PyDict_SetItemString(dict, "__module__", py_modname) < 0)
        goto bad;
    #if PY_MAJOR_VERSION < 3
    result = PyClass_New(bases, dict, name);
    #else
    result = PyObject_CallFunctionObjArgs((PyObject *)&PyType_Type, name, 
bases, dict, NULL);
    #endif
bad:
    Py_XDECREF(py_modname);
    return result;
}

Notes:
 - I assume the patch is also compatible with 3.x, but I haven't tested it.
 - parameter "modname" is no more needed.
 - I could have patched Cython directly, but it's simpler for me to "sed" the 
generated code.

Cheers,
Stephane

_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to