|
21 | 21 | import time
|
22 | 22 | import warnings
|
23 | 23 | from collections.abc import Callable
|
| 24 | +from functools import cache |
24 | 25 | from io import BytesIO, StringIO
|
25 | 26 | from typing import TYPE_CHECKING, Protocol, cast
|
26 | 27 |
|
@@ -271,6 +272,21 @@ def _get_ext_suffix():
|
271 | 272 | return dist_suffix
|
272 | 273 |
|
273 | 274 |
|
| 275 | +@cache # See explanation in docstring. |
| 276 | +def add_gcc_dll_directory() -> None: |
| 277 | + """On Windows, detect and add the location of gcc to the DLL search directory. |
| 278 | +
|
| 279 | + On non-Windows platforms this is a noop. |
| 280 | +
|
| 281 | + The @cache decorator ensures that this function only executes once to avoid |
| 282 | + redundant entries. See <https://github.com/pymc-devs/pytensor/pull/678>. |
| 283 | + """ |
| 284 | + if (sys.platform == "win32") & (hasattr(os, "add_dll_directory")): |
| 285 | + gcc_path = shutil.which("gcc") |
| 286 | + if gcc_path is not None: |
| 287 | + os.add_dll_directory(os.path.dirname(gcc_path)) # type: ignore |
| 288 | + |
| 289 | + |
274 | 290 | def dlimport(fullpath, suffix=None):
|
275 | 291 | """
|
276 | 292 | Dynamically load a .so, .pyd, .dll, or .py file.
|
@@ -320,11 +336,7 @@ def dlimport(fullpath, suffix=None):
|
320 | 336 | _logger.debug(f"module_name {module_name}")
|
321 | 337 |
|
322 | 338 | sys.path[0:0] = [workdir] # insert workdir at beginning (temporarily)
|
323 |
| - # Explicitly add gcc dll directory on Python 3.8+ on Windows |
324 |
| - if (sys.platform == "win32") & (hasattr(os, "add_dll_directory")): |
325 |
| - gcc_path = shutil.which("gcc") |
326 |
| - if gcc_path is not None: |
327 |
| - os.add_dll_directory(os.path.dirname(gcc_path)) |
| 339 | + add_gcc_dll_directory() |
328 | 340 | global import_time
|
329 | 341 | try:
|
330 | 342 | importlib.invalidate_caches()
|
|
0 commit comments