From 2e8f21830caaf186f0f0a1e8855ec87197ddffd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 10:24:51 +0200 Subject: [PATCH 1/9] Revert "bpo-47211: Remove function re.template() and flag re.TEMPLATE (GH-32300)" This reverts commit b09184bf05b07b77c5ecfedd4daa846be3cbf0a9. Fixes https://github.com/python/cpython/issues/92728 --- Lib/re/__init__.py | 8 +++++++- Lib/re/_compiler.py | 2 ++ Lib/re/_constants.py | 1 + Lib/re/_parser.py | 3 ++- Lib/test/test_re.py | 6 +++--- Modules/_sre/sre.c | 1 + Modules/_sre/sre_constants.h | 1 + 7 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Lib/re/__init__.py b/Lib/re/__init__.py index c9b511422f1e59..b887722bbb2cdf 100644 --- a/Lib/re/__init__.py +++ b/Lib/re/__init__.py @@ -129,7 +129,7 @@ # public symbols __all__ = [ "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", "ASCII", "IGNORECASE", "LOCALE", "MULTILINE", "DOTALL", "VERBOSE", "UNICODE", "NOFLAG", "RegexFlag", @@ -148,6 +148,8 @@ class RegexFlag: MULTILINE = M = _compiler.SRE_FLAG_MULTILINE # make anchors look for newline DOTALL = S = _compiler.SRE_FLAG_DOTALL # make dot match newline VERBOSE = X = _compiler.SRE_FLAG_VERBOSE # ignore whitespace and comments + # sre extensions (experimental, don't rely on these) + TEMPLATE = T = _compiler.SRE_FLAG_TEMPLATE # disable backtracking DEBUG = _compiler.SRE_FLAG_DEBUG # dump pattern after compilation __str__ = object.__str__ _numeric_repr_ = hex @@ -229,6 +231,10 @@ def purge(): _cache.clear() _compile_repl.cache_clear() +def template(pattern, flags=0): + "Compile a template pattern, returning a Pattern object" + return _compile(pattern, flags|T) + # SPECIAL_CHARS # closing ')', '}' and ']' # '-' (a range in character set) diff --git a/Lib/re/_compiler.py b/Lib/re/_compiler.py index 63d82025505b74..4b5322338cbd5f 100644 --- a/Lib/re/_compiler.py +++ b/Lib/re/_compiler.py @@ -108,6 +108,8 @@ def _compile(data, pattern, flags): else: emit(ANY) elif op in REPEATING_CODES: + if flags & SRE_FLAG_TEMPLATE: + raise error("internal: unsupported template operator %r" % (op,)) if _simple(av[2]): emit(REPEATING_CODES[op][2]) skip = _len(code); emit(0) diff --git a/Lib/re/_constants.py b/Lib/re/_constants.py index 71204d903b3226..37a32982c2ce41 100644 --- a/Lib/re/_constants.py +++ b/Lib/re/_constants.py @@ -204,6 +204,7 @@ def _makecodes(*names): } # flags +SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) SRE_FLAG_IGNORECASE = 2 # case insensitive SRE_FLAG_LOCALE = 4 # honour system locale SRE_FLAG_MULTILINE = 8 # treat target as multiline string diff --git a/Lib/re/_parser.py b/Lib/re/_parser.py index 33b70973ae6d32..0d9cf632ea7105 100644 --- a/Lib/re/_parser.py +++ b/Lib/re/_parser.py @@ -61,11 +61,12 @@ "x": SRE_FLAG_VERBOSE, # extensions "a": SRE_FLAG_ASCII, + "t": SRE_FLAG_TEMPLATE, "u": 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: # keeps track of state for parsing diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 52ee616e210fbb..56e2e4b7f5731e 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2580,11 +2580,11 @@ def test_flags_repr(self): "re.IGNORECASE|re.DOTALL|re.VERBOSE|0x100000") self.assertEqual( 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)), - "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))), - "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): diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index bd9204da428af8..491734f243849b 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -1323,6 +1323,7 @@ pattern_repr(PatternObject *obj) const char *name; int value; } flag_names[] = { + {"re.TEMPLATE", SRE_FLAG_TEMPLATE}, {"re.IGNORECASE", SRE_FLAG_IGNORECASE}, {"re.LOCALE", SRE_FLAG_LOCALE}, {"re.MULTILINE", SRE_FLAG_MULTILINE}, diff --git a/Modules/_sre/sre_constants.h b/Modules/_sre/sre_constants.h index d5de650b7025af..590d5be7cb4d94 100644 --- a/Modules/_sre/sre_constants.h +++ b/Modules/_sre/sre_constants.h @@ -85,6 +85,7 @@ #define SRE_CATEGORY_UNI_NOT_WORD 15 #define SRE_CATEGORY_UNI_LINEBREAK 16 #define SRE_CATEGORY_UNI_NOT_LINEBREAK 17 +#define SRE_FLAG_TEMPLATE 1 #define SRE_FLAG_IGNORECASE 2 #define SRE_FLAG_LOCALE 4 #define SRE_FLAG_MULTILINE 8 From 82e9f974462fd52cdabe882f2076aac16c240a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 10:52:55 +0200 Subject: [PATCH 2/9] Deprecate re.template --- Lib/re/__init__.py | 19 +++++++++++++++++-- Lib/test/test_re.py | 24 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/Lib/re/__init__.py b/Lib/re/__init__.py index b887722bbb2cdf..bd2bdf36b14bcc 100644 --- a/Lib/re/__init__.py +++ b/Lib/re/__init__.py @@ -232,8 +232,16 @@ def purge(): _compile_repl.cache_clear() def template(pattern, flags=0): - "Compile a template pattern, returning a Pattern object" - return _compile(pattern, flags|T) + "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 # closing ')', '}' and ']' @@ -276,6 +284,13 @@ def _compile(pattern, flags): return pattern if not _compiler.isstring(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) if not (flags & DEBUG): if len(_cache) >= _MAXCACHE: diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 56e2e4b7f5731e..25213d78450430 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2386,6 +2386,30 @@ def test_bug_gh91616(self): self.assertTrue(re.fullmatch(r'(?s:(?>.*?\.).*)\Z', "a.txt")) # reproducer self.assertTrue(re.fullmatch(r'(?s:(?=(?P.*?\.))(?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, ti 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): with captured_stdout() as out: From 88ed787c528086c19cc72be34dec34d3dd30e93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 10:59:10 +0200 Subject: [PATCH 3/9] Blurb it! --- .../next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst diff --git a/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst b/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst new file mode 100644 index 00000000000000..a6c73646c145ce --- /dev/null +++ b/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst @@ -0,0 +1,3 @@ +The :func:`re.template` function and the corresponding :const:`re.TEMPLATE` +and :const:`re.TEMPLATE` are restored after they were removed in 3.11.0b1, +but they are now deprecated, so they might be removed from Python 3.13. From b26b7b6f5e924f19e9f79776db4afe46000410fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 11:01:41 +0200 Subject: [PATCH 4/9] Typos --- .../next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst b/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst index a6c73646c145ce..b39609be2c4cf5 100644 --- a/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst +++ b/Misc/NEWS.d/next/Library/2022-05-24-10-59-02.gh-issue-92728.zxTifq.rst @@ -1,3 +1,3 @@ The :func:`re.template` function and the corresponding :const:`re.TEMPLATE` -and :const:`re.TEMPLATE` are restored after they were removed in 3.11.0b1, +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. From b80e4f4d1640e811cbabc27e84df61bf67198bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 11:03:45 +0200 Subject: [PATCH 5/9] What's new? --- Doc/whatsnew/3.11.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 12b4c22d548078..c7ff6ca4938c70 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -1273,6 +1273,11 @@ Deprecated is now deprecated. Support will be removed in Python 3.13. (Contributed by 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 ============================== From 1a979981a6833a6cf2a4ab48720b7e24b4425590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 11:07:07 +0200 Subject: [PATCH 6/9] Update the comment for SRE_FLAG_TEMPLATE --- Lib/re/_constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/re/_constants.py b/Lib/re/_constants.py index 37a32982c2ce41..1cc85c631f22b4 100644 --- a/Lib/re/_constants.py +++ b/Lib/re/_constants.py @@ -204,7 +204,7 @@ def _makecodes(*names): } # flags -SRE_FLAG_TEMPLATE = 1 # template mode (disable backtracking) +SRE_FLAG_TEMPLATE = 1 # template mode (unknown purpose, deprecated) SRE_FLAG_IGNORECASE = 2 # case insensitive SRE_FLAG_LOCALE = 4 # honour system locale SRE_FLAG_MULTILINE = 8 # treat target as multiline string From cd4b0a058b6237b415ba340bb371ec8ce267e5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 12:02:04 +0200 Subject: [PATCH 7/9] Add a note to the previous changelog entry. --- Misc/NEWS.d/3.11.0b1.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/Misc/NEWS.d/3.11.0b1.rst b/Misc/NEWS.d/3.11.0b1.rst index 0def806185e5a2..c135eff4598e40 100644 --- a/Misc/NEWS.d/3.11.0b1.rst +++ b/Misc/NEWS.d/3.11.0b1.rst @@ -1373,6 +1373,7 @@ Suppress expression chaining for more :mod:`re` parsing errors. Remove undocumented and never working function ``re.template()`` and flag ``re.TEMPLATE``. +This was later reverted in 3.11.0b2 and deprecated instead. .. From 773a6ad25261ab1990ea9a78484984ed1b3e917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 13:49:40 +0200 Subject: [PATCH 8/9] Also update the comment in re/__init__.py --- Lib/re/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/re/__init__.py b/Lib/re/__init__.py index bd2bdf36b14bcc..d58c2117ef3e14 100644 --- a/Lib/re/__init__.py +++ b/Lib/re/__init__.py @@ -149,7 +149,7 @@ class RegexFlag: DOTALL = S = _compiler.SRE_FLAG_DOTALL # make dot match newline VERBOSE = X = _compiler.SRE_FLAG_VERBOSE # ignore whitespace and comments # sre extensions (experimental, don't rely on these) - TEMPLATE = T = _compiler.SRE_FLAG_TEMPLATE # disable backtracking + TEMPLATE = T = _compiler.SRE_FLAG_TEMPLATE # unknown purpose, deprecated DEBUG = _compiler.SRE_FLAG_DEBUG # dump pattern after compilation __str__ = object.__str__ _numeric_repr_ = hex From ef781633d71a83c975df4b955bad550afb896326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 24 May 2022 19:14:55 +0200 Subject: [PATCH 9/9] Typo --- Lib/test/test_re.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 25213d78450430..3752d734dbdef2 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -2405,7 +2405,7 @@ def test_template_function_and_flag_is_deprecated(self): self.assertIn('flag', str(cm.warning)) self.assertNotIn('function', str(cm.warning)) - # while deprecated, ti should still function + # while deprecated, is should still function self.assertEqual(template_re1, template_re2) self.assertTrue(template_re1.match('ahoy')) self.assertFalse(template_re1.match('nope')) pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy