Skip to content

Conversation

@meawoppl
Copy link
Contributor

@meawoppl meawoppl commented Jan 3, 2026

wxPython is kinda annoying/needy to install, and the way the imports are currently make it tough to use headless w/o installing a bunch of extra stuff. This PR uses an existing environment variable to gate the import of wx to areas of the code that actually use GUI elements.

Quick summary of changes:

  • Add get_wx() in compat.py to gate wx imports behind INTERACTIVE_HTML_BOM_NO_DISPLAY environment variable
  • Allows headless HTML BOM generation without wxPython installed
  • GUI features like --show-dialog still require wx

Usage

INTERACTIVE_HTML_BOM_NO_DISPLAY=1 python -m InteractiveHtmlBom.generate_interactive_bom board.kicad_pcb --no-browser

@meawoppl meawoppl force-pushed the meawoppl/optional-wx-dep branch 2 times, most recently from 64d3670 to 2d0397a Compare January 3, 2026 20:51
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is not needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am honestly a bit confused on how this line of code works now that I look at it. I am not sure how this imports resolves... regardless, it triggers import of the __init__ here I think:
https://github.com/openscopeproject/InteractiveHtmlBom/blob/master/InteractiveHtmlBom/__init__.py

Would you prefer I replace the imports there with the get_wx() singleton or move the import?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not part of the package, it exists solely for convenience where you can just download the repo and drop it as a whole in kicad's plugin dir. KiCad's plugin system will run this init file and the import initializes kicad plugin, that's all it does. This file is irrelevant for cli use case so just leave it unchanged.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense wrt. to the existance of the plugin import, that said, that import will still trigger the __init__.py one folder up so would you prefer I replace the imports there with the get_wx() singleton we add here?

Copy link
Member

@qu1ck qu1ck Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't matter what it triggers, this code does not run when you use ibom in cli mode. Leave it unchanged.

one folder up

This is the topmost level init, there is no one folder up. When you run cli it only uses inner folder as a package, this top level folder may as well not exist.

@meawoppl meawoppl force-pushed the meawoppl/optional-wx-dep branch from 2d0397a to 7c796fe Compare January 4, 2026 22:15
app = wx.App()
if hasattr(wx, "APP_ASSERT_SUPPRESS"):
app.SetAssertMode(wx.APP_ASSERT_SUPPRESS)
elif hasattr(wx, "DisableAsserts"):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be kept.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit confusing as this would nominally only run if not creating a wx app, correct?

I feel like we shouldn't have to disable asserts if not even importing wx...

I can move it into the if create_wx_app block, but I think that would be a behavior change. What is this line of code really about?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kicad's code sometimes throws GUI asserts requiring user input to close even when wx app is not created. This line suppresses that so that the app does not crash or get blocked without a desktop environment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@meawoppl meawoppl force-pushed the meawoppl/optional-wx-dep branch from 7c796fe to db509db Compare January 8, 2026 02:57
@meawoppl
Copy link
Contributor Author

meawoppl commented Jan 8, 2026

I think I got everything, lmk if you want anything else changed/tweaked.

Copy link
Member

@qu1ck qu1ck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested it and it works fine except when wx is not available the error is cryptic.

from .compat import get_wx, should_create_wx_app
wx = get_wx()
create_wx_app = should_create_wx_app()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a check here if wx is None and create_wx_app is true then show an error "wxpython is required unless INTERACTIVE_HTML_BOM_NO_DISPLAY environment variable is set" and exit early.

Add get_wx() in compat.py to gate wx imports behind
INTERACTIVE_HTML_BOM_NO_DISPLAY environment variable.
@meawoppl meawoppl force-pushed the meawoppl/optional-wx-dep branch from db509db to 0581d47 Compare January 11, 2026 01:29
@qu1ck qu1ck merged commit 3c2b236 into openscopeproject:master Jan 11, 2026
@qu1ck
Copy link
Member

qu1ck commented Jan 11, 2026

Thank you for your contribution.

@meawoppl
Copy link
Contributor Author

Np. Thanks for making a nice thing.

I might end up running this on a very large number of boards. Any interest in a port of the formats extractors to Rust? I think this would be a couple afternoons work.

@meawoppl meawoppl deleted the meawoppl/optional-wx-dep branch January 14, 2026 16:34
@qu1ck
Copy link
Member

qu1ck commented Jan 15, 2026

To what end? If you think about performance gains I doubt you will gain much considering more time is spent in kicad bindings than actual python stuff unless it's a very large board.
Also do you have rust bindings for old kicad api? This plugin does not use new api yet and even rust bindings for those are just experimental afaik.

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.

2 participants