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