diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 66f3a1f..23337a5 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -36,7 +36,7 @@ permissions: # LIBRARY_DESTINATION_DIRECTORY: Path in this repo where shared library files should be placed. env: LIBRARY_BASE_REPO: NTIA/LFMF - LIBRARY_RELEASE_TAG: v1.1 + LIBRARY_RELEASE_TAG: v1.2-rc.2 LIBRARY_DESTINATION_DIRECTORY: 'src/ITS/Propagation/LFMF' jobs: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7280523..e80e421 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,7 +27,7 @@ permissions: # LIBRARY_DESTINATION_DIRECTORY: Path in this repo where shared library files should be placed. env: LIBRARY_BASE_REPO: NTIA/LFMF - LIBRARY_RELEASE_TAG: v1.1 + LIBRARY_RELEASE_TAG: v1.2-rc.2 LIBRARY_DESTINATION_DIRECTORY: 'src/ITS/Propagation/LFMF' jobs: diff --git a/.zenodo.json b/.zenodo.json index 833748a..8e6cc3e 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -38,5 +38,5 @@ "resource_type": "publication-softwaredocumentation" } ], - "version": "1.1.0" + "version": "1.2.0" } diff --git a/CITATION.cff b/CITATION.cff index 9aed93e..ecede78 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -39,4 +39,4 @@ keywords: - propagation - lfmf - antennas -version: 1.1.0 +version: 1.2.0 diff --git a/src/ITS/Propagation/LFMF/LFMF.py b/src/ITS/Propagation/LFMF/LFMF.py index 50dbaa0..04d5cc6 100644 --- a/src/ITS/Propagation/LFMF/LFMF.py +++ b/src/ITS/Propagation/LFMF/LFMF.py @@ -32,7 +32,7 @@ class LFMFResult(Structure): # Load the shared library -lib = PropLibCDLL("LFMF-1.1") +lib = PropLibCDLL("LFMF-1.2") # Define function prototypes lib.LFMF.restype = c_int @@ -106,3 +106,21 @@ def __convertResultStruct(c_result): result.method = SolutionMethod(c_result.method) return result + + +def GetLibraryName() -> str: + return __read_char_array(lib.GetLibraryNameCharArray()) + + +def GetLibraryVersion() -> str: + return __read_char_array(lib.GetLibraryVersionCharArray()) + + +def __read_char_array(msg) -> str: + try: + msg_bytes = cast(msg, c_char_p).value + if msg_bytes is None: + raise RuntimeError("The TODO-TEMPLATE library returned an empty text response.") + return msg_bytes.decode("utf-8") + finally: + lib.FreeCharArray(msg) \ No newline at end of file diff --git a/src/ITS/Propagation/LFMF/__init__.py b/src/ITS/Propagation/LFMF/__init__.py index a0bde28..e00adf3 100644 --- a/src/ITS/Propagation/LFMF/__init__.py +++ b/src/ITS/Propagation/LFMF/__init__.py @@ -1,10 +1,12 @@ # Version X.Y.Z: X.Y is the version of the C++ source, # and Z is the version of this Python wrapper -__version__ = "1.1.0" +__version__ = "1.2.0" from .LFMF import ( LFMF, Polarization, SolutionMethod, - LFMFResult + LFMFResult, + GetLibraryName, + GetLibraryVersion, ) diff --git a/src/ITS/Propagation/LFMF/proplib_loader.py b/src/ITS/Propagation/LFMF/proplib_loader.py index 32d78b8..f93cc9d 100644 --- a/src/ITS/Propagation/LFMF/proplib_loader.py +++ b/src/ITS/Propagation/LFMF/proplib_loader.py @@ -61,8 +61,12 @@ def __init__(self, name: str) -> None: # Define expected function prototypes self.GetReturnStatusCharArray.restype = POINTER(c_char_p) self.GetReturnStatusCharArray.argtypes = (c_int,) - self.FreeReturnStatusCharArray.restype = None - self.FreeReturnStatusCharArray.argtypes = (POINTER(c_char_p),) + self.FreeCharArray.restype = None + self.FreeCharArray.argtypes = (POINTER(c_char_p),) + self.GetLibraryNameCharArray.restype = POINTER(c_char_p) + self.GetLibraryNameCharArray.argtypes = None + self.GetLibraryVersionCharArray.restype = POINTER(c_char_p) + self.GetLibraryVersionCharArray.argtypes = None @staticmethod @@ -122,5 +126,5 @@ def err_check(self, rtn_code: int) -> None: ) msg_str = msg_bytes.decode("utf-8") finally: - self.FreeReturnStatusCharArray(msg) + self.FreeCharArray(msg) raise RuntimeError(msg_str) diff --git a/tests/test_proplib_loader.py b/tests/test_proplib_loader.py index 77c69e8..e7e1013 100644 --- a/tests/test_proplib_loader.py +++ b/tests/test_proplib_loader.py @@ -64,7 +64,7 @@ def GetReturnStatusCharArray(_code): return cast(c_char_p(error_message), POINTER(c_char_p)) @staticmethod - def FreeReturnStatusCharArray(message) -> None: + def FreeCharArray(message) -> None: freed_messages.append(message) with pytest.raises(RuntimeError, match="example failure"): @@ -82,7 +82,7 @@ def GetReturnStatusCharArray(_code): return cast(c_char_p(None), POINTER(c_char_p)) @staticmethod - def FreeReturnStatusCharArray(message) -> None: + def FreeCharArray(message) -> None: freed_messages.append(message) with pytest.raises(RuntimeError, match="no error text was returned"): diff --git a/tests/test_utils.py b/tests/test_utils.py index a9d0e08..d06b22d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -2,6 +2,8 @@ from pathlib import Path from typing import Optional +from ITS.Propagation import LFMF + # Test data is expected to exist in tests/data TEST_DATA_DIR = Path(__file__).parent / "data" ABSTOL__DB = 0.1 # Absolute tolerance, in dB, to ensure outputs match expected value @@ -38,3 +40,13 @@ def read_csv_test_data(filename: str, data_dir: Optional[Path] = None): for row in reader: # yields (*inputs, rtn, *outputs) yield tuple(map(float, row[:-5])), int(row[-5]), tuple(map(float, row[-4:])) + + +def test_LibraryName(): + name = LFMF.GetLibraryName() + assert name == 'LFMF' + + +def test_LibraryVersion(): + version = LFMF.GetLibraryVersion() + assert version == '1.2' \ No newline at end of file