Skip to content

Commit

Permalink
Changelog, coverage, formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD committed Jul 19, 2023
1 parent 4fdba6c commit 0bccdcc
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 29 deletions.
7 changes: 7 additions & 0 deletions hypothesis-python/RELEASE.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
RELEASE_TYPE: minor

:func:`~hypothesis.strategy.from_regex` now supports the atomic grouping
(``(?>...)``) and possessive quantifier (``*+``, ``++``, ``?+``, ``{m,n}+``)
syntax `added in Python 3.11 <https://docs.python.org/3/whatsnew/3.11.html#re>`__.

Thanks to Cheuk Ting Ho for implementing this!
24 changes: 11 additions & 13 deletions hypothesis-python/src/hypothesis/strategies/_internal/regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@

import operator
import re
import sys

try: # pragma: no cover
import re._constants as sre
import re._parser as sre_parse

ATOMIC_GROUP = sre.ATOMIC_GROUP
POSSESSIVE_REPEAT = sre.POSSESSIVE_REPEAT
except ImportError: # Python < 3.11
import sre_constants as sre
import sre_parse

from hypothesis import reject
from hypothesis import strategies as st
ATOMIC_GROUP = object()
POSSESSIVE_REPEAT = object()

from hypothesis import reject, strategies as st
from hypothesis.internal.charmap import as_general_categories, categories
from hypothesis.internal.compat import int_to_byte

Expand Down Expand Up @@ -52,14 +56,6 @@
GROUP_CACHE_STRATEGY = st.shared(st.builds(dict), key="hypothesis.regex.group_cache")


if sys.version_info[:2] < (3, 11):
ATOMIC_GROUP = object()
POSSESSIVE_REPEAT = object()
else:
ATOMIC_GROUP = sre.ATOMIC_GROUP
POSSESSIVE_REPEAT = sre.POSSESSIVE_REPEAT


@st.composite
def update_group(draw, group_name, strategy):
cache = draw(GROUP_CACHE_STRATEGY)
Expand Down Expand Up @@ -504,10 +500,12 @@ def recurse(codes):
recurse(value[1]),
recurse(value[2]) if value[2] else st.just(empty),
)
elif code == ATOMIC_GROUP:
elif code == ATOMIC_GROUP: # pragma: no cover # new in Python 3.11
return _strategy(value, context, is_unicode)

else:
# Currently there are no known code points other than handled here.
# This code is just future proofing
raise NotImplementedError(f"Unknown code point: {code!r}")
raise NotImplementedError(
f"Unknown code point: {code!r}. Please open an issue."
)
23 changes: 7 additions & 16 deletions hypothesis-python/tests/nocover/test_regex.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@

import pytest

from hypothesis import assume, given, reject
from hypothesis import strategies as st
from hypothesis import assume, given, reject, strategies as st
from hypothesis.strategies._internal.regex import base_regex_strategy


Expand Down Expand Up @@ -92,26 +91,18 @@ def test_fuzz_stuff(data):

@pytest.mark.skipif(sys.version_info[:2] < (3, 11), reason="new syntax")
@given(st.data())
def test_regex_atomic_point(data):
def test_regex_atomic_group(data):
pattern = "a(?>bc|b)c"
flags = 0

regex = re.compile(pattern, flags=flags)

ex = data.draw(st.from_regex(regex))
assert regex.search(ex)
ex = data.draw(st.from_regex(pattern))
assert re.search(pattern, ex)


@pytest.mark.skipif(sys.version_info[:2] < (3, 11), reason="new syntax")
@given(st.data())
def test_regex_processive(data):
def test_regex_possessive(data):
pattern = '"[^"]*+"'
flags = 0

regex = re.compile(pattern, flags=flags)

ex = data.draw(st.from_regex(regex))
assert regex.search(ex)
ex = data.draw(st.from_regex(pattern))
assert re.search(pattern, ex)


# Some preliminaries, to establish what's happening:
Expand Down

0 comments on commit 0bccdcc

Please sign in to comment.