Search code examples
pythoncythondistutilssetup.pycythonize

subclassing cython class: pxd file not found when 'cimport'ing


I have just stumbled across some strange behaviour in cython and I am hoping someone will be able to enlighten me.

I have two packages A and B, both built using distutils because I have several cython classes (many of which wrap c++ classes).

In package A I have a cython class that I call BaseAClass forward declared in a .pxd file and fully declared in the corresponding .pyx. I have many other classes that subclass BaseAClass in package A.

Now in package B I have been able to build classes that take a BaseAClass member, simply by doing

# in package B tree, .pyx file
cimport A.stuff._A as _A
cdef BClass(object):
    cdef _A.BaseAClass my_aclass
    def __cinit__(self, aclass):
        self.my_aclass = aclass

and I have no problems compiling and using these classes.

However if I try to subclass BaseAClass in package B:

# in package B tree, .pyx file
cimport A.stuff._A as _A
cdef BClass(_A.BaseAClass):
    """put a constructor here"""

and I try to cythonize I get the error '_A.pxd' not found. However, if I do

# in package B tree, .pyx file
cdef BClass(A.stuff._A.BaseAClass):
    """put a constructor and methods here"""

no problem! Hopefully someone has a clue of what is going on!

Note that when I compile I pass the extra flag "-I /path/to/packageA/stuff" to make sure that the pxd files in package A are available to package B. Also note that I use a similar cythonize.py as used for scipy and that I already have __init__.py files everywhere and I have even tried adding an __init__.pxd file but it didn't help.


Solution

  • The import should be written as from stuff cimport _A where stuff.pxd is a definition file in the same directory as the .pyx file doing the import.

    The line cimport A.stuff._A as _A makes Cython look for a definition file called _A.pxd which is probably unexpected behaviour.

    Cython likely should not accept an import in the form cimport X.sub_package as Y in the first place.