diff options
| -rw-r--r-- | .travis.yml | 36 | ||||
| -rw-r--r-- | pytest.ini | 6 | ||||
| -rw-r--r-- | sqlparse/__init__.py | 5 | ||||
| -rw-r--r-- | sqlparse/engine/__init__.py | 20 | ||||
| -rw-r--r-- | sqlparse/engine/filter.py | 2 | ||||
| -rw-r--r-- | sqlparse/engine/grouping.py | 9 | ||||
| -rw-r--r-- | sqlparse/filters.py | 26 | ||||
| -rw-r--r-- | sqlparse/sql.py | 2 | ||||
| -rw-r--r-- | sqlparse/tokens.py | 32 | ||||
| -rw-r--r-- | tests/test_functions.py | 3 | ||||
| -rw-r--r-- | tests/test_regressions.py | 4 | ||||
| -rw-r--r-- | tox.ini | 39 |
12 files changed, 84 insertions, 100 deletions
diff --git a/.travis.yml b/.travis.yml index febc5bd..6453a5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,23 +1,31 @@ language: python +python: 3.5 -python: - - "3.5" - - "3.4" - - "3.3" - - "2.7" - - "pypy" - - "pypy3" - - "nightly" +env: + - TOXENV=flake8 + - TOXENV=py27 + - TOXENV=py33 + - TOXENV=py34 + - TOXENV=py35 + - TOXENV=pypy + - TOXENV=pypy3 matrix: - allow_failures: - - python: "nightly" + fast_finish: true + + include: + - python: "nightly" + env: TOXENV=py36 + + allow_failures: + - python: "nightly" install: - - pip install pytest pytest-cov coveralls - - pip install -e . + - pip install tox coveralls -script: py.test --cov=sqlparse +script: + - tox after_success: - coveralls + - coveralls + - bash <(curl -s https://codecov.io/bash) diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index a2cbd90..0000000 --- a/pytest.ini +++ /dev/null @@ -1,6 +0,0 @@ -[pytest] -pep8ignore = - extras/* ALL - examples/* ALL - docs/* ALL - * E125 E127 diff --git a/sqlparse/__init__.py b/sqlparse/__init__.py index e5f4f03..794bf57 100644 --- a/sqlparse/__init__.py +++ b/sqlparse/__init__.py @@ -35,11 +35,11 @@ def parsestream(stream, encoding=None): :returns: A generator of :class:`~sqlparse.sql.Statement` instances. """ stack = engine.FilterStack() - stack.full_analyze() + stack.enable_grouping() return stack.run(stream, encoding) -def format(sql, **options): +def format(sql, encoding=None, **options): """Format *sql* according to *options*. Available options are documented in :ref:`formatting`. @@ -49,7 +49,6 @@ def format(sql, **options): :returns: The formatted SQL statement as string. """ - encoding = options.pop('encoding', None) stack = engine.FilterStack() options = formatter.validate_options(options) stack = formatter.build_filter_stack(stack, options) diff --git a/sqlparse/engine/__init__.py b/sqlparse/engine/__init__.py index 4d7fe88..c6b8b0c 100644 --- a/sqlparse/engine/__init__.py +++ b/sqlparse/engine/__init__.py @@ -9,9 +9,6 @@ from sqlparse import lexer from sqlparse.engine import grouping from sqlparse.engine.filter import StatementFilter -# XXX remove this when cleanup is complete -Filter = object - class FilterStack(object): @@ -22,20 +19,9 @@ class FilterStack(object): self.split_statements = False self._grouping = False - def _flatten(self, stream): - for token in stream: - if token.is_group(): - for t in self._flatten(token.tokens): - yield t - else: - yield token - def enable_grouping(self): self._grouping = True - def full_analyze(self): - self.enable_grouping() - def run(self, sql, encoding=None): stream = lexer.tokenize(sql, encoding) # Process token stream @@ -43,8 +29,8 @@ class FilterStack(object): for filter_ in self.preprocess: stream = filter_.process(self, stream) - if self.stmtprocess or self.postprocess or self.split_statements \ - or self._grouping: + if (self.stmtprocess or self.postprocess or + self.split_statements or self._grouping): splitter = StatementFilter() stream = splitter.process(self, stream) @@ -71,7 +57,7 @@ class FilterStack(object): def _run2(stream): for stmt in stream: - stmt.tokens = list(self._flatten(stmt.tokens)) + stmt.tokens = list(stmt.flatten()) for filter_ in self.postprocess: stmt = filter_.process(self, stmt) yield stmt diff --git a/sqlparse/engine/filter.py b/sqlparse/engine/filter.py index 360ff9b..adf48ad 100644 --- a/sqlparse/engine/filter.py +++ b/sqlparse/engine/filter.py @@ -4,7 +4,7 @@ from sqlparse.sql import Statement, Token from sqlparse import tokens as T -class StatementFilter: +class StatementFilter(object): "Filter that split stream at individual statements" def __init__(self): diff --git a/sqlparse/engine/grouping.py b/sqlparse/engine/grouping.py index f7953e7..7a93b5e 100644 --- a/sqlparse/engine/grouping.py +++ b/sqlparse/engine/grouping.py @@ -27,15 +27,16 @@ def _group_left_right(tlist, m, cls, if valid_left(left) and valid_right(right): if semicolon: + # only overwrite if a semicolon present. sright = tlist.token_next_by(m=M_SEMICOLON, idx=right) - right = sright or right # only overwrite if a semicolon present. + right = sright or right tokens = tlist.tokens_between(left, right) token = tlist.group_tokens(cls, tokens, extend=True) token = tlist.token_next_by(m=m, idx=token) def _group_matching(tlist, cls): - """Groups Tokens that have beginning and end. ie. parenthesis, brackets..""" + """Groups Tokens that have beginning and end.""" idx = 1 if imt(tlist, i=cls) else 0 token = tlist.token_next_by(m=cls.M_OPEN, idx=idx) @@ -223,9 +224,9 @@ def group_functions(tlist): has_create = False has_table = False for tmp_token in tlist.tokens: - if tmp_token.value == u'CREATE': + if tmp_token.value == 'CREATE': has_create = True - if tmp_token.value == u'TABLE': + if tmp_token.value == 'TABLE': has_table = True if has_create and has_table: return diff --git a/sqlparse/filters.py b/sqlparse/filters.py index 72f17d0..f5719e7 100644 --- a/sqlparse/filters.py +++ b/sqlparse/filters.py @@ -17,7 +17,7 @@ from sqlparse.utils import split_unquoted_newlines # -------------------------- # token process -class _CaseFilter: +class _CaseFilter(object): ttype = None @@ -48,7 +48,7 @@ class IdentifierCaseFilter(_CaseFilter): yield ttype, value -class TruncateStringFilter: +class TruncateStringFilter(object): def __init__(self, width, char): self.width = max(width, 1) @@ -69,7 +69,7 @@ class TruncateStringFilter: yield ttype, value -class GetComments: +class GetComments(object): """Get the comments from a stack""" def process(self, stack, stream): for token_type, value in stream: @@ -77,7 +77,7 @@ class GetComments: yield token_type, value -class StripComments: +class StripComments(object): """Strip the comments from a stack""" def process(self, stack, stream): for token_type, value in stream: @@ -113,7 +113,7 @@ def StripWhitespace(stream): last_type = token_type -class IncludeStatement: +class IncludeStatement(object): """Filter that enable a INCLUDE statement""" def __init__(self, dirpath=".", maxrecursive=10, raiseexceptions=False): @@ -196,7 +196,7 @@ class IncludeStatement: # ---------------------- # statement process -class StripCommentsFilter: +class StripCommentsFilter(object): def _get_next_comment(self, tlist): # TODO(andi) Comment types should be unified, see related issue38 @@ -225,7 +225,7 @@ class StripCommentsFilter: self._process(stmt) -class StripWhitespaceFilter: +class StripWhitespaceFilter(object): def _stripws(self, tlist): func_name = '_stripws_%s' % tlist.__class__.__name__.lower() @@ -277,7 +277,7 @@ class StripWhitespaceFilter: stmt.tokens.pop(-1) -class ReindentFilter: +class ReindentFilter(object): def __init__(self, width=2, char=' ', line_width=None): self.width = width @@ -471,7 +471,7 @@ class ReindentFilter: # FIXME: Doesn't work ;) -class RightMarginFilter: +class RightMarginFilter(object): keep_together = ( # sql.TypeCast, sql.Identifier, sql.Alias, @@ -509,7 +509,7 @@ class RightMarginFilter: group.tokens = self._process(stack, group, group.tokens) -class ColumnsSelect: +class ColumnsSelect(object): """Get the columns names of a SELECT query""" def process(self, stack, stream): mode = 0 @@ -563,7 +563,7 @@ class ColumnsSelect: # --------------------------- # postprocess -class SerializerUnicode: +class SerializerUnicode(object): def process(self, stack, stmt): raw = u(stmt) @@ -581,7 +581,7 @@ def Tokens2Unicode(stream): return result -class OutputFilter: +class OutputFilter(object): varname_prefix = '' def __init__(self, varname='sql'): @@ -695,7 +695,7 @@ class OutputPHPFilter(OutputFilter): yield sql.Token(T.Punctuation, ';') -class Limit: +class Limit(object): """Get the LIMIT of a query. If not defined, return -1 (SQL specification for no LIMIT query) diff --git a/sqlparse/sql.py b/sqlparse/sql.py index 9afdac3..3177831 100644 --- a/sqlparse/sql.py +++ b/sqlparse/sql.py @@ -316,7 +316,7 @@ class TokenList(Token): def token_index(self, token, start=0): """Return list index of token.""" - start = self.token_index(start) if not isinstance(start, int) else start + start = start if isinstance(start, int) else self.token_index(start) return start + self.tokens[start:].index(token) def tokens_between(self, start, end, include_end=True): diff --git a/sqlparse/tokens.py b/sqlparse/tokens.py index 98fa8a6..b259627 100644 --- a/sqlparse/tokens.py +++ b/sqlparse/tokens.py @@ -13,31 +13,18 @@ class _TokenType(tuple): parent = None - def split(self): - buf = [] - node = self - while node is not None: - buf.append(node) - node = node.parent - buf.reverse() - return buf + def __contains__(self, item): + return item is not None and (self is item or item[:len(self)] == self) - def __contains__(self, val): - return val is not None and (self is val or val[:len(self)] == self) - - def __getattr__(self, val): - if not val or not val[0].isupper(): - return tuple.__getattribute__(self, val) - new = _TokenType(self + (val,)) - setattr(self, val, new) + def __getattr__(self, name): + new = _TokenType(self + (name,)) + setattr(self, name, new) new.parent = self return new - def __hash__(self): - return hash(tuple(self)) - def __repr__(self): - return 'Token' + (self and '.' or '') + '.'.join(self) + # self can be False only if its the `root` ie. Token itself + return 'Token' + ('.' if self else '') + '.'.join(self) Token = _TokenType() @@ -77,8 +64,3 @@ DML = Keyword.DML DDL = Keyword.DDL CTE = Keyword.CTE Command = Keyword.Command - -Group = Token.Group -Group.Parenthesis = Token.Group.Parenthesis -Group.Comment = Token.Group.Comment -Group.Where = Token.Group.Where diff --git a/tests/test_functions.py b/tests/test_functions.py index 9207815..fd2774e 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -8,9 +8,6 @@ from unittest import main, TestCase from sqlparse.filters import IncludeStatement, Tokens2Unicode from sqlparse.lexer import tokenize -import sys -sys.path.insert(0, '..') - from sqlparse.filters import compact from sqlparse.functions import getcolumns, getlimit, IsType from tests.utils import FILES_DIR diff --git a/tests/test_regressions.py b/tests/test_regressions.py index c66a42d..13ca04b 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -7,7 +7,6 @@ from tests.utils import TestCaseBase, load_file import sqlparse from sqlparse import sql from sqlparse import tokens as T -from sqlparse.compat import u class RegressionTests(TestCaseBase): @@ -296,7 +295,8 @@ def test_issue213_leadingws(): def test_issue227_gettype_cte(): select_stmt = sqlparse.parse('SELECT 1, 2, 3 FROM foo;') assert select_stmt[0].get_type() == 'SELECT' - with_stmt = sqlparse.parse('WITH foo AS (SELECT 1, 2, 3) SELECT * FROM foo;') + with_stmt = sqlparse.parse('WITH foo AS (SELECT 1, 2, 3)' + 'SELECT * FROM foo;') assert with_stmt[0].get_type() == 'SELECT' with2_stmt = sqlparse.parse(''' WITH foo AS (SELECT 1 AS abc, 2 AS def), @@ -1,18 +1,35 @@ [tox] -envlist=flake8,py27,py33,py34,py35,pypy,pypy3 +envlist = + py27, + py33, + py34, + py35, + py36, + pypy, + pypy3, + flake8 [testenv] -deps= - pytest - pytest-cov -commands= - sqlformat --version # Sanity check. - py.test --cov=sqlparse/ tests +deps = + pytest + pytest-cov + pytest-travis-fold +passenv = + TRAVIS +commands = + python --version + sqlformat --version + py.test --cov=sqlparse [testenv:flake8] -basepython=python3.5 -deps=flake8 -commands=flake8 sqlparse +deps = + flake8 +commands = + flake8 sqlparse tests setup.py [flake8] -ignore = W503 +exclude = + sqlparse/compat.py +ignore = + W503, + E731 |
