I'm using cython to expose a C++ library to python, by putting all the wrapper objects and functions in an internal module _pydynd
, then exposing these through a different python module.
I would like to control the name of the module and class that appear in these extension classes, to look like dynd.nd.array
, for example, instead of _pydynd.w_array
, which is the internal name of the wrapper class. Does cython have a mechanism to do this?
I hoped to find something similar to how you can rename C/C++ functions when writing their definitions, but my searches have come up dry. The generated C++ code which should be different is the tp_name
line here:
static PyTypeObject __pyx_type_7_pydynd_w_array = {
PyVarObject_HEAD_INIT(0, 0)
__Pyx_NAMESTR("_pydynd.w_array"), /*tp_name*/
sizeof(struct __pyx_obj_7_pydynd_w_array), /*tp_basicsize*/
UPDATE:
If I try to directly rename the objects, here is what happens:
In [103]: nd.array.__name__
Out[103]: 'w_array'
In [104]: nd.array.__module__
Out[104]: 'dynd._pydynd'
In [105]: nd.array.__name__ = "array"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-105-73d9172a0216> in <module>()
----> 1 nd.array.__name__ = "array"
TypeError: can't set attributes of built-in/extension type 'dynd._pydynd.w_array'
In [106]: nd.array.__module__ = "dynd.nd"
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-106-37f990658ede> in <module>()
----> 1 nd.array.__module__ = "dynd.nd"
TypeError: can't set attributes of built-in/extension type 'dynd._pydynd.w_array'
Cython-0.21 seems to use the location of your .pyx file relative to an __init__.py
file to set the module name.
For file layout
jmap/__init__.py
jmap/client.pyx
the output of cython's compiler includes
#define __Pyx_MODULE_NAME "jmap.client"
moving the location of __init__.py
changes this value. This information may be in the Cython documentation, but I could not find it.
DISCUSSION
This is important to get right to e.g. correctly pickle classes. Specifically a module's concept of its name should be symmetrical with how you import it. This seems obvious, but is easy to break in cython.
Good
>>> from jmap.client import JMapError
>>> JMapError
<class 'jmap.client.JMapError'>
Bad
>>> import jmap
>>> jmap.JMapError
<class 'Client.client.JMapError'>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With