@@ -443,6 +443,57 @@ def test_regex_examples_from_config():
443443 break
444444 assert matched , f"Example '{ example } ' in group '{ name } ' did not match any pattern."
445445
446+
447+ def test_regex_negative_cases ():
448+ """Verify regex patterns prevent false positives (lookaheads, patch bounds) and support whitespace."""
449+ config_path = "regex_config.yaml"
450+ with open (config_path , 'r' ) as f :
451+ config = yaml .safe_load (f )
452+
453+ rules_list = config .get ("rules" , [])
454+
455+ # Target version 3.7
456+ vars = {
457+ "name" : "protobuf" ,
458+ "major" : "3" ,
459+ "minor" : "7" ,
460+ "version" : "3.7" ,
461+ "minor_plus_one" : "8" ,
462+ "minor_minus_one" : "6"
463+ }
464+
465+ # Find specific rule groups
466+ dep_req_group = next (r for r in rules_list if r ["name" ] == "dependency_requirement" )
467+ python_cmd_group = next (r for r in rules_list if r ["name" ] == "explicit_python_command" )
468+ python_req_group = next (r for r in rules_list if r ["name" ] == "python_requires" )
469+ sys_info_group = next (r for r in rules_list if r ["name" ] == "sys_version_info" )
470+
471+ # 1. Verify dependency_requirement looks ahead correctly (no partial match)
472+ dep_pattern = re .compile (dep_req_group ["rules" ][0 ].strip ().format (** vars ), re .IGNORECASE )
473+ assert dep_pattern .search ("protobuf==3.7" )
474+ assert not dep_pattern .search ("protobuf==3.72" )
475+
476+ # 2. Verify explicit_python_command negative lookahead
477+ cmd_pattern = re .compile (python_cmd_group ["rules" ][0 ].strip ().format (** vars ), re .IGNORECASE )
478+ assert cmd_pattern .search ("python3.7" )
479+ assert not cmd_pattern .search ("python3.72" )
480+
481+ # 3. Verify python_requires optional patch limits boundary rules to .0
482+ # Boundary rule 1: >=3.7 (python_requires = '>=3.7.0' is OK, but >=3.7.1 is not equivalent and should be skipped)
483+ req_ge_pattern = re .compile (python_req_group ["rules" ][1 ].strip ().format (** vars ), re .IGNORECASE )
484+ assert req_ge_pattern .search ("python_requires = '>=3.7'" )
485+ assert req_ge_pattern .search ("python_requires = '>=3.7.0'" )
486+ assert not req_ge_pattern .search ("python_requires = '>=3.7.1'" )
487+
488+ # 4. Verify sys_version_info[1] allows optional whitespace
489+ # Matches sys.version_info[ 1 ]
490+ sys_sub_pattern = re .compile (sys_info_group ["rules" ][10 ].strip ().format (** vars ), re .IGNORECASE ) # sys.version_info[1] == 7
491+ assert sys_sub_pattern .search ("sys.version_info[1] == 7" )
492+ assert sys_sub_pattern .search ("sys.version_info[ 1 ] == 7" )
493+ assert sys_sub_pattern .search ("sys.version_info[1 ] == 7" )
494+ assert sys_sub_pattern .search ("sys.version_info[ 1] == 7" )
495+
496+
446497def test_main_exit_code_1 ():
447498 """Test that main() calls sys.exit(1) when matches are found."""
448499 # We can mock scan_repository to return a dummy match
0 commit comments