Handle beta/rc tags, bump beta, add exact version pin to aqt

This commit is contained in:
Damien Elmes 2025-06-19 23:33:51 +07:00
parent a41c60c016
commit a60a955c61
6 changed files with 96 additions and 15 deletions

View file

@ -1 +1 @@
25.06
25.06b2

View file

@ -20,6 +20,45 @@ use ninja_gen::python::PythonTypecheck;
use ninja_gen::rsync::RsyncFiles;
use ninja_gen::Build;
/// Normalize version string by removing leading zeros from numeric parts
/// while preserving pre-release markers (b1, rc2, a3, etc.)
fn normalize_version(version: &str) -> String {
version
.split('.')
.map(|part| {
// Check if the part contains only digits
if part.chars().all(|c| c.is_ascii_digit()) {
// Numeric part: remove leading zeros
part.parse::<u32>().unwrap_or(0).to_string()
} else {
// Mixed part (contains both numbers and pre-release markers)
// Split on first non-digit character and normalize the numeric prefix
let chars = part.chars();
let mut numeric_prefix = String::new();
let mut rest = String::new();
let mut found_non_digit = false;
for ch in chars {
if ch.is_ascii_digit() && !found_non_digit {
numeric_prefix.push(ch);
} else {
found_non_digit = true;
rest.push(ch);
}
}
if numeric_prefix.is_empty() {
part.to_string()
} else {
let normalized_prefix = numeric_prefix.parse::<u32>().unwrap_or(0).to_string();
format!("{}{}", normalized_prefix, rest)
}
}
})
.collect::<Vec<_>>()
.join(".")
}
pub fn setup_venv(build: &mut Build) -> Result<()> {
let extra_binary_exports = &[
"mypy",
@ -131,14 +170,7 @@ impl BuildAction for BuildWheel {
let name = self.name;
// Normalize version like hatchling does: remove leading zeros from version
// parts
let normalized_version = self
.version
.split('.')
.map(|part| part.parse::<u32>().unwrap_or(0).to_string())
.collect::<Vec<_>>()
.join(".");
let normalized_version = normalize_version(&self.version);
let wheel_path = format!("wheels/{name}-{normalized_version}-{tag}.whl");
build.add_outputs("out", vec![wheel_path]);
@ -279,3 +311,25 @@ pub(crate) fn setup_sphinx(build: &mut Build) -> Result<()> {
)?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_normalize_version_basic() {
assert_eq!(normalize_version("1.2.3"), "1.2.3");
assert_eq!(normalize_version("01.02.03"), "1.2.3");
assert_eq!(normalize_version("1.0.0"), "1.0.0");
}
#[test]
fn test_normalize_version_with_prerelease() {
assert_eq!(normalize_version("1.2.3b1"), "1.2.3b1");
assert_eq!(normalize_version("01.02.03b1"), "1.2.3b1");
assert_eq!(normalize_version("1.0.0rc2"), "1.0.0rc2");
assert_eq!(normalize_version("2.1.0a3"), "2.1.0a3");
assert_eq!(normalize_version("1.2.3beta1"), "1.2.3beta1");
assert_eq!(normalize_version("1.2.3alpha1"), "1.2.3alpha1");
}
}

View file

@ -1,7 +1,6 @@
[project]
name = "anki"
# dynamic = ["version"]
version = "0.1.2"
dynamic = ["version"]
requires-python = ">=3.9"
license = "AGPL-3.0-or-later"
dependencies = [

View file

@ -18,6 +18,9 @@ class CustomBuildHook(BuildHookInterface):
"""Initialize the build hook."""
force_include = build_data.setdefault("force_include", {})
# Pin anki==<our version>
self._set_anki_dependency(version, build_data)
# Look for generated files in out/qt/_aqt
project_root = Path(self.root).parent
generated_root = project_root / "out" / "qt" / "_aqt"
@ -30,6 +33,29 @@ class CustomBuildHook(BuildHookInterface):
assert generated_root.exists(), "you should build with --wheel"
self._add_aqt_files(force_include, generated_root)
def _set_anki_dependency(self, version: str, build_data: Dict[str, Any]) -> None:
# Get current dependencies and replace 'anki' with exact version
dependencies = build_data.setdefault("dependencies", [])
# Remove any existing anki dependency
dependencies[:] = [dep for dep in dependencies if not dep.startswith("anki")]
# Handle version detection
actual_version = version
if version == "standard":
# Read actual version from .version file
project_root = Path(self.root).parent
version_file = project_root / ".version"
if version_file.exists():
actual_version = version_file.read_text().strip()
# Only add exact version for real releases, not editable installs
if actual_version != "editable":
dependencies.append(f"anki=={actual_version}")
else:
# For editable installs, just add anki without version constraint
dependencies.append("anki")
def _add_aqt_files(self, force_include: Dict[str, str], aqt_root: Path) -> None:
"""Add _aqt files to the build."""
for path in aqt_root.rglob("*"):

View file

@ -1,7 +1,6 @@
[project]
name = "aqt"
# dynamic = ["version"]
version = "0.1.2"
dynamic = ["version"]
requires-python = ">=3.9"
license = "AGPL-3.0-or-later"
dependencies = [
@ -25,6 +24,7 @@ dependencies = [
"types-pywin32",
"pyqt6>=6.2",
"pyqt6-webengine>=6.2",
# anki dependency is added dynamically in hatch_build.py with exact version
]
[project.optional-dependencies]

View file

@ -2,6 +2,8 @@
set -e
export UV_PUBLISH_TOKEN=$(pass show w/pypi-api-test)
out/extracted/uv/uv publish --index testpypi out/wheels/*
#export UV_PUBLISH_TOKEN=$(pass show w/pypi-api-test)
#out/extracted/uv/uv publish --index testpypi out/wheels/*
export UV_PUBLISH_TOKEN=$(pass show w/pypi-api)
out/extracted/uv/uv publish out/wheels/*