44import math
55import operator
66import re
7+ import warnings
78from fractions import Fraction
89from functools import partial
910from typing import Any , Callable , Dict , List , NoReturn , Optional , Set , Union
@@ -388,6 +389,14 @@ def relative_json_pointers() -> st.SearchStrategy[str]:
388389}
389390
390391
392+ def _warn_invalid_regex (pattern : str , err : re .error , kw : str = "pattern" ) -> None :
393+ warnings .warn (
394+ f"Got { kw } ={ pattern !r} , but this is not valid syntax for a Python regular "
395+ f"expression ({ err } ) so it will not be handled by the strategy. See https://"
396+ "json-schema.org/understanding-json-schema/reference/regular_expressions.html"
397+ )
398+
399+
391400def string_schema (
392401 custom_formats : Dict [str , st .SearchStrategy [str ]], schema : dict
393402) -> st .SearchStrategy [str ]:
@@ -402,14 +411,19 @@ def string_schema(
402411 # See https://json-schema.org/latest/json-schema-validation.html#format
403412 strategy = known_formats [schema ["format" ]]
404413 if "pattern" in schema :
405- # This isn't really supported, but we'll do our best.
406- strategy = strategy .filter (re .compile (schema ["pattern" ]).search )
414+ try :
415+ # This isn't really supported, but we'll do our best with a filter.
416+ strategy = strategy .filter (re .compile (schema ["pattern" ]).search )
417+ except re .error as err :
418+ _warn_invalid_regex (schema ["pattern" ], err )
419+ return st .nothing ()
407420 elif "pattern" in schema :
408421 try :
409422 re .compile (schema ["pattern" ])
410423 strategy = st .from_regex (schema ["pattern" ])
411- except re .error :
424+ except re .error as err :
412425 # Patterns that are invalid in Python, or just malformed
426+ _warn_invalid_regex (schema ["pattern" ], err )
413427 return st .nothing ()
414428 # If we have size bounds but we're generating strings from a regex or pattern,
415429 # apply a filter to ensure our size bounds are respected.
@@ -524,6 +538,15 @@ def object_schema(
524538 additional = schema .get ("additionalProperties" , {})
525539 additional_allowed = additional != FALSEY
526540
541+ for key in list (patterns ):
542+ try :
543+ re .compile (key )
544+ except re .error as err :
545+ _warn_invalid_regex (key , err , "patternProperties entry" )
546+ if min_size == 0 and not required :
547+ return st .builds (dict )
548+ return st .nothing ()
549+
527550 dependencies = schema .get ("dependencies" , {})
528551 dep_names = {k : v for k , v in dependencies .items () if isinstance (v , list )}
529552 dep_schemas = {k : v for k , v in dependencies .items () if k not in dep_names }
0 commit comments