@@ -365,7 +365,7 @@ def __init__(self, path: Path, tmpdir: Path, label: Optional[str] = None):
365
365
self ._program_callbacks = dict [Path , list [Callable [["Program" ], None ]]]()
366
366
# Dictionary from path to parsed file contents.
367
367
# TODO #102: Add type for test_group.yaml (typed Namespace?)
368
- self ._test_group_yamls = dict [Path , dict [str , Any ]]()
368
+ self ._test_case_yamls = dict [Path , dict [str , Any ]]()
369
369
self ._test_group_lock = threading .Lock ()
370
370
371
371
# The label for the problem: A, B, A1, A2, X, ...
@@ -460,83 +460,80 @@ def _read_settings(self):
460
460
self .custom_output : bool = self .settings .custom_output
461
461
462
462
# TODO #102 move to a new TestGroup class
463
- def _parse_test_group_yaml (p , path , bar ):
463
+ def _parse_test_case_and_groups_yaml (p , path : Path , bar : BAR_TYPE ):
464
464
assert path .is_relative_to (p .path / "data" )
465
- for dir in [path ] + list (path .parents ):
465
+ for f in [path ] + list (path .parents ):
466
466
# Do not go above the data directory.
467
- if dir == p .path :
467
+ if f == p .path :
468
468
return
469
469
470
- f = dir / "test_group.yaml"
471
- if not f .is_file () or f in p ._test_group_yamls :
472
- continue
470
+ if f .suffix != ".yaml" :
471
+ f = f / "test_group.yaml"
473
472
with p ._test_group_lock :
474
- if f not in p ._test_group_yamls :
475
- raw = substitute (
476
- f .read_text (),
477
- p .settings .constants ,
478
- pattern = config .CONSTANT_SUBSTITUTE_REGEX ,
479
- )
480
- p ._test_group_yamls [f ] = flags = parse_yaml (raw , path = f , plain = True )
473
+ if not f .is_file () or f in p ._test_case_yamls :
474
+ continue
475
+ raw = substitute (
476
+ f .read_text (),
477
+ p .settings .constants ,
478
+ pattern = config .CONSTANT_SUBSTITUTE_REGEX ,
479
+ )
480
+ p ._test_case_yamls [f ] = flags = parse_yaml (raw , path = f , plain = True )
481
481
482
- parse_deprecated_setting (
483
- flags , "output_validator_flags" , validate .OutputValidator .args_key
484
- )
485
- parse_deprecated_setting (
486
- flags , "input_validator_flags" , validate .InputValidator .args_key
487
- )
482
+ parse_deprecated_setting (
483
+ flags , "output_validator_flags" , validate .OutputValidator .args_key
484
+ )
485
+ parse_deprecated_setting (
486
+ flags , "input_validator_flags" , validate .InputValidator .args_key
487
+ )
488
488
489
- # Verify test_group.yaml
490
- for k in flags :
491
- match k :
492
- case (
493
- validate .OutputValidator .args_key
494
- | validate .AnswerValidator .args_key
495
- | visualize .TestCaseVisualizer .args_key
496
- | visualize .OutputVisualizer .args_key
497
- ):
498
- if not isinstance (flags [k ], list ):
499
- bar .error (
500
- f"{ k } must be a list of strings" ,
501
- resume = True ,
502
- print_item = False ,
503
- )
504
- case validate .InputValidator .args_key :
505
- if not isinstance (flags [k ], (list , dict )):
506
- bar .error (
507
- f"{ k } must be list or map" ,
508
- resume = True ,
509
- print_item = False ,
510
- )
511
- if isinstance (flags [k ], dict ):
512
- input_validator_names = set (
513
- val .name for val in p .validators (validate .InputValidator )
514
- )
515
- for name in set (flags [k ]) - input_validator_names :
516
- bar .warn (
517
- f"Unknown input validator { name } ; expected { input_validator_names } " ,
518
- print_item = False ,
519
- )
520
- case (
521
- "args"
522
- | "description"
523
- | "full_feedback"
524
- | "hint"
525
- | "scoring"
526
- | "static_validation"
527
- ):
528
- bar .warn (
529
- f"{ k } in test_group.yaml not implemented in BAPCtools" ,
530
- print_item = False ,
489
+ # Use variable kwargs so the type checker does not complain when passing them to a PrintBar (nothing happens in that case anyway)
490
+ bar_kwargs = {"resume" : True , "print_item" : False }
491
+
492
+ # Verify test_group.yaml
493
+ for k in flags :
494
+ match k :
495
+ case (
496
+ validate .OutputValidator .args_key
497
+ | validate .AnswerValidator .args_key
498
+ | visualize .TestCaseVisualizer .args_key
499
+ | visualize .OutputVisualizer .args_key
500
+ ):
501
+ if not isinstance (flags [k ], list ):
502
+ bar .error (
503
+ f"{ k } must be a list of strings" ,
504
+ None ,
505
+ ** bar_kwargs ,
531
506
)
532
- case _:
533
- path = f .relative_to (p .path / "data" )
534
- bar .warn (f'Unknown key "{ k } " in { path } ' , print_item = False )
535
- # Do not go above the data directory.
536
- if dir == p .path / "data" :
537
- break
538
-
539
- def get_test_group_yaml (
507
+ case validate .InputValidator .args_key :
508
+ if not isinstance (flags [k ], (list , dict )):
509
+ bar .error (
510
+ f"{ k } must be list or map" ,
511
+ None ,
512
+ ** bar_kwargs ,
513
+ )
514
+ if isinstance (flags [k ], dict ):
515
+ input_validator_names = set (
516
+ val .name for val in p .validators (validate .InputValidator )
517
+ )
518
+ for name in set (flags [k ]) - input_validator_names :
519
+ bar .warn (
520
+ f"Unknown input validator { name } ; expected { input_validator_names } " ,
521
+ None ,
522
+ ** bar_kwargs ,
523
+ )
524
+ case "description" | "hint" :
525
+ pass # We don't do anything with hint or description in BAPCtools, but no need to warn about this
526
+ case "args" | "full_feedback" | "scoring" | "static_validation" :
527
+ bar .warn (
528
+ f"{ k } in test_group.yaml not implemented in BAPCtools" ,
529
+ None ,
530
+ ** bar_kwargs ,
531
+ )
532
+ case _:
533
+ path = f .relative_to (p .path / "data" )
534
+ bar .warn (f'Unknown key "{ k } " in { path } ' , None , ** bar_kwargs )
535
+
536
+ def get_test_case_yaml (
540
537
p ,
541
538
path : Path ,
542
539
key : str ,
@@ -574,19 +571,21 @@ def get_test_group_yaml(
574
571
f"Only input validators support flags by validator name, got { key } and { name } "
575
572
)
576
573
577
- # parse and cache test_group.yaml
578
- p ._parse_test_group_yaml (path , bar )
574
+ # parse and cache <test_case>.yaml and test_group.yaml
575
+ path = path .with_suffix (".yaml" )
576
+ p ._parse_test_case_and_groups_yaml (path , bar )
579
577
580
578
# extract the flags
581
- for dir in [path ] + list (path .parents ):
579
+ for f in [path ] + list (path .parents ):
582
580
# Do not go above the data directory.
583
- if dir == p .path :
581
+ if f == p .path :
584
582
return []
585
583
586
- f = dir / "test_group.yaml"
587
- if f not in p ._test_group_yamls :
584
+ if f .suffix != ".yaml" :
585
+ f = f / "test_group.yaml"
586
+ if f not in p ._test_case_yamls :
588
587
continue
589
- flags = p ._test_group_yamls [f ]
588
+ flags = p ._test_case_yamls [f ]
590
589
if key in flags :
591
590
args = flags [key ]
592
591
if key == validate .InputValidator .args_key :
@@ -1333,7 +1332,7 @@ def validate_valid_extra_data(p) -> bool:
1333
1332
if not p .validators (validate .OutputValidator , strict = True , print_warn = False ):
1334
1333
return True
1335
1334
1336
- args = p .get_test_group_yaml (
1335
+ args = p .get_test_case_yaml (
1337
1336
p .path / "data" / "valid_output" ,
1338
1337
"output_validator_args" ,
1339
1338
PrintBar ("Generic Output Validation" ),
0 commit comments