77import pytest
88
99
10- _ADR_DIR : typing .Final = "docs/adr/"
10+ ADR_DIR : typing .Final = "docs/adr/"
1111_CITATION : typing .Final = re .compile (r"docs/adr/\d{4}(?:-[a-z0-9-]+\.md)?" )
12- _NUMBER_PREFIX : typing .Final = "ADR-"
13- _NUMBER_CITATION : typing .Final = re .compile (_NUMBER_PREFIX + r"\d{4}" )
14- _UNWALKED_DIR : typing .Final = "node_modules"
12+ NUMBER_PREFIX : typing .Final = "ADR-"
13+ _NUMBER_CITATION : typing .Final = re .compile (NUMBER_PREFIX + r"\d{4}" )
14+ UNWALKED_DIR : typing .Final = "node_modules"
1515# mkdocs build output: a second copy of docs/, whose citations are the originals'.
1616_GENERATED_DIR : typing .Final = "site"
1717_SCANNED_SUFFIXES : typing .Final = (".py" , ".md" , ".toml" )
@@ -21,7 +21,7 @@ def _scanned_files(root: pathlib.Path) -> list[pathlib.Path]:
2121 found : list [pathlib .Path ] = []
2222 for dirpath , dirnames , filenames in os .walk (root ):
2323 dirnames [:] = sorted (
24- name for name in dirnames if not name .startswith ("." ) and name not in (_UNWALKED_DIR , _GENERATED_DIR )
24+ name for name in dirnames if not name .startswith ("." ) and name not in (UNWALKED_DIR , _GENERATED_DIR )
2525 )
2626 found .extend (pathlib .Path (dirpath , name ) for name in sorted (filenames ) if name .endswith (_SCANNED_SUFFIXES ))
2727 return found
@@ -41,9 +41,9 @@ def _citations(file: pathlib.Path, source: str) -> set[str]:
4141
4242
4343def _resolves (root : pathlib .Path , cited : str ) -> bool :
44- if cited .startswith (_ADR_DIR ):
44+ if cited .startswith (ADR_DIR ):
4545 return (root / cited ).is_file ()
46- return any ((root / _ADR_DIR ).glob (f"{ cited .removeprefix (_NUMBER_PREFIX )} -*.md" ))
46+ return any ((root / ADR_DIR ).glob (f"{ cited .removeprefix (NUMBER_PREFIX )} -*.md" ))
4747
4848
4949def unresolved_citations (root : pathlib .Path ) -> list [tuple [str , str ]]:
@@ -75,84 +75,3 @@ def test_every_adr_citation_in_the_repo_resolves(pytestconfig: pytest.Config) ->
7575 unresolved = unresolved_citations (pytestconfig .rootpath )
7676
7777 assert unresolved == [], "\n " .join (f"{ file } cites { cited } " for file , cited in unresolved )
78-
79-
80- def test_a_citation_of_a_missing_adr_is_reported_with_its_citing_file (tmp_path : pathlib .Path ) -> None :
81- """The scanner is exercised against a known result, so an empty scan cannot pass as a green one."""
82- (tmp_path / _ADR_DIR ).mkdir (parents = True )
83- (tmp_path / _ADR_DIR / "0001-kept.md" ).write_text ("# kept\n " , encoding = "utf-8" )
84- (tmp_path / "pkg" ).mkdir ()
85- (tmp_path / "pkg" / "mod.py" ).write_text (
86- f'"""Explained in { _ADR_DIR } 0001-kept.md and { _ADR_DIR } 9999-missing.md."""\n ' ,
87- encoding = "utf-8" ,
88- )
89-
90- assert unresolved_citations (tmp_path ) == [("pkg/mod.py" , f"{ _ADR_DIR } 9999-missing.md" )]
91-
92-
93- def test_a_citation_split_across_adjacent_string_literals_is_found (tmp_path : pathlib .Path ) -> None :
94- """Python joins adjacent literals at parse time, which is what the `nack` guard message relies on."""
95- (tmp_path / "guard.py" ).write_text (
96- f'MESSAGE = (\n "See https://example.invalid/blob/main/{ _ADR_DIR } "\n "0003-split.md."\n )\n ' ,
97- encoding = "utf-8" ,
98- )
99-
100- assert unresolved_citations (tmp_path ) == [("guard.py" , f"{ _ADR_DIR } 0003-split.md" )]
101-
102-
103- def test_a_citation_inside_a_hash_comment_is_found (tmp_path : pathlib .Path ) -> None :
104- """Comments never reach the AST, so the raw text is scanned as well."""
105- (tmp_path / "graph.py" ).write_text (f"# The rule is one-way, see { _ADR_DIR } 0009-comment.md\n " , encoding = "utf-8" )
106-
107- assert unresolved_citations (tmp_path ) == [("graph.py" , f"{ _ADR_DIR } 0009-comment.md" )]
108-
109-
110- def test_a_bare_adr_number_naming_no_file_is_reported (tmp_path : pathlib .Path ) -> None :
111- """A renumber leaves `ADR-NNNN` prose behind; only the path form was ever checked."""
112- (tmp_path / _ADR_DIR ).mkdir (parents = True )
113- (tmp_path / _ADR_DIR / "0001-kept.md" ).write_text ("# kept\n " , encoding = "utf-8" )
114- (tmp_path / "smoke.py" ).write_text (
115- f"# the constraint { _NUMBER_PREFIX } 0001 records, unlike { _NUMBER_PREFIX } 9999\n " , encoding = "utf-8"
116- )
117-
118- assert unresolved_citations (tmp_path ) == [("smoke.py" , f"{ _NUMBER_PREFIX } 9999" )]
119-
120-
121- def test_a_bare_adr_path_is_reported_even_when_the_adr_exists (tmp_path : pathlib .Path ) -> None :
122- """`docs/adr/NNNN` with no slug names nothing on disk, so a rename or a drop never breaks it."""
123- (tmp_path / _ADR_DIR ).mkdir (parents = True )
124- (tmp_path / _ADR_DIR / "0002-kept.md" ).write_text ("# kept\n " , encoding = "utf-8" )
125- (tmp_path / "pkg" ).mkdir ()
126- (tmp_path / "pkg" / "mod.py" ).write_text (
127- f'"""Argued in { _ADR_DIR } 0002 and { _ADR_DIR } 0002-kept.md."""\n ' , encoding = "utf-8"
128- )
129-
130- assert unresolved_citations (tmp_path ) == [("pkg/mod.py" , f"{ _ADR_DIR } 0002" )]
131-
132-
133- def test_a_citation_outside_python_is_found (tmp_path : pathlib .Path ) -> None :
134- """`pyproject.toml` explains dependency floors by citing ADRs, and Markdown cites them in prose."""
135- (tmp_path / _ADR_DIR ).mkdir (parents = True )
136- (tmp_path / "pyproject.toml" ).write_text (f"# see { _ADR_DIR } 0002-floor.md\n deps = []\n " , encoding = "utf-8" )
137- (tmp_path / "AGENTS.md" ).write_text (f"Read { _NUMBER_PREFIX } 0004 before editing.\n " , encoding = "utf-8" )
138-
139- assert unresolved_citations (tmp_path ) == [
140- ("AGENTS.md" , f"{ _NUMBER_PREFIX } 0004" ),
141- ("pyproject.toml" , f"{ _ADR_DIR } 0002-floor.md" ),
142- ]
143-
144-
145- def test_a_tree_with_no_citations_and_no_adr_directory_reports_nothing (tmp_path : pathlib .Path ) -> None :
146- (tmp_path / "plain.py" ).write_text ("X = 1\n " , encoding = "utf-8" )
147-
148- assert unresolved_citations (tmp_path ) == []
149-
150-
151- def test_files_under_dot_directories_are_not_scanned (tmp_path : pathlib .Path ) -> None :
152- """A virtualenv or a cache is not this repo's citations."""
153- (tmp_path / ".venv" / "lib" ).mkdir (parents = True )
154- (tmp_path / ".venv" / "lib" / "vendored.py" ).write_text (f"# { _ADR_DIR } 0001-elsewhere.md\n " , encoding = "utf-8" )
155- (tmp_path / _UNWALKED_DIR ).mkdir ()
156- (tmp_path / _UNWALKED_DIR / "dep.py" ).write_text (f"# { _ADR_DIR } 0002-elsewhere.md\n " , encoding = "utf-8" )
157-
158- assert unresolved_citations (tmp_path ) == []
0 commit comments