array-api-extra 0.9.2__tar.gz → 0.10.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/.all-contributorsrc +11 -0
  2. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/CONTRIBUTORS.md +3 -0
  3. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/PKG-INFO +12 -29
  4. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/README.md +3 -0
  5. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/docs/contributing.md +2 -0
  6. array_api_extra-0.10.1/meson.build +39 -0
  7. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/pyproject.toml +89 -85
  8. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/__init__.py +3 -1
  9. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_delegation.py +89 -0
  10. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_at.py +1 -1
  11. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_backends.py +1 -1
  12. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_funcs.py +73 -6
  13. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/testing.py +132 -31
  14. array_api_extra-0.10.1/tests/meson.build +13 -0
  15. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/test_funcs.py +241 -18
  16. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/test_testing.py +124 -1
  17. array_api_extra-0.10.1/vendor_tests/meson.build +8 -0
  18. array_api_extra-0.9.2/.gitattributes +0 -2
  19. array_api_extra-0.9.2/.github/pull_request_template.md +0 -5
  20. array_api_extra-0.9.2/.github/workflows/cd.yml +0 -47
  21. array_api_extra-0.9.2/.github/workflows/ci.yml +0 -79
  22. array_api_extra-0.9.2/.github/workflows/docs-build.yml +0 -27
  23. array_api_extra-0.9.2/.github/workflows/docs-deploy.yml +0 -36
  24. array_api_extra-0.9.2/.gitignore +0 -173
  25. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/.dprint.jsonc +0 -0
  26. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/.editorconfig +0 -0
  27. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/LICENSE +0 -0
  28. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/docs/api-lazy.md +0 -0
  29. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/docs/api-reference.md +0 -0
  30. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/docs/conf.py +0 -0
  31. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/docs/contributors.md +0 -0
  32. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/docs/index.md +0 -0
  33. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/lefthook.yml +0 -0
  34. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/__init__.py +0 -0
  35. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_lazy.py +0 -0
  36. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_testing.py +0 -0
  37. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_utils/__init__.py +0 -0
  38. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_utils/_compat.py +0 -0
  39. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_utils/_compat.pyi +0 -0
  40. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_utils/_helpers.py +0 -0
  41. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_utils/_typing.py +0 -0
  42. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/_lib/_utils/_typing.pyi +0 -0
  43. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/src/array_api_extra/py.typed +0 -0
  44. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/__init__.py +0 -0
  45. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/conftest.py +0 -0
  46. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/test_at.py +0 -0
  47. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/test_helpers.py +0 -0
  48. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/test_lazy.py +0 -0
  49. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/tests/test_version.py +0 -0
  50. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/typos.toml +0 -0
  51. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/vendor_tests/__init__.py +0 -0
  52. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/vendor_tests/_array_api_compat_vendor.py +0 -0
  53. {array_api_extra-0.9.2 → array_api_extra-0.10.1}/vendor_tests/test_vendor.py +0 -0
@@ -308,6 +308,17 @@
308
308
  "ideas",
309
309
  "test"
310
310
  ]
311
+ },
312
+ {
313
+ "login": "steppi",
314
+ "name": "Albert Steppi",
315
+ "avatar_url": "https://avatars.githubusercontent.com/u/1953382?v=4",
316
+ "profile": "http://steppi.github.io",
317
+ "contributions": [
318
+ "code",
319
+ "ideas",
320
+ "test"
321
+ ]
311
322
  }
312
323
  ]
313
324
  }
@@ -44,6 +44,9 @@ This project exists thanks to the following contributors
44
44
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/adriagarp"><img src="https://avatars.githubusercontent.com/u/96059447?v=4?s=100" width="100px;" alt="Adrián García Pitarch"/><br /><sub><b>Adrián García Pitarch</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=adriagarp" title="Code">💻</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=adriagarp" title="Tests">⚠️</a></td>
45
45
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/cakedev0"><img src="https://avatars.githubusercontent.com/u/25986961?v=4?s=100" width="100px;" alt="Arthur Lacote"/><br /><sub><b>Arthur Lacote</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Code">💻</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Documentation">📖</a> <a href="#ideas-cakedev0" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Tests">⚠️</a></td>
46
46
  </tr>
47
+ <tr>
48
+ <td align="center" valign="top" width="14.28%"><a href="http://steppi.github.io"><img src="https://avatars.githubusercontent.com/u/1953382?v=4?s=100" width="100px;" alt="Albert Steppi"/><br /><sub><b>Albert Steppi</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=steppi" title="Code">💻</a> <a href="#ideas-steppi" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=steppi" title="Tests">⚠️</a></td>
49
+ </tr>
47
50
  </tbody>
