Skip to content

Commit d13efdd

Browse files
authored
Merge branch 'main' into python-3.9-eol
2 parents 009e521 + 51d402c commit d13efdd

94 files changed

Lines changed: 4574 additions & 3205 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: griffe API check
6+
7+
description: >-
8+
Check a package's public API (as defined by `__all__`) for changes using
9+
griffe.
10+
11+
inputs:
12+
package-name:
13+
description: "Importable package name to check, e.g. cuda.core"
14+
required: true
15+
package-dir:
16+
description: "Directory to search for the package sources, e.g. cuda_core"
17+
required: true
18+
merge-base:
19+
description: >-
20+
Git ref/sha to compare the current code against, typically the PR's
21+
merge-base with its target branch.
22+
required: true
23+
24+
runs:
25+
using: composite
26+
steps:
27+
- name: Install uv
28+
uses: astral-sh/setup-uv@fac544c07dec837d0ccb6301d7b5580bf5edae39 # v8.2.0
29+
with:
30+
enable-cache: false
31+
32+
- name: Check API
33+
shell: bash --noprofile --norc -euo pipefail {0}
34+
env:
35+
PACKAGE_NAME: ${{ inputs.package-name }}
36+
PACKAGE_DIR: ${{ inputs.package-dir }}
37+
MERGE_BASE: ${{ inputs.merge-base }}
38+
run: |
39+
uvx griffe check "$PACKAGE_NAME" \
40+
--search "$PACKAGE_DIR" \
41+
--find-stubs-packages \
42+
--against "$MERGE_BASE" \
43+
--format github \
44+
2>&1

‎.github/workflows/build-wheel.yml‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,11 @@ jobs:
338338
id: setup-python2
339339
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
340340
with:
341-
python-version: ${{ matrix.python-version }}
342-
# TODO: remove allow-prereleases once 3.15 is officially supported
341+
# TODO: Pin beta.2 precisely until cibuildwheel catches up (b4 broke ABI for Cython);
342+
# this precise pin requires the explicit `freethreaded`.
343+
# When 3.15 is officially supported we can also remove the `allow-prereleases` override.
344+
python-version: ${{ startsWith(matrix.python-version, '3.15') && '3.15.0-beta.2' || matrix.python-version }}
345+
freethreaded: ${{ endsWith(matrix.python-version, 't') }}
343346
allow-prereleases: ${{ startsWith(matrix.python-version, '3.15') }}
344347

345348
- name: verify free-threaded build

‎.github/workflows/ci.yml‎

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ jobs:
103103
test_bindings: ${{ steps.compose.outputs.test_bindings }}
104104
test_core: ${{ steps.compose.outputs.test_core }}
105105
test_pathfinder: ${{ steps.compose.outputs.test_pathfinder }}
106+
pr_merge_base: ${{ steps.filter.outputs.merge_base }}
106107
steps:
107108
- name: Checkout repository
108109
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
@@ -156,6 +157,7 @@ jobs:
156157
echo "python_meta=$(has_match '^cuda_python/')"
157158
echo "test_helpers=$(has_match '^cuda_python_test_helpers/')"
158159
echo "shared=$(has_match '^(\.github/|ci/|scripts/|toolshed/|conftest\.py$|pyproject\.toml$|pixi\.(toml|lock)$|pytest\.ini$|ruff\.toml$)')"
160+
echo "merge_base=${base}"
159161
} >> "$GITHUB_OUTPUT"
160162
161163
- name: Compose gating outputs
@@ -228,6 +230,89 @@ jobs:
228230
echo "test_pathfinder=${test_pathfinder}"
229231
} >> "$GITHUB_OUTPUT"
230232
233+
api-check-core-vs-release:
234+
name: API check (cuda_core vs. latest release)
235+
if: >-
236+
${{ !fromJSON(needs.should-skip.outputs.skip) &&
237+
fromJSON(needs.detect-changes.outputs.core) }}
238+
runs-on: ubuntu-latest
239+
needs:
240+
- should-skip
241+
- detect-changes
242+
permissions:
243+
contents: read
244+
steps:
245+
- name: Checkout repository
246+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
247+
with:
248+
fetch-depth: 1
249+
filter: blob:none
250+
251+
- name: Find latest release tag
252+
id: latest-tag
253+
shell: bash --noprofile --norc -euo pipefail {0}
254+
env:
255+
GH_TOKEN: ${{ github.token }}
256+
run: |
257+
# --paginate fetches all pages; jq outputs one name per line per page;
258+
# head -1 takes the first (newest) match since GitHub returns tags
259+
# newest-first. Fails hard if no cuda-core-v* tag is found.
260+
tag="$(gh api "repos/$GITHUB_REPOSITORY/tags" --paginate \
261+
--jq '.[] | select(.name | startswith("cuda-core-v")) | .name' \
262+
| head -1)"
263+
if [[ -z "${tag}" ]]; then
264+
echo "::error::No cuda-core-v* tag found in the repository." >&2
265+
exit 1
266+
fi
267+
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
268+
269+
- name: Fetch release tag
270+
shell: bash --noprofile --norc -euo pipefail {0}
271+
run: |
272+
git fetch --depth=1 --filter=blob:none origin \
273+
"refs/tags/${{ steps.latest-tag.outputs.tag }}:refs/tags/${{ steps.latest-tag.outputs.tag }}"
274+
275+
- name: Check cuda_core public API
276+
id: griffe
277+
uses: ./.github/actions/griffe-api-check
278+
with:
279+
package-name: cuda.core
280+
package-dir: cuda_core
281+
merge-base: ${{ steps.latest-tag.outputs.tag }}
282+
283+
api-check-core-vs-base:
284+
name: API check (cuda_core vs. merge base)
285+
if: >-
286+
${{ startsWith(github.ref_name, 'pull-request/') &&
287+
!fromJSON(needs.should-skip.outputs.skip) &&
288+
fromJSON(needs.detect-changes.outputs.core) }}
289+
runs-on: ubuntu-latest
290+
needs:
291+
- should-skip
292+
- detect-changes
293+
permissions:
294+
contents: read
295+
steps:
296+
- name: Checkout repository
297+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
298+
with:
299+
fetch-depth: 1
300+
filter: blob:none
301+
302+
- name: Fetch merge base commit
303+
shell: bash --noprofile --norc -euo pipefail {0}
304+
run: |
305+
git fetch --depth=1 --filter=blob:none origin \
306+
"${{ needs.detect-changes.outputs.pr_merge_base }}"
307+
308+
- name: Check cuda_core public API
309+
id: griffe
310+
uses: ./.github/actions/griffe-api-check
311+
with:
312+
package-name: cuda.core
313+
package-dir: cuda_core
314+
merge-base: ${{ needs.detect-changes.outputs.pr_merge_base }}
315+
231316
# NOTE: Build jobs are intentionally split by platform rather than using a single
232317
# matrix. This allows each test job to depend only on its corresponding build,
233318
# so faster platforms can proceed through build & test without waiting for slower

