Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ jobs:
runs-on: ubuntu-latest
- environment: tests-backends-py311
runs-on: ubuntu-latest
- environment: tests-run-deps
runs-on: ubuntu-slim

environment:
name: ci-checks
Expand All @@ -76,7 +78,7 @@ jobs:

- name: Test package
# Save some time; also at the moment of writing coverage crashes on python 3.13t
if: ${{ matrix.environment != 'tests-nogil' }}
if: ${{ matrix.environment != 'tests-nogil' && matrix.environment != 'tests-run-deps' }}
run: pixi run -e "${TASK_ENV}" tests-ci
env:
TASK_ENV: ${{ matrix.environment }}
Expand All @@ -85,6 +87,10 @@ jobs:
if: ${{ matrix.environment == 'tests-nogil' }}
run: pixi run -e tests-nogil tests --parallel-threads=4

- name: Run dependency tests
if: ${{ matrix.environment == 'tests-run-deps' }}
run: pixi run tests-run-deps-cov

- name: Upload coverage report
if: ${{ matrix.environment != 'tests-nogil' }}
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
Expand Down
5 changes: 5 additions & 0 deletions docs/_templates/autosummary/class.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ name | escape | underline }}

.. currentmodule:: {{ module }}

.. autoclass:: {{ fullname }}
5 changes: 5 additions & 0 deletions docs/_templates/autosummary/function.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ name | escape | underline }}

.. currentmodule:: {{ module }}

.. autofunction:: {{ fullname }}
5 changes: 5 additions & 0 deletions docs/_templates/testing-function.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{{ fullname.split('.')[-2:] | join('.') | escape | underline }}

.. currentmodule:: {{ module }}

.. autofunction:: {{ fullname }}
2 changes: 1 addition & 1 deletion docs/api-reference.md → docs/api-assorted.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# API Reference
# Assorted functions

```{eval-rst}
.. currentmodule:: array_api_extra
Expand Down
15 changes: 13 additions & 2 deletions docs/api-lazy.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Tools for lazy backends

These additional functions are meant to be used to support compatibility with
lazy backends, e.g. Dask or JAX:
Additional functions with special behaviour for lazy backends,
e.g. Dask or JAX:

```{eval-rst}
.. currentmodule:: array_api_extra
Expand All @@ -10,6 +10,17 @@ lazy backends, e.g. Dask or JAX:
:toctree: generated

lazy_apply
```

Testing utilities:

```{eval-rst}
.. currentmodule:: array_api_extra
.. autosummary::
:nosignatures:
:template: testing-function.rst
:toctree: generated

testing.lazy_xp_function
testing.patch_lazy_xp_functions
```
18 changes: 18 additions & 0 deletions docs/api-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Testing utilities (`xpx.testing`)

These testing utilities are intended to help transition from using
{py:mod}`numpy.testing`.

```{eval-rst}
.. currentmodule:: array_api_extra.testing
.. autosummary::
:nosignatures:
:template: testing-function.rst
:toctree: generated

