|
| 1 | +"""Regression tests for ``update_lf_base_dependency``. |
| 2 | +
|
| 3 | +The nightly bump pins base's ``lfx`` dependency to the exact ``==X.Y.0.devN`` so the dev |
| 4 | +release resolves down the tree. Base also carries ``lfx[extra]`` references (the relocated |
| 5 | +cassio/toolguard features) that are pulled by ``langflow-base[complete]``. If those keep a |
| 6 | +``~=X.Y.0`` floor while the bare ``lfx`` dep is pinned to the dev version, the floor |
| 7 | +(``>=X.Y.0``) excludes ``X.Y.0.devN`` (PEP 440 dev releases sort *below* the final) and the |
| 8 | +resolve becomes unsatisfiable. These tests lock in that all ``lfx`` forms -- bare and with |
| 9 | +extras -- get the same exact dev pin. |
| 10 | +""" |
| 11 | + |
| 12 | +import re |
| 13 | +import sys |
| 14 | +from pathlib import Path |
| 15 | + |
| 16 | +import pytest |
| 17 | + |
| 18 | +sys.path.insert(0, str(Path(__file__).resolve().parent)) |
| 19 | + |
| 20 | +import update_lf_base_dependency as mod |
| 21 | + |
| 22 | + |
| 23 | +@pytest.fixture |
| 24 | +def pyproject(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path: |
| 25 | + """A throwaway pyproject whose lfx refs mirror src/backend/base/pyproject.toml.""" |
| 26 | + content = ( |
| 27 | + "[project]\n" |
| 28 | + "dependencies = [\n" |
| 29 | + ' "lfx~=1.11.0",\n' |
| 30 | + "]\n" |
| 31 | + "\n" |
| 32 | + "[project.optional-dependencies]\n" |
| 33 | + 'cassandra = ["lfx[cassandra]~=1.11.0"]\n' |
| 34 | + "toolguard = [\"lfx[toolguard]~=1.11.0; python_version < '3.14'\"]\n" |
| 35 | + 'beautifulsoup = ["lfx~=1.11.0"]\n' |
| 36 | + ) |
| 37 | + path = tmp_path / "pyproject.toml" |
| 38 | + path.write_text(content, encoding="utf-8") |
| 39 | + # The script resolves paths relative to BASE_DIR; point it at tmp_path. |
| 40 | + monkeypatch.setattr(mod, "BASE_DIR", tmp_path) |
| 41 | + return path |
| 42 | + |
| 43 | + |
| 44 | +def test_pins_bare_and_extras_lfx_to_exact_dev(pyproject: Path) -> None: |
| 45 | + mod.update_lfx_dep_in_base(pyproject.name, "1.11.0.dev26") |
| 46 | + result = pyproject.read_text(encoding="utf-8") |
| 47 | + |
| 48 | + # Every lfx reference -- bare and with extras -- is pinned to the exact dev version. |
| 49 | + assert '"lfx==1.11.0.dev26"' in result |
| 50 | + assert '"lfx[cassandra]==1.11.0.dev26"' in result |
| 51 | + assert "\"lfx[toolguard]==1.11.0.dev26; python_version < '3.14'\"" in result |
| 52 | + |
| 53 | + # No `~=` floor survives -- a surviving floor is exactly what makes the nightly |
| 54 | + # resolve unsatisfiable. |
| 55 | + assert "~=" not in result |
| 56 | + # Extras are preserved, never dropped. |
| 57 | + assert "[cassandra]" in result |
| 58 | + assert "[toolguard]" in result |
| 59 | + |
| 60 | + |
| 61 | +def test_idempotent_on_already_pinned(pyproject: Path) -> None: |
| 62 | + mod.update_lfx_dep_in_base(pyproject.name, "1.11.0.dev26") |
| 63 | + once = pyproject.read_text(encoding="utf-8") |
| 64 | + mod.update_lfx_dep_in_base(pyproject.name, "1.11.0.dev26") |
| 65 | + twice = pyproject.read_text(encoding="utf-8") |
| 66 | + assert once == twice |
| 67 | + |
| 68 | + |
| 69 | +def test_raises_when_no_lfx_dependency(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: |
| 70 | + path = tmp_path / "pyproject.toml" |
| 71 | + path.write_text('[project]\ndependencies = ["langflow-base~=1.11.0"]\n', encoding="utf-8") |
| 72 | + monkeypatch.setattr(mod, "BASE_DIR", tmp_path) |
| 73 | + with pytest.raises(ValueError, match="LFX dependency not found"): |
| 74 | + mod.update_lfx_dep_in_base(path.name, "1.11.0.dev26") |
| 75 | + |
| 76 | + |
| 77 | +def test_pattern_skips_unrelated_packages(pyproject: Path) -> None: |
| 78 | + """Sibling packages whose names merely start with ``lfx`` must not be repinned.""" |
| 79 | + extra = ' "lfx-bundles~=1.11.0",\n "lfxthing~=1.11.0",\n' |
| 80 | + pyproject.write_text(pyproject.read_text(encoding="utf-8") + extra, encoding="utf-8") |
| 81 | + mod.update_lfx_dep_in_base(pyproject.name, "1.11.0.dev26") |
| 82 | + result = pyproject.read_text(encoding="utf-8") |
| 83 | + # The dedicated `lfx` distribution and its extras are repinned... |
| 84 | + assert '"lfx==1.11.0.dev26"' in result |
| 85 | + # ...but `lfx-bundles` / `lfxthing` keep their own floors untouched. |
| 86 | + assert re.search(r'"lfx-bundles~=1\.11\.0"', result) |
| 87 | + assert re.search(r'"lfxthing~=1\.11\.0"', result) |
0 commit comments