Bug description:
On the main branch a negative lookbehind after a character class is ignored for bytes patterns when both re.IGNORECASE and re.LOCALE are set. [b] matches b'B' under those flags, so \w(?<!b) must not match b'B', but it does. The same flag pair also lets the new [A--B] difference operator match characters that are in B.
import re
W = re.IGNORECASE | re.LOCALE
print(re.fullmatch(rb'[b]', b'B', W))
print(re.fullmatch(rb'\w(?<!b)', b'B', W))
Output on main:
<re.Match object; span=(0, 1), match=b'B'>
<re.Match object; span=(0, 1), match=b'B'>
Expected: the second line is None, which is what 3.14.4 prints.
_fuse_difference() in Lib/re/_optimizer.py rewrites <charset> (?<![B]) into a single character set carrying NEGATE without seeing the compile flags, and under this flag pair that set compiles to IN_LOC_IGNORE, which tests the whole set once per locale case.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
Bug description:
On the main branch a negative lookbehind after a character class is ignored for bytes patterns when both
re.IGNORECASEandre.LOCALEare set.[b]matchesb'B'under those flags, so\w(?<!b)must not matchb'B', but it does. The same flag pair also lets the new[A--B]difference operator match characters that are inB.Output on main:
Expected: the second line is
None, which is what 3.14.4 prints._fuse_difference()inLib/re/_optimizer.pyrewrites<charset> (?<![B])into a single character set carryingNEGATEwithout seeing the compile flags, and under this flag pair that set compiles toIN_LOC_IGNORE, which tests the whole set once per locale case.CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs