Skip to content

Commit 3ced905

Browse files
committed
CI: fix doe import on case-sensitive FS
1 parent d7706f7 commit 3ced905

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

UQPyL/__init__.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
sys.modules.setdefault(__name__ + ".doe", _doe_mod)
2727
sys.modules.setdefault(__name__ + ".DoE", _doe_mod)
2828

29-
# Import subpackages after the shim so downstream imports won't crash.
30-
from . import problem, surrogate, optimization, analysis, util, inference # noqa: E402,F401
31-
32-
# Keep `doe` attribute if available
33-
doe = _doe_mod # noqa: E402
29+
# NOTE:
30+
# Do NOT eagerly import heavy subpackages here (e.g. surrogate.mars contains
31+
# optional compiled extensions). Eager imports can break CI environments where
32+
# some compiled wheels are not available (e.g. cp38-only extensions on cp39).
33+
# Instead, we provide lazy attribute access via __getattr__.
3434

3535
__version__ = "2.1.4"
3636
__author__ = "wmtSky"
@@ -43,4 +43,24 @@
4343
"doe",
4444
"inference",
4545
"util"
46-
]
46+
]
47+
48+
49+
def __getattr__(name):
50+
"""
51+
Lazy import of top-level subpackages.
52+
This keeps `import UQPyL` lightweight and robust across platforms.
53+
"""
54+
if name in __all__:
55+
if name == "doe":
56+
# Prefer the already-resolved module (doe/DoE shim)
57+
if _doe_mod is not None:
58+
return _doe_mod
59+
mod = importlib.import_module(__name__ + "." + name)
60+
globals()[name] = mod
61+
return mod
62+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
63+
64+
65+
def __dir__():
66+
return sorted(list(globals().keys()) + __all__)

UQPyL/surrogate/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
from . import fnn
55
from . import gp
66
from . import kriging
7-
from . import mars
87
from . import svr
98
from . import fnn
10-
from .auto_tuner import AutoTuner
9+
from .auto_tuner import AutoTuner
10+
11+
# MARS depends on optional compiled extensions under `surrogate/mars/core`.
12+
# They may not be available for all Python versions in CI (e.g. cp38-only wheels).
13+
try: # pragma: no cover
14+
from . import mars # noqa: F401
15+
except Exception: # pragma: no cover
16+
mars = None

UQPyL/surrogate/mars/__init__.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,24 @@
1-
from .mars import MARS
1+
"""
2+
MARS surrogate model.
3+
4+
This subpackage uses optional compiled extensions in `UQPyL.surrogate.mars.core`.
5+
If the extensions are not available for the current Python version/platform,
6+
importing MARS will fail. We keep the import optional so other parts of UQPyL
7+
can still be used (and tested) without MARS.
8+
"""
9+
10+
try: # pragma: no cover
11+
from .mars import MARS # noqa: F401
12+
except Exception as e: # pragma: no cover
13+
MARS = None
14+
_IMPORT_ERROR = e
15+
16+
def __getattr__(name):
17+
if name == "MARS":
18+
raise ImportError(
19+
"UQPyL.surrogate.mars.MARS requires compiled extensions under "
20+
"`UQPyL/surrogate/mars/core` for your Python version/platform. "
21+
"Please build/install wheels for your interpreter (e.g. cp39) "
22+
"or use Python 3.8 where prebuilt binaries exist."
23+
) from _IMPORT_ERROR
24+
raise AttributeError(name)

0 commit comments

Comments
 (0)