mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00

- Use --locked to assert that the lockfile won't change, so we need to explicitly 'uv lock' when making changes. Still trying to get to the bottom of why the lockfile sometimes has editable entries, which break things when switching between platforms. - Exclude __pycache__ from wheels - Move the typing stubs to our dev deps (https://github.com/ankitects/anki/pull/4074#pullrequestreview-2948088436)
82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
# Copyright: Ankitects Pty Ltd and contributors
|
|
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Any, Dict
|
|
|
|
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
|
|
|
|
class CustomBuildHook(BuildHookInterface):
|
|
"""Build hook to copy generated files into both sdist and wheel."""
|
|
|
|
PLUGIN_NAME = "custom"
|
|
|
|
def initialize(self, version: str, build_data: Dict[str, Any]) -> None:
|
|
"""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"
|
|
|
|
if not os.environ.get("ANKI_WHEEL_TAG"):
|
|
# On Windows, uv invokes this build hook during the initial uv sync,
|
|
# when the tag has not been declared by our build script.
|
|
return
|
|
|
|
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("*"):
|
|
if path.is_file() and not self._should_exclude(path):
|
|
relative_path = path.relative_to(aqt_root)
|
|
# Place files under _aqt/ in the distribution
|
|
dist_path = "_aqt" / relative_path
|
|
force_include[str(path)] = str(dist_path)
|
|
|
|
def _should_exclude(self, path: Path) -> bool:
|
|
"""Check if a file should be excluded from the wheel."""
|
|
path_str = str(path)
|
|
|
|
# Exclude __pycache__
|
|
if "/__pycache__/" in path_str:
|
|
return True
|
|
|
|
if path.suffix in [".ui", ".scss", ".map", ".ts"]:
|
|
return True
|
|
if path.name.startswith("tsconfig"):
|
|
return True
|
|
if "/aqt/data" in path_str:
|
|
return True
|
|
return False
|