Skip to content

Python binding: remove global ErrorCodes dependency from checkError success path#237

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-global-usage-in-del-method
Draft

Python binding: remove global ErrorCodes dependency from checkError success path#237
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-global-usage-in-del-method

Conversation

Copy link

Copilot AI commented Feb 23, 2026

lib3mf users reported noisy shutdown-time exceptions from generated Python bindings (Base.__del__ReleasecheckError) when module globals were already torn down. The failure was caused by dereferencing ErrorCodes.SUCCESS during interpreter finalization.

  • Change

    • Updated Python binding generation in Source/buildbindingpython.go to avoid enum/global lookup for the success case.
    • Generated checkError now compares directly against the numeric success code (0) instead of ErrorCodes.SUCCESS.value.
  • Why this addresses the issue

    • The destructor path can run during interpreter shutdown, where global symbols may be None/unavailable.
    • Using a literal success code removes that teardown-sensitive dependency while preserving behavior.
  • Generated code delta

    # before
    if errorCode != ErrorCodes.SUCCESS.value:
    
    # after
    if errorCode != 0:
Original prompt

This section details on the original issue you should resolve

<issue_title>Python binding: Avoid using globals in Base.del()</issue_title>
<issue_description>Running 'build123d' examples I saw errors like

Exception ignored in: <function _Base.__del__ at 0x123e68180>
Traceback (most recent call last):
  File "venv/lib/python3.13/site-packages/lib3mf/Lib3MF.py", line 57, in __del__
  File "venv/lib/python3.13/site-packages/lib3mf/Lib3MF.py", line 6832, in Release
  File "venv/lib/python3.13/site-packages/lib3mf/Lib3MF.py", line 6767, in checkError
AttributeError: 'NoneType' object has no attribute 'SUCCESS'

This is error from the "lib3mf" package, and the by "AutomaticComponentToolkit" generated file lib3mf/Autogenerated/Bindings/Python/Lib3MF.py.

This file has been generated by the Automatic Component Toolkit (ACT) version 1.8.0-alpha.

This seems to happen in some situations when the Python script terminates. The error message is most likely harmless, but it is confusing as a user to see this error message and not knowing if things went ok or not.

Looking at the code, the class Base __del__() method calls _wrapper.Release() that calls checkError(). The problem seems to be that when Python cleans up, it might remove the class ErrorCodes before it try remove the class Base, i.e. ErrorCodes is no longer defined. This is likely what gives the error above. This problem is documented at

https://docs.python.org/3.9/reference/datamodel.html#object.__del__

Could the solution be to change the __del__() call to an __exit__() call ? It makes the error message go away but I don't know if it is the right thing to do.

As this happens when terminating, another solution might be to replace the line

if errorCode != ErrorCodes.SUCCESS.value:

with

if ErrorCodes and errorCode != ErrorCodes.SUCCESS.value:

This feels more like a hack and I haven't tested this.</issue_description>

Comments on the Issue (you are @copilot in this section)


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: martinweismann <30837766+martinweismann@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix global usage in Base.__del__() to avoid errors Python binding: remove global ErrorCodes dependency from checkError success path Feb 23, 2026
Copilot AI requested a review from martinweismann February 23, 2026 11:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python binding: Avoid using globals in Base.__del__()

2 participants