Python dependency/wheel tweaks

- 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)
This commit is contained in:
Damien Elmes 2025-06-23 16:59:50 +07:00
parent 7edd9221ac
commit 9b287dc51a
10 changed files with 58 additions and 38 deletions

View file

@ -21,7 +21,7 @@ Please do this as a final step before marking a task as completed.
During development, you can build/check subsections of our code:
- Rust: 'cargo check'
- Python: './tools/dmypy'
- Python: './tools/dmypy', and if wheel-related, './ninja wheels'
- TypeScript/Svelte: './ninja check:svelte'
Be mindful that some changes (such as modifications to .proto files) may

View file

@ -342,7 +342,12 @@ fn build_wheel(build: &mut Build) -> Result<()> {
name: "aqt",
version: anki_version(),
platform: None,
deps: inputs![":qt:aqt", glob!("qt/aqt/**"), "qt/pyproject.toml"],
deps: inputs![
":qt:aqt",
glob!("qt/aqt/**"),
"qt/pyproject.toml",
"qt/hatch_build.py"
],
},
)
}

View file

@ -68,7 +68,8 @@ pub fn build_pylib(build: &mut Build) -> Result<()> {
deps: inputs![
":pylib:anki",
glob!("pylib/anki/**"),
"pylib/pyproject.toml"
"pylib/pyproject.toml",
"pylib/hatch_build.py"
],
},
)?;

View file

