Skip to content

feat: support and check minver - #801

Merged
drbh merged 7 commits into
mainfrom
add-and-check-minver
Sep 1, 2026
Merged

drbh merged 7 commits into
mainfrom
add-and-check-minver

Conversation

@drbh

@drbh drbh commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

this pr adds minver to the metadata so the client library can check if the current version meets the kernel metadata requirements

@drbh drbh changed the title Add and check minver feat: support and check minver Aug 31, 2026
@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@github-actions

github-actions Bot commented Sep 1, 2026 •

Copy link
Copy Markdown

Coverage report — kernels/

Measured on: Python 3.10 / Torch 2.13.0.
Other CI configurations are not included in this number.
Hardware-gated code paths (ROCm/XPU/NPU/Darwin/Windows) are excluded or unreachable on the Linux+CUDA runner.

Total coverage: 86.7% — threshold: 80% — ✅

Per-file breakdown
Name Stmts Miss Cover Missing
src/kernels/__init__.py 14 0 100%
src/kernels/_system.py 6 1 83% 10
src/kernels/_versions.py 78 9 88% 47, 53-54, 57-58, 97, 119, 130, 136
src/kernels/archs.py 56 1 98% 95
src/kernels/backends.py 212 62 71% 40, 44, 48-51, 68, 90, 108, 117, 121, 125-127, 148, 157, 161, 165-167, 188, 199, 201, 208-211, 224, 228, 232-252, 260, 283-303
src/kernels/compat.py 8 1 88% 5
src/kernels/deps.py 81 1 99% 58
src/kernels/hf_hub.py 62 3 95% 18, 20, 114
src/kernels/importer.py 76 6 92% 119, 164, 168, 171, 185-186
src/kernels/install.py 21 7 67% 78-102
src/kernels/layer/__init__.py 6 0 100%
src/kernels/layer/_interval_tree.py 103 4 96% 23, 52, 147, 150
src/kernels/layer/device.py 48 14 71% 42, 47-49, 91, 96-98, 101, 149, 152, 155-157
src/kernels/layer/func.py 87 6 93% 91, 122, 194, 314, 340, 368
src/kernels/layer/globals.py 5 0 100%
src/kernels/layer/kernelize.py 74 8 89% 255, 281, 289-290, 296, 300, 316-318
src/kernels/layer/layer.py 216 15 93% 178, 223, 249, 367, 447-448, 460, 469, 477, 488, 517, 521, 534, 587, 617
src/kernels/layer/mode.py 14 0 100%
src/kernels/layer/repos.py 144 42 71% 27, 33, 36-43, 63-64, 70, 73-76, 90, 94, 103-104, 110, 113-116, 123-124, 130, 133-136, 143-144, 150, 153-156, 163-164, 170, 173-176, 257
src/kernels/load.py 69 2 97% 326, 365
src/kernels/locking.py 89 64 28% 35-83, 91-98, 102-125, 137, 152-159, 165-175, 179-186
src/kernels/python_deps.py 58 6 90% 59-60, 64-65, 101, 104
src/kernels/resolver.py 141 2 99% 182, 188
src/kernels/status.py 49 2 96% 23, 81
src/kernels/variants.py 278 19 93% 64, 95, 116, 146, 255-256, 298-301, 303, 387-394, 400-406, 437-443, 455-461
src/kernels/verify.py 88 1 99% 32
TOTAL 2083 276 87%

Updated by the Test kernels workflow on commit 74806977ef9cb8a5fa07057a2d82c78b073011e4.

Comment thread docs/source/builder/writing-kernels.md Outdated
- `source`: Git-compatible URL (passable to `git clone`) of the kernel-builder
formatted source repository. This repository must contain a `build.toml` and
`flake.nix` so that it can be pulled and built with the kernel builder.
- `minver`: the minimum version of the `kernels` Python library required

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we want this inbuild.toml at all? The kernel builder should determine the minimum version, not the user. They will with a very high probability set the wrong version, e.g.:

  • Not realizing that a kernel with dependencies requires 0.17, setting it to something old (or not at all).
  • Setting it to current version because that's the only thing they tested on, 'just to be safe', not making the kernel work older kernels versions.