48
51
  </table>
49
52
 
@@ -1,46 +1,26 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: array-api-extra
3
- Version: 0.9.2
3
+ Version: 0.10.1
4
4
  Summary: Extra array functions built on top of the array API standard.
5
- Project-URL: Homepage, https://github.com/data-apis/array-api-extra
6
- Project-URL: Bug Tracker, https://github.com/data-apis/array-api-extra/issues
7
- Project-URL: Changelog, https://github.com/data-apis/array-api-extra/releases
8
- Author-email: Lucas Colley <lucas.colley8@gmail.com>
9
- License: MIT License
10
-
11
- Copyright (c) 2024 Consortium for Python Data API Standards
12
-
13
- Permission is hereby granted, free of charge, to any person obtaining a copy
14
- of this software and associated documentation files (the "Software"), to deal
15
- in the Software without restriction, including without limitation the rights
16
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
- copies of the Software, and to permit persons to whom the Software is
18
- furnished to do so, subject to the following conditions:
19
-
20
- The above copyright notice and this permission notice shall be included in all
21
- copies or substantial portions of the Software.
22
-
23
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
- SOFTWARE.
5
+ Author-Email: Lucas Colley <lucas.colley8@gmail.com>
6
+ License-Expression: MIT
30
7
  License-File: LICENSE
31
8
  Classifier: Intended Audience :: Developers
32
9
  Classifier: Operating System :: OS Independent
33
10
  Classifier: Programming Language :: Python
34
11
  Classifier: Programming Language :: Python :: 3
35
12
  Classifier: Programming Language :: Python :: 3 :: Only
36
- Classifier: Programming Language :: Python :: 3.10
37
13
  Classifier: Programming Language :: Python :: 3.11
38
14
  Classifier: Programming Language :: Python :: 3.12
39
15
  Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
40
17
  Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
41
18
  Classifier: Typing :: Typed
42
- Requires-Python: >=3.10
43
- Requires-Dist: array-api-compat<2,>=1.12.0
19
+ Project-URL: Homepage, https://github.com/data-apis/array-api-extra
20
+ Project-URL: Bug Tracker, https://github.com/data-apis/array-api-extra/issues
21
+ Project-URL: Changelog, https://github.com/data-apis/array-api-extra/releases
22
+ Requires-Python: >=3.11
23
+ Requires-Dist: array-api-compat<2,>=1.13.0
44
24
  Description-Content-Type: text/markdown
45
25
 
46
26
  # array-api-extra
@@ -144,6 +124,9 @@ This project exists thanks to the following contributors
144
124
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/adriagarp"><img src="https://avatars.githubusercontent.com/u/96059447?v=4?s=100" width="100px;" alt="Adrián García Pitarch"/><br /><sub><b>Adrián García Pitarch</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=adriagarp" title="Code">💻</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=adriagarp" title="Tests">⚠️</a></td>
145
125
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/cakedev0"><img src="https://avatars.githubusercontent.com/u/25986961?v=4?s=100" width="100px;" alt="Arthur Lacote"/><br /><sub><b>Arthur Lacote</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Code">💻</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Documentation">📖</a> <a href="#ideas-cakedev0" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Tests">⚠️</a></td>
146
126
  </tr>
127
+ <tr>
128
+ <td align="center" valign="top" width="14.28%"><a href="http://steppi.github.io"><img src="https://avatars.githubusercontent.com/u/1953382?v=4?s=100" width="100px;" alt="Albert Steppi"/><br /><sub><b>Albert Steppi</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=steppi" title="Code">💻</a> <a href="#ideas-steppi" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=steppi" title="Tests">⚠️</a></td>
129
+ </tr>
147
130
  </tbody>
148
131
  </table>
149
132
 
@@ -99,6 +99,9 @@ This project exists thanks to the following contributors
99
99
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/adriagarp"><img src="https://avatars.githubusercontent.com/u/96059447?v=4?s=100" width="100px;" alt="Adrián García Pitarch"/><br /><sub><b>Adrián García Pitarch</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=adriagarp" title="Code">💻</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=adriagarp" title="Tests">⚠️</a></td>
100
100
  <td align="center" valign="top" width="14.28%"><a href="https://github.com/cakedev0"><img src="https://avatars.githubusercontent.com/u/25986961?v=4?s=100" width="100px;" alt="Arthur Lacote"/><br /><sub><b>Arthur Lacote</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Code">💻</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Documentation">📖</a> <a href="#ideas-cakedev0" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=cakedev0" title="Tests">⚠️</a></td>
