Skip to content

Commit 7971c54

Browse files
committed
Improve documentation for scoped enum forward declaration regression test
- Add comprehensive docstring explaining the bug, its impact, and the fix - Document the test setup (two-module scenario) - Update test file comments to explain their role in the regression test
1 parent e0055d9 commit 7971c54

File tree

3 files changed

+64
-20
lines changed

3 files changed

+64
-20
lines changed

tests/test_code_generator.py

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -474,22 +474,49 @@ def test_wrap_ignore_foreign_cimports():
474474

475475
def test_enum_class_forward_declaration(tmpdir):
476476
"""
477-
Test that scoped enums (enum class) do NOT generate incorrect forward declarations.
477+
Regression test: Scoped enums (enum class) must not generate cdef class forward declarations.
478478
479-
This test exposes a bug where scoped enums generate a `cdef class` forward declaration
480-
in the .pxd file, but the actual implementation in the .pyx file is a regular Python
481-
`class` inheriting from `_PyEnum`. This mismatch can cause Cython compilation failures
482-
when another module cimports the enum.
479+
Background
480+
----------
481+
When wrapping a C++ scoped enum (enum class) for use across multiple Python extension
482+
modules, autowrap generates two files:
483483
484-
The issue:
485-
- PXD file generates: `cdef class Status: pass`
486-
- PYX file generates: `class Status(_PyEnum): ...`
484+
1. A .pxd file (Cython declaration file) - used by other modules to cimport symbols
485+
2. A .pyx file (Cython implementation file) - contains the actual Python wrapper code
487486
488-
These are incompatible - you can't have a cdef class forward declaration
489-
that is implemented by a regular Python class.
487+
The Bug
488+
-------
489+
Previously, autowrap generated a `cdef class` forward declaration in the .pxd file
490+
for ALL enums, including scoped enums. However, scoped enums are implemented as
491+
regular Python classes (inheriting from Python's Enum), not as Cython extension types.
490492
491-
When write_pxd is True (multi-module scenario), another module doing
492-
`from EnumModule cimport Status` would expect a cdef class but get a Python class.
493+
This caused a type mismatch:
494+
- .pxd file declared: `cdef class Status: pass` (Cython extension type)
495+
- .pyx file defined: `class Status(_PyEnum): ...` (Python class)
496+
497+
Impact
498+
------
499+
In multi-module scenarios, when Module B tries to use an enum defined in Module A:
500+
501+
# In Module B's .pyx file
502+
from ModuleA cimport Status # Expects cdef class, gets Python class
503+
504+
This mismatch could cause Cython compilation errors or runtime issues.
505+
506+
The Fix
507+
-------
508+
Only generate `cdef class` forward declarations for unscoped enums (which ARE
509+
implemented as cdef classes). Scoped enums don't need forward declarations in
510+
the .pxd file since they're regular Python classes.
511+
512+
Test Setup
513+
----------
514+
This test creates a two-module scenario:
515+
- EnumModule: Defines a scoped enum `Status` and a class `StatusHandler`
516+
- ConsumerModule: Uses the `Status` enum from EnumModule
517+
518+
The test verifies that no `cdef class Status:` forward declaration is generated
519+
in the .pxd file when `Status` is a scoped enum implemented as a Python Enum class.
493520
"""
494521
import shutil
495522
import subprocess

tests/test_files/enum_forward_decl/ConsumerModule.pxd

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
# cython: language_level=3
22
#
3-
# Test file for scoped enum forward declaration issue.
3+
# Test file for scoped enum forward declaration regression test.
44
#
5-
# This file imports the Status enum from EnumModule and uses it
6-
# in a consumer class.
5+
# This module imports and uses the Status enum from EnumModule to verify
6+
# that cross-module enum usage works correctly.
7+
#
8+
# In the buggy version, this module would fail to compile because:
9+
# 1. EnumModule.pxd declared `cdef class Status: pass`
10+
# 2. But EnumModule.pyx defined `class Status(_PyEnum): ...`
11+
# 3. When this module did `from EnumModule cimport Status`, Cython expected
12+
# a cdef class but got a regular Python class
13+
#
14+
# See test_enum_class_forward_declaration() in test_code_generator.py for details.
715
#
816
from EnumModule cimport Status
917

tests/test_files/enum_forward_decl/EnumModule.pxd

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,24 @@
11
# cython: language_level=3
22
#
3-
# Test file for scoped enum forward declaration issue.
3+
# Test file for scoped enum forward declaration regression test.
44
#
5-
# This file declares a scoped enum (cpdef enum class) that will be
6-
# wrapped and used across multiple Cython modules.
5+
# This file is part of a two-module test scenario that verifies autowrap
6+
# correctly handles scoped enums (C++11 enum class) in multi-module builds.
7+
#
8+
# The key issue being tested:
9+
# - Scoped enums are wrapped as Python Enum classes (class Foo(_PyEnum))
10+
# - They should NOT generate `cdef class` forward declarations in .pxd files
11+
# - If they did, other modules trying to cimport them would fail
12+
#
13+
# See test_enum_class_forward_declaration() in test_code_generator.py for details.
714
#
815

916
cdef extern from "EnumModule.hpp":
1017

11-
# Scoped enum - note: NOT attached to any class
12-
# This triggers the forward declaration issue
18+
# Scoped enum (C++11 enum class)
19+
# This gets wrapped as a Python Enum class, NOT a Cython cdef class.
20+
# Therefore, it should NOT have a `cdef class Status: pass` forward
21+
# declaration in the generated .pxd file.
1322
cpdef enum class Status:
1423
OK
1524
ERROR

0 commit comments

Comments
 (0)