mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
gh-92728: Restore re.template, but deprecate it (GH-93161)
Revert "bpo-47211: Remove function re.template() and flag re.TEMPLATE (GH-32300)"
This reverts commit b09184bf05
.
This commit is contained in:
parent
08e4e887f2
commit
16a7e4a0b7
10 changed files with 65 additions and 5 deletions
|
@ -1273,6 +1273,11 @@ Deprecated
|
||||||
is now deprecated. Support will be removed in Python 3.13. (Contributed by
|
is now deprecated. Support will be removed in Python 3.13. (Contributed by
|
||||||
Jingchen Ye in :gh:`90224`.)
|
Jingchen Ye in :gh:`90224`.)
|
||||||
|
|
||||||
|
* The :func:`re.template` function and the corresponding :const:`re.TEMPLATE`
|
||||||
|
and :const:`re.T` flags are deprecated, as they were undocumented and
|
||||||
|
lacked an obvious purpose. They will be removed in Python 3.13.
|
||||||
|
(Contributed by Serhiy Storchaka and Miro Hrončok in :gh:`92728`.)
|
||||||
|
|
||||||
|
|
||||||
Pending Removal in Python 3.12
|
Pending Removal in Python 3.12
|
||||||
==============================
|
==============================
|
||||||
|
|
|
@ -129,7 +129,7 @@ import functools
|
||||||
# public symbols
|
# public symbols
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"match", "fullmatch", "search", "sub", "subn", "split",
|
"match", "fullmatch", "search", "sub", "subn", "split",
|
||||||
"findall", "finditer", "compile", "purge", "escape",
|
"findall", "finditer", "compile", "purge", "template", "escape",
|
||||||
"error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U",
|
"error", "Pattern", "Match", "A", "I", "L", "M", "S", "X", "U",
|
||||||
"ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
|
"ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE",
|
||||||
"UNICODE", "NOFLAG", "RegexFlag",
|
"UNICODE", "NOFLAG", "RegexFlag",
|
||||||
|
@ -148,6 +148,8 @@ class RegexFlag:
|
||||||
MULTILINE = M = _compiler.SRE_FLAG_MULTILINE # make anchors look for newline
|
MULTILINE = M = _compiler.SRE_FLAG_MULTILINE # make anchors look for newline
|
||||||
DOTALL = S = _compiler.SRE_FLAG_DOTALL # make dot match newline
|
DOTALL = S = _compiler.SRE_FLAG_DOTALL # make dot match newline
|
||||||
VERBOSE = X = _compiler.SRE_FLAG_VERBOSE # ignore whitespace and comments
|
VERBOSE = X = _compiler.SRE_FLAG_VERBOSE # ignore whitespace and comments
|
||||||
|
# sre extensions (experimental, don't rely on these)
|
||||||
|
TEMPLATE = T = _compiler.SRE_FLAG_TEMPLATE # unknown purpose, deprecated
|
||||||
DEBUG = _compiler.SRE_FLAG_DEBUG # dump pattern after compilation
|
DEBUG = _compiler.SRE_FLAG_DEBUG # dump pattern after compilation
|
||||||
__str__ = object.__str__
|
__str__ = object.__str__
|
||||||
_numeric_repr_ = hex
|
_numeric_repr_ = hex
|
||||||
|
@ -229,6 +231,18 @@ def purge():
|
||||||
_cache.clear()
|
_cache.clear()
|
||||||
_compile_repl.cache_clear()
|
_compile_repl.cache_clear()
|
||||||
|
|
||||||
|
def template(pattern, flags=0):
|
||||||
|
"Compile a template pattern, returning a Pattern object, deprecated"
|
||||||
|
import warnings
|
||||||
|
warnings.warn("The re.template() function is deprecated "
|
||||||
|
"as it is an undocumented function "
|
||||||
|
"without an obvious purpose. "
|
||||||
|
"Use re.compile() instead.",
|
||||||
|
DeprecationWarning)
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
warnings.simplefilter("ignore", DeprecationWarning) # warn just once
|
||||||
|
return _compile(pattern, flags|T)
|
||||||
|
|
||||||
# SPECIAL_CHARS
|
# SPECIAL_CHARS
|
||||||
# closing ')', '}' and ']'
|
# closing ')', '}' and ']'
|
||||||
# '-' (a range in character set)
|
# '-' (a range in character set)
|
||||||
|
@ -270,6 +284,13 @@ def _compile(pattern, flags):
|
||||||
return pattern
|
return pattern
|
||||||
if not _compiler.isstring(pattern):
|
if not _compiler.isstring(pattern):
|
||||||
raise TypeError("first argument must be string or compiled pattern")
|
raise TypeError("first argument must be string or compiled pattern")
|
||||||
|
if flags & T:
|
||||||
|
import warnings
|
||||||
|
warnings.warn("The re.TEMPLATE/re.T flag is deprecated "
|
||||||
|
"as it is an undocumented flag "
|
||||||
|
"without an obvious purpose. "
|
||||||
|
"Don't use it.",
|
||||||
|
DeprecationWarning)
|
||||||
p = _compiler.compile(pattern, flags)
|
p = _compiler.compile(pattern, flags)
|
||||||
if not (flags & DEBUG):
|
if not (flags & DEBUG):
|
||||||
if len(_cache) >= _MAXCACHE:
|
if len(_cache) >= _MAXCACHE:
|
||||||
|
|
|
@ -108,6 +108,8 @@ def _compile(data, pattern, flags):
|
||||||
else:
|
else:
|
||||||
emit(ANY)
|
emit(ANY)
|
||||||
elif op in REPEATING_CODES:
|
elif op in REPEATING_CODES:
|
||||||
|
if flags & SRE_FLAG_TEMPLATE:
|
||||||
|
raise error("internal: unsupported template operator %r" % (op,))
|
||||||
if _simple(av[2]):
|
if _simple(av[2]):
|
||||||
emit(REPEATING_CODES[op][2])
|
emit(REPEATING_CODES[op][2])
|
||||||
skip = _len(code); emit(0)
|
skip = _len(code); emit(0)
|
||||||
|
|
|
@ -204,6 +204,7 @@ CH_UNICODE = {
|
||||||
}
|
}
|
||||||
|
|
||||||
# flags
|
# flags
|
||||||
|
SRE_FLAG_TEMPLATE = 1 # template mode (unknown purpose, deprecated)
|
||||||
SRE_FLAG_IGNORECASE = 2 # case insensitive
|
SRE_FLAG_IGNORECASE = 2 # case insensitive
|
||||||
SRE_FLAG_LOCALE = 4 # honour system locale
|
SRE_FLAG_LOCALE = 4 # honour system locale
|
||||||
SRE_FLAG_MULTILINE = 8 # treat target as multiline string
|
SRE_FLAG_MULTILINE = 8 # treat target as multiline string
|
||||||
|
|
|
@ -61,11 +61,12 @@ FLAGS = {
|
||||||
"x": SRE_FLAG_VERBOSE,
|
"x": SRE_FLAG_VERBOSE,
|
||||||
# extensions
|
# extensions
|
||||||
"a": SRE_FLAG_ASCII,
|
"a": SRE_FLAG_ASCII,
|
||||||
|
"t": SRE_FLAG_TEMPLATE,
|
||||||
"u": SRE_FLAG_UNICODE,
|
"u": SRE_FLAG_UNICODE,
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPE_FLAGS = SRE_FLAG_ASCII | SRE_FLAG_LOCALE | SRE_FLAG_UNICODE
|
TYPE_FLAGS = SRE_FLAG_ASCII | SRE_FLAG_LOCALE | SRE_FLAG_UNICODE
|
||||||
GLOBAL_FLAGS = SRE_FLAG_DEBUG
|
GLOBAL_FLAGS = SRE_FLAG_DEBUG | SRE_FLAG_TEMPLATE
|
||||||
|
|
||||||
class State:
|
class State:
|
||||||
# keeps track of state for parsing
|
# keeps track of state for parsing
|
||||||
|
|
|
@ -2386,6 +2386,30 @@ class ReTests(unittest.TestCase):
|
||||||
self.assertTrue(re.fullmatch(r'(?s:(?>.*?\.).*)\Z', "a.txt")) # reproducer
|
self.assertTrue(re.fullmatch(r'(?s:(?>.*?\.).*)\Z', "a.txt")) # reproducer
|
||||||
self.assertTrue(re.fullmatch(r'(?s:(?=(?P<g0>.*?\.))(?P=g0).*)\Z', "a.txt"))
|
self.assertTrue(re.fullmatch(r'(?s:(?=(?P<g0>.*?\.))(?P=g0).*)\Z', "a.txt"))
|
||||||
|
|
||||||
|
def test_template_function_and_flag_is_deprecated(self):
|
||||||
|
with self.assertWarns(DeprecationWarning) as cm:
|
||||||
|
template_re1 = re.template(r'a')
|
||||||
|
self.assertIn('re.template()', str(cm.warning))
|
||||||
|
self.assertIn('is deprecated', str(cm.warning))
|
||||||
|
self.assertIn('function', str(cm.warning))
|
||||||
|
self.assertNotIn('flag', str(cm.warning))
|
||||||
|
|
||||||
|
with self.assertWarns(DeprecationWarning) as cm:
|
||||||
|
# we deliberately use more flags here to test that that still
|
||||||
|
# triggers the warning
|
||||||
|
# if paranoid, we could test multiple different combinations,
|
||||||
|
# but it's probably not worth it
|
||||||
|
template_re2 = re.compile(r'a', flags=re.TEMPLATE|re.UNICODE)
|
||||||
|
self.assertIn('re.TEMPLATE', str(cm.warning))
|
||||||
|
self.assertIn('is deprecated', str(cm.warning))
|
||||||
|
self.assertIn('flag', str(cm.warning))
|
||||||
|
self.assertNotIn('function', str(cm.warning))
|
||||||
|
|
||||||
|
# while deprecated, is should still function
|
||||||
|
self.assertEqual(template_re1, template_re2)
|
||||||
|
self.assertTrue(template_re1.match('ahoy'))
|
||||||
|
self.assertFalse(template_re1.match('nope'))
|
||||||
|
|
||||||
|
|
||||||
def get_debug_out(pat):
|
def get_debug_out(pat):
|
||||||
with captured_stdout() as out:
|
with captured_stdout() as out:
|
||||||
|
@ -2580,11 +2604,11 @@ class PatternReprTests(unittest.TestCase):
|
||||||
"re.IGNORECASE|re.DOTALL|re.VERBOSE|0x100000")
|
"re.IGNORECASE|re.DOTALL|re.VERBOSE|0x100000")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
repr(~re.I),
|
repr(~re.I),
|
||||||
"re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DOTALL|re.VERBOSE|re.DEBUG|0x1")
|
"re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DOTALL|re.VERBOSE|re.TEMPLATE|re.DEBUG")
|
||||||
self.assertEqual(repr(~(re.I|re.S|re.X)),
|
self.assertEqual(repr(~(re.I|re.S|re.X)),
|
||||||
"re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DEBUG|0x1")
|
"re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.TEMPLATE|re.DEBUG")
|
||||||
self.assertEqual(repr(~(re.I|re.S|re.X|(1<<20))),
|
self.assertEqual(repr(~(re.I|re.S|re.X|(1<<20))),
|
||||||
"re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DEBUG|0xffe01")
|
"re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.TEMPLATE|re.DEBUG|0xffe00")
|
||||||
|
|
||||||
|
|
||||||
class ImplementationTest(unittest.TestCase):
|
class ImplementationTest(unittest.TestCase):
|
||||||
|
|
|
@ -1373,6 +1373,7 @@ Suppress expression chaining for more :mod:`re` parsing errors.
|
||||||
|
|
||||||
Remove undocumented and never working function ``re.template()`` and flag
|
Remove undocumented and never working function ``re.template()`` and flag
|
||||||
``re.TEMPLATE``.
|
``re.TEMPLATE``.
|
||||||
|
This was later reverted in 3.11.0b2 and deprecated instead.
|
||||||
|
|
||||||
..
|
..
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
The :func:`re.template` function and the corresponding :const:`re.TEMPLATE`
|
||||||
|
and :const:`re.T` flags are restored after they were removed in 3.11.0b1,
|
||||||
|
but they are now deprecated, so they might be removed from Python 3.13.
|
|
@ -1323,6 +1323,7 @@ pattern_repr(PatternObject *obj)
|
||||||
const char *name;
|
const char *name;
|
||||||
int value;
|
int value;
|
||||||
} flag_names[] = {
|
} flag_names[] = {
|
||||||
|
{"re.TEMPLATE", SRE_FLAG_TEMPLATE},
|
||||||
{"re.IGNORECASE", SRE_FLAG_IGNORECASE},
|
{"re.IGNORECASE", SRE_FLAG_IGNORECASE},
|
||||||
{"re.LOCALE", SRE_FLAG_LOCALE},
|
{"re.LOCALE", SRE_FLAG_LOCALE},
|
||||||
{"re.MULTILINE", SRE_FLAG_MULTILINE},
|
{"re.MULTILINE", SRE_FLAG_MULTILINE},
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
#define SRE_CATEGORY_UNI_NOT_WORD 15
|
#define SRE_CATEGORY_UNI_NOT_WORD 15
|
||||||
#define SRE_CATEGORY_UNI_LINEBREAK 16
|
#define SRE_CATEGORY_UNI_LINEBREAK 16
|
||||||
#define SRE_CATEGORY_UNI_NOT_LINEBREAK 17
|
#define SRE_CATEGORY_UNI_NOT_LINEBREAK 17
|
||||||
|
#define SRE_FLAG_TEMPLATE 1
|
||||||
#define SRE_FLAG_IGNORECASE 2
|
#define SRE_FLAG_IGNORECASE 2
|
||||||
#define SRE_FLAG_LOCALE 4
|
#define SRE_FLAG_LOCALE 4
|
||||||
#define SRE_FLAG_MULTILINE 8
|
#define SRE_FLAG_MULTILINE 8
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue