diff --git a/.github/workflows/buildwheels.yml b/.github/workflows/buildwheels.yml new file mode 100644 index 0000000..a376267 --- /dev/null +++ b/.github/workflows/buildwheels.yml @@ -0,0 +1,82 @@ +# Action builds a universal (Win32/Win64/macOS-universal/Linux-x64) Python wheel +# from the source code, using Hatchling, and uploads it as an artifact. This wheel +# can then be distributed with new releases. The action is triggered by pushes into `main` +# or pull_requests into `main` or `dev` (for testing). To aid in releases, the workflow is +# also triggered when new SemVer tags are created. This action handles downloading all +# shared library files and including them in the resulting wheel. +name: Build Wheels + +on: + workflow_dispatch: + push: + branches: + - main + tags: + - 'v[0-9]+.*' + pull_request: + branches: + - main + - dev + +env: + LIBRARY_BASE_REPO: NTIA/p2108 + LIBRARY_RELEASE_TAG: v1.0-rc.1 + LIBRARY_DESTINATION_DIRECTORY: 'src/ITS/ITU/PSeries/P2108/' + +jobs: + build_wheel: + name: Build a universal, cross-platform wheel + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + submodules: true + + # Only the binaries required for the current platform are downloaded. Note that the distributed + # wheel for proplib python packages includes all binaries, so that the wheel is inherently cross-platform. + - name: Download required ${{ env.LIBRARY_RELEASE_TAG }} Windows binaries + uses: robinraju/release-downloader@v1 + with: + repository: ${{ env.LIBRARY_BASE_REPO }} + tag: ${{ env.LIBRARY_RELEASE_TAG }} + fileName: '*.dll' + tarBall: false + zipBall: false + out-file-path: ${{ env.LIBRARY_DESTINATION_DIRECTORY }} + + - name: Download required ${{ env.LIBRARY_RELEASE_TAG }} Linux binaries + uses: robinraju/release-downloader@v1 + with: + repository: ${{ env.LIBRARY_BASE_REPO }} + tag: ${{ env.LIBRARY_RELEASE_TAG }} + fileName: '*.so' + tarBall: false + zipBall: false + out-file-path: ${{ env.LIBRARY_DESTINATION_DIRECTORY }} + + - name: Download required ${{ env.LIBRARY_RELEASE_TAG }} macOS binaries + uses: robinraju/release-downloader@v1 + with: + repository: ${{ env.LIBRARY_BASE_REPO }} + tag: ${{ env.LIBRARY_RELEASE_TAG }} + fileName: '*.dylib' + tarBall: false + zipBall: false + out-file-path: ${{ env.LIBRARY_DESTINATION_DIRECTORY }} + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install build dependencies + run: pip install hatchling + + - name: Build wheels + run: hatchling build + + - uses: actions/upload-artifact@v4 + with: + name: Universal Wheel (.whl) + path: dist/*.whl diff --git a/.github/workflows/cff-validator.yml b/.github/workflows/cff-validator.yml new file mode 100644 index 0000000..598eaed --- /dev/null +++ b/.github/workflows/cff-validator.yml @@ -0,0 +1,27 @@ +name: Validate CITATION.cff + +on: + push: + branches: ["main", "dev"] + paths: + - 'CITATION.cff' + - '.github/workflows/cff-validator.yml' + pull_request: + branches: ["main", "dev"] + paths: + - 'CITATION.cff' + - '.github/workflows/cff-validator.yml' + workflow_dispatch: + +jobs: + Validate-CITATION-cff: + runs-on: ubuntu-latest + name: Validate CITATION.cff + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Validate CITATION.cff + uses: dieghernan/cff-validator@v4 diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml new file mode 100644 index 0000000..97f84a9 --- /dev/null +++ b/.github/workflows/pytest.yml @@ -0,0 +1,93 @@ +name: Test with pytest + +on: + workflow_dispatch: + push: + branches: + - main + pull_request: + branches: + - main + - dev + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: true + +env: + LIBRARY_BASE_REPO: NTIA/p2108 + LIBRARY_RELEASE_TAG: v1.0-rc.1 + LIBRARY_DESTINATION_DIRECTORY: 'src/ITS/ITU/PSeries/P2108/' + +jobs: + run-all-tests: + name: ${{ matrix.platform.os-name }} / Py${{ matrix.py }} + runs-on: ${{ matrix.platform.os-runner }} + strategy: + fail-fast: false + matrix: + platform: + - os-name: 'Windows (64-bit)' + os-runner: 'windows-latest' + arch-id: 'x64' + release-file-pattern: '*-x64.dll' + - os-name: 'Windows (32-bit)' + os-runner: 'windows-latest' + arch-id: 'x86' + release-file-pattern: '*-x86.dll' + - os-name: 'macOS (intel/x64)' + os-runner: 'macos-13' + arch-id: 'x64' + release-file-pattern: '*.dylib' + - os-name: 'macOS (apple/arm64)' + os-runner: 'macos-latest' + arch-id: 'arm64' + release-file-pattern: '*.dylib' + - os-name: 'Linux (Ubuntu)' + os-runner: 'ubuntu-latest' + arch-id: 'x64' + release-file-pattern: '*.so' + py: # Python versions to test on all platforms + - "3.9" + - "3.10" + - "3.11" + - "3.12" + steps: + - name: Check out repository + uses: actions/checkout@v4 + with: + submodules: true + + # Cache key is unique to the combination of runner OS + architecture (matrix.arch-id) + release tag + - name: Restore ${{ env.LIBRARY_RELEASE_TAG }} binaries from cache if available + id: cache-restore + uses: actions/cache@v4 + with: + key: ${{ runner.os }}-${{ matrix.platform.arch-id }}-${{ env.LIBRARY_RELEASE_TAG }} + path: ${{ env.LIBRARY_DESTINATION_DIRECTORY}}/${{ matrix.platform.release-file-pattern }} + + # Only the binaries required for the current platform are downloaded. Note that the distributed + # wheel for proplib python packages includes all binaries, so that the wheel is inherently cross-platform. + - name: Download required ${{ env.LIBRARY_RELEASE_TAG }} binaries + if: ${{ steps.cache-restore.outputs.cache-hit != 'true' }} + uses: robinraju/release-downloader@v1 + with: + repository: ${{ env.LIBRARY_BASE_REPO }} + tag: ${{ env.LIBRARY_RELEASE_TAG }} + fileName: ${{ matrix.platform.release-file-pattern }} + tarBall: false + zipBall: false + out-file-path: ${{ env.LIBRARY_DESTINATION_DIRECTORY }} + + - name: Set up Python ${{ matrix.py }} + uses: actions/setup-python@v5 + with: + architecture: ${{ matrix.platform.arch-id }} + python-version: ${{ matrix.py }} + cache: 'pip' + + - name: Install dependencies for testing + run: python -m pip install -e .[tests] + + - name: Run pytest + run: pytest --cov-report=term-missing --no-cov-on-fail --cov diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e1abd5e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "tests/data"] + path = tests/data + url = https://github.com/NTIA/p2108-test-data diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7b9f374..5d06997 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,7 +16,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/asottile/pyupgrade - rev: v3.19.0 + rev: v3.19.1 hooks: - id: pyupgrade args: ["--py39-plus"] @@ -33,7 +33,7 @@ repos: - id: black types: [file, python] - repo: https://github.com/igorshubovych/markdownlint-cli - rev: v0.42.0 + rev: v0.43.0 hooks: - id: markdownlint types: [file, markdown] diff --git a/.zenodo.json b/.zenodo.json index 4f32142..d3fe5d9 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,17 +1,37 @@ { + "upload_type": "software", + "publication_date": "2024-12-11", + "title": "Recommendation ITU-R P.2108, Python Wrapper", "creators": [ { - "orcid": "TODO-TEMPLATE", + "name": "Romaniello, Anthony W.", "affiliation": "U.S. Department of Commerce, National Telecommunications and Information Administration, Institute for Telecommunication Sciences", - "name": "TODO-TEMPLATE" + "orcid": "0000-0001-8437-6504" } ], - "license": "NTIA Public Domain", - "title": "TODO-TEMPLATE, Python Wrapper", - "upload_type": "software", - "version": "TODO-TEMPLATE", - "keywords": ["TODO-TEMPLATE"], - "communities": [ - {"identifier": "its-proplib"} - ] + "description": "This repository contains a Python wrapper for the NTIA/ITS implementation of Recommendation ITU-R P.2108. This Recommendation contains three methods for the prediction of clutter loss: Height Gain Terminal Correction Model, Terrestrial Statistical Model, and Aeronautical Statistical Model. The software implements Section 3 of Annex 1 of the Recommendation. This Python package wraps the NTIA/ITS C++ implementation.", + "keywords": [ + "clutter", + "ITU", + "ITU-R", + "propagation" + ], + "related_identifiers": [ + { + "identifier": "https://github.com/NTIA/p2108", + "relation": "isSupplementTo", + "resource_type": "software" + }, + { + "identifier": "https://github.com/NTIA/p2108-test-data", + "relation": "isSupplementedBy", + "resource_type": "dataset" + }, + { + "identifier": "https://ntia.github.io/propagation-library-wiki/models/P2108/", + "relation": "isDocumentedBy", + "resource_type": "softwaredocumentation" + } + ], + "version": "1.0.0" } diff --git a/CITATION.cff b/CITATION.cff index ab4ac49..7baaa5d 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,22 +1,11 @@ cff-version: 1.2.0 title: >- - Recommendation ITU-R P.2108-1, U.S. Reference Python - Implementation + Recommendation ITU-R P.2108, Python Wrapper message: Please cite this software using these metadata. type: software authors: - - given-names: William - family-names: Kozma - name-suffix: Jr - email: wkozma@ntia.gov - affiliation: >- - U.S. Department of Commerce, National - Telecommunications and Information Administration, - Institute for Telecommunication Sciences - orcid: 'https://orcid.org/0000-0002-7417-4009' - - given-names: Anthony + - given-names: Anthony W. family-names: Romaniello - name-particle: W. email: aromaniello@ntia.gov affiliation: >- U.S. Department of Commerce, National @@ -26,27 +15,20 @@ authors: - name: >- U.S. Department of Commerce, National Telecommunications and Information Administration, - Institute for Telecommunications Sciences + Institute for Telecommunication Sciences address: 325 Broadway city: Boulder country: US post-code: '80305' region: Colorado + alias: NTIA/ITS email: code@ntia.gov website: 'https://its.ntia.gov' - alias: NTIA/ITS -identifiers: - - type: doi - value: 10.5281/zenodo.7114523 - description: TODO PLACEHOLDER how was doi generated, doi given is wrong. repository-code: 'https://github.com/NTIA/p2108-python' -url: 'https://github.com/NTIA/propagation/wiki' -repository: 'https://github.com/NTIA/p2108' +url: 'https://ntia.github.io/propagation-library-wiki/models/P2108/' keywords: - propagation - rf - clutter - itu -license: 'NTIA Public Domain' version: 1.0.0 -date-released: '2024-05-24' diff --git a/GitHubRepoPublicReleaseApproval.md b/GitHubRepoPublicReleaseApproval.md new file mode 100644 index 0000000..551834d --- /dev/null +++ b/GitHubRepoPublicReleaseApproval.md @@ -0,0 +1,32 @@ +# GitHub Repository Public Release Approval + +**Project Name:** NTIA/OSM Research and Development + +**Software Name:** Recommendation ITU-R P.2108, Python Wrapper + +The project identified above, which is contained within the repository this +document is stored in, has met the following criteria for public release: + +1. [ ] The project, including the test criteria, meets the requirements defined +in the ITS Software Development Publication Policy for making a repository public. +The major pre-established criteria for publication are listed below, and the check +mark next to each attests that the criterion has been met. + * [ ] Unit tests are available and the software has been tested against the unit tests. + * [ ] The software can be compiled and/or used on Windows, macOS, and Linux. + * [ ] The repository structure and contents follow from the ITS PropLib template, and + all template or placeholder code has been removed. + * [ ] The repository includes the appropriate `LICENSE.md` file +2. [ ] Any test data necessary for the code and its unit tests to function is included in this +GitHub repository, either directly or as a linked Git submodule. +3. [ ] The README.md file has passed editorial review from the ITS Publications Office. +4. [ ] The project complies with the ITS Code Style Guide or an appropriate style +guide as agreed to by the sponsor, project lead, or Supervising Division Chief. +5. [ ] Approved disclaimer and licensing language has been included. + +In order to complete this approval, please create a new branch, upload and commit +your version of this Markdown document to that branch, then create a pull request +for that branch. The following must login to GitHub and approve that pull request +before the pull request can be merged and this repo made public: + +* Project Lead: Brian Lain +* Supervising Division Chief or Release Authority: Chris Anderson diff --git a/README.md b/README.md index 80abe70..3e403f4 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,36 @@ -# Recommendation ITU-R P.2108 - U.S. Reference Implementation, Python # +# Recommendation ITU-R P.2108 - Python® Wrapper # [![NTIA/ITS PropLib][proplib-badge]][proplib-link] -[![GitHub Release][gh-releases-badge]][gh-releases-link] +[![PyPI Release][pypi-release-badge]][pypi-release-link] +[![GitHub Actions Unit Test Status][gh-actions-test-badge]][gh-actions-test-link] [![GitHub Issues][gh-issues-badge]][gh-issues-link] +[![DOI][doi-badge]][doi-link] [proplib-badge]: https://img.shields.io/badge/PropLib-badge?label=%F0%9F%87%BA%F0%9F%87%B8%20NTIA%2FITS&labelColor=162E51&color=D63E04 [proplib-link]: https://ntia.github.io/propagation-library-wiki - - -[gh-releases-badge]: https://img.shields.io/github/v/release/NTIA/p2108-python?logo=github&label=Release&labelColor=162E51&color=D63E04 -[gh-releases-link]: https://github.com/NTIA/p2108-python/releases +[gh-actions-test-badge]: https://img.shields.io/github/actions/workflow/status/NTIA/p2108-python/pytest.yml?branch=main&logo=pytest&logoColor=ffffff&label=Tests&labelColor=162E51 +[gh-actions-test-link]: https://github.com/NTIA/p2108-python/actions/workflows/pytest.yml +[pypi-release-badge]: https://img.shields.io/pypi/v/proplib-p2108?logo=pypi&logoColor=ffffff&label=Release&labelColor=162E51&color=D63E04 +[pypi-release-link]: https://pypi.org/project/proplib-p2108 [gh-issues-badge]: https://img.shields.io/github/issues/NTIA/p2108-python?logo=github&label=Issues&labelColor=162E51 [gh-issues-link]: https://github.com/NTIA/p2108-python/issues - - +[doi-badge]: https://zenodo.org/badge/804561453.svg +[doi-link]: https://zenodo.org/badge/latestdoi/804561453 -Python® wrapper for U.S. Reference Software Implementation of Recommendation ITU-R -P.2108. This Recommendation contains three methods for the prediction of clutter -loss: Height Gain Terminal Correction Model, Terrestrial Statistical Model, and -Aeronautical Statistical Model. The software implements Section 3 of Annex 1 of -the Recommendation. This Python package wraps the -[base C++ implementation](https://github.com/NTIA/p2108). +This repository contains a Python wrapper for the NTIA/ITS implementation of +Recommendation ITU-R P.2108. This Recommendation contains three methods for the +prediction of clutter loss: Height Gain Terminal Correction Model, Terrestrial +Statistical Model, and Aeronautical Statistical Model. The software implements +Section 3 of Annex 1 of the Recommendation. This Python package wraps the +[NTIA/ITS C++ implementation](https://github.com/NTIA/p2108). ## Getting Started ## -This software is distributed on [PyPi](https://pypi.org/project/p2108) and is easily installable +This software is distributed on [PyPI](https://pypi.org/project/proplib-p2108) and is easily installable using the following command. ```cmd -pip install p2108 +pip install proplib-p2108 ``` General information about using this model is available on @@ -50,42 +52,37 @@ this either from the compiling it yourself from the C++ source code. Either way, ensure that the shared library (`.dll`, `.dylib`, or `.so` file) is placed in `src/ITS/ITU/PSeries/P2108/`, alongside `__init__.py`. -Below are the steps to build and install the Python package from source, including -compiling the library from the C++ source code. Working installations of Git and -Python (3.9 or above) are required. If compiling the shared library, CMake and a C++ compiler -are also required. +Below are the steps to build and install the Python package from the source code. +Working installations of Git and a [currently-supported version](https://devguide.python.org/versions/) +of Python are required. Additional requirements exist if you want to compile the shared +library from C++ source code; see relevant build instructions +[here](https://github.com/NTIA/p2108?tab=readme-ov-file#configure-and-build). + +1. Optionally, configure and activate a virtual environment using a tool such as +[`venv`](https://docs.python.org/3/library/venv.html) or +[conda](https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html). -1. Clone the parent repository, then initialize the Git submodule containing the -Python wrapper. This repository structure makes test data available to the Python -wrapper. +1. Clone this repository, then initialize the Git submodule containing the test data. ```cmd - # Clone the parent repository - git clone https://github.com/NTIA/p2108 - cd p2108 + # Clone the repository + git clone https://github.com/NTIA/p2108-python + cd p2108-python - # Initialize Git submodules (wrappers and external dependencies) + # Initialize Git submodule containing test data git submodule init - # Clone the submodules + # Clone the submodule git submodule update ``` -1. Compile the C++ library for your platform, following instructions -[here](https://github.com/NTIA/p2108?tab=readme-ov-file#configure-and-build). -Following these instructions should automatically copy the shared library -into the location required by the Python wrapper. - - **OR** - - Download the shared library (`.dll`, `.so`, or `.dylib`) from a - [GitHub Release](https://github.com/NTIA/p2108/releases). Then place the' - downloaded file in `src/ITS/ITU/PSeries/P2108/` (alongside `__init__.py`). +1. Download the shared library (`.dll`, `.so`, or `.dylib`) from a +[GitHub Release](https://github.com/NTIA/p2108/releases). Then place the +downloaded file in `src/ITS/ITU/PSeries/P2108/` (alongside `__init__.py`). -1. Install the local package and development dependencies: +1. Install the local package and development dependencies into your current environment: ```cmd - cd wrap/python pip install .[dev] ``` @@ -97,11 +94,9 @@ into the location required by the Python wrapper. ### Running Tests ### -Python unit tests can be run to confirm successful installation. Test data is -expected to be located in the parent repository. Therefore, if you haven't cloned -this repository as a submodule (as described above), you will need to first specify -the location of the test data files in `tests/test_p2108.py` (using the `TEST_DATA_DIR` -variable). Then, run the tests with pytest: +Python unit tests can be run to confirm successful installation. You will need to +clone this repository's test data submodule (as described above). Then, run the tests +with pytest using the following command. ```cmd pytest @@ -112,12 +107,22 @@ contains an extensive set of example values which are useful as validation cases ## References ## -* [ITS Propagation Library Wiki](https://ntia.github.io/propagation-library-wiki) -* [P2108 Wiki Page](https://ntia.github.io/propagation-library-wiki/models/P2108) -* [`ITS.ITU.PSeries.P2108` C++ API Reference](https://ntia.github.io/P2108) -* [Recommendation ITU-R P.2108](https://www.itu.int/rec/R-REC-P.2108/en) -* [Report ITU-R P.2402](https://www.itu.int/pub/R-REP-P.2402) +- [ITS Propagation Library Wiki](https://ntia.github.io/propagation-library-wiki) +- [P2108 Wiki Page](https://ntia.github.io/propagation-library-wiki/models/P2108) +- [`ITS.ITU.PSeries.P2108` C++ API Reference](https://ntia.github.io/P2108) +- [Recommendation ITU-R P.2108](https://www.itu.int/rec/R-REC-P.2108/en) +- [Report ITU-R P.2402](https://www.itu.int/pub/R-REP-P.2402) + +## License ## + +See [LICENSE](./LICENSE.md). + +"Python" and the Python logos are trademarks or registered trademarks of the Python Software Foundation, used by the National Telecommunications and Information Administration with permission from the Foundation. ## Contact ## For technical questions, contact . + +## Disclaimer ## + +Certain commercial equipment, instruments, or materials are identified in this project were used for the convenience of the developers. In no case does such identification imply recommendation or endorsement by the National Telecommunications and Information Administration, nor does it imply that the material or equipment identified is necessarily the best available for the purpose. diff --git a/pyproject.toml b/pyproject.toml index fcbe21e..1925c30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,6 @@ classifiers = [ tests = [ "pytest>=8.2.0,<9.0", "pytest-cov>=6.0.0,<7.0", - "tox>=4.23.2,<5.0", # Keep in sync with tox.ini minimum_version ] dev = [ "hatchling>=1.25.0,<2.0", @@ -53,6 +52,7 @@ dev = [ "P2108[tests]", ] [project.urls] +"PropLib Wiki" = "https://ntia.github.io/propagation-library-wiki/models/P2108/" "Python Wrapper Source" = "https://github.com/NTIA/p2108-python" "Python Wrapper Bug Tracker" = "https://github.com/NTIA/p2108-python/issues" "C++ Source" = "https://github.com/NTIA/p2108" diff --git a/src/ITS/ITU/PSeries/P2108/proplib_loader.py b/src/ITS/ITU/PSeries/P2108/proplib_loader.py index ff8312d..21702e3 100644 --- a/src/ITS/ITU/PSeries/P2108/proplib_loader.py +++ b/src/ITS/ITU/PSeries/P2108/proplib_loader.py @@ -43,6 +43,7 @@ """ import platform +import struct from ctypes import * from pathlib import Path @@ -67,15 +68,24 @@ def get_lib_name(lib_name: str) -> str: :param lib_name: The library name, with no extension or path, e.g., "P2108-1.0" :raises NotImplementedError: For platforms other than Windows, Linux, or macOS. + :raises RuntimeError: On Windows, if unable to determine system architecture. :return: The full filename, including path and extension, of the library. """ # Load the compiled library if platform.uname()[0] == "Windows": - lib_name += ".dll" + arch = struct.calcsize("P") * 8 # 32 or 64 + if arch == 64: + lib_name += "-x64.dll" + elif arch == 32: + lib_name += "-x86.dll" + else: + raise RuntimeError( + "Failed to determine system architecture for DLL loading" + ) elif platform.uname()[0] == "Linux": - lib_name += ".so" + lib_name += "-x86_64.so" elif platform.uname()[0] == "Darwin": - lib_name += ".dylib" + lib_name += "-universal.dylib" else: raise NotImplementedError("Your OS is not yet supported") # Library should be in the same directory as this file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/data b/tests/data new file mode 160000 index 0000000..8a8497d --- /dev/null +++ b/tests/data @@ -0,0 +1 @@ +Subproject commit 8a8497da1ce996d00ba6f291079117c5098b8ded diff --git a/tests/test_p2108.py b/tests/test_p2108.py index 212be5d..24df67b 100644 --- a/tests/test_p2108.py +++ b/tests/test_p2108.py @@ -1,24 +1,8 @@ -import csv -from pathlib import Path - import pytest from ITS.ITU.PSeries import P2108 -# Test data is expected to exist in parent repository -# (i.e., that this Python wrapper repo is cloned as a submodule of the base repo) -TEST_DATA_DIR = (Path(__file__).parent.parent.parent.parent / "tests") / "data" -ABSTOL__DB = 0.1 # Absolute tolerance, in dB, to ensure outputs match expected value - - -# TODO-TEMPLATE: Update CSV reader based on test data CSV structure -def read_csv_test_data(filename: str): - with open(TEST_DATA_DIR / filename) as f: - reader = csv.reader(f) - next(reader) # Skip header row - for row in reader: - # yield (inputs, rtn, output) - yield tuple(map(float, row[:-2])), int(row[-2]), float(row[-1]) +from .test_utils import ABSTOL__DB, read_csv_test_data @pytest.mark.parametrize( diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..73b9392 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,22 @@ +import csv +from pathlib import Path + +# 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 + +# Check if test data directory exists and is not empty +if not TEST_DATA_DIR.exists() or not any(TEST_DATA_DIR.iterdir()): + raise RuntimeError( + f"Test data is not available in {TEST_DATA_DIR}.\n Try running " + + "`git submodule init` and `git submodule update` to clone the test data submodule." + ) + + +def read_csv_test_data(filename: str): + with open(TEST_DATA_DIR / filename) as f: + reader = csv.reader(f) + next(reader) # Skip header row + for row in reader: + # yields (*inputs, rtn, output) + yield tuple(map(float, row[:-2])), int(row[-2]), float(row[-1]) diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 2104a05..0000000 --- a/tox.ini +++ /dev/null @@ -1,25 +0,0 @@ -[tox] -env_list = - py39 - py310 - py311 - py312 - py313 -min_version = 4.23.2 -skip_missing_interpreters = true -no_package = false - -[testenv] -description = Run tests with pytest and generate coverage report -package = wheel -wheel_build_env = .pkg -extras = tests -commands = pytest --cov-report term-missing --no-cov-on-fail --cov {posargs} - -[gh] ; GitHub Actions CI with tox-gh -python = - 3.9 = py39 - 3.10 = py310 - 3.11 = py311 - 3.12 = py312 - 3.13 = py313