Compare commits
107 commits
main
...
fix/pip-am
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
910a657d80 | ||
|
|
c254d82f9d | ||
|
|
1e3190e2e2 | ||
|
|
2bea7862ef |
||
|
|
5ab9e7dbd4 | ||
|
|
735fcde44c |
||
|
|
8d38165771 | ||
|
|
3455b45977 | ||
|
|
b1b499c743 | ||
|
|
b22b243e1b | ||
|
|
ef4894c559 | ||
|
|
18673a562a | ||
|
|
cd50f9e51d | ||
|
|
6c3c01c0c9 | ||
|
|
5dec1284eb | ||
|
|
7beecd279e | ||
|
|
75f831616e | ||
|
|
4373fdbaee | ||
|
|
3f55e7a98c | ||
|
|
a9b3321915 | ||
|
|
a42720636b | ||
|
|
2f111da0f6 | ||
|
|
2c9587d9fc | ||
|
|
c436f3ca67 | ||
|
|
12f34025dc | ||
|
|
5e5c6c8fed | ||
|
|
287243a8fd | ||
|
|
4aa7dd5b18 | ||
|
|
c9aa094c91 | ||
|
|
1b1807ef9a | ||
|
|
a370521879 | ||
|
|
b712f9f557 | ||
|
|
667467a315 | ||
|
|
55075f691e | ||
|
|
0e929cddac | ||
|
|
ecaf3dde2a | ||
|
|
fc9d82f6bf | ||
|
|
4d2afc62a0 | ||
|
|
43c669e6ec | ||
|
|
11b69c1051 | ||
|
|
39c7a4d290 | ||
|
|
ff1088af40 | ||
|
|
6d3849b821 | ||
|
|
8e26a368e1 | ||
|
|
e31d4c6aea | ||
|
|
5688072af6 | ||
|
|
d3ac7447eb | ||
|
|
2fdfe24fb1 | ||
|
|
e2215c9d11 | ||
|
|
b11f13a710 | ||
|
|
66ae2d416c | ||
|
|
b0a35ddeab | ||
|
|
405add94a1 | ||
|
|
64dc11faa2 | ||
|
|
07e2fccf38 | ||
|
|
d482382a92 |
||
|
|
342bbc2333 | ||
|
|
e1fe3be939 | ||
|
|
d459f60458 | ||
|
|
2c4bf9ae35 | ||
|
|
a87a08610e | ||
|
|
41abe89041 | ||
|
|
d638d1bd6f | ||
|
|
2e3b2bdc27 | ||
|
|
9cc539c1b4 | ||
|
|
973c7d80c2 | ||
|
|
c27f9b99e9 | ||
|
|
0c24d61708 | ||
|
|
e9a2b5c010 | ||
|
|
e8355451ea | ||
|
|
a7b4ae19ee | ||
|
|
9066946615 | ||
|
|
b2580ae32b | ||
|
|
7ae9580ce6 | ||
|
|
9ad3b761ee | ||
|
|
8f721d28d6 | ||
|
|
396aa05ead | ||
|
|
2297f73cad | ||
|
|
a728f7c308 | ||
|
|
884152daee | ||
|
|
7437af2e44 | ||
|
|
67678d2c29 | ||
|
|
e568000a92 | ||
|
|
6700dd60f0 | ||
|
|
abf578327c | ||
|
|
a4ae80cd6a | ||
|
|
ec47b2984d | ||
|
|
d9d1a63397 | ||
|
|
0bb6379aad | ||
|
|
1c608e8ff7 | ||
|
|
f9adf6834d | ||
|
|
1fd5853741 | ||
|
|
93a70fbe4e | ||
|
|
8b77451e75 | ||
|
|
481f0618ff | ||
|
|
ddf6f6d1f9 | ||
|
|
dddc9eac92 | ||
|
|
da81c94510 | ||
|
|
4c139503c1 | ||
|
|
9d1e3c38bc | ||
|
|
8bc26f4e1d | ||
|
|
044e67f5aa | ||
|
|
ba36c12240 | ||
|
|
0a5652281f | ||
|
|
bf63f79414 | ||
|
|
2973bea3d0 | ||
|
|
ddbbfe52cf |
3 changed files with 247 additions and 659 deletions
812
pyproject.toml
812
pyproject.toml
File diff suppressed because it is too large
Load diff
|
|
@ -8,12 +8,19 @@ filter_sensitive_data (structlog processor for sanitization), and
|
||||||
get_logger (factory for structured loggers).
|
get_logger (factory for structured loggers).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
from starlette.types import ASGIApp, Message, Receive, Scope, Send
|
|
||||||
|
# Annotations only: importing at runtime would make the ASGI stack a hard
|
||||||
|
# dependency of every CLI command.
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from starlette.types import ASGIApp, Message, Receive, Scope, Send
|
||||||
|
|
||||||
from utils.native_path_leases import redact_native_paths
|
from utils.native_path_leases import redact_native_paths
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved. See /studio/LICENSE.AGPL-3.0
|
||||||
|
|
||||||
|
"""The studio extra must mirror studio/backend/requirements/studio.txt.
|
||||||
|
|
||||||
|
Nothing else keeps them in sync, and drift reintroduces #4701 / #5260 / #7147.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pathlib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
REPO_ROOT = pathlib.Path(__file__).resolve().parents[3]
|
||||||
|
PYPROJECT = REPO_ROOT / "pyproject.toml"
|
||||||
|
STUDIO_TXT = REPO_ROOT / "studio" / "backend" / "requirements" / "studio.txt"
|
||||||
|
|
||||||
|
# Imported at module scope by the chain every CLI command walks: structlog via
|
||||||
|
# studio.backend, click via unsloth_cli/commands/start.py.
|
||||||
|
CORE_RUNTIME_PACKAGES = ("structlog", "click")
|
||||||
|
|
||||||
|
|
||||||
|
def _load_pyproject() -> dict:
|
||||||
|
if sys.version_info >= (3, 11):
|
||||||
|
import tomllib
|
||||||
|
else:
|
||||||
|
tomllib = pytest.importorskip("tomli")
|
||||||
|
return tomllib.loads(PYPROJECT.read_text(encoding = "utf-8"))
|
||||||
|
|
||||||
|
|
||||||
|
def _requirement_lines(path: pathlib.Path) -> list[str]:
|
||||||
|
out = []
|
||||||
|
for line in path.read_text(encoding = "utf-8").splitlines():
|
||||||
|
text = line.split("#", 1)[0].strip()
|
||||||
|
if text and not text.startswith("-"):
|
||||||
|
out.append(text)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def _normalise(name: str) -> str:
|
||||||
|
"""PEP 503 normalisation, so PyJWT/pyjwt and nest_asyncio/nest-asyncio match."""
|
||||||
|
head = name
|
||||||
|
for sep in ("===", "==", ">=", "<=", "~=", "!=", ">", "<", "[", ";", " "):
|
||||||
|
idx = head.find(sep)
|
||||||
|
if idx > 0:
|
||||||
|
head = head[:idx]
|
||||||
|
return head.strip().lower().replace("_", "-").replace(".", "-")
|
||||||
|
|
||||||
|
|
||||||
|
def test_studio_extra_exists():
|
||||||
|
extras = _load_pyproject()["project"]["optional-dependencies"]
|
||||||
|
assert "studio" in extras, (
|
||||||
|
"pyproject.toml has no `studio` extra. The wheel ships studio/ and "
|
||||||
|
"studio.backend*, so their dependencies need a pip-installable home."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_studio_extra_matches_requirements_file():
|
||||||
|
extras = _load_pyproject()["project"]["optional-dependencies"]
|
||||||
|
extra = sorted(_normalise(entry) for entry in extras["studio"])
|
||||||
|
required = sorted(_normalise(entry) for entry in _requirement_lines(STUDIO_TXT))
|
||||||
|
|
||||||
|
missing = sorted(set(required) - set(extra))
|
||||||
|
surplus = sorted(set(extra) - set(required))
|
||||||
|
assert not missing, (
|
||||||
|
f"studio.txt lists {missing} but the `studio` extra does not. "
|
||||||
|
'`pip install "unsloth[studio]"` would build a venv the Studio server '
|
||||||
|
"cannot boot in. Add them to [project.optional-dependencies] studio."
|
||||||
|
)
|
||||||
|
assert not surplus, (
|
||||||
|
f"The `studio` extra lists {surplus} but studio.txt does not. "
|
||||||
|
"Remove them, or add them to studio.txt if install.sh needs them too."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("package", CORE_RUNTIME_PACKAGES)
|
||||||
|
def test_cli_runtime_packages_are_core_dependencies(package):
|
||||||
|
core = [_normalise(entry) for entry in _load_pyproject()["project"]["dependencies"]]
|
||||||
|
assert _normalise(package) in core, (
|
||||||
|
f"{package} is imported at module scope by the studio.backend chain "
|
||||||
|
f"`unsloth train` / `unsloth export` walk, so a plain `pip install "
|
||||||
|
f"unsloth` must provide it or they die with ModuleNotFoundError."
|
||||||
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue