Feature
Several built-in exceptions store their attributes in the instance __dict__ instead of as struct fields, so Exc().__dict__ is non-empty (unlike CPython) and the attributes are not backed by descriptors. SystemExit.code (#8230 / #8282) and StopIteration.value (#8290 / #8301) have been converted already; this issue tracks the rest.
Measured against CPython 3.14.6 (print(exc.__dict__)):
| exception |
leaked into __dict__ |
CPython |
| NameError('m', name='x') |
{'name': 'x'} |
{} |
| AttributeError('m') |
{'name': None, 'obj': None} |
{} |
| ImportError('m') |
{'name': None, 'path': None, 'name_from': None} |
{} |
| SyntaxError('m') |
{'print_file_and_line': None} |
{} |
| SyntaxError('m', (...)) |
+ filename, lineno, offset, text |
{} |
| UnicodeDecodeError(...) |
{'encoding', 'object', 'start', 'end', 'reason'} |
{} |
| UnicodeEncodeError(...) |
same five fields |
{} |
| UnicodeTranslateError(...) |
{'object', 'start', 'end', 'reason'} |
{} |
Their subclasses inherit the same problem (ModuleNotFoundError from ImportError; IndentationError / TabError / _IncompleteInputError from SyntaxError) and should be fixed automatically once the base is converted.
These are the remaining cases of the issue addressed in #8282 and #8301.
SyntaxError already carries a // TODO: members note for this.
Plan
Convert each to a struct field (#[repr(C)] + base field, exposed via #[pygetset]), following the approach established in #8282 and #8301, in separate PRs:
- NameError and AttributeError
- Both are small and use a similar keyword-argument pattern.
- ImportError
- ModuleNotFoundError will inherit the converted fields.
- UnicodeDecodeError, UnicodeEncodeError, and UnicodeTranslateError
- These exceptions share most of their fields, similar to CPython's implementation.
- SyntaxError
- This will also cover IndentationError, TabError, and _IncompleteInputError.
- It is the largest conversion and will require checking the code paths that read these attributes.
Python Documentation or reference to CPython source code
https://docs.python.org/3/library/exceptions.html
These attributes are defined via PyMemberDef (struct members, not instance-dict entries) in CPython's Objects/exceptions.c.
Verified locally against CPython 3.14.6 and RustPython. AI was used to help organize the initial draft; the technical details and final wording were reviewed by me.
Feature
Several built-in exceptions store their attributes in the instance __dict__ instead of as struct fields, so Exc().__dict__ is non-empty (unlike CPython) and the attributes are not backed by descriptors. SystemExit.code (#8230 / #8282) and StopIteration.value (#8290 / #8301) have been converted already; this issue tracks the rest.
Measured against CPython 3.14.6 (print(exc.__dict__)):
Their subclasses inherit the same problem (ModuleNotFoundError from ImportError; IndentationError / TabError / _IncompleteInputError from SyntaxError) and should be fixed automatically once the base is converted.
These are the remaining cases of the issue addressed in #8282 and #8301.
SyntaxError already carries a // TODO: members note for this.
Plan
Convert each to a struct field (#[repr(C)] + base field, exposed via #[pygetset]), following the approach established in #8282 and #8301, in separate PRs:
Python Documentation or reference to CPython source code
https://docs.python.org/3/library/exceptions.html
These attributes are defined via PyMemberDef (struct members, not instance-dict entries) in CPython's Objects/exceptions.c.
Verified locally against CPython 3.14.6 and RustPython. AI was used to help organize the initial draft; the technical details and final wording were reviewed by me.