Skip to content
4 changes: 2 additions & 2 deletions .github/workflows/run_unit_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ jobs:
run: poetry install -v
- name: Display installed dependency versions
run: poetry run pip list
- name: Run unit tests and code coverage
run: poetry run pytest ./tests/unit -v --cov=nitypes --junitxml=test_results/nitypes-${{ matrix.os }}-py${{ matrix.python-version }}.xml
- name: Run unit/acceptance/doc tests and code coverage
run: poetry run pytest -v --cov=nitypes --junitxml=test_results/nitypes-${{ matrix.os }}-py${{ matrix.python-version }}.xml
- name: Run benchmarks
run: poetry run pytest ./tests/benchmark -v --junitxml=test_results/nitypes-benchmarks-${{ matrix.os }}-py${{ matrix.python-version }}.xml
- name: Upload test results
Expand Down
8 changes: 4 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 22 additions & 4 deletions src/nitypes/_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@
)
from nitypes._numpy import isdtype as _np_isdtype

# Some of these doctests use types introduced in NumPy 2.0 (np.long and np.ulong) or highlight
# formatting differences between NumPy 1.x and 2.x (e.g. dtype=int32, 1.23 vs. np.float64(1.23)).
__doctest_requires__ = {("arg_to_float", "is_dtype", "validate_dtype"): ["numpy>=2.0"]}


def arg_to_float(
arg_description: str, value: SupportsFloat | None, default_value: float | None = None
Expand Down Expand Up @@ -143,6 +139,17 @@ def is_dtype(dtype: npt.DTypeLike, supported_dtypes: tuple[npt.DTypeLike, ...])

Unlike :any:`numpy.isdtype`, this function supports structured data types.

# Some of these doctests use types introduced in NumPy 2.0 (np.long and np.ulong) or highlight
# formatting differences between NumPy 1.x and 2.x (e.g. dtype=int32, 1.23 vs.
# np.float64(1.23)).
# We use inline version checks instead of __doctest_requires__ due to a pytest-doctestplus 1.6.0
# bug that doesn't properly parse version requirements like "numpy>=2.0".
# This check may exist in multiple places in the code. If you are making changes, you
# probably need them in every location.
# TODO: Remove these version checks when NumPy < 2.0 compatibility is no longer required.
>>> import numpy as np; import pytest
>>> version_tuple = tuple(map(int, np.__version__.split('.')[:2]))
>>> if version_tuple < (2, 0): pytest.skip("requires numpy>=2.0")
>>> is_dtype(np.float64, (np.float64, np.intc, np.long,))
True
>>> is_dtype("float64", (np.float64, np.intc, np.long,))
Expand Down Expand Up @@ -172,6 +179,17 @@ def is_dtype(dtype: npt.DTypeLike, supported_dtypes: tuple[npt.DTypeLike, ...])
def validate_dtype(dtype: npt.DTypeLike, supported_dtypes: tuple[npt.DTypeLike, ...]) -> None:
"""Validate a dtype-like object against a tuple of supported dtype-like objects.

# Some of these doctests use types introduced in NumPy 2.0 (np.long and np.ulong) or highlight
# formatting differences between NumPy 1.x and 2.x (e.g. dtype=int32, 1.23 vs.
# np.float64(1.23)).
# We use inline version checks instead of __doctest_requires__ due to a pytest-doctestplus 1.6.0
# bug that doesn't properly parse version requirements like "numpy>=2.0".
# This check may exist in multiple places in the code. If you are making changes, you
# probably need them in every location.
# TODO: Remove these version checks when NumPy < 2.0 compatibility is no longer required.
>>> import numpy as np; import pytest
>>> version_tuple = tuple(map(int, np.__version__.split('.')[:2]))
>>> if version_tuple < (2, 0): pytest.skip("requires numpy>=2.0")
>>> validate_dtype(np.float64, (np.float64, np.intc, np.long,))
>>> validate_dtype("float64", (np.float64, np.intc, np.long,))
>>> validate_dtype(np.float64, (np.byte, np.short, np.intc, np.int_, np.long, np.longlong))
Expand Down
11 changes: 9 additions & 2 deletions src/nitypes/complex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@

You can construct an array of complex integers from a sequence of tuples using :func:`numpy.array`:

>>> import numpy as np
# Some of these doctests use types introduced in NumPy 2.0 (np.long and np.ulong) or highlight
# formatting differences between NumPy 1.x and 2.x (e.g. dtype=int32, 1.23 vs. np.float64(1.23)).
# We use inline version checks instead of __doctest_requires__ due to a pytest-doctestplus 1.6.0
# bug that doesn't properly parse version requirements like "numpy>=2.0".
# This check may exist in multiple places in the code. If you are making changes, you
# probably need them in every location.
# TODO: Remove these version checks when NumPy < 2.0 compatibility is no longer required.
>>> import numpy as np; import pytest
>>> if tuple(map(int, np.__version__.split('.')[:2])) < (2, 0): pytest.skip("requires numpy>=2.0")
>>> np.array([(1, 2), (3, 4)], dtype=ComplexInt32DType)
array([(1, 2), (3, 4)], dtype=[('real', '<i2'), ('imag', '<i2')])

Expand Down Expand Up @@ -127,4 +135,3 @@
from nitypes.complex._dtypes import ComplexInt32Base, ComplexInt32DType

__all__ = ["convert_complex", "ComplexInt32DType", "ComplexInt32Base"]
__doctest_requires__ = {".": ["numpy>=2.0"]}
2 changes: 1 addition & 1 deletion src/nitypes/waveform/_digital/_port.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ def _mask_to_column_indices(
[8]
>>> _mask_to_column_indices(0xDEADBEEF, 32, "little")
[0, 1, 2, 3, 5, 6, 7, 9, 10, 11, 12, 13, 15, 16, 18, 19, 21, 23, 25, 26, 27, 28, 30, 31]
>>> _mask_to_column_indices(-1, 8)
>>> _mask_to_column_indices(-1, 8, "little")
Traceback (most recent call last):
...
ValueError: The mask must be a non-negative integer.
Expand Down
4 changes: 2 additions & 2 deletions src/nitypes/waveform/_digital/_waveform.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,10 +273,10 @@ class DigitalWaveform(Generic[TDigitalState]):
and the digital state from the actual and expected waveforms:

>>> result.failures[0] # doctest: +NORMALIZE_WHITESPACE
DigitalWaveformFailure(sample_index=0, expected_sample_index=0, signal_index=0, column_index=1,
DigitalWaveformFailure(sample_index=0, expected_sample_index=0, signal_index=0,
actual_state=<DigitalState.FORCE_UP: 1>, expected_state=<DigitalState.COMPARE_LOW: 3>)
>>> result.failures[1] # doctest: +NORMALIZE_WHITESPACE
DigitalWaveformFailure(sample_index=1, expected_sample_index=1, signal_index=0, column_index=1,
DigitalWaveformFailure(sample_index=1, expected_sample_index=1, signal_index=0,
actual_state=<DigitalState.FORCE_UP: 1>, expected_state=<DigitalState.COMPARE_LOW: 3>)

Timing information
Expand Down