@@ -948,3 +948,65 @@ def test_from_yaml_generation_numeric_tunables_allowed(tmp_path: Path) -> None:
948948 assert c .raw ["narration_from_source" ]["max_context_bytes" ] == 90000
949949 assert c .raw ["manim_scene_generation" ]["temperature" ] == 0.4
950950 assert c .raw ["manim_scene_generation" ]["max_whisper_words_in_prompt" ] == 12
951+
952+
953+ def test_from_yaml_bool_av_sync_tolerance_raises (tmp_path : Path ) -> None :
954+ p = tmp_path / "docgen.yaml"
955+ p .write_text ("validation:\n av_sync:\n tolerance_sec: true\n " , encoding = "utf-8" )
956+ with pytest .raises (
957+ ConfigError , match = "validation.av_sync.tolerance_sec must be a YAML number"
958+ ):
959+ Config .from_yaml (p )
960+
961+
962+ def test_from_yaml_list_ocr_min_confidence_raises (tmp_path : Path ) -> None :
963+ p = tmp_path / "docgen.yaml"
964+ p .write_text (
965+ "validation:\n ocr:\n min_confidence:\n - 40\n " ,
966+ encoding = "utf-8" ,
967+ )
968+ with pytest .raises (
969+ ConfigError , match = "validation.ocr.min_confidence must be a YAML number"
970+ ):
971+ Config .from_yaml (p )
972+
973+
974+ def test_from_yaml_bool_story_end_max_early_sec_raises (tmp_path : Path ) -> None :
975+ p = tmp_path / "docgen.yaml"
976+ p .write_text ("validation:\n story_end:\n max_early_sec: true\n " , encoding = "utf-8" )
977+ with pytest .raises (
978+ ConfigError , match = "validation.story_end.max_early_sec must be a YAML number"
979+ ):
980+ Config .from_yaml (p )
981+
982+
983+ def test_from_yaml_string_timing_sync_tail_gap_raises (tmp_path : Path ) -> None :
984+ p = tmp_path / "docgen.yaml"
985+ p .write_text (
986+ 'validation:\n timing_sync:\n max_tail_gap_sec: "3.0"\n ' ,
987+ encoding = "utf-8" ,
988+ )
989+ with pytest .raises (
990+ ConfigError , match = "validation.timing_sync.max_tail_gap_sec must be a YAML number"
991+ ):
992+ Config .from_yaml (p )
993+
994+
995+ def test_from_yaml_validation_nested_numerics_allowed (tmp_path : Path ) -> None :
996+ p = tmp_path / "docgen.yaml"
997+ p .write_text (
998+ "validation:\n "
999+ " ocr:\n sample_interval_sec: 3\n min_confidence: 50\n "
1000+ " layout:\n min_spacing_px: 12\n edge_margin_px: 18\n "
1001+ " av_sync:\n tolerance_sec: 2.5\n min_anchors_per_segment: 3\n "
1002+ " timing_sync:\n max_tail_gap_sec: 4.0\n max_end_overrun_sec: 1.5\n "
1003+ " story_end:\n max_early_sec: 30\n max_early_ratio: 0.4\n " ,
1004+ encoding = "utf-8" ,
1005+ )
1006+ c = Config .from_yaml (p )
1007+ assert c .ocr_config ["sample_interval_sec" ] == 3
1008+ assert c .ocr_config ["min_confidence" ] == 50
1009+ assert c .layout_config ["min_spacing_px" ] == 12
1010+ assert c .av_sync_config ["tolerance_sec" ] == 2.5
1011+ assert c .timing_sync_config ["max_tail_gap_sec" ] == 4.0
1012+ assert c .story_end_config ["max_early_sec" ] == 30
0 commit comments