Parent / Child Inheritance Circular Import

19 views
Skip to first unread message

Sebastian

unread,
Apr 26, 2024, 4:19:00 PMApr 26
to cython-users
Hi all, given the following minimal example:
___________
class_a.py:

from typing import TYPE_CHECKING
import cython

if TYPE_CHECKING:
    if cython.compiled:
        from cython.cimports.class_b import B
    else:
        from class_b import B


class A:
    def __init__(self):
        pass
   
    def do_something(self):
        cself = cython.cast(B, self)
        cself.a = 1
        cself.do_something_2()
       
    def do_something_2(self):
        cself = cython.cast(B, self)
        cself.b = 2


___________
class_a.pxd:

cdef class A:
    cpdef void do_something(self)
    cpdef void do_something_2(self)


___________
class_b.py:

from class_a import A

class B(A):
    def __init__(self):
        self.a = 0
        self.b = 0


___________
class_b.pxd:

from class_a cimport A

cdef class B(A):
    cdef public int a
    cdef public int b


_____________________________

This compiles fine using cython 3.0.9 and python 3.11.6.
However, when trying to
from class_b import B
I get an Error:
AttributeError: partially initialized module 'class_b' has no attribute 'B' (most likely due to a circular import)

I got the same error before only using python (without cython) when the TYPE_CHECKING was missing. So TYPE_CHECKING solved the issue for python, but it does not seem to work with cython.

Do you have an idea how to make the example work with cython?

Thanks and best regards,
Sebastian

PS: The example code may seem a bit strange, trying to cast self to B... This is supposed to be a work around, so I can have a child class that inherits methods from a parent class but may have diffferent typed class attributes. I currently don't know if this will work, because I stumbled across the issue described above.

da-woods

unread,
May 1, 2024, 2:33:55 AMMay 1
to cython...@googlegroups.com
Hi,

I don't think `cimports` can happen conditionally, because the cimport information is used during compile-time so I'm not sure putting in an "if" block will solve anything.

What I think will work importing the module rather than the class from the module:

import cython.cimports.class_b as class_b
# (and changing "B" to "class_b.B")

That only requires the module to have been loaded at the point you use it rather than trying to find "B" at the point you import it. So it'll work provided you don't lookup "B" during the init code for your module "class_A" (which you don't).
--

---
You received this message because you are subscribed to the Google Groups "cython-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cython-users...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/cython-users/13f5bc43-b3f0-4a24-809a-9a6bedcfb6d7n%40googlegroups.com.


Reply all
Reply to author
Forward
0 new messages