From a9e0afb7fa8324f538e80d3f516b89ca54aa06ed Mon Sep 17 00:00:00 2001 From: Nathaniel Starkman Date: Wed, 8 Jan 2025 11:22:54 -0500 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=B7=20build(benchmarks):=20add=20more?= =?UTF-8?q?=20benchmarks=20and=20config=20(#363)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 👷 build(benchmarks): add more benchmarks and config * ⬆️ dep-bump(deps): bump and set optional dependency pins Signed-off-by: Nathaniel Starkman --- .python-version | 2 +- pyproject.toml | 26 ++--- tests/benchmark/test_dimensions.py | 94 ------------------ tests/benchmark/test_dims.py | 78 +++++++++++++++ tests/benchmark/test_quaxed.py | 19 ++-- tests/benchmark/test_units.py | 79 +++++++-------- tests/benchmark/test_unitsystems.py | 122 +++++++++++++++++++++++ uv.lock | 145 ++++++++++++++++++++-------- 8 files changed, 363 insertions(+), 202 deletions(-) delete mode 100644 tests/benchmark/test_dimensions.py create mode 100644 tests/benchmark/test_dims.py create mode 100644 tests/benchmark/test_unitsystems.py diff --git a/.python-version b/.python-version index 2c073331..e4fba218 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.11 +3.12 diff --git a/pyproject.toml b/pyproject.toml index 08b3674c..e2042bc1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,7 +54,7 @@ all = ["unxt[backend-astropy,interop-gala,interop-mpl]"] backend-astropy = ["astropy>=6.0"] interop-gala = ["gala>=1.8"] - interop-mpl = ["matplotlib>=3.4"] + interop-mpl = ["matplotlib>=3.5"] [project.urls] "Bug Tracker" = "https://github.com/GalacticDynamics/unxt/issues" @@ -80,12 +80,12 @@ "pytz>=2024.2", # for copyright date "sphinx-book-theme==1.1.3", "sphinx-prompt>=1.8.0", - "sphinx-tippy", + "sphinx-tippy>=0.4.3", "sphinx>=7.0", - "sphinx_autodoc_typehints", - "sphinx_copybutton", - "sphinx_design", - "sphinx_togglebutton", + "sphinx_autodoc_typehints>=3.0.0", + "sphinx_copybutton>=0.5.2", + "sphinx_design>=0.6.1", + "sphinx_togglebutton>=0.3.2", "sphinxext-opengraph>=0.9.1", "sphinxext-rediraffe>=0.2.7", ] @@ -94,13 +94,17 @@ "hypothesis[numpy]>=6.112.2", "pytest>=8.3.3", "pytest-arraydiff>=0.6.1", - "pytest-codspeed", - "pytest-cov >=3", - "pytest-env", - "pytest-github-actions-annotate-failures", + "pytest-benchmark>=5.1", + "pytest-codspeed>=3.1", + "pytest-cov>=3", + "pytest-env>=1.1.5", + "pytest-github-actions-annotate-failures>=0.2.0", "sybil>=8.0.0", +] + pytest-benchmark-parallel = [ + "pytest-xdist>=3.6.1", ] - test-mpl = ["pytest-mpl"] + test-mpl = ["pytest-mpl>=0.17.0"] test-all = [{ include-group = "test" }, { include-group = "test-mpl" }] diff --git a/tests/benchmark/test_dimensions.py b/tests/benchmark/test_dimensions.py deleted file mode 100644 index 4ef59b28..00000000 --- a/tests/benchmark/test_dimensions.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Benchmark tests for quaxified jax.""" - -import jax -import pytest - -import unxt as u - -LENGTH = u.dimension("length") - - -@pytest.fixture -def func_dimension_is_length(): - return lambda x: u.dimension(x) == LENGTH - - -@pytest.fixture -def func_dimension_of_length(): - return lambda x: u.dimension_of(x) == LENGTH - - -##################################################################### -# `dimension` - - -@pytest.mark.parametrize( - "args", - [ - (u.dimension("length"),), # -> Dimension('length') - ("length",), # -> Dimension('length') - ], -) -@pytest.mark.benchmark(group="dimensions", warmup=False) -def test_dimension(args): - """Test calling `unxt.dimension`.""" - _ = u.dimension(*args) - - -@pytest.mark.parametrize( - "args", - [ - (u.dimension("length"),), # -> Dimension('length') - ("length",), # -> Dimension('length') - ], -) -@pytest.mark.benchmark(group="dimensions", warmup=True) -def test_dimension_execute(func_dimension_is_length, args): - """Test the speed of calling the function.""" - _ = jax.block_until_ready(func_dimension_is_length(*args)) - - -##################################################################### -# `dimension_of` - - -@pytest.mark.parametrize( - "args", - [ - (u.dimension("length"),), # -> Dimension('length') - (u.unit("m"),), # -> Dimension('length') - (u.Quantity(1, "m"),), # -> Dimension('length') - (2,), # -> None - ], -) -@pytest.mark.benchmark(group="dimensions", warmup=False) -def test_dimension_of(args): - """Test calling `unxt.dimension_of`.""" - _ = u.dimension_of(*args) - - -@pytest.mark.parametrize( - "args", - [ - (u.Quantity(1, "m"),), # -> Dimension('length') - ], -) -@pytest.mark.benchmark(group="dimensions", warmup=False) -def test_dimension_of_jit_compile(func_dimension_of_length, args): - """Test the speed of jitting.""" - _ = jax.jit(func_dimension_of_length).lower(*args).compile() - - -@pytest.mark.parametrize( - "args", - [ - (u.dimension("length"),), # -> Dimension('length') - (u.unit("m"),), # -> Dimension('length') - (u.Quantity(1, "m"),), # -> Dimension('length') - (2,), # -> None - ], -) -@pytest.mark.benchmark(group="dimensions", warmup=True) -def test_dimension_of_execute(func_dimension_of_length, args): - """Test the speed of calling the function.""" - _ = jax.block_until_ready(func_dimension_of_length(*args)) diff --git a/tests/benchmark/test_dims.py b/tests/benchmark/test_dims.py new file mode 100644 index 00000000..bcdf341f --- /dev/null +++ b/tests/benchmark/test_dims.py @@ -0,0 +1,78 @@ +"""Benchmark tests for quaxified jax.""" + +import equinox as eqx +import jax +import pytest +from jaxlib.xla_extension import PjitFunction + +import unxt as u + + +@pytest.fixture +def func_dimension() -> PjitFunction: + return eqx.filter_jit(u.dimension) + + +@pytest.fixture +def func_dimension_of() -> PjitFunction: + return eqx.filter_jit(u.dimension_of) + + +##################################################################### +# `dimension` + +args = [(u.dimension("length"),), ("length",)] + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="dimensions", warmup=False, max_time=1.0) +def test_dimension(args): + """Test calling `unxt.dimension`.""" + _ = u.dimension(*args) + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="dimensions", warmup=False, max_time=1.0) +def test_dimension_jit_compile(func_dimension, args): + """Test the speed of jitting.""" + _ = func_dimension.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="dimensions", warmup=True, max_time=1.0) +def test_dimension_execute(func_dimension, args): + """Test the speed of calling the function.""" + _ = jax.block_until_ready(func_dimension(*args)) + + +##################################################################### +# `dimension_of` + + +args = [ + (u.dimension("length"),), # -> Dimension('length') + (u.unit("m"),), # -> Dimension('length') + (u.Quantity(1, "m"),), # -> Dimension('length') + (2,), # -> None +] + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="dimensions", warmup=False, max_time=1.0) +def test_dimension_of(args): + """Test calling `unxt.dimension_of`.""" + _ = u.dimension_of(*args) + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="dimensions", warmup=False, max_time=1.0) +def test_dimension_of_jit_compile(func_dimension_of, args): + """Test the speed of jitting.""" + _ = func_dimension_of.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="dimensions", warmup=True, max_time=1.0) +def test_dimension_of_execute(func_dimension_of, args): + """Test the speed of calling the function.""" + _ = jax.block_until_ready(func_dimension_of(*args)) diff --git a/tests/benchmark/test_quaxed.py b/tests/benchmark/test_quaxed.py index ed36885f..8ffa2ad3 100644 --- a/tests/benchmark/test_quaxed.py +++ b/tests/benchmark/test_quaxed.py @@ -1,4 +1,4 @@ -"""Benchmark tests for quaxified jax.""" +"""Benchmark tests for quaxed functions on quantities.""" from collections.abc import Callable from typing import Any, TypeAlias, TypedDict @@ -12,25 +12,19 @@ import unxt as u -x_nodim = u.Quantity(jnp.linspace(0, 1, 1000), "") -x_length = u.Quantity(jnp.linspace(0, 1, 1000), "m") -x_angle = u.Quantity(jnp.linspace(0, 1, 1000), "rad") - - Args: TypeAlias = tuple[Any, ...] +x = jnp.linspace(0, 1, 1000) +x_nodim = u.Quantity(x, "") +x_length = u.Quantity(x, "m") +x_angle = u.Quantity(x, "rad") + def process_func(func: Callable[..., Any], args: Args) -> tuple[Compiled, Args]: """JIT and compile the function.""" return jax.jit(func), args -# def process_execute_func(func, args): -# """JIT and compile the function.""" -# compiled_eager_func = jax.jit(func).lower(*args).compile() -# return compiled_eager_func, args - - class ParameterizationKWArgs(TypedDict): """Keyword arguments for a pytest parameterization.""" @@ -57,6 +51,7 @@ def process_pytest_argvalues( return {"argvalues": processed_argvalues, "ids": ids} +# TODO: also benchmark UncheckedQuantity funcs_and_args: list[tuple[Callable[..., Any], Unpack[tuple[Args, ...]]]] = [ (jnp.abs, (x_nodim,), (x_length,)), (jnp.acos, (x_nodim,)), diff --git a/tests/benchmark/test_units.py b/tests/benchmark/test_units.py index fbca1a15..ec56c6f1 100644 --- a/tests/benchmark/test_units.py +++ b/tests/benchmark/test_units.py @@ -1,78 +1,73 @@ """Benchmark tests for `unxt.units`.""" +import equinox as eqx import jax import pytest +from jaxlib.xla_extension import PjitFunction import unxt as u -METER = u.unit("m") - @pytest.fixture -def func_unit_is_length(): - return lambda x: u.unit(x) == METER +def func_unit() -> PjitFunction: + return eqx.filter_jit(u.unit) @pytest.fixture -def func_unit_of_length(): - return lambda x: u.unit_of(x) == METER +def func_unit_of() -> PjitFunction: + # need to filter_jit because arg can be a array or other object + return eqx.filter_jit(u.unit_of) ##################################################################### # `unit` +args = [(u.unit("meter"),), ("meter",)] + -@pytest.mark.parametrize( - "args", - [ - (u.unit("meter"),), # -> Unit('meter') - ("meter",), # -> Unit('meter') - ], -) -@pytest.mark.benchmark(group="units", warmup=False) +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="units", warmup=False, max_time=1.0) def test_unit(args): """Test calling `unxt.unit`.""" _ = u.unit(*args) -@pytest.mark.parametrize( - "args", - [ - (u.unit("meter"),), # -> Unit('meter') - ("meter",), # -> Unit('meter') - ], -) -@pytest.mark.benchmark(group="units", warmup=True) -def test_unit_execute(func_unit_is_length, args): +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="units", warmup=True, max_time=1.0) +def test_unit_jit_compile(func_unit, args): + """Test the speed of calling the function.""" + _ = func_unit.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="units", warmup=True, max_time=1.0) +def test_unit_execute(func_unit, args): """Test the speed of calling the function.""" - _ = jax.block_until_ready(func_unit_is_length(*args)) + _ = jax.block_until_ready(func_unit(*args)) ##################################################################### # `unit_of` +args = [(u.unit("meter"),), (u.Quantity(1, "m"),), (2,)] -@pytest.mark.parametrize( - "args", - [ - (u.unit("meter"),), # -> Unit('meter') - (u.Quantity(1, "m"),), # -> Unit('meter') - (2,), - ], -) -@pytest.mark.benchmark(group="units", warmup=False) + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="units", warmup=False, max_time=1.0) def test_unit_of(args): """Test calling `unxt.unit_of`.""" _ = u.unit_of(*args) -@pytest.mark.parametrize( - "args", - [ - (u.Quantity(1, "m"),), # -> Unit('meter') - ], -) -@pytest.mark.benchmark(group="units", warmup=False) -def test_unit_of_jit_compile(func_unit_of_length, args): +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="units", warmup=False, max_time=1.0) +def test_unit_of_jit_compile(func_unit_of, args): """Test the speed of jitting a function.""" - _ = jax.jit(func_unit_of_length).lower(*args).compile() + _ = func_unit_of.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="units", warmup=True, max_time=1.0) +def test_unit_of_execute(func_unit_of, args): + """Test the speed of calling the function.""" + _ = jax.block_until_ready(func_unit_of(*args)) diff --git a/tests/benchmark/test_unitsystems.py b/tests/benchmark/test_unitsystems.py new file mode 100644 index 00000000..a28fcf15 --- /dev/null +++ b/tests/benchmark/test_unitsystems.py @@ -0,0 +1,122 @@ +"""Benchmark tests for `unxt.unitsystems`.""" + +import equinox as eqx +import jax +import pytest +from jaxlib.xla_extension import PjitFunction + +import unxt as u + + +@pytest.fixture +def func_unitsystem() -> PjitFunction: + # The lambda function is necessary because JIT doesn't understand how to + # introspect the signature of a multiple-dispatch function. + return eqx.filter_jit(lambda *args: u.unitsystem(*args)) + + +@pytest.fixture +def func_unitsystem_of() -> PjitFunction: + return eqx.filter_jit(u.unitsystem_of) + + +@pytest.fixture +def func_equivalent() -> PjitFunction: + return eqx.filter_jit(u.unitsystems.equivalent) + + +##################################################################### +# `dimension` + +args = [ + (u.unitsystem("kpc", "Myr", "Msun", "radian"),), + (("kpc", "Myr", "Msun", "radian"),), + ("kpc", "Myr", "Msun", "radian"), + (), # -> dimensionless + (None,), # -> dimensionless + ("galactic",), + (u.unitsystem("galactic"), "candela"), + (u.unitsystems.StandardUSysFlag, "galactic"), + (u.unitsystems.DynamicalSimUSysFlag, "m", "kg"), +] + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=False, max_time=1.0) +def test_unitsystem(args): + """Test calling `unxt.unitsystem`.""" + _ = u.unitsystem(*args) + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=False, max_time=1.0) +def test_unitsystem_jit_compile(func_unitsystem, args): + """Test the speed of jitting.""" + _ = func_unitsystem.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=True, max_time=1.0) +def test_unitsystem_execute(func_unitsystem, args): + """Test the speed of calling the function.""" + _ = jax.block_until_ready(func_unitsystem(*args)) + + +##################################################################### +# `unitsystem_of` + + +args = [ + (u.unitsystem("kpc", "Myr", "Msun", "radian"),), + (2,), # -> None +] + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=False, max_time=1.0) +def test_unitsystem_of(args): + """Test calling `unxt.unitsystem_of`.""" + _ = u.unitsystem_of(*args) + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=False, max_time=1.0) +def test_unitsystem_of_jit_compile(func_unitsystem_of, args): + """Test the speed of jitting.""" + _ = func_unitsystem_of.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=True, max_time=1.0) +def test_unitsystem_of_execute(func_unitsystem_of, args): + """Test the speed of calling the function.""" + _ = jax.block_until_ready(func_unitsystem_of(*args)) + + +##################################################################### +# `equivalent` + +args = [ + (u.unitsystem("kpc", "Myr", "Msun", "radian"), u.unitsystems.galactic), +] + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=False, max_time=1.0) +def test_equivalent(args): + """Test calling `unxt.equivalent`.""" + _ = u.unitsystems.equivalent(*args) + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=False, max_time=1.0) +def test_equivalent_jit_compile(func_equivalent, args): + """Test the speed of jitting.""" + _ = func_equivalent.lower(*args).compile() + + +@pytest.mark.parametrize("args", args, ids=str) +@pytest.mark.benchmark(group="unitsystems", warmup=True, max_time=1.0) +def test_equivalent_execute(func_equivalent, args): + """Test the speed of calling the function.""" + _ = jax.block_until_ready(func_equivalent(*args)) diff --git a/uv.lock b/uv.lock index d3a88987..587285ed 100644 --- a/uv.lock +++ b/uv.lock @@ -566,6 +566,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/15/9f/3be7f03bf66c8d7d2956b727d984595e4af899f3c15ef2c653029008bf3b/equinox-0.11.8-py3-none-any.whl", hash = "sha256:552292b473956693e8e8973bdae9b58aaec54fd48e192921beb82995e3a9c995", size = 179319 }, ] +[[package]] +name = "execnet" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bb/ff/b4c0dc78fbe20c3e59c0c7334de0c27eb4001a2b2017999af398bf730817/execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3", size = 166524 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/09/2aea36ff60d16dd8879bdb2f5b3ee0ba8d08cbbdcdfe870e695ce3784385/execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc", size = 40612 }, +] + [[package]] name = "executing" version = "2.1.0" @@ -1680,6 +1689,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842 }, ] +[[package]] +name = "py-cpuinfo" +version = "9.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335 }, +] + [[package]] name = "pyasn1" version = "0.6.1" @@ -1748,11 +1766,11 @@ wheels = [ [[package]] name = "pygments" -version = "2.16.0" +version = "2.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/11/a0/7e8158246de1f7062a9a01963503d83dc64a6d1d6b2e3aa2e46e92b94314/Pygments-2.16.0.tar.gz", hash = "sha256:4f6df32f21dca07a54a0a130bda9a25d2241e9e0a206841d061c85a60cc96145", size = 4873265 } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/9a/40aa8248006cbe35b8bffc83cfca0ffdf68306d4354bca334a25b4b275a0/Pygments-2.16.0-py3-none-any.whl", hash = "sha256:90e046f72a58b65edd7e6bd99926ffa1b9d19e23db166905046bea0069c0894d", size = 1164744 }, + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, ] [[package]] @@ -1792,20 +1810,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cf/2a/2f8efb1ef8048aec7b44f37bc3fecb8c2c22e3238781d3e93c58d9c89268/pytest_arraydiff-0.6.1-py3-none-any.whl", hash = "sha256:64be1cc8e79874203eca80b1959134b8bb7a47b41cf7631310ba7fe6e5840694", size = 10042 }, ] +[[package]] +name = "pytest-benchmark" +version = "5.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "py-cpuinfo" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/39/d0/a8bd08d641b393db3be3819b03e2d9bb8760ca8479080a26a5f6e540e99c/pytest-benchmark-5.1.0.tar.gz", hash = "sha256:9ea661cdc292e8231f7cd4c10b0319e56a2118e2c09d9f50e1b3d150d2aca105", size = 337810 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/d6/b41653199ea09d5969d4e385df9bbfd9a100f28ca7e824ce7c0a016e3053/pytest_benchmark-5.1.0-py3-none-any.whl", hash = "sha256:922de2dfa3033c227c96da942d1878191afa135a29485fb942e85dff1c592c89", size = 44259 }, +] + [[package]] name = "pytest-codspeed" -version = "3.0.0" +version = "3.1.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi" }, - { name = "filelock" }, { name = "pytest" }, { name = "rich" }, - { name = "setuptools", marker = "python_full_version >= '3.12' or (extra == 'extra-4-unxt-cpu' and extra == 'extra-4-unxt-cuda') or (extra == 'extra-4-unxt-cpu' and extra == 'extra-4-unxt-cuda12') or (extra == 'extra-4-unxt-cpu' and extra == 'extra-4-unxt-cuda12-local') or (extra == 'extra-4-unxt-cpu' and extra == 'extra-4-unxt-k8s') or (extra == 'extra-4-unxt-cpu' and extra == 'extra-4-unxt-rocm') or (extra == 'extra-4-unxt-cuda' and extra == 'extra-4-unxt-cuda12') or (extra == 'extra-4-unxt-cuda' and extra == 'extra-4-unxt-cuda12-local') or (extra == 'extra-4-unxt-cuda' and extra == 'extra-4-unxt-k8s') or (extra == 'extra-4-unxt-cuda' and extra == 'extra-4-unxt-rocm') or (extra == 'extra-4-unxt-cuda12' and extra == 'extra-4-unxt-cuda12-local') or (extra == 'extra-4-unxt-cuda12' and extra == 'extra-4-unxt-k8s') or (extra == 'extra-4-unxt-cuda12' and extra == 'extra-4-unxt-rocm') or (extra == 'extra-4-unxt-cuda12-local' and extra == 'extra-4-unxt-k8s') or (extra == 'extra-4-unxt-cuda12-local' and extra == 'extra-4-unxt-rocm') or (extra == 'extra-4-unxt-k8s' and extra == 'extra-4-unxt-rocm')" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ba/78/40e613268cce75b11cd35ea9fdc280fb648e2233fc4187c76112377b1869/pytest_codspeed-3.0.0.tar.gz", hash = "sha256:c5b80100ea32dd44079bb2db298288763eb8fe859eafa1650a8711bd2c32fd06", size = 12540 } +sdist = { url = "https://files.pythonhosted.org/packages/6a/5f/d03f78b4ba6df28ab78fe49b70319f9d5c2d6c15c966c18038b3a534b729/pytest_codspeed-3.1.1.tar.gz", hash = "sha256:bed35cc6a381786af70ccbcec35a1bbc4c1246da7d63151aba799ae2bb655fe4", size = 18214 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a6/79/fa067436033410ac16e5d14b61b1a5f355688930ca8c6a8c61a52b2cbe0a/pytest_codspeed-3.0.0-py3-none-any.whl", hash = "sha256:ab1b8cb9da72e0d394718333d1abc7bea38524e09fd4854bc70a91abbcdcb20e", size = 15640 }, + { url = "https://files.pythonhosted.org/packages/ff/26/bcfe1613fbbaf1d21ca8d2ed4fd2e1f38b8dde3b96fdf5782d97ce66976d/pytest_codspeed-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d988c795c0f69f9713fa291b99ccaaf74686dbaa3ad5fc47a60a3c46e041953", size = 26014 }, + { url = "https://files.pythonhosted.org/packages/b0/70/c861427beabb7103a1eac435b8b755e62261936585d21e1124e80010fb38/pytest_codspeed-3.1.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9cb7b25ddab46ecc1dcef3ae8c3443e08bc72c6200bcc5f7a7d589e550744b6", size = 24647 }, + { url = "https://files.pythonhosted.org/packages/3b/5d/cdfec392635c681bca9b1321930089fcf26fdbdd6279479890ddf6523f43/pytest_codspeed-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f5709d2078e33e70f9f87156c7ff3a3ed30874ce0a51019ebc0996826f2af4f", size = 26383 }, + { url = "https://files.pythonhosted.org/packages/08/e0/2104c26c008e376c3973c48be08c6f23cd869831fb374ed5614dd8183ee0/pytest_codspeed-3.1.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0cbc9ea51856a3600668fd58e4e01cb158855712df484eb96dfe32d06e24be52", size = 25141 }, + { url = "https://files.pythonhosted.org/packages/9a/9a/f63000ef81880b871d1a498612103c27b7c32fb93db9e37838f406b38c08/pytest_codspeed-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54c6fb0d60d86be814696e847d032f93044978b9f3042934296f95681f4996f3", size = 26382 }, + { url = "https://files.pythonhosted.org/packages/af/86/fbf3315eff4d666fe7c957ef34e7406e49ceb819b3e8607cc561c3e0c3d4/pytest_codspeed-3.1.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6b5e98eb63af069d91bd9e6c3a35d2db47f1023e1b5e00eb8270e3153f3470d9", size = 25132 }, + { url = "https://files.pythonhosted.org/packages/f7/7b/4c016c23c7437f1e552392dd27c64c714692bd8adb534151fbf1dcf3481b/pytest_codspeed-3.1.1-py3-none-any.whl", hash = "sha256:4736340678464f525dde539e42049e526758931cc688c9aa69a4b7e3da613aa0", size = 14209 }, ] [[package]] @@ -1861,6 +1896,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f3/32/3b5d6973cc8bdc320736ee608377e2756b1042ed162ca2d2ee5555f2d117/pytest_mpl-0.17.0-py3-none-any.whl", hash = "sha256:2ee7cf902ef071e45ae14fe190b3d8a9839c2fd8933e0514bf58df310d8ed66b", size = 27555 }, ] +[[package]] +name = "pytest-xdist" +version = "3.6.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "execnet" }, + { name = "pytest" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/41/c4/3c310a19bc1f1e9ef50075582652673ef2bfc8cd62afef9585683821902f/pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d", size = 84060 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6d/82/1d96bf03ee4c0fdc3c0cbe61470070e659ca78dc0086fb88b66c185e2449/pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7", size = 46108 }, +] + [[package]] name = "python-dateutil" version = "2.9.0.post0" @@ -2224,7 +2272,7 @@ wheels = [ [[package]] name = "sphinx" -version = "7.3.7" +version = "8.1.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "alabaster" }, @@ -2244,21 +2292,21 @@ dependencies = [ { name = "sphinxcontrib-qthelp" }, { name = "sphinxcontrib-serializinghtml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b7/0a/b88033900b1582f5ed8f880263363daef968d1cd064175e32abfd9714410/sphinx-7.3.7.tar.gz", hash = "sha256:a4a7db75ed37531c05002d56ed6948d4c42f473a36f46e1382b0bd76ca9627bc", size = 7094808 } +sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/be0b61178fe2cdcb67e2a92fc9ebb488e3c51c4f74a36a7824c0adf23425/sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927", size = 8184611 } wheels = [ - { url = "https://files.pythonhosted.org/packages/b4/fa/130c32ed94cf270e3d0b9ded16fb7b2c8fea86fa7263c29a696a30c1dde7/sphinx-7.3.7-py3-none-any.whl", hash = "sha256:413f75440be4cacf328f580b4274ada4565fb2187d696a84970c23f77b64d8c3", size = 3335650 }, + { url = "https://files.pythonhosted.org/packages/26/60/1ddff83a56d33aaf6f10ec8ce84b4c007d9368b21008876fceda7e7381ef/sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2", size = 3487125 }, ] [[package]] name = "sphinx-autodoc-typehints" -version = "2.3.0" +version = "3.0.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "sphinx" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/74/cd/03e7b917230dc057922130a79ba0240df1693bfd76727ea33fae84b39138/sphinx_autodoc_typehints-2.3.0.tar.gz", hash = "sha256:535c78ed2d6a1bad393ba9f3dfa2602cf424e2631ee207263e07874c38fde084", size = 40709 } +sdist = { url = "https://files.pythonhosted.org/packages/2f/37/725d06f80cbe85b8538021df4515b7408af231cbe8b201a3bb2cf773a83d/sphinx_autodoc_typehints-3.0.0.tar.gz", hash = "sha256:d5cdab471efb10fcff4ffe81a2ef713398bc891af9d942a4b763f5ed1d9bf550", size = 35943 } wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/f3/e0a4ce49da4b6f4e4ce84b3c39a0677831884cb9d8a87ccbf1e9e56e53ac/sphinx_autodoc_typehints-2.3.0-py3-none-any.whl", hash = "sha256:3098e2c6d0ba99eacd013eb06861acc9b51c6e595be86ab05c08ee5506ac0c67", size = 19836 }, + { url = "https://files.pythonhosted.org/packages/f2/36/110d38a8b481b915d77461ca68764ebacf7aeba84be7cbe2dc965a65ae80/sphinx_autodoc_typehints-3.0.0-py3-none-any.whl", hash = "sha256:b82bf83e23ae3d5dc25881004a6d6614be6291ff8ff165b2d1e18799f0f6bd74", size = 20041 }, ] [[package]] @@ -2300,16 +2348,19 @@ wheels = [ [[package]] name = "sphinx-prompt" -version = "1.8.0" +version = "1.9.0" source = { registry = "https://pypi.org/simple" } dependencies = [ + { name = "certifi" }, { name = "docutils" }, + { name = "idna" }, { name = "pygments" }, { name = "sphinx" }, + { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e7/fb/7a07b8df1ca2418147a6b13e3f6b445071f2565198b45efa631d0d6ef0cd/sphinx_prompt-1.8.0.tar.gz", hash = "sha256:47482f86fcec29662fdfd23e7c04ef03582714195d01f5d565403320084372ed", size = 5121 } +sdist = { url = "https://files.pythonhosted.org/packages/34/fe/ac4e24f35b5148b31ac717ae7dcc7a2f7ec56eb729e22c7252ed8ad2d9a5/sphinx_prompt-1.9.0.tar.gz", hash = "sha256:471b3c6d466dce780a9b167d9541865fd4e9a80ed46e31b06a52a0529ae995a1", size = 5340 } wheels = [ - { url = "https://files.pythonhosted.org/packages/39/49/f890a2668b7cbf375f5528b549c8d36dd2e801b0fbb7b2b5ef65663ecb6c/sphinx_prompt-1.8.0-py3-none-any.whl", hash = "sha256:369ecc633f0711886f9b3a078c83264245be1adf46abeeb9b88b5519e4b51007", size = 7298 }, + { url = "https://files.pythonhosted.org/packages/76/98/e90ca466e0ede452d3e5a8d92b8fb68db6de269856e019ed9cab69440522/sphinx_prompt-1.9.0-py3-none-any.whl", hash = "sha256:fd731446c03f043d1ff6df9f22414495b23067c67011cc21658ea8d36b3575fc", size = 7311 }, ] [[package]] @@ -2563,7 +2614,7 @@ wheels = [ [[package]] name = "unxt" -version = "1.0.1.dev24+g8ce714e.d20250108" +version = "1.0.1.dev25+g89da29b.d20250108" source = { editable = "." } dependencies = [ { name = "astropy" }, @@ -2625,6 +2676,7 @@ dev = [ { name = "nox" }, { name = "pytest" }, { name = "pytest-arraydiff" }, + { name = "pytest-benchmark" }, { name = "pytest-codspeed" }, { name = "pytest-cov" }, { name = "pytest-env" }, @@ -2661,10 +2713,14 @@ docs = [ nox = [ { name = "nox" }, ] +pytest-benchmark-parallel = [ + { name = "pytest-xdist" }, +] test = [ { name = "hypothesis", extra = ["numpy"] }, { name = "pytest" }, { name = "pytest-arraydiff" }, + { name = "pytest-benchmark" }, { name = "pytest-codspeed" }, { name = "pytest-cov" }, { name = "pytest-env" }, @@ -2675,6 +2731,7 @@ test-all = [ { name = "hypothesis", extra = ["numpy"] }, { name = "pytest" }, { name = "pytest-arraydiff" }, + { name = "pytest-benchmark" }, { name = "pytest-codspeed" }, { name = "pytest-cov" }, { name = "pytest-env" }, @@ -2705,8 +2762,8 @@ requires-dist = [ { name = "jax", extras = ["rocm"], marker = "extra == 'rocm'" }, { name = "jaxlib", specifier = ">0.4.32" }, { name = "jaxtyping", specifier = ">=0.2.34" }, - { name = "matplotlib", marker = "extra == 'all'", specifier = ">=3.4" }, - { name = "matplotlib", marker = "extra == 'interop-mpl'", specifier = ">=3.4" }, + { name = "matplotlib", marker = "extra == 'all'", specifier = ">=3.5" }, + { name = "matplotlib", marker = "extra == 'interop-mpl'", specifier = ">=3.5" }, { name = "optional-dependencies", specifier = ">=0.3.2" }, { name = "plum-dispatch", specifier = ">=2.5.5" }, { name = "quax", specifier = ">=0.0.5" }, @@ -2725,20 +2782,21 @@ dev = [ { name = "nox", specifier = ">=2024.10.9" }, { name = "pytest", specifier = ">=8.3.3" }, { name = "pytest-arraydiff", specifier = ">=0.6.1" }, - { name = "pytest-codspeed" }, + { name = "pytest-benchmark", specifier = ">=5.1" }, + { name = "pytest-codspeed", specifier = ">=3.1" }, { name = "pytest-cov", specifier = ">=3" }, - { name = "pytest-env" }, - { name = "pytest-github-actions-annotate-failures" }, - { name = "pytest-mpl" }, + { name = "pytest-env", specifier = ">=1.1.5" }, + { name = "pytest-github-actions-annotate-failures", specifier = ">=0.2.0" }, + { name = "pytest-mpl", specifier = ">=0.17.0" }, { name = "pytz", specifier = ">=2024.2" }, { name = "sphinx", specifier = ">=7.0" }, - { name = "sphinx-autodoc-typehints" }, + { name = "sphinx-autodoc-typehints", specifier = ">=3.0.0" }, { name = "sphinx-book-theme", specifier = "==1.1.3" }, - { name = "sphinx-copybutton" }, - { name = "sphinx-design" }, + { name = "sphinx-copybutton", specifier = ">=0.5.2" }, + { name = "sphinx-design", specifier = ">=0.6.1" }, { name = "sphinx-prompt", specifier = ">=1.8.0" }, - { name = "sphinx-tippy" }, - { name = "sphinx-togglebutton" }, + { name = "sphinx-tippy", specifier = ">=0.4.3" }, + { name = "sphinx-togglebutton", specifier = ">=0.3.2" }, { name = "sphinxext-opengraph", specifier = ">=0.9.1" }, { name = "sphinxext-rediraffe", specifier = ">=0.2.7" }, { name = "sybil", specifier = ">=8.0.0" }, @@ -2748,39 +2806,42 @@ docs = [ { name = "myst-parser", specifier = ">=0.13" }, { name = "pytz", specifier = ">=2024.2" }, { name = "sphinx", specifier = ">=7.0" }, - { name = "sphinx-autodoc-typehints" }, + { name = "sphinx-autodoc-typehints", specifier = ">=3.0.0" }, { name = "sphinx-book-theme", specifier = "==1.1.3" }, - { name = "sphinx-copybutton" }, - { name = "sphinx-design" }, + { name = "sphinx-copybutton", specifier = ">=0.5.2" }, + { name = "sphinx-design", specifier = ">=0.6.1" }, { name = "sphinx-prompt", specifier = ">=1.8.0" }, - { name = "sphinx-tippy" }, - { name = "sphinx-togglebutton" }, + { name = "sphinx-tippy", specifier = ">=0.4.3" }, + { name = "sphinx-togglebutton", specifier = ">=0.3.2" }, { name = "sphinxext-opengraph", specifier = ">=0.9.1" }, { name = "sphinxext-rediraffe", specifier = ">=0.2.7" }, ] nox = [{ name = "nox", specifier = ">=2024.10.9" }] +pytest-benchmark-parallel = [{ name = "pytest-xdist", specifier = ">=3.6.1" }] test = [ { name = "hypothesis", extras = ["numpy"], specifier = ">=6.112.2" }, { name = "pytest", specifier = ">=8.3.3" }, { name = "pytest-arraydiff", specifier = ">=0.6.1" }, - { name = "pytest-codspeed" }, + { name = "pytest-benchmark", specifier = ">=5.1" }, + { name = "pytest-codspeed", specifier = ">=3.1" }, { name = "pytest-cov", specifier = ">=3" }, - { name = "pytest-env" }, - { name = "pytest-github-actions-annotate-failures" }, + { name = "pytest-env", specifier = ">=1.1.5" }, + { name = "pytest-github-actions-annotate-failures", specifier = ">=0.2.0" }, { name = "sybil", specifier = ">=8.0.0" }, ] test-all = [ { name = "hypothesis", extras = ["numpy"], specifier = ">=6.112.2" }, { name = "pytest", specifier = ">=8.3.3" }, { name = "pytest-arraydiff", specifier = ">=0.6.1" }, - { name = "pytest-codspeed" }, + { name = "pytest-benchmark", specifier = ">=5.1" }, + { name = "pytest-codspeed", specifier = ">=3.1" }, { name = "pytest-cov", specifier = ">=3" }, - { name = "pytest-env" }, - { name = "pytest-github-actions-annotate-failures" }, - { name = "pytest-mpl" }, + { name = "pytest-env", specifier = ">=1.1.5" }, + { name = "pytest-github-actions-annotate-failures", specifier = ">=0.2.0" }, + { name = "pytest-mpl", specifier = ">=0.17.0" }, { name = "sybil", specifier = ">=8.0.0" }, ] -test-mpl = [{ name = "pytest-mpl" }] +test-mpl = [{ name = "pytest-mpl", specifier = ">=0.17.0" }] [[package]] name = "urllib3"