assert_close
assert_equal
assert_less
```

See also utilities specific to testing lazy backends in {doc}`api-lazy`.
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,6 @@
("py:class", "_io.BytesIO"),
]

templates_path = ["_templates"]

always_document_param_types = True
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
:maxdepth: 2
:hidden:
self
api-reference.md
api-assorted.md
api-testing.md
api-lazy.md
contributing.md
contributors.md
Expand Down
156 changes: 156 additions & 0 deletions pixi.lock

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

16 changes: 16 additions & 0 deletions pixi.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ lint = { features = ["py314", "lint"], solve-group = "py314" }
docs = { features = ["py314", "docs"], solve-group = "py314" }
tests = { features = ["py314", "tests"], solve-group = "py314" }
tests-py314 = { features = ["py314", "tests"], solve-group = "py314" } # alias of tests
tests-run-deps = { features = ["py314", "tests-run-deps"], solve-group = "py314" }

# Some backends may pin numpy; use separate solve-group
dev = { features = ["py314", "lint", "tests", "docs", "dev", "backends"], solve-group = "backends" }
Expand Down Expand Up @@ -117,6 +118,21 @@ tests-ci = { depends-on = ["tests-cov", "tests-vendor"], description = "Run test
coverage = { cmd = "coverage html", depends-on = ["tests-cov"], description = "Generate test coverage html report", default-environment = "tests" }
open-coverage = { cmd = "open htmlcov/index.html", depends-on = ["coverage"], description = "Open test coverage report", default-environment = "tests" }

# tests with only run dependencies
[feature.tests-run-deps.dependencies]
pytest = ">=9.0.3"
pytest-cov = ">=7.1.0"

[feature.tests-run-deps.tasks.tests-run-deps]
cmd = "pytest -v run_deps_tests"
Comment thread
lucascolley marked this conversation as resolved.
description = "Run run-dependency tests"
default-environment = "tests-run-deps"

[feature.tests-run-deps.tasks.tests-run-deps-cov]
cmd = "pytest -v -ra --cov --cov-report=xml --cov-report=term --durations=20 run_deps_tests"
description = "Run run-dependency tests with coverage"
default-environment = "tests-run-deps"

[feature.docs.dependencies]
sphinx = ">=7.4.7"
furo = ">=2025.12.19"
Expand Down
18 changes: 14 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ run.source = ["array_api_extra"]
# mypy

[tool.mypy]
files = ["src", "tests", "vendor_tests"]
files = ["src", "tests", "vendor_tests", "run_deps_tests"]
python_version = "3.11"
warn_unused_configs = true
strict = true
Expand All @@ -80,6 +80,10 @@ disable_error_code = ["no-untyped-def"] # test(...) without -> None
module = ["vendor_tests/array_api_compat/*"]
ignore_errors = true

[[tool.mypy.overrides]]
module = ["run_deps_tests/*"]
disable_error_code = ["no-untyped-def"] # test(...) without -> None

# pyrefly

[tool.pyrefly.errors]
Expand Down Expand Up @@ -107,10 +111,14 @@ errors = { unannotated-return = false }
matches = "vendor_tests/*.py"
errors = { unannotated-return = false }

[[tool.pyrefly.sub-config]]
matches = "run_deps_tests/*.py"
errors = { unannotated-return = false }

# pyright

[tool.basedpyright]
include = ["src", "tests", "vendor_tests"]
include = ["src", "tests", "vendor_tests", "run_deps_tests"]
exclude = ["vendor_tests/array_api_compat"]
pythonVersion = "3.11"
pythonPlatform = "All"
Expand Down Expand Up @@ -138,6 +146,7 @@ reportUnknownLambdaType = false
executionEnvironments = [
{ root = "tests", reportPrivateUsage = false, reportUnknownArgumentType = false },
{ root = "vendor_tests", reportPrivateUsage = false, reportUnknownArgumentType = false },
{ root = "run_deps_tests", reportPrivateUsage = false, reportUnknownArgumentType = false },
{ root = "src" },
]

Expand Down Expand Up @@ -210,6 +219,7 @@ checks = [
"SA01", # data-apis/array-api-extra#87
"ES01", # most docstrings do not need an extended summary
]
exclude = [ # don't report on objects that match any of these regex
'.*test_*',
exclude_files = [
'^tests/.*',
'^vendor_tests/.*',
]
15 changes: 15 additions & 0 deletions run_deps_tests/test_run_deps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
"""Tests to run with only runtime dependencies."""

import importlib

import pytest

import array_api_extra.testing as xpt


def test_no_numpy() -> None:
"""Check `xpx.testing` assertion error message when NumPy is unavailable."""
if importlib.util.find_spec("numpy") is not None: # pyright: ignore[reportAttributeAccessIssue]
pytest.skip("Test for when `numpy` is not importable.")
with pytest.raises(ImportError, match=r"assertion.*require.*numpy"):
xpt.assert_equal(1, 1) # type: ignore[arg-type] # pyright: ignore[reportArgumentType]
Loading