utils/dep_freshness/tests/test_parsers.py
Krzysztof kuhy Rudnicki 71133a808f Judge peer dependencies by range, and check the packageManager pin
Two npm-specific corrections found by running the gate over web_ui.

**`peerDependencies` must not be exact-pinned.** The gate was reporting
`react: ">=19"` as "not exact-pinned", and acting on that would have been
actively harmful: a peer range declares what a CONSUMER may bring, so pinning
it forces every consumer of @kuhyx/web-ui onto one exact React. Peers are now
judged the way toolchain ranges are -- does the range still admit latest? --
and only reported when it does not.

**`packageManager` is a real dependency.** corepack enforces it, so
`pnpm@10.13.1` is an exact pin that nothing was checking. It is now read and
compared, which immediately surfaced that both TS packages sit on pnpm 10.13.1
against 11.24.0.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CRykabMwPgDzFHcARoqpaK
2026-08-28 13:38:40 +02:00

166 lines
5.6 KiB
Python

"""Manifest parsing, including the shapes that used to crash the gate.
`plugin_platform_interface: any` and a `requirements.txt` of bare names were
the two Phase-0 "the gate cannot even parse these" cases. They parse now, and
land as findings — a gate that dies on the input it exists to police is worse
than no gate.
"""
from __future__ import annotations
from dep_freshness.parsers import fvm, javascript, pubspec, python, rust
from dep_freshness.tests.conftest import write
PUBSPEC = """\
name: demo
environment:
sdk: ^3.12.2
dependencies:
flutter:
sdk: flutter
http: 1.6.0
plugin_platform_interface: any
crdt_sync:
git:
url: https://github.com/kuhyx/utils
ref: crdt_sync_dart-v0.11.0
path: crdt_sync_dart
dev_dependencies:
flutter_test:
sdk: flutter
very_good_analysis: ^10.2.0
dependency_overrides:
meta: 1.16.0
"""
def _by_name(deps):
return {d.name: d for d in deps}
def test_pubspec_reads_every_dependency_shape(tmp_path):
deps = _by_name(pubspec.parse(write(tmp_path, "pubspec.yaml", PUBSPEC)))
assert deps["http"].pinned == "1.6.0"
assert deps["plugin_platform_interface"].pinned is None
assert deps["crdt_sync_dart"].ecosystem == "gittag"
assert deps["crdt_sync_dart"].pinned == "0.11.0"
assert deps["dart"].constraint == "^3.12.2"
assert deps["very_good_analysis"].caret_ok
assert deps["meta"].override
def test_pubspec_skips_sdk_packages(tmp_path):
deps = _by_name(pubspec.parse(write(tmp_path, "pubspec.yaml", PUBSPEC)))
assert "flutter" not in deps
assert "flutter_test" not in deps
def test_a_missing_lockfile_is_a_library_not_a_violation(tmp_path):
"""Four of the nine shared libs gitignore their lock on purpose."""
deps = _by_name(pubspec.parse(write(tmp_path, "pubspec.yaml", PUBSPEC)))
assert deps["http"].locked is None
def test_pubspec_reads_the_lockfile_when_one_is_committed(tmp_path):
write(tmp_path, "pubspec.yaml", PUBSPEC)
write(tmp_path, "pubspec.lock", "packages:\n http:\n version: \"1.5.0\"\n")
deps = _by_name(pubspec.parse(tmp_path / "pubspec.yaml"))
assert deps["http"].locked == "1.5.0"
def test_line_numbers_prefer_the_least_indented_key(tmp_path):
"""A nested `path:` inside a git block must not win over the real dep."""
body = PUBSPEC.replace(" http: 1.6.0", " path: 1.9.1\n http: 1.6.0")
deps = _by_name(pubspec.parse(write(tmp_path, "pubspec.yaml", body)))
assert deps["path"].line == 7 # not the nested `path:` in the git block
def test_requirements_bare_names_parse_as_unpinned(tmp_path):
path = write(tmp_path, "requirements.txt", "numpy\npillow\n# a comment\n-e .\n")
deps = python.parse_requirements(path)
assert [d.name for d in deps] == ["numpy", "pillow"]
assert all(d.pinned is None for d in deps)
def test_requirements_handles_extras_markers_and_pins(tmp_path):
path = write(
tmp_path, "requirements.txt",
'ruff==0.16.5\nuvicorn[standard]==0.30.0\nfoo>=1.0 ; python_version>"3.9"\n',
)
deps = {d.name: d for d in python.parse_requirements(path)}
assert deps["ruff"].pinned == "0.16.5"
assert deps["uvicorn"].pinned == "0.30.0"
assert deps["foo"].pinned is None
def test_pyproject_reads_project_and_group_dependencies(tmp_path):
path = write(tmp_path, "pyproject.toml", """\
[project]
requires-python = ">=3.10"
dependencies = ["httpx==0.28.1"]
[project.optional-dependencies]
dev = ["pytest==8.4.2"]
[dependency-groups]
lint = ["ruff==0.16.5"]
""")
deps = {d.name: d for d in python.parse_pyproject(path)}
assert deps["httpx"].pinned == "0.28.1"
assert deps["pytest"].pinned == "8.4.2"
assert deps["ruff"].pinned == "0.16.5"
assert deps["python"].constraint == ">=3.10"
def test_package_json_reads_the_package_manager_pin(tmp_path):
"""corepack enforces `packageManager`, so it is a real dependency."""
path = write(tmp_path, "package.json", '{"packageManager": "pnpm@10.13.1"}')
deps = {d.name: d for d in javascript.parse_package_json(path)}
assert deps["pnpm"].pinned == "10.13.1"
def test_a_package_manager_without_a_version_is_ignored(tmp_path):
path = write(tmp_path, "package.json", '{"packageManager": "pnpm"}')
assert javascript.parse_package_json(path) == []
def test_peer_dependencies_are_marked_as_such(tmp_path):
path = write(tmp_path, "package.json",
'{"peerDependencies": {"react": ">=19"}}')
assert javascript.parse_package_json(path)[0].peer
def test_package_json_reads_engines_and_overrides(tmp_path):
path = write(tmp_path, "package.json", """\
{"engines": {"node": "24.20.0"},
"dependencies": {"react": "19.2.0", "local": "workspace:*"},
"devDependencies": {"vitest": "^4.1.10"},
"resolutions": {"semver": "7.7.1"}}
""")
deps = {d.name: d for d in javascript.parse_package_json(path)}
assert deps["node"].pinned == "24.20.0"
assert deps["react"].pinned == "19.2.0"
assert "local" not in deps
assert deps["vitest"].pinned is None
assert deps["semver"].override
def test_cargo_treats_a_two_part_version_as_a_range(tmp_path):
path = write(tmp_path, "Cargo.toml", """\
[dependencies]
serde = "1.0.229"
loose = "1.0"
local = { path = "../x" }
tabled = { version = "0.20.0" }
""")
deps = {d.name: d for d in rust.parse(path)}
assert deps["serde"].pinned == "1.0.229"
assert deps["loose"].pinned is None
assert deps["tabled"].pinned == "0.20.0"
assert "local" not in deps
def test_fvmrc_channel_is_not_a_version(tmp_path):
channel = fvm.parse(write(tmp_path, ".fvmrc", '{"flutter": "stable"}'))
assert channel[0].pinned is None
pinned = fvm.parse(write(tmp_path, ".fvmrc", '{"flutter": "3.47.2"}'))
assert pinned[0].pinned == "3.47.2"