101
101
  </tr>
102
+ <tr>
103
+ <td align="center" valign="top" width="14.28%"><a href="http://steppi.github.io"><img src="https://avatars.githubusercontent.com/u/1953382?v=4?s=100" width="100px;" alt="Albert Steppi"/><br /><sub><b>Albert Steppi</b></sub></a><br /><a href="https://github.com/data-apis/array-api-extra/commits?author=steppi" title="Code">💻</a> <a href="#ideas-steppi" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/data-apis/array-api-extra/commits?author=steppi" title="Tests">⚠️</a></td>
104
+ </tr>
102
105
  </tbody>
103
106
  </table>
104
107
 
@@ -20,6 +20,8 @@ Thanks to [all contributors](contributors.md) so far!
20
20
  - Import your function to `src/array_api_extra/__init__.py` and add it to
21
21
  `__all__` there.
22
22
  - Add a test class for your function in `tests/test_funcs.py`.
23
+ - Ensure that `lazy_xp_function` is called on the function if lazy backends
24
+ are supposed to be tested.
23
25
  - Add your function to `docs/api-reference.md`.
24
26
  - [Make a PR!](https://github.com/data-apis/array-api-extra/pulls)
25
27
 
@@ -0,0 +1,39 @@
1
+ project(
2
+ 'array-api-extra',
3
+ version: '0.10.1'
4
+ )
5
+
6
+ py = import('python').find_installation()
7
+
8
+ # NOTE: downstream projects may rely on this variable name when vendoring,
9
+ # do not change it without consulting with downstream projects
10
+ sources = {
11
+ 'array_api_extra': files(
12
+ 'src/array_api_extra/__init__.py',
13
+ 'src/array_api_extra/_delegation.py',
14
+ 'src/array_api_extra/testing.py',
15
+ ),
16
+ 'array_api_extra/_lib': files(
17
+ 'src/array_api_extra/_lib/__init__.py',
18
+ 'src/array_api_extra/_lib/_at.py',
19
+ 'src/array_api_extra/_lib/_backends.py',
20
+ 'src/array_api_extra/_lib/_funcs.py',
21
+ 'src/array_api_extra/_lib/_lazy.py',
22
+ 'src/array_api_extra/_lib/_testing.py',
23
+ ),
24
+ 'array_api_extra/_lib/_utils': files(
25
+ 'src/array_api_extra/_lib/_utils/__init__.py',
26
+ 'src/array_api_extra/_lib/_utils/_compat.py',
27
+ 'src/array_api_extra/_lib/_utils/_compat.pyi',
28
+ 'src/array_api_extra/_lib/_utils/_helpers.py',
29
+ 'src/array_api_extra/_lib/_utils/_typing.py',
30
+ 'src/array_api_extra/_lib/_utils/_typing.pyi',
31
+ ),
32
+ }
33
+
34
+ foreach subdir, files : sources
35
+ py.install_sources(files, subdir: subdir)
36
+ endforeach
37
+
38
+ subdir('tests')
39
+ subdir('vendor_tests')
@@ -1,77 +1,113 @@
1
1
  [build-system]
2
- requires = ["hatchling"]
3
- build-backend = "hatchling.build"
2
+ requires = ["meson-python"]
3
+ build-backend = "mesonpy"
4
4
 
5
5
  [project]
6
6
  name = "array-api-extra"
7
+ version = "0.10.1"
7
8
  authors = [
8
9
  { name = "Lucas Colley", email = "lucas.colley8@gmail.com" },
9
10
  # { name = "Open Source Contributors" }, # https://github.com/pypi/warehouse/issues/14813
10
11
  ]
11
12
  description = "Extra array functions built on top of the array API standard."
12
13
  readme = "README.md"
13
- license.file = "LICENSE"
14
- requires-python = ">=3.10"
14
+ license = "MIT"
15
+ license-files = ["LICENSE"]
16
+ requires-python = ">=3.11"
15
17
  classifiers = [
16
18
  "Intended Audience :: Developers",
17
19
  "Operating System :: OS Independent",
18
20
  "Programming Language :: Python",
19
21
  "Programming Language :: Python :: 3",
20
22
  "Programming Language :: Python :: 3 :: Only",
21
- "Programming Language :: Python :: 3.10",
22
23
  "Programming Language :: Python :: 3.11",
23
24
  "Programming Language :: Python :: 3.12",
24
25
  "Programming Language :: Python :: 3.13",
26
+ "Programming Language :: Python :: 3.14",
25
27
  "Programming Language :: Python :: Free Threading :: 3 - Stable",
26
28
  "Typing :: Typed",
27
29
  ]
28
- dynamic = ["version"]
29
- dependencies = ["array-api-compat>=1.12.0,<2"]
30
+ dependencies = ["array-api-compat>=1.13.0,<2"]
30
31
 
31
32
  [project.urls]
32
33
  Homepage = "https://github.com/data-apis/array-api-extra"
33
34
  "Bug Tracker" = "https://github.com/data-apis/array-api-extra/issues"
34
35
  Changelog = "https://github.com/data-apis/array-api-extra/releases"
35
36
 
36
- # Hatch
37
-
38
- [tool.hatch]
39
- version.path = "src/array_api_extra/__init__.py"
40
-
41
- [tool.hatch.build.targets.sdist]
42
- exclude = ["codecov.yml", "pixi.lock", "RELEASING.md", "renovate.json"]
43
-
44
- #  Pixi
37
+ # Pixi
45
38
 
46
39
  [tool.pixi.workspace]
47
40
  channels = ["https://prefix.dev/conda-forge"]
48
41
  platforms = ["linux-64", "osx-64", "osx-arm64", "win-64"]
42
+ preview = ["pixi-build"]
43
+
44
+ ### array-api-extra package definition ###
45
+
46
+ [tool.pixi.package.build.backend]
47
+ name = "pixi-build-python"
48
+ version = "*"
49
+
50
+ [tool.pixi.package.host-dependencies]
51
+ meson-python = "*"
52
+ uv = "*" # interfaces with meson-python instead of pip
53
+
54
+ [tool.pixi.package.run-dependencies]
55
+ array-api-compat = "*"
56
+
57
+ ### workspace environments ###
58
+
59
+ [tool.pixi.environments]
60
+ default = { features = ["py314"], solve-group = "py314" }
61
+ lint = { features = ["py314", "lint"], solve-group = "py314" }
62
+ docs = { features = ["py314", "docs"], solve-group = "py314" }
63
+ tests = { features = ["py314", "tests"], solve-group = "py314" }
64
+ tests-py314 = { features = ["py314", "tests"], solve-group = "py314" } # alias of tests
65
+
66
+ # Some backends may pin numpy; use separate solve-group
67
+ dev = { features = ["py314", "lint", "tests", "docs", "dev", "backends"], solve-group = "backends" }
68
+ tests-backends = { features = ["py314", "tests", "backends"], solve-group = "backends" }
69
+ tests-backends-py311 = { features = ["py311", "tests", "backends"] }
70
+
71
+ # CUDA not available on free github actions and on some developers' PCs
72
+ dev-cuda = { features = ["py314", "lint", "tests", "docs", "dev", "backends", "cuda-backends"], solve-group = "cuda" }
73
+ tests-cuda = { features = ["py314", "tests", "backends", "cuda-backends"], solve-group = "cuda" }
74
+ tests-cuda-py311 = { features = ["py311", "tests", "backends", "cuda-backends"] }
75
+
76
+ # Ungrouped environments
77
+ tests-numpy1 = ["py311", "tests", "numpy1"]
78
+ tests-py311 = ["py311", "tests"]
79
+ tests-nogil = ["nogil", "tests"]
80
+
81
+ ### default feature definition ###
82
+
83
+ [tool.pixi.dev]
84
+ # this pulls in array-api-extra's host and run dependencies
85
+ array-api-extra.path = "."
49
86
 
50
87
  [tool.pixi.dependencies]
51
- array-api-compat = ">=1.12.0,<2"
88
+ array-api-extra.path = "."
52
89
 
53
- [tool.pixi.pypi-dependencies]
54
- array-api-extra = { path = ".", editable = true }
90
+ ### non-default feature definitions ###
55
91
 
56
92
  [tool.pixi.feature.lint.dependencies]
57
93
  typing-extensions = ">=4.15.0"
58
94
  pylint = ">=4.0.4"
59
95
  mypy = ">=1.19.1"
60
- basedpyright = ">=1.36.1"
96
+ basedpyright = ">=1.38.0"
61
97
  numpydoc = ">=1.10.0,<2"
62
98
  # import dependencies for mypy:
63
99
  array-api-strict = ">=2.4.1,<2.5"
64
100
  numpy = ">=2.1.3"
65
- hypothesis = ">=6.148.2"
66
- dask-core = ">=2025.12.0" # No distributed, tornado, etc.
101
+ hypothesis = ">=6.151.2"
102
+ dask-core = ">=2026.1.2" # No distributed, tornado, etc.
67
103
  dprint = ">=0.50.0,<0.51"
68
- lefthook = ">=2.0.12,<3"
69
- ruff = ">=0.14.10,<0.15"
70
- typos = ">=1.40.0,<2"
71
- actionlint = ">=1.7.9,<2"
104
+ lefthook = ">=2.1.1,<3"
105
+ ruff = ">=0.15.1,<0.16"
106
+ typos = ">=1.43.4,<2"
107
+ actionlint = ">=1.7.10,<2"
72
108
  blacken-docs = ">=1.20.0,<2"
73
109
  pytest = ">=9.0.2,<10"
74
- validate-pyproject = ">=0.24.1,<0.25"
110
+ validate-pyproject = ">=0.25,<0.26"
75
111
  # NOTE: don't add cupy, jax, pytorch, or sparse here,
76
112
  # as they slow down mypy and are not portable across target OSs
77
113
 
@@ -95,9 +131,10 @@ lint = { cmd = "lefthook run pre-commit --all-files --force", description = "Run
95
131
  [tool.pixi.feature.tests.dependencies]
96
132
  pytest = ">=9.0.2"
97
133
  pytest-cov = ">=7.0.0"
98
- hypothesis = ">=6.148.2"
134
+ hypothesis = ">=6.151.2"
99
135
  array-api-strict = ">=2.4.1,<2.5"
100
136
  numpy = ">=1.22.0"
137
+ scipy = ">=1.15.2,<2"
101
138
 
102
139
  [tool.pixi.feature.tests.tasks]
103
140
  tests = { cmd = "pytest -v", description = "Run tests" }
@@ -116,11 +153,11 @@ open-coverage = { cmd = "open htmlcov/index.html", depends-on = ["coverage"], de
116
153
  [tool.pixi.feature.docs.dependencies]
117
154
  sphinx = ">=7.4.7"
118
155
  furo = ">=2024.8.6"
119
- myst-parser = ">=4.0.1"
156
+ myst-parser = ">=5.0.0"
120
157
  sphinx-copybutton = ">=0.5.2"
121
158
  sphinx-autodoc-typehints = ">=1.25.3"
122
159
  # Needed to import parsed modules with autodoc
123
- dask-core = ">=2025.12.0" # No distributed, tornado, etc.
160
+ dask-core = ">=2026.1.2" # No distributed, tornado, etc.
124
161
  pytest = ">=9.0.2"
125
162
  typing-extensions = ">=4.15.0"
126
163
  numpy = ">=2.1.3"
@@ -135,35 +172,32 @@ ipython = ">=7.33.0"
135
172
  [tool.pixi.feature.dev.tasks]
136
173
  ipython = { cmd = "ipython", description = "Launch ipython" }
137
174
 
138
- [tool.pixi.feature.py310.dependencies]
139
- python = "~=3.10.0"
175
+ [tool.pixi.feature.py311.dependencies]
176
+ python = "~=3.11.0"
140
177
 
141
- [tool.pixi.feature.py313.dependencies]
142
- python = "~=3.13.0"
178
+ [tool.pixi.feature.py314.dependencies]
179
+ python = "~=3.14.0"
143
180
 
144
181
  [tool.pixi.feature.numpy1.dependencies]
145
182
  # Oldest NumPy version supported by scikit-learn.
146
183
  # Note that this is older than what SPEC0 recommends.
147
- numpy = "=1.22.0"
184
+ numpy = "=1.24.1"
148
185
 
149
186
  # Backends that can run on CPU-only hosts
150
187
  # Note: JAX and PyTorch will install CPU variants.
151
188
  [tool.pixi.feature.backends.dependencies]
152
- pytorch = ">=2.7.1"
153
- dask-core = ">=2025.12.0" # No distributed, tornado, etc.
189
+ pytorch = ">=2.10.0"
190
+ dask-core = ">=2026.1.2" # No distributed, tornado, etc.
154
191
  sparse = ">=0.17.0"
155
192
 
156
193
  [tool.pixi.feature.backends.target.linux-64.dependencies]
157
- # On CPU Python 3.10, use 0.6.2
158
- # On CPU Python >=3.11, use >=0.7.0
159
- # On GPU, use 0.6.0 (0.6.2 and 0.7.0 both segfault); see jaxlib pin below.
160
- jax = ">=0.6.0"
194
+ jax = ">=0.7.2"
161
195
 
162
196
  [tool.pixi.feature.backends.target.osx-64.dependencies]
163
- jax = ">=0.6.0"
197
+ jax = ">=0.7.2"
164
198
 
165
199
  [tool.pixi.feature.backends.target.osx-arm64.dependencies]
166
- jax = ">=0.6.0"
200
+ jax = ">=0.7.2"
167
201
 
168
202
  [tool.pixi.feature.backends.target.win-64.dependencies]
169
203
  # jax = "*" # unavailable
@@ -177,60 +211,30 @@ jax = ">=0.6.0"
177
211
  [tool.pixi.feature.cuda-backends]
178
212
  system-requirements = { cuda = "12" }
179
213
 
180
- [tool.pixi.feature.cuda-backends.target.linux-64.dependencies]
214
+ [tool.pixi.feature.cuda-backends.target.linux.dependencies]
181
215
  cupy = ">=13.6.0"
182
- # JAX 0.6.2 and 0.7.0 segfault on CUDA
183
- jaxlib = { version = ">=0.6.0,!=0.6.2,!=0.7.0", build = "cuda12*" }
184
- pytorch = { version = ">=2.7.1", build = "cuda12*" }
185
-
186
- [tool.pixi.feature.cuda-backends.target.osx-64.dependencies]
187
- # cupy = "*" # unavailable
188
- # jaxlib = { version = "*", build = "cuda12*" } # unavailable
189
- # pytorch = { version = "*", build = "cuda12*" } # unavailable
216
+ jaxlib = { version = ">=0.7.2", build = "cuda12*" }
217
+ pytorch = { version = ">=2.10.0", build = "cuda12*" }
190
218
 
191
- [tool.pixi.feature.cuda-backends.target.osx-arm64.dependencies]
219
+ [tool.pixi.feature.cuda-backends.target.osx.dependencies]
192
220
  # cupy = "*" # unavailable
193
221
  # jaxlib = { version = "*", build = "cuda12*" } # unavailable
194
222
  # pytorch = { version = "*", build = "cuda12*" } # unavailable
195
223
 
196
- [tool.pixi.feature.cuda-backends.target.win-64.dependencies]
224
+ [tool.pixi.feature.cuda-backends.target.win.dependencies]
197
225
  cupy = ">=13.6.0"
198
226
  # jaxlib = { version = "*", build = "cuda12*" } # unavailable
199
- pytorch = { version = ">=2.8.0", build = "cuda12*" }
227
+ pytorch = { version = ">=2.10.0", build = "cuda12*" }
200
228
 
201
229
  [tool.pixi.feature.nogil.dependencies]
202
230
  python-freethreading = "~=3.13.0"
203
- pytest-run-parallel = ">=0.8.0"
231
+ pytest-run-parallel = ">=0.8.2"
204
232
  numpy = ">=2.3.5"
205
233
  # pytorch = "*" # Not available on Python 3.13t yet
206
- dask-core = ">=2025.12.0" # No distributed, tornado, etc.
234
+ dask-core = ">=2026.1.2" # No distributed, tornado, etc.
207
235
  # sparse = "*" # numba not available on Python 3.13t yet
208
236
  # jax = "*" # ml_dtypes not available on Python 3.13t yet
209
237
 
210
- [tool.pixi.environments]
211
- default = { features = ["py313"], solve-group = "py313" }
212
- lint = { features = ["py313", "lint"], solve-group = "py313" }
213
- docs = { features = ["py313", "docs"], solve-group = "py313" }
214
- tests = { features = ["py313", "tests"], solve-group = "py313" }
215
- tests-py313 = { features = ["py313", "tests"], solve-group = "py313" } # alias of tests
216
-
217
- # Some backends may pin numpy; use separate solve-group
218
- dev = { features = ["py313", "lint", "tests", "docs", "dev", "backends"], solve-group = "backends" }
219
- tests-backends = { features = ["py313", "tests", "backends"], solve-group = "backends" }
220
- # Note: Python 3.10 has already been dropped by some backends (like JAX),
221
- # so this is testing older versions.
222
- tests-backends-py310 = { features = ["py310", "tests", "backends"] }
223
-
224
- # CUDA not available on free github actions and on some developers' PCs
225
- dev-cuda = { features = ["py313", "lint", "tests", "docs", "dev", "backends", "cuda-backends"], solve-group = "cuda" }
226
- tests-cuda = { features = ["py313", "tests", "backends", "cuda-backends"], solve-group = "cuda" }
227
- tests-cuda-py310 = { features = ["py310", "tests", "backends", "cuda-backends"] }
228
-
229
- # Ungrouped environments
230
- tests-numpy1 = ["py310", "tests", "numpy1"]
231
- tests-py310 = ["py310", "tests"]
232
- tests-nogil = ["nogil", "tests"]
233
-
234
238
  # pytest
235
239
 
236
240
  [tool.pytest.ini_options]
@@ -254,7 +258,7 @@ run.source = ["array_api_extra"]
254
258
 
255
259
  [tool.mypy]
256
260
  files = ["src", "tests"]
257
- python_version = "3.10"
261
+ python_version = "3.11"
258
262
  warn_unused_configs = true
259
263
  strict = true
260
264
  enable_error_code = ["ignore-without-code", "truthy-bool"]
@@ -273,7 +277,7 @@ disable_error_code = ["no-untyped-def"] # test(...) without -> None
273
277
 
274
278
  [tool.basedpyright]
275
279
  include = ["src", "tests"]
276
- pythonVersion = "3.10"
280
+ pythonVersion = "3.11"
277
281
  pythonPlatform = "All"
278
282
  typeCheckingMode = "all"
279
283
 
@@ -304,7 +308,7 @@ executionEnvironments = [
304
308
  # Ruff
305
309
 
306
310
  [tool.ruff]
307
- target-version = "py310"
311
+ target-version = "py311"
308
312
 
309
313
  [tool.ruff.lint]
310
314
  extend-select = [
@@ -349,7 +353,7 @@ ignore = [
349
353
  # Pylint
350
354
 
351
355
  [tool.pylint]
352
- py-version = "3.10"
356
+ py-version = "3.11"
353
357
  reports.output-format = "colorized"
354
358
  messages_control.disable = [
355
359
  "design", # ignore heavily opinionated design checks
@@ -12,6 +12,7 @@ from ._delegation import (
12
12
  one_hot,
13
13
  pad,
14
14
  partition,
15
+ searchsorted,
15
16
  setdiff1d,
16
17
  sinc,
17
18
  union1d,
@@ -26,7 +27,7 @@ from ._lib._funcs import (
26
27
  )
27
28
  from ._lib._lazy import lazy_apply
28
29
 
29
- __version__ = "0.9.2"
30
+ __version__ = "0.10.1"
30
31
 
31
32
  # pylint: disable=duplicate-code
32
33
  __all__ = [
@@ -49,6 +50,7 @@ __all__ = [
49
50
  "one_hot",
50
51
  "pad",
51
52
  "partition",
53
+ "searchsorted",
52
54
  "setdiff1d",
53
55
  "sinc",
54
56
  "union1d",
@@ -27,6 +27,7 @@ __all__ = [
27
27
  "nan_to_num",
28
28
  "one_hot",
29
29
  "pad",
30
+ "searchsorted",
30
31
  "sinc",
31
32
  ]
32
33
 
@@ -632,6 +633,85 @@ def pad(
632
633
  return _funcs.pad(x, pad_width, constant_values=constant_values, xp=xp)
633
634
 
634
635
 
636
+ def searchsorted(
637
+ x1: Array,
638
+ x2: Array,
639
+ /,
640
+ *,
641
+ side: Literal["left", "right"] = "left",
642
+ xp: ModuleType | None = None,
643
+ ) -> Array:
644
+ """
645
+ Find indices where elements should be inserted to maintain order.
646
+
647
+ Find the indices into a sorted array ``x1`` such that if the elements in ``x2``
648
+ were inserted before the indices, the resulting array would remain sorted.
649
+
650
+ The behavior of this function is similar to that of `array_api.searchsorted`,
651
+ but it relaxes the requirement that `x1` must be one-dimensional.
652
+ This function is vectorized, treating slices along the last axis
653
+ as elements and preceding axes as batch (or "loop") dimensions.
654
+
655
+ Parameters
656
+ ----------
657
+ x1 : Array
658
+ Input array. Should have a real-valued data type. Must be sorted in ascending
659
+ order along the last axis.
660
+ x2 : Array
661
+ Array containing search values. Should have a real-valued data type. Must have
662
+ the same shape as ``x1`` except along the last axis.
663
+ side : {'left', 'right'}, optional
664
+ Argument controlling which index is returned if an element of ``x2`` is equal to
665
+ one or more elements of ``x1``: ``'left'`` returns the index of the first of
666
+ these elements; ``'right'`` returns the next index after the last of these
667
+ elements. Default: ``'left'``.
668
+ xp : array_namespace, optional
669
+ The standard-compatible namespace for the array arguments. Default: infer.
670
+
671
+ Returns
672
+ -------
673
+ Array: integer array
674
+ An array of indices with the same shape as ``x2``.
675
+
676
+ Examples
677
+ --------
678
+ >>> import array_api_strict as xp
679
+ >>> import array_api_extra as xpx
680
+ >>> x = xp.asarray([11, 12, 13, 13, 14, 15])
681
+ >>> xpx.searchsorted(x, xp.asarray([10, 11.5, 14.5, 16]), xp=xp)
682
+ Array([0, 1, 5, 6], dtype=array_api_strict.int64)
683
+ >>> xpx.searchsorted(x, xp.asarray(13), xp=xp)
684
+ Array(2, dtype=array_api_strict.int64)
685
+ >>> xpx.searchsorted(x, xp.asarray(13), side='right', xp=xp)
686
+ Array(4, dtype=array_api_strict.int64)
687
+
688
+ `searchsorted` is vectorized along the last axis.
689
+
690
+ >>> x1 = xp.asarray([[1., 2., 3., 4.], [5., 6., 7., 8.]])
691
+ >>> x2 = xp.asarray([[1.1, 3.3], [6.6, 8.8]])
692
+ >>> xpx.searchsorted(x1, x2, xp=xp)
693
+ Array([[1, 3],
694
+ [2, 4]], dtype=array_api_strict.int64)
695
+ """
696
+ if xp is None:
697
+ xp = array_namespace(x1, x2)
698
+
699
+ if side not in {"left", "right"}:
700
+ message = "`side` must be either 'left' or 'right'."
701
+ raise ValueError(message)
702
+
703
+ xp_default_int = _funcs.default_dtype(xp, kind="integral")
704
+ x2_0d = x2.ndim == 0
705
+ x1_1d = x1.ndim <= 1
706
+
707
+ if x1_1d or is_torch_namespace(xp):
708
+ x2 = xp.reshape(x2, ()) if (x2_0d and x1_1d) else x2
709
+ out = xp.searchsorted(x1, x2, side=side)
710
+ return xp.astype(out, xp_default_int, copy=False)
711
+
712
+ return _funcs.searchsorted(x1, x2, side=side, xp=xp)
713
+
714
+
635
715
  def setdiff1d(
636
716
  x1: Array | complex,
637
717
  x2: Array | complex,
@@ -1048,6 +1128,15 @@ def union1d(a: Array, b: Array, /, *, xp: ModuleType | None = None) -> Array:
1048
1128
  -------
1049
1129
  Array
1050
1130
  Unique, sorted union of the input arrays.
1131
+
1132
+ See Also
1133
+ --------
1134
+ jax.numpy.union1d : Corresponding function in JAX.
1135
+
1136
+ Notes
1137
+ -----
1138
+ This function is not compatible with `jax.jit`.
1139
+ See the docstring of the corresponding JAX function for more information.
1051
1140
  """
1052
1141
  if xp is None:
1053
1142
  xp = array_namespace(a, b)
@@ -21,7 +21,7 @@ from ._utils._typing import Array, SetIndex
21
21
 
22
22
  if TYPE_CHECKING: # pragma: no cover
23
23
  # TODO import from typing (requires Python >=3.11)
24
- from typing_extensions import Self
24
+ from typing import Self
25
25
 
26
26
 
27
27
  class _AtOp(Enum):
@@ -10,7 +10,7 @@ import pytest
10
10
 
11
11
  __all__ = ["NUMPY_VERSION", "Backend"]
12
12
 
13
- NUMPY_VERSION = tuple(int(v) for v in np.__version__.split(".")[:3]) # pyright: ignore[reportUnknownArgumentType]
13
+ NUMPY_VERSION = tuple(int(v) for v in np.__version__.split(".")[:3])
14
14
 
15
15
 
16
16
  class Backend(Enum): # numpydoc ignore=PR02