pip: restore the rich, audio and flash-attn dependencies main declares
This commit is contained in:
parent
b6e7ffcd76
commit
e14e2d89bf
3 changed files with 80 additions and 2 deletions
|
|
@ -59,6 +59,10 @@ dependencies = [
|
|||
# imports that, so every command needs it. typer supplied it until 0.27
|
||||
# dropped the dependency, which left this satisfied only by chance.
|
||||
"click>=8.0",
|
||||
# unsloth_cli/__init__.py imports commands/chat.py, which imports rich at
|
||||
# module level, so every command needs it. typer still pulls rich, but it
|
||||
# pulled click too until 0.26.0 dropped it: same shape, so declare it.
|
||||
"rich",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
|
@ -506,16 +510,19 @@ cu126-torch2100 = [
|
|||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu126onlytorch2100]",
|
||||
"unsloth[audio-torch210]",
|
||||
]
|
||||
cu128-torch2100 = [
|
||||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu128onlytorch2100]",
|
||||
"unsloth[audio-torch210]",
|
||||
]
|
||||
cu130-torch2100 = [
|
||||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu130onlytorch2100]",
|
||||
"unsloth[audio-torch210]",
|
||||
]
|
||||
kaggle = [
|
||||
"unsloth[huggingface]",
|
||||
|
|
@ -537,6 +544,17 @@ flashattention = [
|
|||
"ninja ; ('linux' in sys_platform)",
|
||||
"flash-attn>=2.6.3 ; ('linux' in sys_platform)",
|
||||
]
|
||||
# torchcodec is the audio decode path; its releases track torch minor versions,
|
||||
# so each torch minor gets its own window (#7225).
|
||||
audio-torch280 = [
|
||||
"torchcodec>=0.6.0,<0.8.0 ; python_version >= '3.9'",
|
||||
]
|
||||
audio-torch290 = [
|
||||
"torchcodec>=0.8.0,<0.10.0 ; python_version >= '3.10'",
|
||||
]
|
||||
audio-torch210 = [
|
||||
"torchcodec>=0.10.0,<0.11.0 ; python_version >= '3.10'",
|
||||
]
|
||||
colab-ampere-torch211 = [
|
||||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
|
|
@ -769,6 +787,7 @@ cu130-ampere-torch280 = [
|
|||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu130onlytorch280]",
|
||||
"unsloth[flashattention]",
|
||||
]
|
||||
cu126-ampere-torch290 = [
|
||||
"unsloth[huggingface]",
|
||||
|
|
@ -804,16 +823,19 @@ cu126-ampere-torch2100 = [
|
|||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu126onlytorch2100]",
|
||||
"unsloth[audio-torch210]",
|
||||
]
|
||||
cu128-ampere-torch2100 = [
|
||||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu128onlytorch2100]",
|
||||
"unsloth[audio-torch210]",
|
||||
]
|
||||
cu130-ampere-torch2100 = [
|
||||
"unsloth[huggingface]",
|
||||
"bitsandbytes>=0.45.5,!=0.46.0,!=0.48.0",
|
||||
"unsloth[cu130onlytorch2100]",
|
||||
"unsloth[audio-torch210]",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
|
|
|
|||
|
|
@ -101,3 +101,52 @@ class TestAmdExtraIsInstallableFromPyPI:
|
|||
extras = _load()["project"].get("optional-dependencies", {})
|
||||
assert any("huggingfacenotorch" in d for d in extras["amd"])
|
||||
assert "huggingfacenotorch" in extras
|
||||
|
||||
|
||||
class TestRuntimeImportsAreDeclared:
|
||||
"""This branch's base install has to satisfy every module-scope import on the CLI
|
||||
entry path. typer supplied click until 0.26.0 dropped it (#7504); it still supplies
|
||||
rich, so rich is satisfied only by chance unless we declare it ourselves."""
|
||||
|
||||
ENTRY_PATH_IMPORTS = ("click", "rich", "structlog", "typer")
|
||||
|
||||
def test_cli_entry_path_imports_are_base_dependencies(self):
|
||||
packaging_requirements = pytest.importorskip("packaging.requirements")
|
||||
base = _load()["project"].get("dependencies", [])
|
||||
declared = {
|
||||
packaging_requirements.Requirement(r).name.lower().replace("_", "-")
|
||||
for r in base
|
||||
}
|
||||
missing = [p for p in self.ENTRY_PATH_IMPORTS if p not in declared]
|
||||
assert missing == [], (
|
||||
"imported at module scope by unsloth_cli/__init__.py's import chain but not "
|
||||
f"declared in base dependencies: {missing}"
|
||||
)
|
||||
|
||||
|
||||
class TestAcceleratorExtrasCarryTheirCompanions:
|
||||
"""Each accelerator extra composes a stack: `-ampere-` variants add flash-attn and
|
||||
torch 2.10 variants add the torchcodec audio path. A variant that silently drops one
|
||||
installs a quietly weaker environment than its siblings."""
|
||||
|
||||
def test_torch2100_extras_pull_the_audio_path(self):
|
||||
extras = _load()["project"].get("optional-dependencies", {})
|
||||
targets = [
|
||||
n
|
||||
for n in extras
|
||||
if n.endswith("torch2100") and "only" not in n and n.startswith("cu")
|
||||
]
|
||||
assert targets, "expected cu*-torch2100 extras to exist"
|
||||
missing = [n for n in targets if not any("audio-torch" in d for d in extras[n])]
|
||||
assert missing == [], f"torch 2.10 extras missing the audio extra: {missing}"
|
||||
|
||||
def test_ampere_torch280_extras_pull_flash_attention(self):
|
||||
extras = _load()["project"].get("optional-dependencies", {})
|
||||
targets = [n for n in extras if n.endswith("-ampere-torch280")]
|
||||
assert targets, "expected *-ampere-torch280 extras to exist"
|
||||
missing = [
|
||||
n
|
||||
for n in targets
|
||||
if not any("flashattention" in d or "flash-attn" in d for d in extras[n])
|
||||
]
|
||||
assert missing == [], f"ampere torch 2.8 extras missing flash-attn: {missing}"
|
||||
|
|
|
|||
|
|
@ -45,15 +45,22 @@ def _stub_torch(monkeypatch, version: str):
|
|||
|
||||
|
||||
def test_torch210_extras_bundle_audio_torch210():
|
||||
"""The ROCm extras pin torch from the AMD wheel index, which PyPI rejects as a
|
||||
direct reference, so this branch does not carry them. Check whichever torch 2.10
|
||||
extras it does define, and require at least one."""
|
||||
text = PYPROJECT.read_text(encoding = "utf-8")
|
||||
checked = 0
|
||||
for extra in (
|
||||
"cu128-torch2100",
|
||||
"cu126-ampere-torch2100",
|
||||
"rocm72-torch2100",
|
||||
):
|
||||
match = re.search(rf"^{extra} = \[(.*?)^\]", text, re.MULTILINE | re.DOTALL)
|
||||
assert match is not None, extra
|
||||
assert "unsloth[audio-torch210]" in match.group(1)
|
||||
if match is None:
|
||||
continue
|
||||
assert "unsloth[audio-torch210]" in match.group(1), extra
|
||||
checked += 1
|
||||
assert checked, "no torch 2.10 extra found to check"
|
||||
|
||||
|
||||
def test_torchcodec_matrix_matches_notebook_validator():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue