File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -5,11 +5,12 @@ repositories that install `docgen` and maintain their own demo bundle. The
55library no longer ships an in-repo dogfood; consumers are the integration test
66of record.
77
8- ** Active:** ** [ timestamps-merge-stems.md] ( timestamps-merge-stems.md ) ** — CLI
9- ` timestamps ` must merge stems into existing ` timing.json ` , not wipe extra keys
10- or overwrite garbage JSON.
8+ ** Active:** ** [ wizard-exclude-lists.md] ( wizard-exclude-lists.md ) ** —
9+ ` wizard.exclude_patterns ` / ` scan_extensions ` must be string lists, not scalars.
1110
1211** Shipped:**
12+ - ** [ timestamps-merge-stems.md] ( timestamps-merge-stems.md ) ** — CLI ` timestamps `
13+ merges stems into existing ` timing.json ` instead of wiping extra keys (#93 ).
1314- ** [ asset-graph-timing.md] ( asset-graph-timing.md ) ** — wizard freshness must
1415 not treat corrupt ` timing.json ` as a missing timestamps entry (#92 ).
1516- ** [ yaml-generate-mappings.md] ( yaml-generate-mappings.md ) ** — ` yaml-generate `
Original file line number Diff line number Diff line change 11# Milestone: CLI timestamps must merge stems, not wipe ` timing.json `
22
3- ** Status:** Active
4- ** PR:** pending
3+ ** Status:** Shipped
4+ ** PR:** # 93
55** Depends on:** ` milestones/timestamps-fail-closed.md ` (PR #78 ),
66` milestones/timing-json-parse.md ` (PR #89 )
77
Original file line number Diff line number Diff line change 1+ # Milestone: wizard exclude/scan lists must not be scalars
2+
3+ ** Status:** Active
4+ ** PR:** pending
5+ ** Depends on:** ` milestones/yaml-generate-mappings.md ` (PR #91 ),
6+ ` milestones/config-mapping-keys.md ` (PR #83 )
7+
8+ ## Problem
9+
10+ ` wizard.exclude_patterns ` is a list of glob strings. A YAML string was:
11+
12+ 1 . ** Wiped** by ` yaml-generate ` ` merge_defaults ` (` ex = [] ` ).
13+ 2 . ** Iterated as characters** by wizard ` /api/scan ` (` fnmatch ` over ` "a" ` , ` "r" ` , …).
14+
15+ ` wizard.scan_extensions ` as a string similarly overwrote the default extension
16+ tuple in ` wizard_config ` and scanned the wrong files.
17+
18+ ## Goal
19+
20+ Fail closed at ` Config.from_yaml ` (` string_list_block ` ) and in ` merge_defaults `
21+ (present non-list raises ` ValueError ` ). Missing keys still default.
22+
23+ ## Done when
24+
25+ - [x] ` wizard.exclude_patterns ` / ` wizard.scan_extensions ` if present must be
26+ YAML lists of strings.
27+ - [x] ` merge_defaults ` does not replace a string ` exclude_patterns ` with ` [] ` .
28+ - [x] Tests for string exclude_patterns and scan_extensions.
29+ - [x] ` ruff check src/ tests/ `
30+ - [x] ` pytest tests/ `
31+ - [x] ` docgen benchmark ` (no clock change)
32+
33+ ## Out of scope
34+
35+ - Empty ` exclude_patterns: [] ` remains allowed (archive dirs are still skipped
36+ via ` is_under_archive_dir ` ).
37+ - Wizard ` .docgen-state.json ` corrupt still resets to empty.
Original file line number Diff line number Diff line change @@ -248,6 +248,21 @@ def __post_init__(self) -> None:
248248 f"{ src } : visual_map.{ sid_s } must be a YAML mapping, "
249249 f"not { type (spec ).__name__ } "
250250 )
251+ wiz = self ._block ("wizard" )
252+ if wiz .get ("exclude_patterns" ) is not None :
253+ string_list_block (
254+ wiz ,
255+ "exclude_patterns" ,
256+ label = "wizard.exclude_patterns" ,
257+ source = src ,
258+ )
259+ if wiz .get ("scan_extensions" ) is not None :
260+ string_list_block (
261+ wiz ,
262+ "scan_extensions" ,
263+ label = "wizard.scan_extensions" ,
264+ source = src ,
265+ )
251266
252267 def _source_label (self ) -> str :
253268 return self .yaml_path .name if self .yaml_path else "docgen.yaml"
Original file line number Diff line number Diff line change @@ -109,10 +109,14 @@ def merge_defaults(
109109 raw ["wizard" ] = wiz
110110 else :
111111 wiz = _require_yaml_mapping (wiz , label = "wizard" )
112- ex = wiz .setdefault ("exclude_patterns" , [] )
113- if not isinstance ( ex , list ) :
112+ ex = wiz .get ("exclude_patterns" )
113+ if ex is None :
114114 ex = []
115115 wiz ["exclude_patterns" ] = ex
116+ elif not isinstance (ex , list ):
117+ raise ValueError (
118+ f"wizard.exclude_patterns must be a YAML list, not { type (ex ).__name__ } "
119+ )
116120 if ARCHIVE_EXCLUDE not in ex :
117121 ex .append (ARCHIVE_EXCLUDE )
118122 changes .append (f"wizard.exclude_patterns: added { ARCHIVE_EXCLUDE !r} " )
Original file line number Diff line number Diff line change @@ -319,3 +319,17 @@ def test_from_yaml_list_manim_scene_generation_raises(tmp_path: Path) -> None:
319319 p .write_text ("manim_scene_generation: []\n " , encoding = "utf-8" )
320320 with pytest .raises (ConfigError , match = "manim_scene_generation must be a YAML mapping" ):
321321 Config .from_yaml (p )
322+
323+
324+ def test_from_yaml_string_wizard_exclude_patterns_raises (tmp_path : Path ) -> None :
325+ p = tmp_path / "docgen.yaml"
326+ p .write_text ("wizard:\n exclude_patterns: archive\n " , encoding = "utf-8" )
327+ with pytest .raises (ConfigError , match = "wizard.exclude_patterns must be a YAML list" ):
328+ Config .from_yaml (p )
329+
330+
331+ def test_from_yaml_string_wizard_scan_extensions_raises (tmp_path : Path ) -> None :
332+ p = tmp_path / "docgen.yaml"
333+ p .write_text ("wizard:\n scan_extensions: .md\n " , encoding = "utf-8" )
334+ with pytest .raises (ConfigError , match = "wizard.scan_extensions must be a YAML list" ):
335+ Config .from_yaml (p )
Original file line number Diff line number Diff line change @@ -94,6 +94,13 @@ def test_merge_defaults_idempotent_archive(tmp_path: Path) -> None:
9494 assert not any ("archive" in x and "added" in x for x in ch )
9595
9696
97+ def test_merge_defaults_rejects_string_wizard_exclude_patterns (tmp_path : Path ) -> None :
98+ cfg = _minimal_cfg (tmp_path )
99+ raw = {"wizard" : {"exclude_patterns" : "**/archive/**" }, "discovery" : {"auto_visual_map" : False }}
100+ with pytest .raises (ValueError , match = "wizard.exclude_patterns must be a YAML list" ):
101+ merge_defaults (raw , cfg )
102+
103+
97104def test_merge_defaults_syncs_manim_segments_from_visual_map (tmp_path : Path ) -> None :
98105 raw = {
99106 "repo_root" : "." ,
You can’t perform that action at this time.
0 commit comments