|
11 | 11 |
|
12 | 12 | import jsonschema |
13 | 13 | from hypothesis import assume, provisional as prov, strategies as st |
14 | | -from hypothesis.errors import InvalidArgument |
| 14 | +from hypothesis.errors import HypothesisWarning, InvalidArgument |
15 | 15 | from hypothesis.internal.conjecture import utils as cu |
16 | 16 |
|
17 | 17 | from ._canonicalise import ( |
@@ -76,8 +76,11 @@ def from_schema( |
76 | 76 | ) -> st.SearchStrategy[JSONType]: |
77 | 77 | """Take a JSON schema and return a strategy for allowed JSON objects. |
78 | 78 |
|
79 | | - Schema reuse with "definitions" and "$ref" is not yet supported, but |
80 | | - everything else in drafts 04, 05, and 07 is fully tested and working. |
| 79 | + To generate specific string formats, pass a ``custom_formats`` dict |
| 80 | + mapping the format name to a strategy for allowed strings. |
| 81 | +
|
| 82 | + Supports JSONSchema drafts 04, 06, and 07, with the exception of |
| 83 | + recursive references. |
81 | 84 | """ |
82 | 85 | try: |
83 | 86 | return __from_schema(schema, custom_formats=custom_formats) |
@@ -127,13 +130,18 @@ def __from_schema( |
127 | 130 | for name, strat in custom_formats.items(): |
128 | 131 | if not isinstance(name, str): |
129 | 132 | raise InvalidArgument(f"format name {name!r} must be a string") |
130 | | - if name in STRING_FORMATS: |
131 | | - raise InvalidArgument(f"Cannot redefine standard format {name!r}") |
132 | 133 | if not isinstance(strat, st.SearchStrategy): |
133 | 134 | raise InvalidArgument( |
134 | 135 | f"custom_formats[{name!r}]={strat!r} must be a Hypothesis " |
135 | 136 | "strategy which generates strings matching this format." |
136 | 137 | ) |
| 138 | + if name in STRING_FORMATS: |
| 139 | + warnings.warn( |
| 140 | + f"Overriding standard format {name!r} - was " |
| 141 | + f"{STRING_FORMATS[name]!r}, now {strat!r}", |
| 142 | + HypothesisWarning, |
| 143 | + stacklevel=2, |
| 144 | + ) |
137 | 145 | format_checker = jsonschema.FormatChecker() |
138 | 146 | custom_formats = { |
139 | 147 | name: _get_format_filter(name, format_checker, strategy) |
@@ -406,7 +414,7 @@ def string_schema( |
406 | 414 | min_size = schema.get("minLength", 0) |
407 | 415 | max_size = schema.get("maxLength") |
408 | 416 | strategy = st.text(min_size=min_size, max_size=max_size) |
409 | | - known_formats = {**(custom_formats or {}), **STRING_FORMATS} |
| 417 | + known_formats = {**STRING_FORMATS, **(custom_formats or {})} |
410 | 418 | if schema.get("format") in known_formats: |
411 | 419 | # Unknown "format" specifiers should be ignored for validation. |
412 | 420 | # See https://json-schema.org/latest/json-schema-validation.html#format |
|
0 commit comments