‎.github/workflows/release.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ jobs:
158158
steps:
159159
- name: Checkout Source
160160
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
161+
with:
162+
ref: ${{ inputs.git-tag }}
161163

162164
- name: Set up Python
163165
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0

‎.github/workflows/test-wheel-linux.yml‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,11 @@ jobs:
296296
- name: Set up Python ${{ matrix.PY_VER }}
297297
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
298298
with:
299-
python-version: ${{ matrix.PY_VER }}
300-
# TODO: remove allow-prereleases once 3.15 is officially supported
299+
# TODO: Pin beta.2 precisely until cibuildwheel catches up (b4 broke ABI for Cython)
300+
# this precise pin requires the explicit `freethreaded`.
301+
# When 3.15 is officially supported we can also remove the `allow-prereleases` override.
302+
python-version: ${{ startsWith(matrix.PY_VER, '3.15') && '3.15.0-beta.2' || matrix.PY_VER }}
303+
freethreaded: ${{ endsWith(matrix.PY_VER, 't') }}
301304
allow-prereleases: ${{ startsWith(matrix.PY_VER, '3.15') }}
302305
env:
303306
# we use self-hosted runners on which setup-python behaves weirdly (Python include can't be found)...

‎.github/workflows/test-wheel-windows.yml‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,12 @@ jobs:
276276
- name: Set up Python ${{ matrix.PY_VER }}
277277
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
278278
with:
279-
python-version: ${{ matrix.PY_VER }}
279+
# TODO: Pin beta.2 precisely until cibuildwheel catches up (b4 broke ABI for Cython)
280+
# this precise pin requires the explicit `freethreaded`.
281+
# When 3.15 is officially supported we can also remove the `allow-prereleases` override.
282+
python-version: ${{ startsWith(matrix.PY_VER, '3.15') && '3.15.0-beta.2' || matrix.PY_VER }}
283+
freethreaded: ${{ endsWith(matrix.PY_VER, 't') }}
284+
allow-prereleases: ${{ startsWith(matrix.PY_VER, '3.15') }}
280285

281286
- name: Verify LongPathsEnabled
282287
run: |

‎.pre-commit-config.yaml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ repos:
5050
files: ^cuda_bindings/
5151
types: [text]
5252

53+
- id: check-pixi-cuda-version
54+
name: Check pixi cuda-version pins track ci/versions.yml
55+
entry: python ./ci/tools/check_pixi_cuda_version.py
56+
language: python
57+
additional_dependencies: [pyyaml==6.0.3]
58+
files: '^(ci/versions\.yml|cuda_bindings/pixi\.toml|cuda_core/pixi\.toml)$'
59+
pass_filenames: false
60+
5361
- id: no-markdown-in-docs-source
5462
name: Prevent markdown files in docs/source directories
5563
entry: bash -c

‎CONTRIBUTING.md‎

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of
1919

