]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[2.7] bpo-30375: Correct the stacklevel of regex compiling warnings. (#1595) (#1648)
authorSerhiy Storchaka <storchaka@gmail.com>
Thu, 18 May 2017 10:46:17 +0000 (13:46 +0300)
committerGitHub <noreply@github.com>
Thu, 18 May 2017 10:46:17 +0000 (13:46 +0300)
Warnings emitted when compile a regular expression now always point
to the line in the user code.  Previously they could point into inners
of the re module if emitted from inside of groups or conditionals.

(cherry picked from commit c7ac7280c321b3c1679fe5f657a6be0f86adf173)

Lib/sre_parse.py
Misc/NEWS

index e0d003ed85bda19080a298a8f4fc01be4135c9a0..3f6ddd263928832a1af571707f80c49eda9ca9c5 100644 (file)
@@ -234,7 +234,7 @@ def isname(name):
             return False
     return True
 
-def _class_escape(source, escape):
+def _class_escape(source, escape, nested):
     # handle escape code inside character class
     code = ESCAPES.get(escape)
     if code:
@@ -266,16 +266,16 @@ def _class_escape(source, escape):
                 if c in 'Uu':
                     warnings.warn('bad escape %s; Unicode escapes are '
                                   'supported only since Python 3.3' % escape,
-                                  FutureWarning, stacklevel=8)
+                                  FutureWarning, stacklevel=nested + 6)
                 else:
                     warnings.warnpy3k('bad escape %s' % escape,
-                                      DeprecationWarning, stacklevel=8)
+                                      DeprecationWarning, stacklevel=nested + 6)
             return LITERAL, ord(escape[1])
     except ValueError:
         pass
     raise error, "bogus escape: %s" % repr(escape)
 
-def _escape(source, escape, state):
+def _escape(source, escape, state, nested):
     # handle escape code in expression
     code = CATEGORIES.get(escape)
     if code:
@@ -315,7 +315,7 @@ def _escape(source, escape, state):
                     import warnings
                     warnings.warn('group references in lookbehind '
                                   'assertions are not supported',
-                                  RuntimeWarning)
+                                  RuntimeWarning, stacklevel=nested + 6)
                 return GROUPREF, group
             raise ValueError
         if len(escape) == 2:
@@ -324,23 +324,23 @@ def _escape(source, escape, state):
                 if c in 'Uu':
                     warnings.warn('bad escape %s; Unicode escapes are '
                                   'supported only since Python 3.3' % escape,
-                                  FutureWarning, stacklevel=8)
+                                  FutureWarning, stacklevel=nested + 6)
                 else:
                     warnings.warnpy3k('bad escape %s' % escape,
-                                      DeprecationWarning, stacklevel=8)
+                                      DeprecationWarning, stacklevel=nested + 6)
             return LITERAL, ord(escape[1])
     except ValueError:
         pass
     raise error, "bogus escape: %s" % repr(escape)
 
-def _parse_sub(source, state, nested=1):
+def _parse_sub(source, state, nested):
     # parse an alternation: a|b|c
 
     items = []
     itemsappend = items.append
     sourcematch = source.match
     while 1:
-        itemsappend(_parse(source, state))
+        itemsappend(_parse(source, state, nested + 1))
         if sourcematch("|"):
             continue
         if not nested:
@@ -392,10 +392,10 @@ def _parse_sub(source, state, nested=1):
     subpattern.append((BRANCH, (None, items)))
     return subpattern
 
-def _parse_sub_cond(source, state, condgroup):
-    item_yes = _parse(source, state)
+def _parse_sub_cond(source, state, condgroup, nested):
+    item_yes = _parse(source, state, nested + 1)
     if source.match("|"):
-        item_no = _parse(source, state)
+        item_no = _parse(source, state, nested + 1)
         if source.match("|"):
             raise error, "conditional backref with more than two branches"
     else:
@@ -411,7 +411,7 @@ _ASSERTCHARS = set("=!<")
 _LOOKBEHINDASSERTCHARS = set("=!")
 _REPEATCODES = set([MIN_REPEAT, MAX_REPEAT])
 
-def _parse(source, state):
+def _parse(source, state, nested):
     # parse a simple pattern
     subpattern = SubPattern(state)
 
@@ -462,7 +462,7 @@ def _parse(source, state):
                 if this == "]" and set != start:
                     break
                 elif this and this[0] == "\\":
-                    code1 = _class_escape(source, this)
+                    code1 = _class_escape(source, this, nested + 1)
                 elif this:
                     code1 = LITERAL, ord(this)
                 else:
@@ -478,7 +478,7 @@ def _parse(source, state):
                         break
                     elif this:
                         if this[0] == "\\":
-                            code2 = _class_escape(source, this)
+                            code2 = _class_escape(source, this, nested + 1)
                         else:
                             code2 = LITERAL, ord(this)
                         if code1[0] != LITERAL or code2[0] != LITERAL:
@@ -608,7 +608,7 @@ def _parse(source, state):
                             import warnings
                             warnings.warn('group references in lookbehind '
                                           'assertions are not supported',
-                                          RuntimeWarning)
+                                          RuntimeWarning, stacklevel=nested + 6)
                         subpatternappend((GROUPREF, gid))
                         continue
                     else:
@@ -638,7 +638,7 @@ def _parse(source, state):
                         dir = -1 # lookbehind
                         char = sourceget()
                         state.lookbehind += 1
-                    p = _parse_sub(source, state)
+                    p = _parse_sub(source, state, nested + 1)
                     if dir < 0:
                         state.lookbehind -= 1
                     if not sourcematch(")"):
@@ -675,7 +675,7 @@ def _parse(source, state):
                         import warnings
                         warnings.warn('group references in lookbehind '
                                       'assertions are not supported',
-                                      RuntimeWarning)
+                                      RuntimeWarning, stacklevel=nested + 6)
                 else:
                     # flags
                     if not source.next in FLAGS:
@@ -690,9 +690,9 @@ def _parse(source, state):
                 else:
                     group = state.opengroup(name)
                 if condgroup:
-                    p = _parse_sub_cond(source, state, condgroup)
+                    p = _parse_sub_cond(source, state, condgroup, nested + 1)
                 else:
-                    p = _parse_sub(source, state)
+                    p = _parse_sub(source, state, nested + 1)
                 if not sourcematch(")"):
                     raise error, "unbalanced parenthesis"
                 if group is not None:
@@ -714,7 +714,7 @@ def _parse(source, state):
             subpattern.append((AT, AT_END))
 
         elif this and this[0] == "\\":
-            code = _escape(source, this, state)
+            code = _escape(source, this, state, nested + 1)
             subpatternappend(code)
 
         else:
index 3f34c6c2645e79a11bb334d6bc31fa14914bd1f8..967e8614bb4a99cb6fe9418edf97bc2ce4c30df9 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -42,6 +42,10 @@ Extension Modules
 Library
 -------
 
+- bpo-30375: Warnings emitted when compile a regular expression now always
+  point to the line in the user code.  Previously they could point into inners
+  of the re module if emitted from inside of groups or conditionals.
+
 - bpo-30363: Running Python with the -3 option now warns about regular
   expression syntax that is invalid or has different semantic in Python 3
   or will change the behavior in future Python versions.