Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/sqlparse/utils.py: 23%
57 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1#
2# Copyright (C) 2009-2020 the sqlparse authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of python-sqlparse and is released under
6# the BSD License: https://opensource.org/licenses/BSD-3-Clause
8import itertools
9import re
10from collections import deque
11from contextlib import contextmanager
13# This regular expression replaces the home-cooked parser that was here before.
14# It is much faster, but requires an extra post-processing step to get the
15# desired results (that are compatible with what you would expect from the
16# str.splitlines() method).
17#
18# It matches groups of characters: newlines, quoted strings, or unquoted text,
19# and splits on that basis. The post-processing step puts those back together
20# into the actual lines of SQL.
21SPLIT_REGEX = re.compile(r"""
22(
23 (?: # Start of non-capturing group
24 (?:\r\n|\r|\n) | # Match any single newline, or
25 [^\r\n'"]+ | # Match any character series without quotes or
26 # newlines, or
27 "(?:[^"\\]|\\.)*" | # Match double-quoted strings, or
28 '(?:[^'\\]|\\.)*' # Match single quoted strings
29 )
30)
31""", re.VERBOSE)
33LINE_MATCH = re.compile(r'(\r\n|\r|\n)')
36def split_unquoted_newlines(stmt):
37 """Split a string on all unquoted newlines.
39 Unlike str.splitlines(), this will ignore CR/LF/CR+LF if the requisite
40 character is inside of a string."""
41 text = str(stmt)
42 lines = SPLIT_REGEX.split(text)
43 outputlines = ['']
44 for line in lines:
45 if not line:
46 continue
47 elif LINE_MATCH.match(line):
48 outputlines.append('')
49 else:
50 outputlines[-1] += line
51 return outputlines
54def remove_quotes(val):
55 """Helper that removes surrounding quotes from strings."""
56 if val is None:
57 return
58 if val[0] in ('"', "'", '`') and val[0] == val[-1]:
59 val = val[1:-1]
60 return val
63def recurse(*cls):
64 """Function decorator to help with recursion
66 :param cls: Classes to not recurse over
67 :return: function
68 """
69 def wrap(f):
70 def wrapped_f(tlist):
71 for sgroup in tlist.get_sublists():
72 if not isinstance(sgroup, cls):
73 wrapped_f(sgroup)
74 f(tlist)
76 return wrapped_f
78 return wrap
81def imt(token, i=None, m=None, t=None):
82 """Helper function to simplify comparisons Instance, Match and TokenType
83 :param token:
84 :param i: Class or Tuple/List of Classes
85 :param m: Tuple of TokenType & Value. Can be list of Tuple for multiple
86 :param t: TokenType or Tuple/List of TokenTypes
87 :return: bool
88 """
89 clss = i
90 types = [t, ] if t and not isinstance(t, list) else t
91 mpatterns = [m, ] if m and not isinstance(m, list) else m
93 if token is None:
94 return False
95 elif clss and isinstance(token, clss):
96 return True
97 elif mpatterns and any(token.match(*pattern) for pattern in mpatterns):
98 return True
99 elif types and any(token.ttype in ttype for ttype in types):
100 return True
101 else:
102 return False
105def consume(iterator, n):
106 """Advance the iterator n-steps ahead. If n is none, consume entirely."""
107 deque(itertools.islice(iterator, n), maxlen=0)
110@contextmanager
111def offset(filter_, n=0):
112 filter_.offset += n
113 yield
114 filter_.offset -= n
117@contextmanager
118def indent(filter_, n=1):
119 filter_.indent += n
120 yield
121 filter_.indent -= n