I think the best way to tackle this is to add a method to Config:

fn required_kernels_version(&self, backend: Backend) -> Version<3> {
  // ...
}

That determines based on the features used inside Config what to set the version to. The default would be 0.14, but e.g. if there is a non-empty list of kernel dependencies for the given backend, set it to 0.17.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense, removed it from build.toml. the builder now derives it with Build::required_kernels_version(backend), defaulting to 0.14.0 and bumping to 0.17.0 when the backend has kernel dependencies. since [general] denies unknown fields, setting minver in build.toml is now a parse error rather than a silently ignored key

Comment thread kernels-data/src/metadata.rs Outdated
pub id: String,
pub version: usize,
#[serde(skip_serializing_if = "Option::is_none")]
pub minver: Option<Version<3>>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should be explicit and use kernels_minver.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed to kernels_minver (kernels-minver in metadata.json). kept it optional so metadata written before the key existed still parses

Comment thread kernels-data/bindings/python/src/lib.rs Outdated
id: String,
name: PyKernelName,
version: usize,
minver: Option<String>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
minver: Option<String>,
minver: Option<PyVersion>,

We still need a conversion from Version<N>, but I intentionally made PyVersion store a Box<[usize]> so that Version<N> can be boxed and used inside PyVersion.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated to Option<PyVersion> with a From<Version<N>> impl. the trailing zero stripping moved into a shared helper so a converted Version<3> and a parsed version compare equal

Comment thread kernels/src/kernels/importer.py Outdated
# Avoid an import cycle.
from kernels import __version__

if parse(__version__) < parse(minver):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For minver, we shouldn't rely on parse but the fact that we already have a typed version in Rust-land (see comments above).

For the __version__, we might also have to strip dev tags and such, otherwise we'll get not-matching versions on our development branch:

❯ python3 -c 'from packaging.version import parse; print(parse("0.17.0.dev0") < parse("0.17.0"))'                                                                                                                                  
True

This would be really annoying, since I don't think we want to write dev versions to metadata.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the check now compares two kernels_data.Version

parse is only used on our own __version__ to take the release segment, so 0.17.0.dev0 satisfies a 0.17.0 requirement (the warning still prints the verbatim __version__)

note: if __version__ is not pep 440 (e.g. a vcs derived version) the check is skipped, since a warning should not be able to break the import

@drbh
drbh force-pushed the add-and-check-minver branch from e78a05f to c235f23 Compare September 1, 2026 14:23
}

impl PyVersion {
/// Construct a version from its components, stripping trailing zeros so

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If what we are wrapping is a Version<3> and the versions are identical, there will always be the same number of trailing zeros. Version<N> is there to strongly type versions.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed the trailing zero stripping and the normalized helper, versions are stored as is now

Comment on lines +28 to +30
fn from(version: Version<N>) -> Self {
PyVersion::normalized(version.to_vec())
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Directly put the Version<N> in the box. We keep all the guarantees of it.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done, From<Version<N>> now boxes the components directly through the [usize] deref, no copy into a Vec first

Ok(Self {
inner: parts.into_boxed_slice(),
})
Ok(PyVersion::normalized(parts))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, we can't have the same guarantees in Python-land since we get a string. Maybe we can require another argument for the expected length?

Or put the trailing zero logic in Eq/Ord.

@drbh drbh Sep 1, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

went with the Eq/Ord option to keep from_str a single argument. comparisons are component-wise with missing components counting as zero, so 0.17 and 0.17.0 compare as equal (Hash skips trailing zeros to stay consistent with Eq). storage is untouched, str() round trips what was parsed

note: this also covers the pep 440 release segment in _installed_version, parse("0.17").release is (0, 17) and would otherwise compare below a 0.17.0 minver

@danieldk danieldk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! 🚀

@drbh
drbh merged commit 9447c18 into main Sep 1, 2026
53 of 54 checks passed

This branch was previously deployed

1 inactive deployment
testpypi — 74806977 Deployed Sep 1, 2026 by drbh via Publish Python 🐍 distribution 📦 to TestPyPI #2064
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants