From 744dbfae14a063ca3a2e6a4fa11041659da50786 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 07:41:34 +0000 Subject: [PATCH 1/3] Initial plan From 1ee1b372a68de57775646367c3e4519806eb8c39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 07:45:20 +0000 Subject: [PATCH 2/3] Fix cross-platform init: guard os.add_dll_directory for Windows, use os.pathsep, add MIKEPLUSPY_INSTALL_BIN env var Co-authored-by: ryan-kipawa <74630349+ryan-kipawa@users.noreply.github.com> --- mikeplus/__init__.py | 1 + mikeplus/utils.py | 21 +++++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/mikeplus/__init__.py b/mikeplus/__init__.py index 5b0064d..0bac2ea 100644 --- a/mikeplus/__init__.py +++ b/mikeplus/__init__.py @@ -26,6 +26,7 @@ fallback_mikeplus_install_root=Path("C:/Program Files (x86)/DHI/MIKE+/2026"), env_var_name_install_root="MIKEPLUSPY_INSTALL_ROOT", # set this environment variable to use custom install path bin_path=Path("bin/x64"), + env_var_name_bin_path="MIKEPLUSPY_INSTALL_BIN", # set this environment variable to use a custom bin path suffix (e.g. 'bin/x64') ) # keep here for backward compatibility (mikeio1d uses) ... remove in 2026.0.0 diff --git a/mikeplus/utils.py b/mikeplus/utils.py index 69b46af..27962b6 100644 --- a/mikeplus/utils.py +++ b/mikeplus/utils.py @@ -20,6 +20,7 @@ def setup_bin_path( fallback_mikeplus_install_root: Path, env_var_name_install_root: str, bin_path: Path, + env_var_name_bin_path: str = "MIKEPLUSPY_INSTALL_BIN", ) -> tuple[Path | None, Any]: """Set up the bin path for mikepluspy.""" global _setup_called @@ -30,6 +31,11 @@ def setup_bin_path( fallback_mikeplus_install_root = Path(fallback_mikeplus_install_root) bin_path = Path(bin_path) + env_var_bin_path: str | None = os.getenv(env_var_name_bin_path) + if env_var_bin_path is not None: + # env var specifies the relative bin path suffix, e.g. 'bin/x64' + bin_path = Path(env_var_bin_path) + # bin path for DHI.Mike.Install (required for versions before MIKE+ 2025 Update 1) sys.path.append(str(Path(__file__).parent / "bin")) @@ -66,12 +72,12 @@ def _try_setup_custom_bin_path( _update_python_env_path([str(mikeplus_install_bin)]) _update_clr_assembly_resolve(str(mikeplus_install_bin)) - dll_dir_handle = os.add_dll_directory(str(mikeplus_install_bin)) # type: ignore + dll_dir_handle = os.add_dll_directory(str(mikeplus_install_bin)) if sys.platform == "win32" else None # type: ignore return mikeplus_install_root, dll_dir_handle def _update_python_env_path(mikeplus_env_paths: list[str]): - os.environ["PATH"] = ";".join(mikeplus_env_paths) + ";" + os.environ["PATH"] + os.environ["PATH"] = os.pathsep.join(mikeplus_env_paths) + os.pathsep + os.environ["PATH"] def _update_clr_assembly_resolve(mikeplus_install_bin: str): @@ -97,12 +103,12 @@ def _try_mike_install_bin_setup(major_assembly_version: int): # MikeImport adds install bin to end of PATH, this brings it to the front env_path = System.Environment.GetEnvironmentVariable("PATH") - all_paths = [Path(p) for p in env_path.split(";")] + all_paths = [Path(p) for p in env_path.split(os.pathsep)] mikeplus_env_paths = [ str(p) for p in all_paths if p.is_relative_to(mikeplus_install_root) ] _update_python_env_path(mikeplus_env_paths) - dll_dir_handle = os.add_dll_directory(str(mikeplus_env_paths[0])) # type: ignore + dll_dir_handle = os.add_dll_directory(str(mikeplus_env_paths[0])) if sys.platform == "win32" else None # type: ignore return mikeplus_install_root, dll_dir_handle except Exception: return None, None @@ -127,9 +133,12 @@ def _try_setup_default_bin_path( ) _update_python_env_path([str(fallback_mikeplus_install_root / bin_path)]) _update_clr_assembly_resolve(str(fallback_mikeplus_install_root / bin_path)) - return fallback_mikeplus_install_root, os.add_dll_directory( # type: ignore - str(fallback_mikeplus_install_root / bin_path) + dll_dir_handle = ( + os.add_dll_directory(str(fallback_mikeplus_install_root / bin_path)) # type: ignore + if sys.platform == "win32" + else None ) + return fallback_mikeplus_install_root, dll_dir_handle def to_sql(value) -> str: From 8dd2f5a6067ed57d3dffc32c6eae28e88ed0bd99 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 07:56:49 +0000 Subject: [PATCH 3/3] Address PR review: simplify bin path env var, add warning messages for all setup_bin_path outcomes Co-authored-by: ryan-kipawa <74630349+ryan-kipawa@users.noreply.github.com> --- mikeplus/__init__.py | 5 +++-- mikeplus/utils.py | 22 ++++++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/mikeplus/__init__.py b/mikeplus/__init__.py index 0bac2ea..df41306 100644 --- a/mikeplus/__init__.py +++ b/mikeplus/__init__.py @@ -19,14 +19,15 @@ ) import clr # noqa: E402 +import os # noqa: E402 + from .utils import setup_bin_path as _setup_bin_path # noqa: E402 _install_root, _dll_dir_handle = _setup_bin_path( major_assembly_version=24, fallback_mikeplus_install_root=Path("C:/Program Files (x86)/DHI/MIKE+/2026"), env_var_name_install_root="MIKEPLUSPY_INSTALL_ROOT", # set this environment variable to use custom install path - bin_path=Path("bin/x64"), - env_var_name_bin_path="MIKEPLUSPY_INSTALL_BIN", # set this environment variable to use a custom bin path suffix (e.g. 'bin/x64') + bin_path=Path(os.getenv("MIKEPLUSPY_INSTALL_BIN", "bin/x64")), # set MIKEPLUSPY_INSTALL_BIN to use a custom bin path suffix (e.g. 'bin/x64') ) # keep here for backward compatibility (mikeio1d uses) ... remove in 2026.0.0 diff --git a/mikeplus/utils.py b/mikeplus/utils.py index 27962b6..cea39c7 100644 --- a/mikeplus/utils.py +++ b/mikeplus/utils.py @@ -20,7 +20,6 @@ def setup_bin_path( fallback_mikeplus_install_root: Path, env_var_name_install_root: str, bin_path: Path, - env_var_name_bin_path: str = "MIKEPLUSPY_INSTALL_BIN", ) -> tuple[Path | None, Any]: """Set up the bin path for mikepluspy.""" global _setup_called @@ -31,11 +30,6 @@ def setup_bin_path( fallback_mikeplus_install_root = Path(fallback_mikeplus_install_root) bin_path = Path(bin_path) - env_var_bin_path: str | None = os.getenv(env_var_name_bin_path) - if env_var_bin_path is not None: - # env var specifies the relative bin path suffix, e.g. 'bin/x64' - bin_path = Path(env_var_bin_path) - # bin path for DHI.Mike.Install (required for versions before MIKE+ 2025 Update 1) sys.path.append(str(Path(__file__).parent / "bin")) @@ -67,9 +61,16 @@ def _try_setup_custom_bin_path( mikeplus_install_bin = mikeplus_install_root / bin_path if not mikeplus_install_bin.exists(): raise FileNotFoundError( - f"{env_var_name_install_root} {bin_path} does not exist: {mikeplus_install_bin}" + f"{env_var_name_install_root}={env_var_install_root!r}: bin path does not exist: '{mikeplus_install_bin}'. " + f"Ensure the path is correct or unset {env_var_name_install_root} to use auto-detection." ) + warnings.warn( + f"Using custom MIKE+ installation from {env_var_name_install_root}='{mikeplus_install_root}' " + f"(bin: '{mikeplus_install_bin}').", + category=UserWarning, + stacklevel=2, + ) _update_python_env_path([str(mikeplus_install_bin)]) _update_clr_assembly_resolve(str(mikeplus_install_bin)) dll_dir_handle = os.add_dll_directory(str(mikeplus_install_bin)) if sys.platform == "win32" else None # type: ignore @@ -110,7 +111,12 @@ def _try_mike_install_bin_setup(major_assembly_version: int): _update_python_env_path(mikeplus_env_paths) dll_dir_handle = os.add_dll_directory(str(mikeplus_env_paths[0])) if sys.platform == "win32" else None # type: ignore return mikeplus_install_root, dll_dir_handle - except Exception: + except Exception as e: + warnings.warn( + f"DHI.Mike.Install auto-detection failed ({e}). Falling back to default MIKE+ installation path.", + category=UserWarning, + stacklevel=2, + ) return None, None