|
7 | 7 | import warnings |
8 | 8 | from fractions import Fraction |
9 | 9 | from functools import partial |
| 10 | +from inspect import signature |
10 | 11 | from typing import Any, Callable, Dict, List, NoReturn, Optional, Set, Union |
11 | 12 |
|
12 | 13 | import jsonschema |
13 | 14 | from hypothesis import assume, provisional as prov, strategies as st |
14 | 15 | from hypothesis.errors import HypothesisWarning, InvalidArgument |
15 | 16 | from hypothesis.internal.conjecture import utils as cu |
| 17 | +from hypothesis.strategies._internal.regex import regex_strategy |
16 | 18 |
|
17 | 19 | from ._canonicalise import ( |
18 | 20 | FALSEY, |
|
41 | 43 | ) |
42 | 44 | _FORMATS_TOKEN = object() |
43 | 45 |
|
| 46 | +from_js_regex: Callable[[str], st.SearchStrategy[str]] = st.from_regex |
| 47 | +if len(signature(regex_strategy).parameters) == 3: # pragma: no branch |
| 48 | + # On Hypothesis >= 6.31.6, we can use this to get the ECMA semantics of "$". |
| 49 | + # Conditionally-defined so that we degrade relatively gracefully if you update |
| 50 | + # Hypothesis but not hypothesis-jsonschema once we have a more general fix. |
| 51 | + |
| 52 | + def from_js_regex(pattern: str) -> st.SearchStrategy[str]: |
| 53 | + return regex_strategy( |
| 54 | + pattern, fullmatch=False, _temp_jsonschema_hack_no_end_newline=True |
| 55 | + ) |
| 56 | + |
44 | 57 |
|
45 | 58 | def merged_as_strategies( |
46 | 59 | schemas: List[Schema], custom_formats: Optional[Dict[str, st.SearchStrategy[str]]] |
@@ -429,7 +442,7 @@ def string_schema( |
429 | 442 | elif "pattern" in schema: |
430 | 443 | try: |
431 | 444 | re.compile(schema["pattern"]) |
432 | | - strategy = st.from_regex(schema["pattern"]) |
| 445 | + strategy = from_js_regex(schema["pattern"]) |
433 | 446 | except re.error as err: |
434 | 447 | # Patterns that are invalid in Python, or just malformed |
435 | 448 | _warn_invalid_regex(schema["pattern"], err) |
@@ -585,7 +598,7 @@ def object_schema( |
585 | 598 | if additional_allowed |
586 | 599 | else st.nothing(), |
587 | 600 | st.sampled_from(known_optional_names) if known_optional_names else st.nothing(), |
588 | | - st.one_of([st.from_regex(p).filter(valid_name) for p in sorted(patterns)]), |
| 601 | + st.one_of([from_js_regex(p).filter(valid_name) for p in sorted(patterns)]), |
589 | 602 | ) |
590 | 603 | all_names_strategy = st.one_of([s for s in name_strats if not s.is_empty]) |
591 | 604 |
|
|
0 commit comments