Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion scripts/repo_shape.py
Original file line number Diff line number Diff line change
Expand Up @@ -1055,11 +1055,20 @@ def load_yaml(path: Path) -> Any:
and only then fails to decode it, so the `OSError` clause never sees it
and, uncaught, it left every reader as a Python traceback (#192) rather
than the `REFUSED yaml-unreadable` line a missing file already gets.

AN `OSError` NAMES THE FILE ONCE (#712). `str()` of one is `[Errno 13]
Permission denied: '<path>'`, so `<path>: <that>` named the path twice,
the second time in Python's quoting. The line is `<path>: cannot be read
(<the system's reason>)`, the words `validate-pins.py` gives a workflow
file it cannot open (#359), and the refusal is still raised `from` the
`OSError`, which that validator reads to name the file relative to its
root.
"""
try:
text = Path(path).read_text(encoding="utf-8")
except OSError as exc:
raise Refusal("yaml-unreadable", f"{path}: {exc}") from exc
raise Refusal("yaml-unreadable",
f"{path}: cannot be read ({_os_reason(exc)})") from exc
except UnicodeDecodeError as exc:
raise Refusal(
"yaml-unreadable",
Expand Down
489 changes: 370 additions & 119 deletions templates/assembly-root/scripts/validate-pins.py

Large diffs are not rendered by default.

11 changes: 5 additions & 6 deletions tests/test_bump_leg_unreadable.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,11 @@ def test_the_other_legs_pin_stays_the_validators_refusal(project, scaffolded,
commit_bytes(project, Path("contracts") / "code-pin.yaml", LATIN1_COMMENT,
append=True)

# The file is named by the VALIDATOR, whose `load_yaml` prints the Path it
# was given, absolute and in the platform's own spelling:
# `...\Atlas\contracts\code-pin.yaml` on Windows. This tool's own refusals
# name a file by its repository path, `as_posix()`, and are asserted as
# such everywhere else in this module; this one is not its text.
pin = str(Path("contracts") / "code-pin.yaml")
# The file is named by the VALIDATOR, relative to the root and POSIX on
# every platform, as this tool's own refusals name one (#712). It named
# the Path its `load_yaml` was given, absolute and in the platform's own
# spelling: `...\Atlas\contracts\code-pin.yaml` on Windows.
pin = "contracts/code-pin.yaml"
stderr = refused_and_untouched(
project, scaffolded, advanced, "bump-leg-validators-red",
"yaml-unreadable", pin)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_reader_refusals_named.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ def test_the_roots_validate_pins_gives_the_remedy_and_not_the_lockstep(
cwd=project)
assert checked.returncode == 2, checked.stderr + checked.stdout
assert checked.stderr.splitlines() == [
f"REFUSED yaml-unparsable: {pin.resolve()}: line {line}: {OPENS} "
f"REFUSED yaml-unparsable: contracts/spec-pin.yaml: line {line}: "
f"{OPENS} "
"`@`, which is reserved in YAML: '@x'", remedy_for("@x")]
assert REMEDIATION not in checked.stderr

Expand Down
6 changes: 4 additions & 2 deletions tests/test_refusal_default_remediation.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ def _break_spec_pin(project: Path, how: str) -> str:
f"'{short}', which is not 40 hex. An abbreviated oid, a "
"branch or a tag is a moving reference.")
pin.write_bytes(b"commit: [unclosed\n")
return (f"REFUSED yaml-unparsable: {pin.resolve()}: not a flow "
# Named relative to the root, as the gate names every file (#712).
return ("REFUSED yaml-unparsable: contracts/spec-pin.yaml: not a flow "
"collection: '[unclosed'")


Expand All @@ -265,7 +266,8 @@ def test_validate_pins_prints_the_lockstep_remedy_as_it_always_did(
"""The assembly root's own gate is the one place the lockstep remedy is
the right one, and it prints it under each refusal that names no other:
its own (`pin-tag-only`) and one `repo_shape` raises for it
(`yaml-unparsable`), byte for byte what it printed before #370."""
(`yaml-unparsable`), byte for byte what it printed before #370, under
a line that names the pin relative to the root since #712."""
line = _break_spec_pin(project, how)
checked = run_script(project / "scripts" / "validate-pins.py",
"--quiet", cwd=project)
Expand Down
Loading
Loading