diff --git a/.version b/.version index 9bab2a4b4..d1e34a036 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -25.06 +25.06b2 diff --git a/build/configure/src/python.rs b/build/configure/src/python.rs index 7cd66b76e..474a55f31 100644 --- a/build/configure/src/python.rs +++ b/build/configure/src/python.rs @@ -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::().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::().unwrap_or(0).to_string(); + format!("{}{}", normalized_prefix, rest) + } + } + }) + .collect::>() + .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::().unwrap_or(0).to_string()) - .collect::>() - .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"); + } +} diff --git a/pylib/pyproject.toml b/pylib/pyproject.toml index a12c6848b..555f30c86 100644 --- a/pylib/pyproject.toml +++ b/pylib/pyproject.toml @@ -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 = [ diff --git a/qt/hatch_build.py b/qt/hatch_build.py index e475b5d84..52ca7a0ec 100644 --- a/qt/hatch_build.py +++ b/qt/hatch_build.py @@ -18,6 +18,9 @@ class CustomBuildHook(BuildHookInterface): """Initialize the build hook.""" force_include = build_data.setdefault("force_include", {}) + # Pin anki== + 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("*"): diff --git a/qt/pyproject.toml b/qt/pyproject.toml index d8b4c4306..0c1d1b2ae 100644 --- a/qt/pyproject.toml +++ b/qt/pyproject.toml @@ -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] diff --git a/tools/publish b/tools/publish index 570f75c85..4c625c36d 100755 --- a/tools/publish +++ b/tools/publish @@ -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/*