Skip to content

Commit 3c2b236

Browse files
meawopplqu1ck
authored andcommitted
Make wx dependency optional for CLI usage
Add get_wx() in compat.py to gate wx imports behind INTERACTIVE_HTML_BOM_NO_DISPLAY environment variable.
1 parent 0bf986c commit 3c2b236

File tree

5 files changed

+52
-23
lines changed

5 files changed

+52
-23
lines changed

InteractiveHtmlBom/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
import threading
44
import time
55

6-
import wx
7-
import wx.aui
6+
from .compat import get_wx
87

98

109
def check_for_bom_button():
10+
wx = get_wx()
1111
# From Miles McCoo's blog
1212
# https://kicad.mmccoo.com/2017/03/05/adding-your-own-command-buttons-to-the-pcbnew-gui/
1313
def find_pcbnew_window():

InteractiveHtmlBom/compat.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Compatibility utilities for optional wx dependency."""
2+
3+
import os
4+
5+
_wx = None
6+
7+
8+
def should_create_wx_app():
9+
"""Check if we should create a wx app based on environment."""
10+
return 'INTERACTIVE_HTML_BOM_NO_DISPLAY' not in os.environ
11+
12+
13+
def get_wx():
14+
"""Get the wx module, or None if not available."""
15+
global _wx
16+
if _wx is not None:
17+
return _wx
18+
try:
19+
import wx
20+
_wx = wx
21+
return _wx
22+
except ImportError:
23+
return None

InteractiveHtmlBom/core/config.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
import os
55
import re
66

7-
from wx import FileConfig
8-
9-
from .. import dialog
7+
from ..compat import get_wx
108

119

1210
class Config:
@@ -107,7 +105,7 @@ def load_from_ini(self):
107105
else:
108106
return
109107

110-
f = FileConfig(localFilename=file)
108+
f = get_wx().FileConfig(localFilename=file)
111109

112110
f.SetPath('/html_defaults')
113111
self.dark_mode = f.ReadBool('dark_mode', self.dark_mode)
@@ -170,7 +168,7 @@ def load_from_ini(self):
170168
def save(self, locally):
171169
file = self.local_config_file if locally else self.global_config_file
172170
print('Saving to', file)
173-
f = FileConfig(localFilename=file)
171+
f = get_wx().FileConfig(localFilename=file)
174172

175173
f.SetPath('/html_defaults')
176174
f.WriteBool('dark_mode', self.dark_mode)

InteractiveHtmlBom/core/ibom.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,11 @@
88
import sys
99
from datetime import datetime
1010

11-
import wx
12-
1311
from . import units
1412
from .config import Config
15-
from ..dialog import SettingsDialog
1613
from ..ecad.common import EcadParser, Component
1714
from ..errors import ParsingException
15+
from ..compat import get_wx
1816

1917

2018
class Logger(object):
@@ -38,13 +36,13 @@ def error(self, msg):
3836
if self.cli:
3937
self.logger.error(msg)
4038
else:
41-
wx.MessageBox(msg)
39+
get_wx().MessageBox(msg)
4240

4341
def warn(self, msg):
4442
if self.cli:
4543
self.logger.warning(msg)
4644
else:
47-
wx.LogWarning(msg)
45+
get_wx().LogWarning(msg)
4846

4947

5048
log = None
@@ -341,6 +339,8 @@ def main(parser, config, logger):
341339

342340
def run_with_dialog(parser, config, logger):
343341
# type: (EcadParser, Config, Logger) -> None
342+
from ..dialog import SettingsDialog
343+
344344
def save_config(dialog_panel, locally=False):
345345
config.set_from_dialog(dialog_panel)
346346
config.save(locally)
@@ -358,7 +358,7 @@ def save_config(dialog_panel, locally=False):
358358
if extra_data_file is not None:
359359
dlg.set_extra_data_path(extra_data_file)
360360
config.transfer_to_dialog(dlg.panel)
361-
if dlg.ShowModal() == wx.ID_OK:
361+
if dlg.ShowModal() == get_wx().ID_OK:
362362
config.set_from_dialog(dlg.panel)
363363
main(parser, config, logger)
364364
finally:

InteractiveHtmlBom/generate_interactive_bom.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import argparse
55
import os
66
import sys
7+
78
# Add ../ to the path
89
# Works if this script is executed without installing the module
910
script_dir = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
@@ -23,23 +24,30 @@ def to_utf(s):
2324

2425

2526
def main():
26-
create_wx_app = 'INTERACTIVE_HTML_BOM_NO_DISPLAY' not in os.environ
27-
28-
import wx
29-
30-
if create_wx_app:
31-
app = wx.App()
32-
if hasattr(wx, "APP_ASSERT_SUPPRESS"):
33-
app.SetAssertMode(wx.APP_ASSERT_SUPPRESS)
34-
elif hasattr(wx, "DisableAsserts"):
35-
wx.DisableAsserts()
27+
from .compat import get_wx, should_create_wx_app
28+
wx = get_wx()
29+
create_wx_app = should_create_wx_app()
30+
31+
if wx is None and create_wx_app:
32+
print("wxpython is required unless INTERACTIVE_HTML_BOM_NO_DISPLAY "
33+
"environment variable is set")
34+
sys.exit(1)
35+
36+
if wx is not None:
37+
if create_wx_app:
38+
app = wx.App()
39+
if hasattr(wx, "APP_ASSERT_SUPPRESS"):
40+
app.SetAssertMode(wx.APP_ASSERT_SUPPRESS)
41+
elif hasattr(wx, "DisableAsserts"):
42+
wx.DisableAsserts()
3643

3744
from .core import ibom
3845
from .core.config import Config
3946
from .ecad import get_parser_by_extension
4047
from .version import version
4148
from .errors import (ExitCodes, ParsingException, exit_error)
4249

50+
4351
parser = argparse.ArgumentParser(
4452
description='KiCad InteractiveHtmlBom plugin CLI.',
4553
formatter_class=argparse.ArgumentDefaultsHelpFormatter)

0 commit comments

Comments
 (0)