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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 2 additions & 29 deletions kernels-data/bindings/python/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,17 @@ use kernels_data::config::{Backend, KernelDependency, KernelName, KernelVersion}
use kernels_data::digest::{Digest, DigestAlgorithm, DigestViolation};
use kernels_data::git::{GitStatus, Oid};
use kernels_data::metadata::{BackendInfo, KernelBuilderVersion, Metadata, Provenance};
use kernels_data::version::Version;
use pyo3::Bound as PyBound;
use pyo3::exceptions::{PyException, PyOSError, PyRuntimeError, PyValueError};
use pyo3::prelude::*;

mod config;
mod lock;
mod version;

use config::{PyBuild, PyGeneral};
use lock::{PyKernelLock, PyKernelLocks, PyKernelPaths, PyNixKernelLock, PyNixKernelLocks};

/// A dotted numeric version (e.g. `12.8.0`). Trailing zeros are stripped
/// during normalization.
#[pyclass(name = "Version", frozen, eq, ord, hash)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
struct PyVersion {
inner: Version,
}

#[pymethods]
impl PyVersion {
/// Parse a version string of the form `X`, `X.Y`, `X.Y.Z`, ...
#[staticmethod]
#[pyo3(name = "from_str")]
fn py_from_str(s: &str) -> PyResult<Self> {
Version::from_str(s)
.map(|inner| Self { inner })
.map_err(|err| PyValueError::new_err(format!("Cannot parse version `{s}`: {err}")))
}

fn __str__(&self) -> String {
self.inner.to_string()
}

fn __repr__(&self) -> String {
format!("Version('{}')", self.inner)
}
}
use version::PyVersion;

/// A validated kernel name matching `^[a-z][-a-z0-9]*[a-z0-9]$`.
#[pyclass(name = "KernelName", frozen, eq, hash)]
Expand Down
54 changes: 54 additions & 0 deletions kernels-data/bindings/python/src/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;

/// A dotted numeric version (e.g. `12.8.0`). Trailing zeros are stripped
/// during normalization.
#[pyclass(name = "Version", frozen, eq, ord, hash)]
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub(crate) struct PyVersion {
// We are storing this as a `Box<[usize]>` to allow storing kernels-data
// `Version` in directly in `PyVersion` as well.
inner: Box<[usize]>,
}

#[pymethods]
impl PyVersion {
/// Parse a version string of the form `X`, `X.Y`, `X.Y.Z`, ...
#[staticmethod]
#[pyo3(name = "from_str")]
fn py_from_str(s: &str) -> PyResult<Self> {
let version = s.trim();
if version.is_empty() {
return Err(PyValueError::new_err(format!(
"Cannot parse version `{s}`: empty version string"
)));
}
let mut parts = Vec::new();
for part in version.split('.') {
let component: usize = part.parse().map_err(|_| {
PyValueError::new_err(format!(
"Cannot parse version `{s}`: version must consist of numbers"
))
})?;
parts.push(component);
}
// Remove trailing zeros for normalization.
let trailing_zeros = parts.iter().rev().take_while(|&&x| x == 0).count();
parts.truncate(parts.len() - trailing_zeros);
Ok(Self {
inner: parts.into_boxed_slice(),
})
}

fn __str__(&self) -> String {
self.inner
.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join(".")
}

fn __repr__(&self) -> String {
format!("Version('{}')", self.__str__())
}
}
24 changes: 0 additions & 24 deletions kernels-data/bindings/python/tests/test_kernels_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
KernelName,
KernelVersion,
Metadata,
Version,
)


Expand All @@ -18,29 +17,6 @@ def _write_metadata(path, **fields):
return path


def test_version_parse_and_normalize():
assert str(Version.from_str("12.8.0")) == "12.8"
assert str(Version.from_str("1")) == "1"
assert str(Version.from_str("1.2.3")) == "1.2.3"


def test_version_ordering_and_hash():
v1 = Version.from_str("1.2")
v2 = Version.from_str("1.2.0")
v3 = Version.from_str("1.3")
assert v1 == v2
assert v1 < v3
assert hash(v1) == hash(v2)
assert {v1, v2, v3} == {v1, v3}


def test_version_invalid():
with pytest.raises(ValueError):
Version.from_str("abc")
with pytest.raises(ValueError):
Version.from_str("")


def test_kernel_name_valid():
n = KernelName("my-kernel")
assert str(n) == "my-kernel"
Expand Down
26 changes: 26 additions & 0 deletions kernels-data/bindings/python/tests/test_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import pytest

from kernels_data import Version


def test_version_parse_and_normalize():
assert str(Version.from_str("12.8.0")) == "12.8"
assert str(Version.from_str("1")) == "1"
assert str(Version.from_str("1.2.3")) == "1.2.3"
Comment on lines +7 to +9

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.

One for 13.0 as well since it came up quite a bit? 😁

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

😁 but not in a Python context though.



def test_version_ordering_and_hash():
v1 = Version.from_str("1.2")
v2 = Version.from_str("1.2.0")
v3 = Version.from_str("1.3")
assert v1 == v2
assert v1 < v3
assert hash(v1) == hash(v2)
assert {v1, v2, v3} == {v1, v3}


def test_version_invalid():
with pytest.raises(ValueError):
Version.from_str("abc")
with pytest.raises(ValueError):
Version.from_str("")
16 changes: 8 additions & 8 deletions kernels-data/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,8 @@ impl General {
}

