question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Handling cdef class inheritance and circular cimports

See original GitHub issue

I have the following simplified scenario for my game engine I am writing in cython. I have an “App” cdef class that is responsible for processing a list of “System” cdef class objects. I would like each “System” object to have a reference back to its parent “App” object that it belongs to. The “System” cdef class has some basic functions, and I want to extend this class in sub-cdef-classes (e.g. “GraphicsSystem”, “AudioSystem”, “PhysicsSystem”, etc.). This boils down to the following code:

#system.pxd
from pyorama.app cimport *

cdef class System:
    cdef App app
    
    cpdef void init(self)
    cpdef void quit(self)
    cpdef void update(self)

#system.pyx
cdef class System:
    
    def __init__(self):
        self.app = None
    
    cpdef void init(self): print("system init")
    cpdef void quit(self): print("system quit")
    cpdef void update(self): print("system update")
#graphics_system.pxd
from pyorama.system cimport *

cdef class GraphicsSystem(System):
    pass

#graphics_system.pyx
cdef class GraphicsSystem(System):
    pass
#app.pxd
from pyorama.graphics_system cimport *
cdef class App:
    pass

#app.pyx
cdef class App:
    pass

Attempting to compile this yields the following error message during the cythonization phase:

anish@laptop:~/Documents/Programming/cython/inheritance$ python3 setup.py build_ext -i
Compiling ./pyorama/graphics_system.pyx because it depends on ./pyorama/system.pxd.
Compiling ./pyorama/app.pyx because it depends on ./pyorama/system.pxd.
Compiling ./pyorama/system.pyx because it changed.
[1/3] Cythonizing ./pyorama/system.pyx

Error compiling Cython file:
------------------------------------------------------------
...
from pyorama.system cimport *

cdef class GraphicsSystem(System):
    ^
------------------------------------------------------------

pyorama/graphics_system.pxd:3:5: Compiler crash in AnalyseDeclarationsTransform

ModuleNode.body = StatListNode(graphics_system.pxd:1:0)
StatListNode.stats[1] = CClassDefNode(graphics_system.pxd:3:5,
    as_name = 'GraphicsSystem',
    class_name = 'GraphicsSystem',
    in_pxd = True,
    module_name = '',
    visibility = 'private')

Compiler crash traceback from this point on:
  File "Cython/Compiler/Visitor.py", line 180, in Cython.Compiler.Visitor.TreeVisitor._visit
  File "/home/anish/.local/lib/python3.6/site-packages/Cython/Compiler/ParseTreeTransforms.py", line 1621, in visit_CClassDefNode
    node = self.visit_ClassDefNode(node)
  File "Cython/Compiler/Visitor.py", line 383, in Cython.Compiler.Visitor.EnvTransform.visit_ClassDefNode
AttributeError: 'CClassDefNode' object has no attribute 'scope'

Error compiling Cython file:
------------------------------------------------------------
...
from pyorama.system cimport *

cdef class GraphicsSystem(System):
    ^
------------------------------------------------------------

pyorama/graphics_system.pxd:3:5: C class 'GraphicsSystem' already defined
Traceback (most recent call last):
  File "setup.py", line 66, in <module>
    compiler_directives=directives,
  File "/home/anish/.local/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1097, in cythonize
    cythonize_one(*args)
  File "/home/anish/.local/lib/python3.6/site-packages/Cython/Build/Dependencies.py", line 1220, in cythonize_one
    raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: ./pyorama/system.pyx

Commenting out the cimport in the “App” allows the code to compile, and using the “GraphicsSystem” cdef class in other cython modules works without issue. Similarly, cimporting “System” into the app.pxd file works without issues; it appears that just the subclass causes issues during compilation. Any help would be appreciated!

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
DeathDragon7050commented, Sep 15, 2020

Hi thanks for responding. I’ve tried to cut down the code to as basic as possible and it fits your example basically exactly. I guess all we can hope for is it to be patched. I am not sure if it is the same issue but basically my code is useless because this appears to affect all of the files in my project. It seems I am unable to properly cimport any extension types and subclass them. Only solution I can really see is to put all the contents of every file into one file which obviously really is not something that is ideal. By the way, your game engine looks really cool, well done.

0reactions
AnishNcommented, Sep 15, 2020

Just tested out that old code and it still gives me the same issues as before. I have attached it as a zip file if anyone wants to try and compile it. Interestingly, adding an __init__.py file changes the error message from pyorama/graphics_system.pyx:2:26: First base of 'GraphicsSystem' is not an extension type to pyorama/graphics_system.pxd:4:5: C class 'GraphicsSystem' already defined.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Extension Types — Cython 3.0.0a11 documentation
You define an extension type using the cdef class statement or decorating the class with ... import cython from cython.cimports.my_module import Shrubbery ...
Read more >
Python circular imports with inheritance
The obvious solution is to put both classes into the same file (same module ). They are tightly related, so it makes perfect...
Read more >
Extension types (aka. cdef classes) - 《Cython 0.29.6 ...
Normal Python classes can inherit from cdef classes, but not the other way around. ... from libc.math cimport sin; cdef class Function: ...
Read more >
[Cython] Cython circular cdef import patch
imports. It does NOT solve python circular import issues. ... b.pyx or a.pyx (such as to instantiate a class). ... line. This enables...
Read more >
Cython - Ocean Ode
FIRST stage is handled by cythonize cmd, compiling Cython source ... direct Python/C API creation is not for the uninitiated, hence Cython cdef...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found