diff --git a/docs/md/ostags.md b/docs/md/ostags.md index e140d98..ea9440c 100644 --- a/docs/md/ostags.md +++ b/docs/md/ostags.md @@ -43,3 +43,14 @@ OSTag.convert(platform.system(), "py2mf") The second argument specifies the mapping in format `2`, where `` and `` may take values `py`, `mf`, or `gh`. **Note**: source and target must be different. + +## Getting suffixes + +A convenience function is available to get the appropriate binary file extensions for a given operating system, identified by tag (or the current operating system if no tag is provided). The return value is a 2-tuple containing the executable and library extensions, respectively. + +```python +get_binary_suffixes() # get extensions for current OS +get_binary_suffixes("linux") # returns ("", ".so") +get_binary_suffixes("linux") # returns ("", ".so") +get_binary_suffixes("win64") # returns (".exe", ".dll") +``` diff --git a/modflow_devtools/misc.py b/modflow_devtools/misc.py index c326c0b..31d540d 100644 --- a/modflow_devtools/misc.py +++ b/modflow_devtools/misc.py @@ -82,7 +82,12 @@ def __exit__(self, exc_type, exc_value, traceback): def get_ostag() -> str: - """Determine operating system tag from sys.platform.""" + """ + Determine operating system tag from sys.platform. + + .. deprecated:: 1.1.0 + Use ``ostags.get_modflow_ostag()`` instead. + """ if sys.platform.startswith("linux"): return "linux" elif sys.platform.startswith("win"): @@ -93,7 +98,12 @@ def get_ostag() -> str: def get_suffixes(ostag) -> Tuple[str, str]: - """Returns executable and library suffixes for the given OS (as returned by sys.platform)""" + """ + Returns executable and library suffixes for the given OS (as returned by sys.platform) + + .. deprecated:: 1.1.0 + Use ``ostags.get_binary_suffixes()`` instead. + """ tag = ostag.lower() @@ -136,6 +146,23 @@ def run_py_script(script, *args, verbose=False): def get_current_branch() -> str: + """ + Tries to determine the name of the current branch, first by the GITHUB_REF + environent variable, then by asking ``git`` if GITHUB_REF is not set. + + Returns + ------- + str + name of the current branch + + Raises + ------ + RuntimeError + if ``git`` is not available + ValueError + if the current branch could not be determined + """ + # check if on GitHub Actions CI ref = environ.get("GITHUB_REF") if ref is not None: @@ -160,6 +187,7 @@ def get_packages(namefile_path: PathLike) -> List[str]: ---------- namefile_path : PathLike path to MODFLOW 6 simulation or model name file + Returns ------- a list of packages used by the simulation or model @@ -215,7 +243,9 @@ def parse_model_namefile(line): def has_package(namefile_path: PathLike, package: str) -> bool: - """Determines whether the model with the given namefile contains the selected package""" + """ + Determines whether the model with the given namefile contains the selected package. + """ packages = get_packages(namefile_path) return package.lower() in packages @@ -306,7 +336,9 @@ def get_model_paths( def is_connected(hostname): """ Tests whether the given URL is accessible. - See https://stackoverflow.com/a/20913928/.""" + See https://stackoverflow.com/a/20913928/. + """ + try: host = socket.gethostbyname(hostname) s = socket.create_connection((host, 80), 2) @@ -318,7 +350,10 @@ def is_connected(hostname): def is_in_ci(): - """Determines whether the current process is running GitHub Actions CI""" + """ + Determines whether the current process is running GitHub Actions CI + by checking for the "CI" environment variable. + """ # if running in GitHub Actions CI, "CI" variable always set to true # https://docs.github.com/en/actions/learn-github-actions/environment-variables#default-environment-variables @@ -328,7 +363,7 @@ def is_in_ci(): def is_github_rate_limited() -> Optional[bool]: """ Determines if a GitHub API rate limit is applied to the current IP. - Running this function will consume an API request! + Calling this function will consume an API request! Returns ------- diff --git a/modflow_devtools/ostags.py b/modflow_devtools/ostags.py index 55e7706..3c68ed3 100644 --- a/modflow_devtools/ostags.py +++ b/modflow_devtools/ostags.py @@ -1,18 +1,20 @@ """ -MODFLOW 6, Python3, and build servers may all refer to operating -systems by different names. This module contains conversion utilities. +MODFLOW 6, Python3, and GitHub Actions refer to operating +systems differently. This module contains conversion utilities. """ +import sys from enum import Enum from platform import system +from typing import Tuple _system = system() def get_modflow_ostag() -> str: if _system == "Windows": - return "win64" + return "win" + ("64" if sys.maxsize > 2**32 else "32") elif _system == "Linux": return "linux" elif _system == "Darwin": @@ -30,6 +32,44 @@ def get_github_ostag() -> str: raise NotImplementedError(f"Unsupported system: {_system}") +def get_binary_suffixes(ostag: str = None) -> Tuple[str, str]: + """ + Returns executable and library suffixes for the given OS tag, if provided, + otherwise for the current operating system. + + Parameters + ---------- + ostag : str, optional + The OS tag. May be provided in modflow, python, or github format. + + Returns + ------- + Tuple[str, str] + The executable and library suffixes, respectively. + """ + + if ostag is None: + ostag = get_modflow_ostag() + + def _suffixes(tag): + if tag in ["win32", "win64"]: + return ".exe", ".dll" + elif tag == "linux": + return "", ".so" + elif tag == "mac" or tag == "darwin": + return "", ".dylib" + else: + raise KeyError(f"unrecognized OS tag: {tag!r}") + + try: + return _suffixes(ostag.lower()) + except: + try: + return _suffixes(python_to_modflow_ostag(ostag)) + except: + return _suffixes(github_to_modflow_ostag(ostag)) + + def python_to_modflow_ostag(tag: str) -> str: """ Convert a platform.system() string to an ostag as expected diff --git a/modflow_devtools/test/test_ostags.py b/modflow_devtools/test/test_ostags.py index 02d9adb..7ad3b91 100644 --- a/modflow_devtools/test/test_ostags.py +++ b/modflow_devtools/test/test_ostags.py @@ -1,7 +1,12 @@ from platform import system import pytest -from modflow_devtools.ostags import OSTag, get_github_ostag, get_modflow_ostag +from modflow_devtools.ostags import ( + OSTag, + get_binary_suffixes, + get_github_ostag, + get_modflow_ostag, +) _system = system() @@ -53,3 +58,37 @@ def test_get_github_ostag(): ) def test_ostag_convert(cvt, tag, exp): assert OSTag.convert(tag, cvt) == exp + + +def test_get_binary_suffixes(): + exe, lib = get_binary_suffixes() + if _system == "Windows": + assert exe == ".exe" + assert lib == ".dll" + elif _system == "Linux": + assert exe == "" + assert lib == ".so" + elif _system == "Darwin": + assert exe == "" + assert lib == ".dylib" + + +@pytest.mark.parametrize( + "tag,exe,lib", + [ + ("win64", ".exe", ".dll"), + ("win32", ".exe", ".dll"), + ("Windows", ".exe", ".dll"), + ("linux", "", ".so"), + ("Linux", "", ".so"), + ("mac", "", ".dylib"), + ("macOS", "", ".dylib"), + ("Darwin", "", ".dylib"), + ], +) +def test_get_binary_suffixes_given_tag(tag, exe, lib): + from modflow_devtools.misc import get_suffixes + + assert get_binary_suffixes(tag) == (exe, lib) + if tag in ("win64", "win32", "linux", "mac"): + assert get_suffixes(tag) == (exe, lib)