From 75808fa50d9c94368c259f593699401210544bd7 Mon Sep 17 00:00:00 2001 From: Niklas Z Date: Sun, 21 Jul 2024 19:23:52 +0200 Subject: [PATCH] [10] Add coverage to CI pipeline (#12) * BLD: - first test of a GitHub CI for testing * FIX: - fixed wrong pip install and python versions in CI ? * FIX: - fixed loading of test files that do not contain test but dependencies that cannot be loaded ? * BUG: - escaped imports of unaccessible dependencies for test-file generation in GitHub CI tests by making the `if __name__ == "__main__"` include these imports and function definitions * TST: - test whether Cython build can be removed from GitHub actions for testing ? * TST: - reverted removal of Cython for testing * PKG: - moved the full package back into an `src`-folder BLD: - updated `pyproject.toml` and `setup.py` to account for the movement to the `src`-folder - removed dedicated Cython build from CI test pipeline * BLD: - changed CI pipeline target branches * BLD: - augmented CI checks with format, type, and lint checks * BUG: - fixed CI pipeline wrong folder include ? BLD: - added isort check * BUG: - fixed broken `isort` usage in CI? * FIX: - fixed missing `isort` dependency in CI? - fixed wrong import sort order in Cython Hermite functions * FIX: - fixed missing `colorama` dependency for `isort` in CI ? * FIX: - type-ignored Cython import that was not properly resolved by `pyright` ? * FIX: - fixed missing import of Cython module for `pyright` in CI ? * FIX: - again trying to resolve the wrong import error of Cython module by `pyright` in CI ? * FIX: - fixed wrong `pyright` Cython import error of Cython import in CI * BLD: - removed pushes to `develop` from the GitHub CI actions * BLD: - added missing comma to the name of the GitHub CI action * [10 develop] Add coverage to CI pipeline (#11) * DOC: - added Python versions and `black` code style to `README` * DOC: - added `isort` badge to `README` * TST: - added `--no-jit`-flag to `pytest` to enable proper coverage of Numba functions * tmp: - first test of CI with coverage report ? * BUG: - fixed failure of `pytest-xdist` and `pytest-cov` in GitHub CI (works locally) ? * BUG: - fixed accidentally placed `\` for `./tests` in coverage CI action ? * BUG: - added codecov to CI pipeline ? * TST: - tried to readd `pytest-xdist` for coverage reports ? * wip: - reset example Jupyter notebook number 3 * MAINT: - made `_get_num_workers` a function of the `_utils`-model TST: - increased coverage to 100% by testing `np.float32` x-values for the Hermite functions was well as super negative numbers of requested workers * DOC: - added setup, installation, and development instructions to `README` * DOC: - switched back from `README.rst` to `README.md` BLD: - made CI pipeline push actions apply to the main branch only --- .github/workflows/python-package.yml | 9 +- README.md | 134 ++++++++++++++++++ README.rst | 79 ----------- .../03_hermite_functions_performance.ipynb | 71 +--------- src/robust_hermite_ft/_utils/__init__.py | 19 +++ src/robust_hermite_ft/_utils/numba_helpers.py | 82 +++++++++++ .../_utils/parallel_helpers.py | 50 +++++++ .../hermite_functions/_interface.py | 38 +---- .../hermite_functions/_numba_funcs.py | 9 +- tests/conftest.py | 69 +++++++++ tests/test_hermite_functions.py | 18 ++- tests/test_utils.py | 83 +++++++++++ 12 files changed, 471 insertions(+), 190 deletions(-) create mode 100644 README.md delete mode 100644 README.rst create mode 100644 src/robust_hermite_ft/_utils/__init__.py create mode 100644 src/robust_hermite_ft/_utils/numba_helpers.py create mode 100644 src/robust_hermite_ft/_utils/parallel_helpers.py create mode 100644 tests/conftest.py create mode 100644 tests/test_utils.py diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 6227a1d..6b7e732 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -50,4 +50,11 @@ jobs: - name: Run tests run: | - pytest -n=auto -x + pytest --cov=robust_hermite_ft ./tests -n="auto" --cov-report=xml -x --no-jit + + - name: Upload coverage report + uses: codecov/codecov-action@v4.0.1 + with: + file: ./coverage.xml + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/README.md b/README.md new file mode 100644 index 0000000..3b4c7a5 --- /dev/null +++ b/README.md @@ -0,0 +1,134 @@ +# `robust_hermite_ft` + +[![python-3.9](https://img.shields.io/badge/python-3.9-blue.svg)](https://www.python.org/downloads/release/python-390/) +[![python-3.10](https://img.shields.io/badge/python-3.10-blue.svg)](https://www.python.org/downloads/release/python-3100/) +[![python-3.11](https://img.shields.io/badge/python-3.11-blue.svg)](https://www.python.org/downloads/release/python-3110/) +[![python-3.12](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/downloads/release/python-3120/) +[![code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) +[![code style: isort](https://img.shields.io/badge/code%20style-isort-000000.svg)](https://pycqa.github.io/isort/) +[![codecov](https://codecov.io/gh/MothNik/robust_hermite_ft/branch/10-improve-and-add-coverage-to-CI/graph/badge.svg)](https://codecov.io/gh/MothNik/robust_hermite_ft/branch/10-improve-and-add-coverage-to-CI) +

+ +You want to compute the Fourier transform of a signal, but your signal can be corrupted by outliers? If so, this package is for you even though you will have to say goodbye to the _"fast"_ in _Fast Fourier Transform_ 🏃🙅‍♀️ + +🏗️🚧 👷👷‍♂️👷‍♀️🏗️🚧 + +Currently under construction. Please check back later. + +## ⚙️ Setup and 🪛 Development + +### 🎁 Installation + +Currently, the package is not yet available on PyPI. To install it, you can clone the repository + +```bash +git clone https://github.com/MothNik/robust_hermite_ft.git +``` + +and from within the repositories root directory, install it with + +```bash +pip install -e . +``` + +for normal use or + +```bash +pip install -e .["dev"] +``` + +for development which will also install the development dependencies. + +⚠️ **Warning**: This will require a C-compiler to be installed on your system to +compile the Cython code. + +### 🔎 Code quality + +The following checks for `black`, `isort`, `pyright`, `ruff`, and +`cython-lint` - that are also part of the CI pipeline - can be run with + +```bash +black --check --diff --color ./examples ./src ./tests +isort --check --diff --color ./examples ./src ./tests +pyright +ruff check ./examples ./src ./tests +cython-lint src/robust_hermite_ft/hermite_functions/_c_hermite.pyx +``` + +### ✅❌ Tests + +To run the tests - almost like in the CI pipeline - you can use + +```bash +pytest --cov=robust_hermite_ft ./tests -n="auto" --cov-report=xml -x --no-jit +``` + +for parallelized testing whose coverage report will be stored in the folder +`./htmlcov`. + +## 〰️ Hermite functions + +Being the eigenfunctions of the Fourier transform, Hermite functions are excellent +candidates for the basis functions for a Least Squares Regression approach to the Fourier +transform. However, their evaluation can be a bit tricky. + +The module `hermite_functions` offers a numerically stable way to evaluate Hermite +functions or arbitrary order $n$ and argument - that can be scaled with a factor +$\alpha$: + +

+ +

+ +The Hermite functions are defined as + +

+ +

+ +with the Hermite polynomials + +

+ +

+ +By making use of logarithm tricks, the evaluation that might involve infinitely high +polynomial values and at the same time infinitely small Gaussians - that are on top of +that scaled by an infinitely high factorial - can be computed safely and yield accurate +results. + +For doing so, the relation between the dilated and the non-dilated Hermite functions + +

+ +

+ +and the recurrence relation for the Hermite functions + +

+ +

+ +are used, but not directly. Instead, the latest evaluated Hermite function is kept at a +value of either -1, 0, or +1 during the recursion and the logarithm of a correction +factor is tracked and applied when the respective Hermite function is finally evaluated +and stored. This approach is based on [[1]](#references). + +The implementation is tested against a symbolic evaluation with `sympy` that uses 200 +digits of precision and it can be shown that even orders as high as 2,000 can still be +computed even though neither the polynomial, the Gaussian nor the factorial can be +evaluated for this anymore. The factorial for example would already have overflown for +orders of 170 in `float64`-precision. + +

+ +

+ +As a sanity check, their orthogonality is part of the tests together with a test for +the fact that the absolute values of the Hermite functions for real input cannot exceed +the value $\frac{1}{\pi^{-\frac{1}{4}}\cdot\sqrt{\alpha}}$. + +## References + +- [1] Bunck B. F., A fast algorithm for evaluation of normalized Hermite + functions, BIT Numer Math (2009), 49, pp. 281–295, DOI: [https://doi.org/10.1007/s10543-009-0216-1](https://doi.org/10.1007/s10543-009-0216-1) diff --git a/README.rst b/README.rst deleted file mode 100644 index 55dc82c..0000000 --- a/README.rst +++ /dev/null @@ -1,79 +0,0 @@ -``robust_hermite_ft`` -===================== - -You want to compute the Fourier transform of a signal, but your signal can be corrupted -by outliers? If so, this package is for you even though you will have to say goodbye to -the *"fast"* in *Fast Fourier Transform* 🏃🙅‍♀️ - -🏗️🚧 👷👷‍♂️👷‍♀️🏗️🚧 - -Currently under construction. Please check back later. - -〰️ Hermite functions ---------------------- - -Being the eigenfunctions of the Fourier transform, Hermite functions are excellent -candidates for the basis functions for a Least Squares Regression approach to the Fourier -transform. However, their evaluation can be a bit tricky. - -The module ``hermite_functions`` offers a numerically stable way to evaluate Hermite -functions or arbitrary order :math:`n` and argument - that can be scaled with a factor -:math:`{\alpha}` - -.. image:: docs/hermite_functions/DilatedHermiteFunctions_DifferentScales.png - :width: 1000px - :align: center - -The Hermite functions are defined as - -.. image:: docs/hermite_functions/equations/DilatedHermiteFunctions.png - :width: 500px - :align: left - -with the Hermite polynomials - -.. image:: docs/hermite_functions/equations/DilatedHermitePolynomials.png - :width: 681px - :align: left - -By making use of logarithm tricks, the evaluation that might involve infinitely high -polynomial values and at the same time infinitely small Gaussians - that are on top of -that scaled by an infinitely high factorial - can be computed safely and yield accurate -results. - -For doing so, the relation between the dilated and the non-dilated Hermite functions - -.. image:: docs/hermite_functions/equations/HermiteFunctions_UndilatedToDilated.png - :width: 321px - :align: left - -and the recurrence relation for the Hermite functions - -.. image:: docs/hermite_functions/equations/HermiteFunctions_RecurrenceRelation.png - :width: 699px - :align: left - -are used, but not directly. Instead, the latest evaluated Hermite function is kept at a -value of either -1, 0, or +1 during the recursion and the logarithm of a correction -factor is tracked and applied when the respective Hermite function is finally evaluated -and stored. This approach is based on [1_]. - -This approach is tested against a symbolic evaluation with ``sympy`` that uses 200 -digits of precision and it can be shown that even orders as high as 2,000 can still be -computed even though neither the polynomial, the Gaussian nor the factorial can be -evaluated for this anymore. The factorial for example would already have overflown for -orders of 170 in ``float64``-precision. - -.. image:: docs/hermite_functions/DilatedHermiteFunctions_Stability.png - :width: 1000px - :align: center - -As a sanity check, their orthogonality is part of the tests together with a test for -the fact that the absolute values of the Hermite functions for real input cannot exceed -the value :math:`\frac{\pi^{-\frac{1}{4}}}{\sqrt{\alpha}}`. - -References ----------- -.. [1] Bunck B. F., A fast algorithm for evaluation of normalized Hermite - functions, BIT Numer Math (2009), 49, pp. 281–295, DOI: - ``_ \ No newline at end of file diff --git a/examples/03_hermite_functions_performance.ipynb b/examples/03_hermite_functions_performance.ipynb index c6d8b21..87e2333 100644 --- a/examples/03_hermite_functions_performance.ipynb +++ b/examples/03_hermite_functions_performance.ipynb @@ -14,7 +14,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -42,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -84,72 +84,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "f0285f48f94e472cb725c4e72cf4bc56", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n"
-      ],
-      "text/plain": []
-     },
-     "metadata": {},
-     "output_type": "display_data"
-    },
-    {
-     "data": {
-      "text/html": [
-       "
\n",
-       "
\n" - ], - "text/plain": [ - "\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "d0b416486374463886fb359a7d66acad", - "version_major": 2, - "version_minor": 0 - }, - "image/png": "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", - "text/html": [ - "\n", - "
\n", - "
\n", - " Figure\n", - "
\n", - " \n", - "
\n", - " " - ], - "text/plain": [ - "Canvas(toolbar=Toolbar(toolitems=[('Home', 'Reset original view', 'home', 'home'), ('Back', 'Back to previous …" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "plt.close(\"all\")\n", "\n", diff --git a/src/robust_hermite_ft/_utils/__init__.py b/src/robust_hermite_ft/_utils/__init__.py new file mode 100644 index 0000000..1c82f7e --- /dev/null +++ b/src/robust_hermite_ft/_utils/__init__.py @@ -0,0 +1,19 @@ +""" +Module :mod:`_utils` + +This module provides utility functionalities that are used throughout the package, e.g., + +- handling of Numba-related tasks + +""" + +# === Imports === + +from .numba_helpers import ( # noqa: F401 + NUMBA_NO_JIT_ARGV, + NUMBA_NO_JIT_ENV_KEY, + NumbaJitActions, + do_numba_normal_jit_action, + no_jit, +) +from .parallel_helpers import _get_num_workers # noqa: F401 diff --git a/src/robust_hermite_ft/_utils/numba_helpers.py b/src/robust_hermite_ft/_utils/numba_helpers.py new file mode 100644 index 0000000..53cbb5d --- /dev/null +++ b/src/robust_hermite_ft/_utils/numba_helpers.py @@ -0,0 +1,82 @@ +""" +Module :mod:`_utils.numba_helpers` + +This module implements auxiliary functionalities to handle Numba-related tasks, such as + +- checking whether Numba ``jit``-compilation has been explicitly specified to take no + effect, e.g., for test coverage + +""" + +# === Imports === + +import os +from enum import Enum +from typing import Callable + +# === Models === + +# an Enum that specifies the possible actions that can be taken regarding Numba +# ``jit``-compilation + + +class NumbaJitActions(Enum): + """ + Specifies the possible actions that can be taken regarding Numba + ``jit``-compilation. + + """ + + NORMAL = "0" + DEACTIVATE = "1" + + +# === Constants === + +# the runtime argument that is used to specify that Numba ``jit``-compilation should +# take no effect +NUMBA_NO_JIT_ARGV = "--no-jit" + +# the environment variable that is used to specify that Numba ``jit``-compilation should +# take no effect +NUMBA_NO_JIT_ENV_KEY = "CUSTOM_NUMBA_NO_JIT" + + +# whether the environment variable is set to specify that Numba ``jit``-compilation +# should take effect or not in the current runtime environment +do_numba_normal_jit_action = ( + os.environ.get(NUMBA_NO_JIT_ENV_KEY, NumbaJitActions.NORMAL.value) + == NumbaJitActions.NORMAL.value +) + + +# === Functions === + + +def no_jit(*args, **kwargs) -> Callable: + """ + Fake decorator that can be used to make sure that Numba ``jit``-compilation has no + effect. + + Parameters + ---------- + func : :class:`Callable` + The function that is decorated. + + args : :class:`tuple` + The fake positional arguments. + + kwargs : :class:`dict` + The fake keyword arguments. + + Returns + ------- + decorated_func : :class:`Callable` + The decorated function. + + """ + + def decorator(func: Callable) -> Callable: + return func + + return decorator diff --git a/src/robust_hermite_ft/_utils/parallel_helpers.py b/src/robust_hermite_ft/_utils/parallel_helpers.py new file mode 100644 index 0000000..83edf6d --- /dev/null +++ b/src/robust_hermite_ft/_utils/parallel_helpers.py @@ -0,0 +1,50 @@ +""" +Module :mod:`_utils.parallel_helpers` + +This module provides functionalities to handle parallel computations, e.g., + +- obtaining the number of threads available for the process + +""" + +# === Imports === + +import psutil + +# === Functions === + + +def _get_num_workers(workers: int) -> int: + """ + Gets the number of available workers for the process calling this function. + + Parameters + ---------- + workers : :class:`int` + Number of workers requested. + + Returns + ------- + workers : :class:`int` + Number of workers available. + + """ + + # the number of workers may not be less than -1 + if workers < -1: + raise ValueError( + f"Expected 'workers' to be greater or equal to -1 but got {workers}." + ) + + # then, the maximum number of workers is determined ... + # NOTE: the following does not count the number of total threads, but the number of + # threads available to the process calling this function + process = psutil.Process() + max_workers = len(process.cpu_affinity()) # type: ignore + del process + + # ... and overwrites the number of workers if it is set to -1 + workers = max_workers if workers == -1 else workers + + # the number of workers is limited between 1 and the number of available threads + return max(1, min(workers, max_workers)) diff --git a/src/robust_hermite_ft/hermite_functions/_interface.py b/src/robust_hermite_ft/hermite_functions/_interface.py index 7608dda..d2d809f 100644 --- a/src/robust_hermite_ft/hermite_functions/_interface.py +++ b/src/robust_hermite_ft/hermite_functions/_interface.py @@ -16,8 +16,8 @@ from typing import Tuple, Union import numpy as np -import psutil +from .._utils import _get_num_workers from ._numba_funcs import nb_hermite_function_basis as _nb_hermite_function_basis from ._numpy_funcs import _hermite_function_basis as _np_hermite_function_basis from ._numpy_funcs import _single_hermite_function as _np_single_hermite_function @@ -29,42 +29,6 @@ # === Auxiliary Functions === -def _get_num_workers(workers: int) -> int: - """ - Gets the number of available workers for the process calling this function. - - Parameters - ---------- - workers : :class:`int` - Number of workers requested. - - Returns - ------- - workers : :class:`int` - Number of workers available. - - """ - - # the number of workers may not be less than -1 - if workers < -1: - raise ValueError( - f"Expected 'workers' to be greater or equal to -1 but got {workers}." - ) - - # then, the maximum number of workers is determined ... - # NOTE: the following does not count the number of total threads, but the number of - # threads available to the process calling this function - process = psutil.Process() - max_workers = len(process.cpu_affinity()) # type: ignore - del process - - # ... and overwrites the number of workers if it is set to -1 - workers = max_workers if workers == -1 else workers - - # the number of workers is limited between 1 and the number of available threads - return max(1, min(workers, max_workers)) - - def _get_validated_hermite_function_input( x: Union[float, int, np.ndarray], n: int, diff --git a/src/robust_hermite_ft/hermite_functions/_numba_funcs.py b/src/robust_hermite_ft/hermite_functions/_numba_funcs.py index c440207..051658b 100644 --- a/src/robust_hermite_ft/hermite_functions/_numba_funcs.py +++ b/src/robust_hermite_ft/hermite_functions/_numba_funcs.py @@ -14,6 +14,8 @@ from numpy import abs as np_abs from numpy import exp, log, sqrt, square +from .._utils.numba_helpers import do_numba_normal_jit_action + # === Functions === @@ -130,7 +132,10 @@ def _hermite_function_basis( # if available, the functions are compiled by Numba try: - from numba import jit + if do_numba_normal_jit_action: # pragma: no cover + from numba import jit + else: + from .._utils import no_jit as jit # if it is enabled, the functions are compiled nb_hermite_function_basis = jit( @@ -141,7 +146,7 @@ def _hermite_function_basis( # otherwise, the NumPy-based implementation of the Hermite functions is declared as the # Numba-based implementation -except ImportError: +except ImportError: # pragma: no cover from ._numpy_funcs import _hermite_function_basis nb_hermite_function_basis = _hermite_function_basis diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..ed1b951 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,69 @@ +""" +Configuration file for ``pytest``. + +This handles + +- the command line option to deactivate Numba ``jit``-compilation so that the coverage + tests can be run properly + +""" + +# === Imports === + +import os +from enum import Enum + +# === Models === + +# NOTE: the following code is copied from src/robust_hermite_ft/_utils/numba_helpers.py +# to avoid an import of the package before the environment variable is set + +# an Enum that specifies the possible actions that can be taken regarding Numba +# ``jit``-compilation + + +class NumbaJitActions(Enum): + """ + Specifies the possible actions that can be taken regarding Numba + ``jit``-compilation. + + """ + + NORMAL = "0" + DEACTIVATE = "1" + + +# === Constants === + +# the runtime argument that is used to specify that Numba ``jit``-compilation should +# take no effect +NUMBA_NO_JIT_ARGV = "--no-jit" + +# the environment variable that is used to specify that Numba ``jit``-compilation should +# take no effect +NUMBA_NO_JIT_ENV_KEY = "CUSTOM_NUMBA_NO_JIT" + +# === Functions === + + +def pytest_addoption(parser): + """ + Adds the command line option to deactivate Numba ``jit``-compilation. + + """ + + parser.addoption( + NUMBA_NO_JIT_ARGV, + action="store_true", + help="Disable Numba JIT compilation", + ) + + +def pytest_configure(config): + """ + Configures the runtime environment based on the command line option. + + """ + + if config.getoption(NUMBA_NO_JIT_ARGV): + os.environ[NUMBA_NO_JIT_ENV_KEY] = NumbaJitActions.DEACTIVATE.value diff --git a/tests/test_hermite_functions.py b/tests/test_hermite_functions.py index 505443d..660f12c 100644 --- a/tests/test_hermite_functions.py +++ b/tests/test_hermite_functions.py @@ -9,7 +9,7 @@ import os from dataclasses import dataclass from enum import Enum, auto -from typing import Any, Callable, Dict, Generator, Tuple, Union +from typing import Any, Callable, Dict, Generator, Tuple, Type, Union import numpy as np import pytest @@ -154,6 +154,7 @@ def setup_hermite_function_implementations( # === Tests === +@pytest.mark.parametrize("x_dtype", [np.float32, np.float64]) @pytest.mark.parametrize( "implementation", [ @@ -168,6 +169,7 @@ def test_dilated_hermite_function_basis( ReferenceHermiteFunctionBasis, None, None ], implementation: HermiteFunctionImplementations, + x_dtype: Type, ) -> None: """ This test checks the implementation of the function @@ -184,18 +186,26 @@ def test_dilated_hermite_function_basis( implementation=implementation ) numerical_herm_func_basis = func( - x=reference.x_values, # type: ignore + x=reference.x_values.astype(x_dtype), # type: ignore n=reference.n, alpha=reference.alpha, **kwargs, ) # the reference values are compared with the numerical results + # NOTE: the numerical tolerance has to be based on the data type of the x-values + # because the build-up of rounding errors is quite pronounced due to the + # x-values being involved in the recursions + if x_dtype == np.float32: + atol, rtol = 1e-5, 1e-5 + else: + atol, rtol = 1e-12, 1e-12 + assert np.allclose( numerical_herm_func_basis, reference.hermite_function_basis, - atol=1e-12, - rtol=1e-12, + atol=atol, + rtol=rtol, ), f"For n = {reference.n} and alpha = {reference.alpha}" diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..b0d62a0 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,83 @@ +""" +This test suite implements the tests for the module :mod:`_utils`. + +""" + +# === Imports === + +from typing import Literal, Union + +import pytest +from psutil import Process + +from robust_hermite_ft._utils import _get_num_workers + +# === Types === + +# the type of the number of workers that need to be evaluated dynamically with +# ``psutil`` +DynamicWorkers = Literal["__dynamic__"] + +# === Constants === + +# the value of the number of workers that need to be evaluated dynamically with +# ``psutil`` +DYNAMIC_WORKERS = "__dynamic__" + + +# === Tests === + + +@pytest.mark.parametrize( + "workers, expected", + [ + ( # Test 0) 1 worker requested + 1, + 1, + ), + ( # Test 1) 1000 workers requested which should be limited to the maximum + 1_000, + "__dynamic__", + ), + ( # Test 2) 0 workers requested which should be limited to the minimum + 0, + 1, + ), + ( # Test 3) -1 workers requested which should be limited to the maximum + -1, + "__dynamic__", + ), + ( # Test 4) -2 workers requested which should raise a ValueError + -2, + ValueError("Expected 'workers' to be greater or equal to -1"), + ), + ], +) +def test_get_num_workers(workers: int, expected: Union[int, DynamicWorkers, Exception]): + """ + Tests that the function :func:`_get_num_workers` returns the expected number of + workers or raises the expected exception. + + """ + + # in the case of a ValueError, the exception is raised + if isinstance(expected, Exception): + # the function is called and the exception is checked + with pytest.raises(type(expected), match=str(expected)): + _get_num_workers(workers=workers) + + return + + # the number of workers is determined + num_workers = _get_num_workers(workers=workers) + + # the number of workers is checked + # for the dynamic case, the number of workers is determined with ``psutil`` + if expected == DYNAMIC_WORKERS: + # the number of workers is determined dynamically + process = Process() + expected = len(process.cpu_affinity()) # type: ignore + del process + + # the check is performed + assert num_workers == expected