pub struct CudaGeneral {
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub kernel_depends: Option<Vec<KernelDependency>>,
pub python_depends: Option<Vec<String>>,
}
Expand All @@ -236,8 +236,8 @@ pub struct Hub {

pub struct Torch {
pub include: Option<Vec<String>>,
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub pyext: Option<Vec<String>>,
pub src: Vec<PathBuf>,
pub stable_abi: Option<TorchAbi>,
Expand All @@ -249,14 +249,14 @@ pub struct Torch {
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum TorchAbi {
All(Version),
Mapping(BTreeMap<Backend, Version>),
All(Version<2>),
Mapping(BTreeMap<Backend, Version<2>>),
}

impl TorchAbi {
/// Stable ABI version to target for `backend`, or `None` if it should be
/// built without the stable ABI.
pub fn for_backend(&self, backend: Backend) -> Option<&Version> {
pub fn for_backend(&self, backend: Backend) -> Option<&Version<2>> {
match self {
TorchAbi::All(version) => Some(version),
TorchAbi::Mapping(mapping) => mapping.get(&backend),
Expand Down Expand Up @@ -327,7 +327,7 @@ pub enum Kernel {
Cuda {
cuda_capabilities: Option<Vec<String>>,
cuda_flags: Option<Vec<String>>,
cuda_minver: Option<Version>,
cuda_minver: Option<Version<2>>,
cxx_flags: Option<Vec<String>>,
depends: Vec<Dependency>,
include: Option<Vec<String>>,
Expand Down
10 changes: 5 additions & 5 deletions kernels-data/src/config/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ pub struct General {
#[serde(default)]
pub universal: bool,

pub cuda_maxver: Option<Version>,
pub cuda_maxver: Option<Version<2>>,

pub cuda_minver: Option<Version>,
pub cuda_minver: Option<Version<2>>,

pub hub: Option<Hub>,

Expand Down Expand Up @@ -63,8 +63,8 @@ impl Display for PythonDependency {
#[serde(deny_unknown_fields)]
pub struct Torch {
pub include: Option<Vec<String>>,
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub pyext: Option<Vec<String>>,

#[serde(default)]
Expand All @@ -85,7 +85,7 @@ pub enum Kernel {
Cuda {
cuda_capabilities: Option<Vec<String>>,
cuda_flags: Option<Vec<String>>,
cuda_minver: Option<Version>,
cuda_minver: Option<Version<2>>,
cxx_flags: Option<Vec<String>>,
depends: Vec<Dependency>,
include: Option<Vec<String>>,
Expand Down
10 changes: 5 additions & 5 deletions kernels-data/src/config/v3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ pub struct General {
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct CudaGeneral {
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub python_depends: Option<Vec<String>>,
}

Expand All @@ -84,8 +84,8 @@ pub struct Hub {
#[serde(deny_unknown_fields)]
pub struct Torch {
pub include: Option<Vec<String>>,
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub pyext: Option<Vec<String>>,

#[serde(default)]
Expand Down Expand Up @@ -114,7 +114,7 @@ pub enum Kernel {
Cuda {
cuda_capabilities: Option<Vec<String>>,
cuda_flags: Option<Vec<String>>,
cuda_minver: Option<Version>,
cuda_minver: Option<Version<2>>,
cxx_flags: Option<Vec<String>>,
depends: Vec<Dependency>,
include: Option<Vec<String>>,
Expand Down
12 changes: 6 additions & 6 deletions kernels-data/src/config/v4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ pub struct General {
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct CudaGeneral {
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub python_depends: Option<Vec<String>>,
}

Expand All @@ -83,14 +83,14 @@ pub struct Hub {
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct Torch {
pub include: Option<Vec<String>>,
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub pyext: Option<Vec<String>>,

#[serde(default)]
pub src: Vec<PathBuf>,

pub stable_abi: Option<Version>,
pub stable_abi: Option<Version<2>>,

pub cxx_flags: Option<Vec<String>>,
}
Expand Down Expand Up @@ -130,7 +130,7 @@ pub enum Kernel {
Cuda {
cuda_capabilities: Option<Vec<String>>,
cuda_flags: Option<Vec<String>>,
cuda_minver: Option<Version>,
cuda_minver: Option<Version<2>>,
cxx_flags: Option<Vec<String>>,
depends: Vec<Dependency>,
include: Option<Vec<String>>,
Expand Down
10 changes: 5 additions & 5 deletions kernels-data/src/config/v5.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,8 @@ pub struct General {
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct CudaGeneral {
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub kernel_depends: Option<Vec<KernelDependency>>,
pub python_depends: Option<Vec<String>>,
}
Expand Down Expand Up @@ -109,8 +109,8 @@ pub struct Hub {
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
pub struct Torch {
pub include: Option<Vec<String>>,
pub minver: Option<Version>,
pub maxver: Option<Version>,
pub minver: Option<Version<2>>,
pub maxver: Option<Version<2>>,
pub pyext: Option<Vec<String>>,

#[serde(default)]
Expand Down Expand Up @@ -157,7 +157,7 @@ pub enum Kernel {
Cuda {
cuda_capabilities: Option<Vec<String>>,
cuda_flags: Option<Vec<String>>,
cuda_minver: Option<Version>,
cuda_minver: Option<Version<2>>,
cxx_flags: Option<Vec<String>>,
depends: Vec<Dependency>,
include: Option<Vec<String>>,
Expand Down
Loading
Loading