2020
- [Contributing to CUDA Python](#contributing-to-cuda-python)
2121
- [Table of Contents](#table-of-contents)
22+
- [Cloning the repository](#cloning-the-repository)
23+
- [Recommended clone](#recommended-clone)
24+
- [Fixing an existing clone](#fixing-an-existing-clone)
25+
- [Symptoms of a bad clone](#symptoms-of-a-bad-clone)
2226
- [Type stubs for cuda.core](#type-stubs-for-cudacore)
2327
- [Pre-commit](#pre-commit)
2428
- [Signing Your Work](#signing-your-work)
@@ -34,6 +38,94 @@ Thank you for your interest in contributing to CUDA Python! Based on the type of
3438
- [Code coverage](#code-coverage)
3539

3640

41+
## Cloning the repository
42+
43+
Every package in this repository derives its version from git tags using
44+
[`setuptools-scm`](https://setuptools-scm.readthedocs.io/), so **how you clone
45+
determines whether you can build at all, and whether the version you build is
46+
correct.** Each package matches its own tag prefix:
47+
48+
| Package | Tag pattern |
49+
| --- | --- |
50+
| `cuda-bindings`, `cuda-python` | `v*` (e.g. `v13.3.1`) |
51+
| `cuda-core` | `cuda-core-v*` (e.g. `cuda-core-v1.1.0`) |
52+
| `cuda-pathfinder` | `cuda-pathfinder-v*` (e.g. `cuda-pathfinder-v1.6.0`) |
53+
54+
Each package sets `root = ".."` in its `[tool.setuptools_scm]` table, meaning the
55+
version is read from the *repository root* rather than the package directory. A
56+
working build therefore needs all of the following:
57+
58+
1. **A real git clone.** Source zips and GitHub "Download ZIP" archives have no
59+
git metadata and the build fails outright. (Tarballs produced by
60+
`git archive` do work, thanks to the `.git_archival.txt` substitutions
61+
configured in `.gitattributes`.)
62+
2. **The full repository**, not just the package subdirectory, because the
63+
version lookup walks up to the repository root.
64+
3. **Tags, reaching back at least as far as the most recent tag** matching the
65+
package you are building. `git describe` needs to find that tag; the history
66+
between it and your checkout must be present too.
67+
68+
### Recommended clone
69+
70+
The default `git clone` gives you everything you need:
71+
72+
```console
73+
$ git clone https://github.com/NVIDIA/cuda-python.git
74+
```
75+
76+
77+
78+
### Fixing an existing clone
79+
80+
If you already have a shallow clone:
81+
82+
```console
83+
$ git fetch --unshallow --tags
84+
```
85+
86+
If you are working from a personal fork, your fork's tags stop tracking upstream
87+
the moment new releases are cut, which silently yields a stale version. Fetch
88+
tags from upstream directly:
89+
90+
```console
91+
$ git remote add upstream https://github.com/NVIDIA/cuda-python.git
92+
$ git fetch --tags upstream
93+
```
94+
95+
Keep doing this periodically — a fork that was correct when you created it will
96+
drift.
97+
98+
### Symptoms of a bad clone
99+
100+
Only case 3 below reports an error. The first two fail *silently*, producing a
101+
wrong version that surfaces much later as a confusing dependency-resolution or
102+
version-check failure:
103+
104+
1. **No tags reachable.** The build succeeds and produces a version starting at
105+
`0.1.dev`: a `--depth 1` clone yields `0.1.dev1+g0d22cb444`, a full clone made
106+
with `--no-tags` yields `0.1.dev2114+g0d22cb444`. Installing `cuda-python`
107+
built this way then fails, because its `install_requires` pins
108+
`cuda-bindings` to that same bogus version.
109+
2. **Stale tags** (a fork that has not fetched upstream in a while): you get a
110+
plausible-looking but wrong version, e.g. `13.0.4.dev650+g0d22cb44` when the
111+
real latest tag is `v13.3.1`. Nothing warns you. Note there is no leading
112+
`v` — the tag prefix is stripped by `tag_regex`.
113+
3. **No git metadata** (source zip): the build fails with
114+
`LookupError: setuptools-scm was unable to detect version`.
115+
116+
As a last resort — for example when building inside a container that has no git
117+
history — you can bypass the lookup entirely:
118+
119+
```console
120+
$ SETUPTOOLS_SCM_PRETEND_VERSION_FOR_CUDA_CORE=1.1.0 pip install ./cuda_core
121+
```
122+
123+
The environment variable is suffixed with the distribution name, uppercased with
124+
hyphens replaced by underscores: `..._FOR_CUDA_BINDINGS`, `..._FOR_CUDA_CORE`,
125+
`..._FOR_CUDA_PATHFINDER`, `..._FOR_CUDA_PYTHON`. Use this only when you
126+
genuinely cannot provide tags; it is not a substitute for a correct clone.
127+
128+
37129
## Type stubs for cuda.core
38130

39131
`cuda.core` is a PEP 561-compliant package: it ships a `py.typed` marker and

0 commit comments

Comments
 (0)