From 50b6c8d1b6773d181a4b751789c8c26caf75593b Mon Sep 17 00:00:00 2001 From: Moritz Frey Date: Fri, 5 Dec 2025 12:56:23 +0100 Subject: [PATCH 1/5] Add utilities for remote cubit execution --- src/cubitpy/conf.py | 58 ++++++++++++++++++- .../cubit_wrapper/cubit_wrapper_host.py | 12 ++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/cubitpy/conf.py b/src/cubitpy/conf.py index f018e95..b776f0d 100644 --- a/src/cubitpy/conf.py +++ b/src/cubitpy/conf.py @@ -26,8 +26,11 @@ import glob import os import shutil +import warnings from sys import platform +import yaml + from cubitpy.cubitpy_types import ( BoundaryConditionType, CubitItems, @@ -85,8 +88,56 @@ def __init__(self): @staticmethod def get_cubit_root_path(**kwargs): """Get Path to cubit root directory.""" + if cupy.is_remote(): + warnings.warn( + "Cubit is running in remote mode because CUBIT_REMOTE_CONFIG_FILE is set. " + "The remote Cubit installation will be used, and the local CUBIT_ROOT " + "setting is ignored.", + UserWarning, + ) return get_path("CUBIT_ROOT", os.path.isdir, **kwargs) + @staticmethod + def get_cubit_remote_config_filepath(): + """Return path to remote config if it exists, else None.""" + return get_path("CUBIT_REMOTE_CONFIG_FILE", os.path.isfile, throw_error=False) + + @classmethod + def get_cubit_remote_config(cls): + """Load (user, host, remote_cubit_root) from YAML config.""" + TEMPLATE = ( + "\nExpected YAML format:\n" + "----------------------------------------\n" + "remote:\n" + ' user: ""\n' + ' host: ""\n' + " remote_cubit_root: \n" + "----------------------------------------\n" + ) + + def fail(msg): + """Helper to raise error with template.""" + raise RuntimeError(msg + TEMPLATE) + + path = cls.get_cubit_remote_config_filepath() + if not path: + fail("Config file not found.") + + try: + with open(path, "r") as f: + data = yaml.safe_load(f) + except Exception as e: + fail(f"Failed to read YAML at '{path}': {e}") + + remote = data.get("remote") if isinstance(data, dict) else None + if not remote: + fail("Missing 'remote' section.") + + try: + return remote["user"], remote["host"], remote["remote_cubit_root"] + except KeyError as k: + fail(f"Missing key: {k.args[0]}") + @classmethod def get_cubit_exe_path(cls, **kwargs): """Get Path to cubit executable.""" @@ -154,11 +205,16 @@ def get_cubit_interpreter(cls): def is_coreform(cls): """Return if the given path is a path to cubit coreform.""" cubit_root = cls.get_cubit_root_path() - if "15.2" in cubit_root: + if "15.2" in cubit_root and not cls.is_remote(): return False else: return True + @classmethod + def is_remote(cls): + """Return True if a remote config path is defined.""" + return cls.get_cubit_remote_config_filepath() is not None + # Global object with options for cubitpy. cupy = CubitOptions() diff --git a/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py b/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py index adc1a88..d11cd30 100644 --- a/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py +++ b/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py @@ -64,6 +64,18 @@ def __init__( Python interpreter to be used for running cubit. """ + # ------------------------------------------------------------------ + # Remote mode – run cubit on a remote machine via SSH + # ------------------------------------------------------------------ + if cupy.is_remote(): + raise NotImplementedError("Remote cubit mode is not yet implemented.") + + return + + # ------------------------------------------------------------------ + # Local mode – run cubit on the local machine + # ------------------------------------------------------------------ + if interpreter is None: interpreter = f"popen//python={cupy.get_cubit_interpreter()}" From a6efb5c990232966d658768d2df130618fd325c0 Mon Sep 17 00:00:00 2001 From: Moritz Frey Date: Tue, 9 Dec 2025 17:10:50 +0100 Subject: [PATCH 2/5] Introduce cubitpy config file --- src/cubitpy/conf.py | 145 +++++++++++++----- .../cubit_wrapper/cubit_wrapper_host.py | 114 +++++++------- src/cubitpy/cubitpy.py | 31 +++- 3 files changed, 186 insertions(+), 104 deletions(-) diff --git a/src/cubitpy/conf.py b/src/cubitpy/conf.py index b776f0d..0533ba8 100644 --- a/src/cubitpy/conf.py +++ b/src/cubitpy/conf.py @@ -27,6 +27,7 @@ import os import shutil import warnings +from pathlib import Path from sys import platform import yaml @@ -56,6 +57,8 @@ def get_path(environment_variable, test_function, *, throw_error=True): class CubitOptions(object): """Object for types in cubitpy.""" + _CONFIG = None + def __init__(self): # Temporary directory for cubitpy. self.temp_dir = os.path.join( @@ -88,60 +91,121 @@ def __init__(self): @staticmethod def get_cubit_root_path(**kwargs): """Get Path to cubit root directory.""" - if cupy.is_remote(): - warnings.warn( - "Cubit is running in remote mode because CUBIT_REMOTE_CONFIG_FILE is set. " - "The remote Cubit installation will be used, and the local CUBIT_ROOT " - "setting is ignored.", - UserWarning, - ) + warnings.warn( + "Using CUBIT_ROOT for locating the local Cubit installation is deprecated. " + "Please define 'local_config.cubit_path' in your cubitpy configuration YAML. ", + DeprecationWarning, + ) return get_path("CUBIT_ROOT", os.path.isdir, **kwargs) @staticmethod - def get_cubit_remote_config_filepath(): + def get_cubit_config_filepath(): """Return path to remote config if it exists, else None.""" - return get_path("CUBIT_REMOTE_CONFIG_FILE", os.path.isfile, throw_error=False) + return get_path("CUBITPY_CONFIG_PATH", os.path.isfile, throw_error=False) @classmethod - def get_cubit_remote_config(cls): - """Load (user, host, remote_cubit_root) from YAML config.""" + def validate_cubit_config(cls): + """Validate the already loaded config dict and raise helpful errors.""" + + cfg = cls._CONFIG + if cfg is None: + raise RuntimeError( + "Config not loaded yet. Call cupy.get_cubit_config(...) first." + ) + TEMPLATE = ( - "\nExpected YAML format:\n" + "\n\nCorrect YAML structure:\n" "----------------------------------------\n" - "remote:\n" + 'cubitpy_mode: "remote" # or "local"\n' + "\n" + "remote_config:\n" ' user: ""\n' ' host: ""\n' - " remote_cubit_root: \n" + ' cubit_path: ""\n' + "\n" + "local_config:\n" + ' cubit_path: ""\n' + "----------------------------------------\n" + "- If mode = 'remote': remote_config MUST exist and contain user, host, cubit_path.\n" + "- If mode = 'local' : local_config MUST exist and contain cubit_path.\n" + "- The unused section may be omitted.\n" "----------------------------------------\n" ) - def fail(msg): - """Helper to raise error with template.""" + def fail(msg: str): + """Helper to raise a RuntimeError with template.""" raise RuntimeError(msg + TEMPLATE) - path = cls.get_cubit_remote_config_filepath() - if not path: - fail("Config file not found.") + # Check mode + if "cubitpy_mode" not in cfg: + fail("Missing required key: 'cubitpy_mode'.") + + mode = cfg["cubitpy_mode"] + if mode not in ("remote", "local"): + fail(f"Invalid cubitpy_mode '{mode}'. Expected 'remote' or 'local'.") + + if mode == "remote": + if "remote_config" not in cfg: + fail("cubitpy_mode='remote' requires a 'remote_config' section.") + + rcfg = cfg["remote_config"] + required = ["user", "host", "cubit_path"] + missing = [k for k in required if k not in rcfg or not rcfg[k]] + if missing: + fail("remote_config is missing required fields: " + ", ".join(missing)) + + if mode == "local": + if "local_config" not in cfg: + fail("cubitpy_mode='local' requires a 'local_config' section.") - try: - with open(path, "r") as f: - data = yaml.safe_load(f) - except Exception as e: - fail(f"Failed to read YAML at '{path}': {e}") + lcfg = cfg["local_config"] + if "cubit_path" not in lcfg or not lcfg["cubit_path"]: + fail("local_config must contain a non-empty 'cubit_path'.") - remote = data.get("remote") if isinstance(data, dict) else None - if not remote: - fail("Missing 'remote' section.") + local_cubit_path = lcfg["cubit_path"] + if not Path(local_cubit_path).expanduser().exists(): + raise FileNotFoundError( + f"local_config.cubit_path '{local_cubit_path}' does not exist." + ) + + @classmethod + def load_cubit_config(cls, config_path: Path | None = None): + """Read the CubitPy YAML config.""" + + if config_path is None: + config_path = cls.get_cubit_config_filepath() + + if not config_path: + warnings.warn( + "CubitPy configuration file not found." "Using default config: local", + DeprecationWarning, + ) + root_path = cls.get_cubit_root_path(throw_error=True) + + default_cfg = { + "cubitpy_mode": "local", + "local_config": {"cubit_path": root_path}, + "remote_config": {}, + } + + cubit_config_dict = default_cfg + else: + try: + with open(config_path, "r") as f: + cubit_config_dict = yaml.safe_load(f) + except Exception as e: + raise ImportError(f"Failed to read YAML at '{config_path}': {e}") + + if not isinstance(cubit_config_dict, dict): + raise ImportError("YAML top level must be a mapping (dict).") - try: - return remote["user"], remote["host"], remote["remote_cubit_root"] - except KeyError as k: - fail(f"Missing key: {k.args[0]}") + cls._CONFIG = cubit_config_dict + cls.validate_cubit_config() @classmethod def get_cubit_exe_path(cls, **kwargs): """Get Path to cubit executable.""" - cubit_root = cls.get_cubit_root_path(**kwargs) + cubit_root = cls._CONFIG["local_config"]["cubit_path"] if platform == "linux" or platform == "linux2": if cupy.is_coreform(): return os.path.join(cubit_root, "bin", "coreform_cubit") @@ -159,7 +223,7 @@ def get_cubit_exe_path(cls, **kwargs): @classmethod def get_cubit_lib_path(cls, **kwargs): """Get Path to cubit lib directory.""" - cubit_root = cls.get_cubit_root_path(**kwargs) + cubit_root = cls._CONFIG["local_config"]["cubit_path"] if platform == "linux" or platform == "linux2": return os.path.join(cubit_root, "bin") elif platform == "darwin": @@ -173,7 +237,7 @@ def get_cubit_lib_path(cls, **kwargs): @classmethod def get_cubit_interpreter(cls): """Get the path to the python interpreter to be used for CubitPy.""" - cubit_root = cls.get_cubit_root_path() + cubit_root = cls._CONFIG["local_config"]["cubit_path"] if cls.is_coreform(): pattern = "**/python3" full_pattern = os.path.join(cubit_root, pattern) @@ -204,16 +268,21 @@ def get_cubit_interpreter(cls): @classmethod def is_coreform(cls): """Return if the given path is a path to cubit coreform.""" - cubit_root = cls.get_cubit_root_path() + cubit_root = cls._CONFIG["local_config"]["cubit_path"] if "15.2" in cubit_root and not cls.is_remote(): return False else: return True @classmethod - def is_remote(cls): - """Return True if a remote config path is defined.""" - return cls.get_cubit_remote_config_filepath() is not None + def is_remote(cls) -> bool: + """Return True if cubit is running remotely based on the loaded + config.""" + if cls._CONFIG is None: + raise RuntimeError( + "Config not loaded yet. Call load_cubit_config() first use of is_remote." + ) + return cls._CONFIG.get("cubitpy_mode") == "remote" # Global object with options for cubitpy. diff --git a/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py b/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py index d11cd30..d680da6 100644 --- a/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py +++ b/src/cubitpy/cubit_wrapper/cubit_wrapper_host.py @@ -64,79 +64,73 @@ def __init__( Python interpreter to be used for running cubit. """ - # ------------------------------------------------------------------ # Remote mode – run cubit on a remote machine via SSH - # ------------------------------------------------------------------ if cupy.is_remote(): raise NotImplementedError("Remote cubit mode is not yet implemented.") - return - - # ------------------------------------------------------------------ # Local mode – run cubit on the local machine - # ------------------------------------------------------------------ - - if interpreter is None: - interpreter = f"popen//python={cupy.get_cubit_interpreter()}" + else: + if interpreter is None: + interpreter = f"popen//python={cupy.get_cubit_interpreter()}" - if cubit_lib is None: - cubit_lib = cupy.get_cubit_lib_path() + if cubit_lib is None: + cubit_lib = cupy.get_cubit_lib_path() - # Set up the client python interpreter - self.gw = execnet.makegateway(interpreter) - self.gw.reconfigure(py3str_as_py2str=True) + # Set up the client python interpreter + self.gw = execnet.makegateway(interpreter) + self.gw.reconfigure(py3str_as_py2str=True) - # Load the main code in the client python interpreter - client_python_file = os.path.join( - os.path.dirname(__file__), "cubit_wrapper_client.py" - ) - with open(client_python_file, "r") as myfile: - data = myfile.read() - - # Set up the connection channel - self.channel = self.gw.remote_exec(data) - - # Send parameters to the client interpreter - parameters = {} - parameters["__file__"] = __file__ - parameters["cubit_lib_path"] = cubit_lib - - # Arguments for cubit - if cubit_args is None: - arguments = [ - "cubit", - # "-log", # Write the log to a file - # "dev/null", - "-information", # Do not output information of cubit - "Off", - "-nojournal", # Do write a journal file - "-noecho", # Do not output commands used in cubit - ] - else: - arguments = ["cubit"] + cubit_args + # Load the main code in the client python interpreter + client_python_file = os.path.join( + os.path.dirname(__file__), "cubit_wrapper_client.py" + ) + with open(client_python_file, "r") as myfile: + data = myfile.read() + + # Set up the connection channel + self.channel = self.gw.remote_exec(data) + + # Send parameters to the client interpreter + parameters = {} + parameters["__file__"] = __file__ + parameters["cubit_lib_path"] = cubit_lib + + # Arguments for cubit + if cubit_args is None: + arguments = [ + "cubit", + # "-log", # Write the log to a file + # "dev/null", + "-information", # Do not output information of cubit + "Off", + "-nojournal", # Do write a journal file + "-noecho", # Do not output commands used in cubit + ] + else: + arguments = ["cubit"] + cubit_args - # Check if a log file was given in the cubit arguments - for arg in arguments: - if arg.startswith("-log="): - log_given = True - break - else: - log_given = False + # Check if a log file was given in the cubit arguments + for arg in arguments: + if arg.startswith("-log="): + log_given = True + break + else: + log_given = False - self.log_check = False + self.log_check = False - if not log_given: - # Write the log to a temporary file and check the contents after each call to cubit - arguments.extend(["-log", cupy.temp_log]) - parameters["tty"] = cupy.temp_log - self.log_check = True + if not log_given: + # Write the log to a temporary file and check the contents after each call to cubit + arguments.extend(["-log", cupy.temp_log]) + parameters["tty"] = cupy.temp_log + self.log_check = True - # Send the parameters to the client interpreter - self.send_and_return(parameters) + # Send the parameters to the client interpreter + self.send_and_return(parameters) - # Initialize cubit in the client and create the linking object here - cubit_id = self.send_and_return(["init", arguments]) - self.cubit = CubitObjectMain(self, cubit_id) + # Initialize cubit in the client and create the linking object here + cubit_id = self.send_and_return(["init", arguments]) + self.cubit = CubitObjectMain(self, cubit_id) def cleanup_execnet_gateway(): """We need to register a function called at interpreter shutdown diff --git a/src/cubitpy/cubitpy.py b/src/cubitpy/cubitpy.py index abf1a74..f984d44 100644 --- a/src/cubitpy/cubitpy.py +++ b/src/cubitpy/cubitpy.py @@ -25,6 +25,7 @@ import subprocess # nosec B404 import time import warnings +from pathlib import Path, PureWindowsPath import netCDF4 from fourcipp.fourc_input import FourCInput @@ -62,26 +63,44 @@ def _get_and_check_ids(name, container, id_list, given_id): class CubitPy(object): """A wrapper class with additional functionality for cubit.""" - def __init__(self, *, cubit_exe=None, **kwargs): + def __init__( + self, *, cubit_config_path: Path | None = None, cubit_exe=None, **kwargs + ): """Initialize CubitPy. Args ---- + cubit_config_path: Path + Path to the cubitpy configuration file. + cubit_exe: str Path to the cubit executable kwargs: Arguments passed on to the creation of the python wrapper """ - - # Set paths - if cubit_exe is None: - cubit_exe = cupy.get_cubit_exe_path() - self.cubit_exe = cubit_exe + # load config + cupy.load_cubit_config(cubit_config_path) # Set the "real" cubit object self.cubit = CubitConnect(**kwargs).cubit + # Set paths + if not cupy.is_remote(): + if cubit_exe is None: + cubit_exe = cupy.get_cubit_exe_path() + self.cubit_exe = cubit_exe + + # Set remote paths + if cupy.is_remote(): + if self.get_remote_os().lower().startswith("windows"): + self.temp_dir_remote = PureWindowsPath("C:") / PureWindowsPath( + cupy.temp_dir + ) + print(f"[REMOTE TEMP DIR] {self.temp_dir_remote}") + else: + raise NotImplementedError("Remote non-Windows OS not tested") + # Reset cubit self.cubit.cmd("reset") self.cubit.cmd("set geometry engine acis") From b9ab2d132771a48b5114f45fe28b8e6804f56aad Mon Sep 17 00:00:00 2001 From: Moritz Frey Date: Wed, 10 Dec 2025 15:23:58 +0100 Subject: [PATCH 3/5] Change config variables --- src/cubitpy/conf.py | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/cubitpy/conf.py b/src/cubitpy/conf.py index 0533ba8..d3a2b08 100644 --- a/src/cubitpy/conf.py +++ b/src/cubitpy/conf.py @@ -57,7 +57,7 @@ def get_path(environment_variable, test_function, *, throw_error=True): class CubitOptions(object): """Object for types in cubitpy.""" - _CONFIG = None + _config = None def __init__(self): # Temporary directory for cubitpy. @@ -107,8 +107,8 @@ def get_cubit_config_filepath(): def validate_cubit_config(cls): """Validate the already loaded config dict and raise helpful errors.""" - cfg = cls._CONFIG - if cfg is None: + config = cls._config + if config is None: raise RuntimeError( "Config not loaded yet. Call cupy.get_cubit_config(...) first." ) @@ -137,32 +137,34 @@ def fail(msg: str): raise RuntimeError(msg + TEMPLATE) # Check mode - if "cubitpy_mode" not in cfg: + if "cubitpy_mode" not in config: fail("Missing required key: 'cubitpy_mode'.") - mode = cfg["cubitpy_mode"] + mode = config["cubitpy_mode"] if mode not in ("remote", "local"): fail(f"Invalid cubitpy_mode '{mode}'. Expected 'remote' or 'local'.") if mode == "remote": - if "remote_config" not in cfg: + if "remote_config" not in config: fail("cubitpy_mode='remote' requires a 'remote_config' section.") - rcfg = cfg["remote_config"] + remote_config = config["remote_config"] required = ["user", "host", "cubit_path"] - missing = [k for k in required if k not in rcfg or not rcfg[k]] + missing = [ + k for k in required if k not in remote_config or not remote_config[k] + ] if missing: fail("remote_config is missing required fields: " + ", ".join(missing)) if mode == "local": - if "local_config" not in cfg: + if "local_config" not in config: fail("cubitpy_mode='local' requires a 'local_config' section.") - lcfg = cfg["local_config"] - if "cubit_path" not in lcfg or not lcfg["cubit_path"]: + local_config = config["local_config"] + if "cubit_path" not in local_config or not local_config["cubit_path"]: fail("local_config must contain a non-empty 'cubit_path'.") - local_cubit_path = lcfg["cubit_path"] + local_cubit_path = local_config["cubit_path"] if not Path(local_cubit_path).expanduser().exists(): raise FileNotFoundError( f"local_config.cubit_path '{local_cubit_path}' does not exist." @@ -182,13 +184,13 @@ def load_cubit_config(cls, config_path: Path | None = None): ) root_path = cls.get_cubit_root_path(throw_error=True) - default_cfg = { + default_config = { "cubitpy_mode": "local", "local_config": {"cubit_path": root_path}, "remote_config": {}, } - cubit_config_dict = default_cfg + cubit_config_dict = default_config else: try: with open(config_path, "r") as f: @@ -199,13 +201,13 @@ def load_cubit_config(cls, config_path: Path | None = None): if not isinstance(cubit_config_dict, dict): raise ImportError("YAML top level must be a mapping (dict).") - cls._CONFIG = cubit_config_dict + cls._config = cubit_config_dict cls.validate_cubit_config() @classmethod def get_cubit_exe_path(cls, **kwargs): """Get Path to cubit executable.""" - cubit_root = cls._CONFIG["local_config"]["cubit_path"] + cubit_root = cls._config["local_config"]["cubit_path"] if platform == "linux" or platform == "linux2": if cupy.is_coreform(): return os.path.join(cubit_root, "bin", "coreform_cubit") @@ -223,7 +225,7 @@ def get_cubit_exe_path(cls, **kwargs): @classmethod def get_cubit_lib_path(cls, **kwargs): """Get Path to cubit lib directory.""" - cubit_root = cls._CONFIG["local_config"]["cubit_path"] + cubit_root = cls._config["local_config"]["cubit_path"] if platform == "linux" or platform == "linux2": return os.path.join(cubit_root, "bin") elif platform == "darwin": @@ -237,7 +239,7 @@ def get_cubit_lib_path(cls, **kwargs): @classmethod def get_cubit_interpreter(cls): """Get the path to the python interpreter to be used for CubitPy.""" - cubit_root = cls._CONFIG["local_config"]["cubit_path"] + cubit_root = cls._config["local_config"]["cubit_path"] if cls.is_coreform(): pattern = "**/python3" full_pattern = os.path.join(cubit_root, pattern) @@ -268,7 +270,7 @@ def get_cubit_interpreter(cls): @classmethod def is_coreform(cls): """Return if the given path is a path to cubit coreform.""" - cubit_root = cls._CONFIG["local_config"]["cubit_path"] + cubit_root = cls._config["local_config"]["cubit_path"] if "15.2" in cubit_root and not cls.is_remote(): return False else: @@ -278,11 +280,11 @@ def is_coreform(cls): def is_remote(cls) -> bool: """Return True if cubit is running remotely based on the loaded config.""" - if cls._CONFIG is None: + if cls._config is None: raise RuntimeError( "Config not loaded yet. Call load_cubit_config() first use of is_remote." ) - return cls._CONFIG.get("cubitpy_mode") == "remote" + return cls._config.get("cubitpy_mode") == "remote" # Global object with options for cubitpy. From 18b915d8e87324f7358df89849c3a7a9c53b17b4 Mon Sep 17 00:00:00 2001 From: Moritz Frey Date: Wed, 10 Dec 2025 15:38:12 +0100 Subject: [PATCH 4/5] Remove obsolete code --- src/cubitpy/conf.py | 12 +----------- src/cubitpy/cubitpy.py | 8 ++------ 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/cubitpy/conf.py b/src/cubitpy/conf.py index d3a2b08..71af0c0 100644 --- a/src/cubitpy/conf.py +++ b/src/cubitpy/conf.py @@ -88,16 +88,6 @@ def __init__(self): # Tolerance for geometry. self.eps_pos = 1e-10 - @staticmethod - def get_cubit_root_path(**kwargs): - """Get Path to cubit root directory.""" - warnings.warn( - "Using CUBIT_ROOT for locating the local Cubit installation is deprecated. " - "Please define 'local_config.cubit_path' in your cubitpy configuration YAML. ", - DeprecationWarning, - ) - return get_path("CUBIT_ROOT", os.path.isdir, **kwargs) - @staticmethod def get_cubit_config_filepath(): """Return path to remote config if it exists, else None.""" @@ -182,7 +172,7 @@ def load_cubit_config(cls, config_path: Path | None = None): "CubitPy configuration file not found." "Using default config: local", DeprecationWarning, ) - root_path = cls.get_cubit_root_path(throw_error=True) + root_path = get_path("CUBIT_ROOT", os.path.isdir, throw_error=True) default_config = { "cubitpy_mode": "local", diff --git a/src/cubitpy/cubitpy.py b/src/cubitpy/cubitpy.py index f984d44..649ecd0 100644 --- a/src/cubitpy/cubitpy.py +++ b/src/cubitpy/cubitpy.py @@ -63,9 +63,7 @@ def _get_and_check_ids(name, container, id_list, given_id): class CubitPy(object): """A wrapper class with additional functionality for cubit.""" - def __init__( - self, *, cubit_config_path: Path | None = None, cubit_exe=None, **kwargs - ): + def __init__(self, *, cubit_config_path: Path | None = None, **kwargs): """Initialize CubitPy. Args @@ -87,9 +85,7 @@ def __init__( # Set paths if not cupy.is_remote(): - if cubit_exe is None: - cubit_exe = cupy.get_cubit_exe_path() - self.cubit_exe = cubit_exe + self.cubit_exe = cupy.get_cubit_exe_path() # Set remote paths if cupy.is_remote(): From 0acf4307815df28496a242232206333b7993a435 Mon Sep 17 00:00:00 2001 From: moritz frey Date: Mon, 15 Dec 2025 21:25:25 +0100 Subject: [PATCH 5/5] Adress comments --- src/cubitpy/cubitpy.py | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/cubitpy/cubitpy.py b/src/cubitpy/cubitpy.py index 649ecd0..5697419 100644 --- a/src/cubitpy/cubitpy.py +++ b/src/cubitpy/cubitpy.py @@ -25,7 +25,7 @@ import subprocess # nosec B404 import time import warnings -from pathlib import Path, PureWindowsPath +from pathlib import Path import netCDF4 from fourcipp.fourc_input import FourCInput @@ -71,9 +71,6 @@ def __init__(self, *, cubit_config_path: Path | None = None, **kwargs): cubit_config_path: Path Path to the cubitpy configuration file. - cubit_exe: str - Path to the cubit executable - kwargs: Arguments passed on to the creation of the python wrapper """ @@ -83,19 +80,13 @@ def __init__(self, *, cubit_config_path: Path | None = None, **kwargs): # Set the "real" cubit object self.cubit = CubitConnect(**kwargs).cubit - # Set paths - if not cupy.is_remote(): - self.cubit_exe = cupy.get_cubit_exe_path() - # Set remote paths if cupy.is_remote(): - if self.get_remote_os().lower().startswith("windows"): - self.temp_dir_remote = PureWindowsPath("C:") / PureWindowsPath( - cupy.temp_dir - ) - print(f"[REMOTE TEMP DIR] {self.temp_dir_remote}") - else: - raise NotImplementedError("Remote non-Windows OS not tested") + raise NotImplementedError( + "Remote cubit connections are not yet supported in CubitPy." + ) + else: + self.cubit_exe = cupy.get_cubit_exe_path() # Reset cubit self.cubit.cmd("reset")