@ -35,7 +35,7 @@ pub fn setup_pyenv(args: PyenvArgs) {
run_command(
Command::new(args.uv_bin)
.env("UV_PROJECT_ENVIRONMENT", args.pyenv_folder.clone())
.args(["sync", "--frozen"])
.args(["sync", "--locked"])
.args(args.extra_args),
);

View file

@ -35,8 +35,16 @@ class CustomBuildHook(BuildHookInterface):
assert generated_root.exists(), "you should build with --wheel"
for path in generated_root.rglob("*"):
if path.is_file():
if path.is_file() and not self._should_exclude(path):
relative_path = path.relative_to(generated_root)
# Place files under anki/ in the distribution
dist_path = "anki" / 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."""
# Exclude __pycache__
path_str = str(path)
if "/__pycache__/" in path_str:
return True
return False

View file

@ -10,10 +10,8 @@ dependencies = [
"orjson",
"protobuf>=4.21",
"requests[socks]",
# remove after we update to min python 3.11+
"typing_extensions",
"types-protobuf",
"types-requests",
"types-orjson",
# platform-specific dependencies
"distro; sys_platform != 'darwin' and sys_platform != 'win32'",
"psutil; sys_platform == 'win32'",

View file

@ -17,6 +17,16 @@ dev = [
"colorama", # for isort --color
"wheel",
"hatchling", # for type checking hatch_build.py files
"mock",
"types-protobuf",
"types-requests",
"types-orjson",
"types-decorator",
"types-flask",
"types-flask-cors",
"types-markdown",
"types-waitress",
"types-pywin32",
]
[project.optional-dependencies]

View file

@ -67,11 +67,16 @@ class CustomBuildHook(BuildHookInterface):
def _should_exclude(self, path: Path) -> bool:
"""Check if a file should be excluded from the wheel."""
# Match the exclusions from write_wheel.py exclude_aqt function
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 str(path):
if "/aqt/data" in path_str:
return True
return False

View file

@ -15,13 +15,6 @@ dependencies = [
"pywin32; sys.platform == 'win32'",
"anki-mac-helper; sys.platform == 'darwin'",
"pip-system-certs!=5.1",
"mock",
"types-decorator",
"types-flask",
"types-flask-cors",
"types-markdown",
"types-waitress",
"types-pywin32",
"pyqt6>=6.2",
"pyqt6-webengine>=6.2",
# anki dependency is added dynamically in hatch_build.py with exact version

42
uv.lock
View file

@ -59,9 +59,6 @@ dependencies = [
{ name = "protobuf" },
{ name = "psutil", marker = "sys_platform == 'win32' or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt66') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt67' and extra == 'extra-3-aqt-qt69')" },
{ name = "requests", extra = ["socks"] },
{ name = "types-orjson" },
{ name = "types-protobuf" },
{ name = "types-requests" },
{ name = "typing-extensions" },
]
@ -75,9 +72,6 @@ requires-dist = [
{ name = "protobuf", specifier = ">=4.21" },
{ name = "psutil", marker = "sys_platform == 'win32'" },
{ name = "requests", extras = ["socks"] },
{ name = "types-orjson" },
{ name = "types-protobuf" },
{ name = "types-requests" },
{ name = "typing-extensions" },
]
@ -111,11 +105,21 @@ dev = [
{ name = "colorama" },
{ name = "hatchling" },
{ name = "isort" },
{ name = "mock" },
{ name = "mypy" },
{ name = "mypy-protobuf" },
{ name = "pychromedevtools" },
{ name = "pylint" },
{ name = "pytest" },
{ name = "types-decorator" },
{ name = "types-flask" },
{ name = "types-flask-cors" },
{ name = "types-markdown" },
{ name = "types-orjson" },
{ name = "types-protobuf" },
{ name = "types-pywin32" },
{ name = "types-requests" },
{ name = "types-waitress" },
{ name = "wheel" },
]
@ -133,11 +137,21 @@ dev = [
{ name = "colorama" },
{ name = "hatchling" },
{ name = "isort" },
{ name = "mock" },
{ name = "mypy" },
{ name = "mypy-protobuf" },
{ name = "pychromedevtools" },
{ name = "pylint" },
{ name = "pytest" },
{ name = "types-decorator" },
{ name = "types-flask" },
{ name = "types-flask-cors" },
{ name = "types-markdown" },
{ name = "types-orjson" },
{ name = "types-protobuf" },
{ name = "types-pywin32" },
{ name = "types-requests" },
{ name = "types-waitress" },
{ name = "wheel" },
]
@ -158,7 +172,6 @@ dependencies = [
{ name = "flask" },
{ name = "flask-cors" },
{ name = "jsonschema" },
{ name = "mock" },
{ name = "pip-system-certs", version = "4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10' or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt66') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt67' and extra == 'extra-3-aqt-qt69')" },
{ name = "pip-system-certs", version = "5.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10' or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt66') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt67' and extra == 'extra-3-aqt-qt69')" },
{ name = "psutil", marker = "sys_platform == 'win32' or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt66') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt67' and extra == 'extra-3-aqt-qt69')" },
@ -173,12 +186,6 @@ dependencies = [
{ name = "pywin32", marker = "sys_platform == 'win32' or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt66') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt67' and extra == 'extra-3-aqt-qt69')" },
{ name = "requests" },
{ name = "send2trash" },
{ name = "types-decorator" },
{ name = "types-flask" },
{ name = "types-flask-cors" },
{ name = "types-markdown" },
{ name = "types-pywin32" },
{ name = "types-waitress" },
{ name = "waitress" },
]
@ -223,7 +230,6 @@ requires-dist = [
{ name = "flask" },
{ name = "flask-cors" },
{ name = "jsonschema" },
{ name = "mock" },
{ name = "pip-system-certs", specifier = "!=5.1" },
{ name = "psutil", marker = "sys_platform == 'win32'" },
{ name = "pyqt6", specifier = ">=6.2" },
@ -251,12 +257,6 @@ requires-dist = [
{ name = "pywin32", marker = "sys_platform == 'win32'" },
{ name = "requests" },
{ name = "send2trash" },
{ name = "types-decorator" },
{ name = "types-flask" },
{ name = "types-flask-cors" },
{ name = "types-markdown" },
{ name = "types-pywin32" },
{ name = "types-waitress" },
{ name = "waitress", specifier = ">=2.0.0" },
]
provides-extras = ["audio", "qt", "qt66", "qt67", "qt69"]
@ -595,7 +595,7 @@ name = "importlib-metadata"
version = "8.7.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "zipp" },
{ name = "zipp", marker = "python_full_version < '3.10' or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt66') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt67') or (extra == 'extra-3-aqt-qt66' and extra == 'extra-3-aqt-qt69') or (extra == 'extra-3-aqt-qt67' and extra == 'extra-3-aqt-qt69')" },
]
sdist = { url = "https://files.pythonhosted.org/packages/76/66/650a33bd90f786193e4de4b3ad86ea60b53c89b669a5c7be931fac31cdb0/importlib_metadata-8.7.0.tar.gz", hash = "sha256:d13b81ad223b890aa16c5471f2ac3056cf76c5f10f82d6f9292f0b415f389000", size = 56641, upload-time = "2025-04-27T15:29:01.736Z" }
wheels = [