17.12
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009-2018 the sqlparse authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of python-sqlparse and is released under
|
||||
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
"""Parse SQL statements."""
|
||||
|
||||
# Setup namespace
|
||||
from sqlparse import sql
|
||||
from sqlparse import cli
|
||||
from sqlparse import engine
|
||||
from sqlparse import tokens
|
||||
from sqlparse import filters
|
||||
from sqlparse import formatter
|
||||
|
||||
from sqlparse.compat import text_type
|
||||
|
||||
__version__ = '0.3.0'
|
||||
__all__ = ['engine', 'filters', 'formatter', 'sql', 'tokens', 'cli']
|
||||
|
||||
|
||||
def parse(sql, encoding=None):
|
||||
"""Parse sql and return a list of statements.
|
||||
|
||||
:param sql: A string containing one or more SQL statements.
|
||||
:param encoding: The encoding of the statement (optional).
|
||||
:returns: A tuple of :class:`~sqlparse.sql.Statement` instances.
|
||||
"""
|
||||
return tuple(parsestream(sql, encoding))
|
||||
|
||||
|
||||
def parsestream(stream, encoding=None):
|
||||
"""Parses sql statements from file-like object.
|
||||
|
||||
:param stream: A file-like object.
|
||||
:param encoding: The encoding of the stream contents (optional).
|
||||
:returns: A generator of :class:`~sqlparse.sql.Statement` instances.
|
||||
"""
|
||||
stack = engine.FilterStack()
|
||||
stack.enable_grouping()
|
||||
return stack.run(stream, encoding)
|
||||
|
||||
|
||||
def format(sql, encoding=None, **options):
|
||||
"""Format *sql* according to *options*.
|
||||
|
||||
Available options are documented in :ref:`formatting`.
|
||||
|
||||
In addition to the formatting options this function accepts the
|
||||
keyword "encoding" which determines the encoding of the statement.
|
||||
|
||||
:returns: The formatted SQL statement as string.
|
||||
"""
|
||||
stack = engine.FilterStack()
|
||||
options = formatter.validate_options(options)
|
||||
stack = formatter.build_filter_stack(stack, options)
|
||||
stack.postprocess.append(filters.SerializerUnicode())
|
||||
return u''.join(stack.run(sql, encoding))
|
||||
|
||||
|
||||
def split(sql, encoding=None):
|
||||
"""Split *sql* into single statements.
|
||||
|
||||
:param sql: A string containing one or more SQL statements.
|
||||
:param encoding: The encoding of the statement (optional).
|
||||
:returns: A list of strings.
|
||||
"""
|
||||
stack = engine.FilterStack()
|
||||
return [text_type(stmt).strip() for stmt in stack.run(sql, encoding)]
|
||||
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009-2018 the sqlparse authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of python-sqlparse and is released under
|
||||
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
"""Entrypoint module for `python -m sqlparse`.
|
||||
|
||||
Why does this file exist, and why __main__? For more info, read:
|
||||
- https://www.python.org/dev/peps/pep-0338/
|
||||
- https://docs.python.org/2/using/cmdline.html#cmdoption-m
|
||||
- https://docs.python.org/3/using/cmdline.html#cmdoption-m
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from sqlparse.cli import main
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,41 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009-2018 the sqlparse authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of python-sqlparse and is released under
|
||||
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
from sqlparse.filters.others import SerializerUnicode
|
||||
from sqlparse.filters.others import StripCommentsFilter
|
||||
from sqlparse.filters.others import StripWhitespaceFilter
|
||||
from sqlparse.filters.others import SpacesAroundOperatorsFilter
|
||||
|
||||
from sqlparse.filters.output import OutputPHPFilter
|
||||
from sqlparse.filters.output import OutputPythonFilter
|
||||
|
||||
from sqlparse.filters.tokens import KeywordCaseFilter
|
||||
from sqlparse.filters.tokens import IdentifierCaseFilter
|
||||
from sqlparse.filters.tokens import TruncateStringFilter
|
||||
|
||||
from sqlparse.filters.reindent import ReindentFilter
|
||||
from sqlparse.filters.right_margin import RightMarginFilter
|
||||
from sqlparse.filters.aligned_indent import AlignedIndentFilter
|
||||
|
||||
__all__ = [
|
||||
'SerializerUnicode',
|
||||
'StripCommentsFilter',
|
||||
'StripWhitespaceFilter',
|
||||
'SpacesAroundOperatorsFilter',
|
||||
|
||||
'OutputPHPFilter',
|
||||
'OutputPythonFilter',
|
||||
|
||||
'KeywordCaseFilter',
|
||||
'IdentifierCaseFilter',
|
||||
'TruncateStringFilter',
|
||||
|
||||
'ReindentFilter',
|
||||
'RightMarginFilter',
|
||||
'AlignedIndentFilter',
|
||||
]
|
||||
@@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009-2018 the sqlparse authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of python-sqlparse and is released under
|
||||
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
from sqlparse import tokens as T
|
||||
from sqlparse.compat import text_type
|
||||
|
||||
|
||||
class _CaseFilter(object):
|
||||
ttype = None
|
||||
|
||||
def __init__(self, case=None):
|
||||
case = case or 'upper'
|
||||
self.convert = getattr(text_type, case)
|
||||
|
||||
def process(self, stream):
|
||||
for ttype, value in stream:
|
||||
if ttype in self.ttype:
|
||||
value = self.convert(value)
|
||||
yield ttype, value
|
||||
|
||||
|
||||
class KeywordCaseFilter(_CaseFilter):
|
||||
ttype = T.Keyword
|
||||
|
||||
|
||||
class IdentifierCaseFilter(_CaseFilter):
|
||||
ttype = T.Name, T.String.Symbol
|
||||
|
||||
def process(self, stream):
|
||||
for ttype, value in stream:
|
||||
if ttype in self.ttype and value.strip()[0] != '"':
|
||||
value = self.convert(value)
|
||||
yield ttype, value
|
||||
|
||||
|
||||
class TruncateStringFilter(object):
|
||||
def __init__(self, width, char):
|
||||
self.width = width
|
||||
self.char = char
|
||||
|
||||
def process(self, stream):
|
||||
for ttype, value in stream:
|
||||
if ttype != T.Literal.String.Single:
|
||||
yield ttype, value
|
||||
continue
|
||||
|
||||
if value[:2] == "''":
|
||||
inner = value[2:-2]
|
||||
quote = "''"
|
||||
else:
|
||||
inner = value[1:-1]
|
||||
quote = "'"
|
||||
|
||||
if len(inner) > self.width:
|
||||
value = ''.join((quote, inner[:self.width], self.char, quote))
|
||||
yield ttype, value
|
||||
@@ -0,0 +1,123 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2009-2018 the sqlparse authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of python-sqlparse and is released under
|
||||
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
|
||||
|
||||
import itertools
|
||||
import re
|
||||
from collections import deque
|
||||
from contextlib import contextmanager
|
||||
from sqlparse.compat import text_type
|
||||
|
||||
# This regular expression replaces the home-cooked parser that was here before.
|
||||
# It is much faster, but requires an extra post-processing step to get the
|
||||
# desired results (that are compatible with what you would expect from the
|
||||
# str.splitlines() method).
|
||||
#
|
||||
# It matches groups of characters: newlines, quoted strings, or unquoted text,
|
||||
# and splits on that basis. The post-processing step puts those back together
|
||||
# into the actual lines of SQL.
|
||||
SPLIT_REGEX = re.compile(r"""
|
||||
(
|
||||
(?: # Start of non-capturing group
|
||||
(?:\r\n|\r|\n) | # Match any single newline, or
|
||||
[^\r\n'"]+ | # Match any character series without quotes or
|
||||
# newlines, or
|
||||
"(?:[^"\\]|\\.)*" | # Match double-quoted strings, or
|
||||
'(?:[^'\\]|\\.)*' # Match single quoted strings
|
||||
)
|
||||
)
|
||||
""", re.VERBOSE)
|
||||
|
||||
LINE_MATCH = re.compile(r'(\r\n|\r|\n)')
|
||||
|
||||
|
||||
def split_unquoted_newlines(stmt):
|
||||
"""Split a string on all unquoted newlines.
|
||||
|
||||
Unlike str.splitlines(), this will ignore CR/LF/CR+LF if the requisite
|
||||
character is inside of a string."""
|
||||
text = text_type(stmt)
|
||||
lines = SPLIT_REGEX.split(text)
|
||||
outputlines = ['']
|
||||
for line in lines:
|
||||
if not line:
|
||||
continue
|
||||
elif LINE_MATCH.match(line):
|
||||
outputlines.append('')
|
||||
else:
|
||||
outputlines[-1] += line
|
||||
return outputlines
|
||||
|
||||
|
||||
def remove_quotes(val):
|
||||
"""Helper that removes surrounding quotes from strings."""
|
||||
if val is None:
|
||||
return
|
||||
if val[0] in ('"', "'") and val[0] == val[-1]:
|
||||
val = val[1:-1]
|
||||
return val
|
||||
|
||||
|
||||
def recurse(*cls):
|
||||
"""Function decorator to help with recursion
|
||||
|
||||
:param cls: Classes to not recurse over
|
||||
:return: function
|
||||
"""
|
||||
def wrap(f):
|
||||
def wrapped_f(tlist):
|
||||
for sgroup in tlist.get_sublists():
|
||||
if not isinstance(sgroup, cls):
|
||||
wrapped_f(sgroup)
|
||||
f(tlist)
|
||||
|
||||
return wrapped_f
|
||||
|
||||
return wrap
|
||||
|
||||
|
||||
def imt(token, i=None, m=None, t=None):
|
||||
"""Helper function to simplify comparisons Instance, Match and TokenType
|
||||
:param token:
|
||||
:param i: Class or Tuple/List of Classes
|
||||
:param m: Tuple of TokenType & Value. Can be list of Tuple for multiple
|
||||
:param t: TokenType or Tuple/List of TokenTypes
|
||||
:return: bool
|
||||
"""
|
||||
clss = i
|
||||
types = [t, ] if t and not isinstance(t, list) else t
|
||||
mpatterns = [m, ] if m and not isinstance(m, list) else m
|
||||
|
||||
if token is None:
|
||||
return False
|
||||
elif clss and isinstance(token, clss):
|
||||
return True
|
||||
elif mpatterns and any(token.match(*pattern) for pattern in mpatterns):
|
||||
return True
|
||||
elif types and any(token.ttype in ttype for ttype in types):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def consume(iterator, n):
|
||||
"""Advance the iterator n-steps ahead. If n is none, consume entirely."""
|
||||
deque(itertools.islice(iterator, n), maxlen=0)
|
||||
|
||||
|
||||
@contextmanager
|
||||
def offset(filter_, n=0):
|
||||
filter_.offset += n
|
||||
yield
|
||||
filter_.offset -= n
|
||||
|
||||
|
||||
@contextmanager
|
||||
def indent(filter_, n=1):
|
||||
filter_.indent += n
|
||||
yield
|
||||
filter_.indent -= n
|
||||
Reference in New Issue
Block a user