diff options
| -rw-r--r-- | debug_toolbar/management/commands/debugsqlshell.py | 4 | ||||
| -rw-r--r-- | debug_toolbar/utils/sql.py | 20 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/__init__.py | 55 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/engine/__init__.py | 80 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/engine/filter.py | 104 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/engine/grouping.py | 314 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/filters.py | 439 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/formatter.py | 120 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/keywords.py | 565 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/lexer.py | 331 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/sql.py | 529 | ||||
| -rw-r--r-- | debug_toolbar/utils/sqlparse/tokens.py | 83 | ||||
| -rw-r--r-- | setup.py | 3 | ||||
| -rw-r--r-- | tox.ini | 26 | 
14 files changed, 43 insertions, 2630 deletions
| diff --git a/debug_toolbar/management/commands/debugsqlshell.py b/debug_toolbar/management/commands/debugsqlshell.py index c0e1fc1..e96f46d 100644 --- a/debug_toolbar/management/commands/debugsqlshell.py +++ b/debug_toolbar/management/commands/debugsqlshell.py @@ -2,7 +2,9 @@ from datetime import datetime  from django.db.backends import util -from debug_toolbar.utils import ms_from_timedelta, sqlparse +import sqlparse + +from debug_toolbar.utils import ms_from_timedelta  class PrintQueryWrapper(util.CursorDebugWrapper): diff --git a/debug_toolbar/utils/sql.py b/debug_toolbar/utils/sql.py index 909edf7..5de7da5 100644 --- a/debug_toolbar/utils/sql.py +++ b/debug_toolbar/utils/sql.py @@ -1,6 +1,22 @@  import re -from debug_toolbar.utils import sqlparse -from debug_toolbar.utils.sqlparse.filters import BoldKeywordFilter + +from django.utils.html import escape + +import sqlparse +from sqlparse import tokens as T + + +class BoldKeywordFilter: +    """sqlparse filter to bold SQL keywords""" +    def process(self, stack, stream): +        """Process the token stream""" +        for token_type, value in stream: +            is_keyword = token_type in T.Keyword +            if is_keyword: +                yield T.Text, '<strong>' +            yield token_type, escape(value) +            if is_keyword: +                yield T.Text, '</strong>'  def reformat_sql(sql): diff --git a/debug_toolbar/utils/sqlparse/__init__.py b/debug_toolbar/utils/sqlparse/__init__.py deleted file mode 100644 index 99db30e..0000000 --- a/debug_toolbar/utils/sqlparse/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com -# -# This module is part of python-sqlparse and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php. - -"""Parse SQL statements.""" - - -__version__ = '0.1.3' - - -class SQLParseError(Exception): -    """Base class for exceptions in this module.""" - - -# Setup namespace -from debug_toolbar.utils.sqlparse import engine -from debug_toolbar.utils.sqlparse import filters -from debug_toolbar.utils.sqlparse import formatter - - -def parse(sql): -    """Parse sql and return a list of statements. - -    *sql* is a single string containting one or more SQL statements. - -    Returns a tuple of :class:`~sqlparse.sql.Statement` instances. -    """ -    stack = engine.FilterStack() -    stack.full_analyze() -    return tuple(stack.run(sql)) - - -def format(sql, **options): -    """Format *sql* according to *options*. - -    Available options are documented in :ref:`formatting`. - -    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 ''.join(stack.run(sql)) - - -def split(sql): -    """Split *sql* into single statements. - -    Returns a list of strings. -    """ -    stack = engine.FilterStack() -    stack.split_statements = True -    return [unicode(stmt) for stmt in stack.run(sql)] diff --git a/debug_toolbar/utils/sqlparse/engine/__init__.py b/debug_toolbar/utils/sqlparse/engine/__init__.py deleted file mode 100644 index e838a3e..0000000 --- a/debug_toolbar/utils/sqlparse/engine/__init__.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com -# -# This module is part of python-sqlparse and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php. - -"""filter""" - -from debug_toolbar.utils.sqlparse import lexer -from debug_toolbar.utils.sqlparse.engine import grouping -from debug_toolbar.utils.sqlparse.engine.filter import StatementFilter - -# XXX remove this when cleanup is complete -Filter = object - - -class FilterStack(object): - -    def __init__(self): -        self.preprocess = [] -        self.stmtprocess = [] -        self.postprocess = [] -        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): -        stream = lexer.tokenize(sql) -        # Process token stream -        if self.preprocess: -            for filter_ in self.preprocess: -                stream = filter_.process(self, stream) - -        if (self.stmtprocess or self.postprocess or self.split_statements -            or self._grouping): -            splitter = StatementFilter() -            stream = splitter.process(self, stream) - -        if self._grouping: - -            def _group(stream): -                for stmt in stream: -                    grouping.group(stmt) -                    yield stmt -            stream = _group(stream) - -        if self.stmtprocess: - -            def _run1(stream): -                ret = [] -                for stmt in stream: -                    for filter_ in self.stmtprocess: -                        filter_.process(self, stmt) -                    ret.append(stmt) -                return ret -            stream = _run1(stream) - -        if self.postprocess: - -            def _run2(stream): -                for stmt in stream: -                    stmt.tokens = list(self._flatten(stmt.tokens)) -                    for filter_ in self.postprocess: -                        stmt = filter_.process(self, stmt) -                    yield stmt -            stream = _run2(stream) - -        return stream diff --git a/debug_toolbar/utils/sqlparse/engine/filter.py b/debug_toolbar/utils/sqlparse/engine/filter.py deleted file mode 100644 index a31c5de..0000000 --- a/debug_toolbar/utils/sqlparse/engine/filter.py +++ /dev/null @@ -1,104 +0,0 @@ -# -*- coding: utf-8 -*- - -from debug_toolbar.utils.sqlparse.sql import Statement, Token -from debug_toolbar.utils.sqlparse import tokens as T - - -class TokenFilter(object): - -    def __init__(self, **options): -        self.options = options - -    def process(self, stack, stream): -        """Process token stream.""" -        raise NotImplementedError - - -class StatementFilter(TokenFilter): - -    def __init__(self): -        TokenFilter.__init__(self) -        self._in_declare = False -        self._in_dbldollar = False -        self._is_create = False -        self._begin_depth = 0 - -    def _reset(self): -        self._in_declare = False -        self._in_dbldollar = False -        self._is_create = False -        self._begin_depth = 0 - -    def _change_splitlevel(self, ttype, value): -        # PostgreSQL -        if (ttype == T.Name.Builtin -            and value.startswith('$') and value.endswith('$')): -            if self._in_dbldollar: -                self._in_dbldollar = False -                return -1 -            else: -                self._in_dbldollar = True -                return 1 -        elif self._in_dbldollar: -            return 0 - -        # ANSI -        if ttype not in T.Keyword: -            return 0 - -        unified = value.upper() - -        if unified == 'DECLARE' and self._is_create: -            self._in_declare = True -            return 1 - -        if unified == 'BEGIN': -            self._begin_depth += 1 -            if self._in_declare:  # FIXME(andi): This makes no sense. -                return 0 -            return 0 - -        if unified == 'END': -            # Should this respect a preceeding BEGIN? -            # In CASE ... WHEN ... END this results in a split level -1. -            self._begin_depth = max(0, self._begin_depth - 1) -            return -1 - -        if ttype is T.Keyword.DDL and unified.startswith('CREATE'): -            self._is_create = True -            return 0 - -        if unified in ('IF', 'FOR') and self._is_create and self._begin_depth > 0: -            return 1 - -        # Default -        return 0 - -    def process(self, stack, stream): -        splitlevel = 0 -        stmt = None -        consume_ws = False -        stmt_tokens = [] -        for ttype, value in stream: -            # Before appending the token -            if (consume_ws and ttype is not T.Whitespace -                and ttype is not T.Comment.Single): -                consume_ws = False -                stmt.tokens = stmt_tokens -                yield stmt -                self._reset() -                stmt = None -                splitlevel = 0 -            if stmt is None: -                stmt = Statement() -                stmt_tokens = [] -            splitlevel += self._change_splitlevel(ttype, value) -            # Append the token -            stmt_tokens.append(Token(ttype, value)) -            # After appending the token -            if (splitlevel <= 0 and ttype is T.Punctuation -                and value == ';'): -                consume_ws = True -        if stmt is not None: -            stmt.tokens = stmt_tokens -            yield stmt diff --git a/debug_toolbar/utils/sqlparse/engine/grouping.py b/debug_toolbar/utils/sqlparse/engine/grouping.py deleted file mode 100644 index 4e50c7b..0000000 --- a/debug_toolbar/utils/sqlparse/engine/grouping.py +++ /dev/null @@ -1,314 +0,0 @@ -# -*- coding: utf-8 -*- - -import itertools - -from debug_toolbar.utils.sqlparse import sql -from debug_toolbar.utils.sqlparse import tokens as T - -try: -    next -except NameError:  # Python < 2.6 -    next = lambda i: i.next() - - -def _group_left_right(tlist, ttype, value, cls, -                      check_right=lambda t: True, -                      check_left=lambda t: True, -                      include_semicolon=False): -    [_group_left_right(sgroup, ttype, value, cls, check_right, -                       include_semicolon) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, cls)] -    idx = 0 -    token = tlist.token_next_match(idx, ttype, value) -    while token: -        right = tlist.token_next(tlist.token_index(token)) -        left = tlist.token_prev(tlist.token_index(token)) -        if right is None or not check_right(right): -            token = tlist.token_next_match(tlist.token_index(token) + 1, -                                           ttype, value) -        elif left is None or not check_right(left): -            token = tlist.token_next_match(tlist.token_index(token) + 1, -                                           ttype, value) -        else: -            if include_semicolon: -                sright = tlist.token_next_match(tlist.token_index(right), -                                                T.Punctuation, ';') -                if sright is not None: -                    # only overwrite "right" if a semicolon is actually -                    # present. -                    right = sright -            tokens = tlist.tokens_between(left, right)[1:] -            if not isinstance(left, cls): -                new = cls([left]) -                new_idx = tlist.token_index(left) -                tlist.tokens.remove(left) -                tlist.tokens.insert(new_idx, new) -                left = new -            left.tokens.extend(tokens) -            for t in tokens: -                tlist.tokens.remove(t) -            token = tlist.token_next_match(tlist.token_index(left) + 1, -                                           ttype, value) - - -def _group_matching(tlist, start_ttype, start_value, end_ttype, end_value, -                    cls, include_semicolon=False, recurse=False): -    def _find_matching(i, tl, stt, sva, ett, eva): -        depth = 1 -        for t in tl.tokens[i:]: -            if t.match(stt, sva): -                depth += 1 -            elif t.match(ett, eva): -                depth -= 1 -                if depth == 1: -                    return t -        return None -    [_group_matching(sgroup, start_ttype, start_value, end_ttype, end_value, -                     cls, include_semicolon) for sgroup in tlist.get_sublists() -     if recurse] -    if isinstance(tlist, cls): -        idx = 1 -    else: -        idx = 0 -    token = tlist.token_next_match(idx, start_ttype, start_value) -    while token: -        tidx = tlist.token_index(token) -        end = _find_matching(tidx, tlist, start_ttype, start_value, -                             end_ttype, end_value) -        if end is None: -            idx = tidx + 1 -        else: -            if include_semicolon: -                next_ = tlist.token_next(tlist.token_index(end)) -                if next_ and next_.match(T.Punctuation, ';'): -                    end = next_ -            group = tlist.group_tokens(cls, tlist.tokens_between(token, end)) -            _group_matching(group, start_ttype, start_value, -                            end_ttype, end_value, cls, include_semicolon) -            idx = tlist.token_index(group) + 1 -        token = tlist.token_next_match(idx, start_ttype, start_value) - - -def group_if(tlist): -    _group_matching(tlist, T.Keyword, 'IF', T.Keyword, 'END IF', sql.If, True) - - -def group_for(tlist): -    _group_matching(tlist, T.Keyword, 'FOR', T.Keyword, 'END LOOP', -                    sql.For, True) - - -def group_as(tlist): - -    def _right_valid(token): -        # Currently limited to DML/DDL. Maybe additional more non SQL reserved -        # keywords should appear here (see issue8). -        return not token.ttype in (T.DML, T.DDL) -    _group_left_right(tlist, T.Keyword, 'AS', sql.Identifier, -                      check_right=_right_valid) - - -def group_assignment(tlist): -    _group_left_right(tlist, T.Assignment, ':=', sql.Assignment, -                      include_semicolon=True) - - -def group_comparison(tlist): - -    def _parts_valid(token): -        return (token.ttype in (T.String.Symbol, T.Name, T.Number, -                                T.Number.Integer, T.Literal, -                                T.Literal.Number.Integer) -                or isinstance(token, (sql.Identifier,))) -    _group_left_right(tlist, T.Operator.Comparison, None, sql.Comparison, -                      check_left=_parts_valid, check_right=_parts_valid) - - -def group_case(tlist): -    _group_matching(tlist, T.Keyword, 'CASE', T.Keyword, 'END', sql.Case, -                    include_semicolon=True, recurse=True) - - -def group_identifier(tlist): -    def _consume_cycle(tl, i): -        x = itertools.cycle(( -            lambda y: (y.match(T.Punctuation, '.') -                       or y.ttype is T.Operator), -            lambda y: (y.ttype in (T.String.Symbol, -                                   T.Name, -                                   T.Wildcard, -                                   T.Literal.Number.Integer)))) -        for t in tl.tokens[i:]: -            if next(x)(t): -                yield t -            else: -                raise StopIteration - -    # bottom up approach: group subgroups first -    [group_identifier(sgroup) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, sql.Identifier)] - -    # real processing -    idx = 0 -    token = tlist.token_next_by_instance(idx, sql.Function) -    if token is None: -        token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) -    while token: -        identifier_tokens = [token] + list( -            _consume_cycle(tlist, -                           tlist.token_index(token) + 1)) -        if not (len(identifier_tokens) == 1 -                and isinstance(identifier_tokens[0], sql.Function)): -            group = tlist.group_tokens(sql.Identifier, identifier_tokens) -            idx = tlist.token_index(group) + 1 -        else: -            idx += 1 -        token = tlist.token_next_by_instance(idx, sql.Function) -        if token is None: -            token = tlist.token_next_by_type(idx, (T.String.Symbol, T.Name)) - - -def group_identifier_list(tlist): -    [group_identifier_list(sgroup) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, sql.IdentifierList)] -    idx = 0 -    # Allowed list items -    fend1_funcs = [lambda t: isinstance(t, (sql.Identifier, sql.Function)), -                   lambda t: t.is_whitespace(), -                   lambda t: t.ttype == T.Name, -                   lambda t: t.ttype == T.Wildcard, -                   lambda t: t.match(T.Keyword, 'null'), -                   lambda t: t.ttype == T.Number.Integer, -                   lambda t: t.ttype == T.String.Single, -                   lambda t: isinstance(t, sql.Comparison), -                   ] -    tcomma = tlist.token_next_match(idx, T.Punctuation, ',') -    start = None -    while tcomma is not None: -        before = tlist.token_prev(tcomma) -        after = tlist.token_next(tcomma) -        # Check if the tokens around tcomma belong to a list -        bpassed = apassed = False -        for func in fend1_funcs: -            if before is not None and func(before): -                bpassed = True -            if after is not None and func(after): -                apassed = True -        if not bpassed or not apassed: -            # Something's wrong here, skip ahead to next "," -            start = None -            tcomma = tlist.token_next_match(tlist.token_index(tcomma) + 1, -                                            T.Punctuation, ',') -        else: -            if start is None: -                start = before -            next_ = tlist.token_next(after) -            if next_ is None or not next_.match(T.Punctuation, ','): -                # Reached the end of the list -                tokens = tlist.tokens_between(start, after) -                group = tlist.group_tokens(sql.IdentifierList, tokens) -                start = None -                tcomma = tlist.token_next_match(tlist.token_index(group) + 1, -                                                T.Punctuation, ',') -            else: -                tcomma = next_ - - -def group_parenthesis(tlist): -    _group_matching(tlist, T.Punctuation, '(', T.Punctuation, ')', -                    sql.Parenthesis) - - -def group_comments(tlist): -    [group_comments(sgroup) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, sql.Comment)] -    idx = 0 -    token = tlist.token_next_by_type(idx, T.Comment) -    while token: -        tidx = tlist.token_index(token) -        end = tlist.token_not_matching(tidx + 1, -                                       [lambda t: t.ttype in T.Comment, -                                        lambda t: t.is_whitespace()]) -        if end is None: -            idx = tidx + 1 -        else: -            eidx = tlist.token_index(end) -            grp_tokens = tlist.tokens_between(token, -                                              tlist.token_prev(eidx, False)) -            group = tlist.group_tokens(sql.Comment, grp_tokens) -            idx = tlist.token_index(group) -        token = tlist.token_next_by_type(idx, T.Comment) - - -def group_where(tlist): -    [group_where(sgroup) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, sql.Where)] -    idx = 0 -    token = tlist.token_next_match(idx, T.Keyword, 'WHERE') -    stopwords = ('ORDER', 'GROUP', 'LIMIT', 'UNION') -    while token: -        tidx = tlist.token_index(token) -        end = tlist.token_next_match(tidx + 1, T.Keyword, stopwords) -        if end is None: -            end = tlist._groupable_tokens[-1] -        else: -            end = tlist.tokens[tlist.token_index(end) - 1] -        group = tlist.group_tokens(sql.Where, -                                   tlist.tokens_between(token, end), -                                   ignore_ws=True) -        idx = tlist.token_index(group) -        token = tlist.token_next_match(idx, T.Keyword, 'WHERE') - - -def group_aliased(tlist): -    [group_aliased(sgroup) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, (sql.Identifier, sql.Function))] -    idx = 0 -    token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function)) -    while token: -        next_ = tlist.token_next(tlist.token_index(token)) -        if next_ is not None and isinstance(next_, (sql.Identifier, sql.Function)): -            grp = tlist.tokens_between(token, next_)[1:] -            token.tokens.extend(grp) -            for t in grp: -                tlist.tokens.remove(t) -        idx = tlist.token_index(token) + 1 -        token = tlist.token_next_by_instance(idx, (sql.Identifier, sql.Function)) - - -def group_typecasts(tlist): -    _group_left_right(tlist, T.Punctuation, '::', sql.Identifier) - - -def group_functions(tlist): -    [group_functions(sgroup) for sgroup in tlist.get_sublists() -     if not isinstance(sgroup, sql.Function)] -    idx = 0 -    token = tlist.token_next_by_type(idx, T.Name) -    while token: -        next_ = tlist.token_next(token) -        if not isinstance(next_, sql.Parenthesis): -            idx = tlist.token_index(token) + 1 -        else: -            func = tlist.group_tokens(sql.Function, -                                      tlist.tokens_between(token, next_)) -            idx = tlist.token_index(func) + 1 -        token = tlist.token_next_by_type(idx, T.Name) - - -def group(tlist): -    for func in [group_parenthesis, -                 group_functions, -                 group_comments, -                 group_where, -                 group_case, -                 group_identifier, -                 group_typecasts, -                 group_as, -                 group_aliased, -                 group_assignment, -                 group_comparison, -                 group_identifier_list, -                 group_if, -                 group_for]: -        func(tlist) diff --git a/debug_toolbar/utils/sqlparse/filters.py b/debug_toolbar/utils/sqlparse/filters.py deleted file mode 100644 index 6443a3c..0000000 --- a/debug_toolbar/utils/sqlparse/filters.py +++ /dev/null @@ -1,439 +0,0 @@ -# -*- coding: utf-8 -*- - -import re -from django.utils.html import escape - -from debug_toolbar.utils.sqlparse import tokens as T -from debug_toolbar.utils.sqlparse import sql - - -class Filter(object): - -    def process(self, *args): -        raise NotImplementedError - - -class TokenFilter(Filter): - -    def process(self, stack, stream): -        raise NotImplementedError - - -# -------------------------- -# token process - -class _CaseFilter(TokenFilter): - -    ttype = None - -    def __init__(self, case=None): -        if case is None: -            case = 'upper' -        assert case in ['lower', 'upper', 'capitalize'] -        self.convert = getattr(unicode, case) - -    def process(self, stack, 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, stack, stream): -        for ttype, value in stream: -            if ttype in self.ttype and not value.strip()[0] == '"': -                value = self.convert(value) -            yield ttype, value - - -# ---------------------- -# statement process - -class StripCommentsFilter(Filter): - -    def _get_next_comment(self, tlist): -        # TODO(andi) Comment types should be unified, see related issue38 -        token = tlist.token_next_by_instance(0, sql.Comment) -        if token is None: -            token = tlist.token_next_by_type(0, T.Comment) -        return token - -    def _process(self, tlist): -        token = self._get_next_comment(tlist) -        while token: -            tidx = tlist.token_index(token) -            prev = tlist.token_prev(tidx, False) -            next_ = tlist.token_next(tidx, False) -            # Replace by whitespace if prev and next exist and if they're not -            # whitespaces. This doesn't apply if prev or next is a paranthesis. -            if (prev is not None and next_ is not None -                and not prev.is_whitespace() and not next_.is_whitespace() -                and not (prev.match(T.Punctuation, '(') -                         or next_.match(T.Punctuation, ')'))): -                tlist.tokens[tidx] = sql.Token(T.Whitespace, ' ') -            else: -                tlist.tokens.pop(tidx) -            token = self._get_next_comment(tlist) - -    def process(self, stack, stmt): -        [self.process(stack, sgroup) for sgroup in stmt.get_sublists()] -        self._process(stmt) - - -class StripWhitespaceFilter(Filter): - -    def _stripws(self, tlist): -        func_name = '_stripws_%s' % tlist.__class__.__name__.lower() -        func = getattr(self, func_name, self._stripws_default) -        func(tlist) - -    def _stripws_default(self, tlist): -        last_was_ws = False -        for token in tlist.tokens: -            if token.is_whitespace(): -                if last_was_ws: -                    token.value = '' -                else: -                    token.value = ' ' -            last_was_ws = token.is_whitespace() - -    def _stripws_parenthesis(self, tlist): -        if tlist.tokens[1].is_whitespace(): -            tlist.tokens.pop(1) -        if tlist.tokens[-2].is_whitespace(): -            tlist.tokens.pop(-2) -        self._stripws_default(tlist) - -    def process(self, stack, stmt): -        [self.process(stack, sgroup) for sgroup in stmt.get_sublists()] -        self._stripws(stmt) -        if stmt.tokens[-1].is_whitespace(): -            stmt.tokens.pop(-1) - - -class ReindentFilter(Filter): - -    def __init__(self, width=2, char=' ', line_width=None): -        self.width = width -        self.char = char -        self.indent = 0 -        self.offset = 0 -        self.line_width = line_width -        self._curr_stmt = None -        self._last_stmt = None - -    def _get_offset(self, token): -        all_ = list(self._curr_stmt.flatten()) -        idx = all_.index(token) -        raw = ''.join(unicode(x) for x in all_[:idx + 1]) -        line = raw.splitlines()[-1] -        # Now take current offset into account and return relative offset. -        full_offset = len(line) - len(self.char * (self.width * self.indent)) -        return full_offset - self.offset - -    def nl(self): -        # TODO: newline character should be configurable -        ws = '\n' + (self.char * ((self.indent * self.width) + self.offset)) -        return sql.Token(T.Whitespace, ws) - -    def _split_kwds(self, tlist): -        split_words = ('FROM', 'JOIN$', 'AND', 'OR', -                       'GROUP', 'ORDER', 'UNION', 'VALUES', -                       'SET', 'BETWEEN') - -        def _next_token(i): -            t = tlist.token_next_match(i, T.Keyword, split_words, -                                       regex=True) -            if t and t.value.upper() == 'BETWEEN': -                t = _next_token(tlist.token_index(t) + 1) -                if t and t.value.upper() == 'AND': -                    t = _next_token(tlist.token_index(t) + 1) -            return t - -        idx = 0 -        token = _next_token(idx) -        while token: -            prev = tlist.token_prev(tlist.token_index(token), False) -            offset = 1 -            if prev and prev.is_whitespace(): -                tlist.tokens.pop(tlist.token_index(prev)) -                offset += 1 -            if (prev -                and isinstance(prev, sql.Comment) -                and (str(prev).endswith('\n') -                     or str(prev).endswith('\r'))): -                nl = tlist.token_next(token) -            else: -                nl = self.nl() -                tlist.insert_before(token, nl) -            token = _next_token(tlist.token_index(nl) + offset) - -    def _split_statements(self, tlist): -        idx = 0 -        token = tlist.token_next_by_type(idx, (T.Keyword.DDL, T.Keyword.DML)) -        while token: -            prev = tlist.token_prev(tlist.token_index(token), False) -            if prev and prev.is_whitespace(): -                tlist.tokens.pop(tlist.token_index(prev)) -            # only break if it's not the first token -            if prev: -                nl = self.nl() -                tlist.insert_before(token, nl) -            token = tlist.token_next_by_type(tlist.token_index(token) + 1, -                                             (T.Keyword.DDL, T.Keyword.DML)) - -    def _process(self, tlist): -        func_name = '_process_%s' % tlist.__class__.__name__.lower() -        func = getattr(self, func_name, self._process_default) -        func(tlist) - -    def _process_where(self, tlist): -        token = tlist.token_next_match(0, T.Keyword, 'WHERE') -        tlist.insert_before(token, self.nl()) -        self.indent += 1 -        self._process_default(tlist) -        self.indent -= 1 - -    def _process_parenthesis(self, tlist): -        first = tlist.token_next(0) -        indented = False -        if first and first.ttype in (T.Keyword.DML, T.Keyword.DDL): -            self.indent += 1 -            tlist.tokens.insert(0, self.nl()) -            indented = True -        num_offset = self._get_offset(tlist.token_next_match(0, -                                                        T.Punctuation, '(')) -        self.offset += num_offset -        self._process_default(tlist, stmts=not indented) -        if indented: -            self.indent -= 1 -        self.offset -= num_offset - -    def _process_identifierlist(self, tlist): -        identifiers = tlist.get_identifiers() -        if len(identifiers) > 1 and not tlist.within(sql.Function): -            first = list(identifiers[0].flatten())[0] -            num_offset = self._get_offset(first) - len(first.value) -            self.offset += num_offset -            for token in identifiers[1:]: -                tlist.insert_before(token, self.nl()) -            self.offset -= num_offset -        self._process_default(tlist) - -    def _process_case(self, tlist): -        is_first = True -        num_offset = None -        case = tlist.tokens[0] -        outer_offset = self._get_offset(case) - len(case.value) -        self.offset += outer_offset -        for cond, value in tlist.get_cases(): -            if is_first: -                tcond = list(cond[0].flatten())[0] -                is_first = False -                num_offset = self._get_offset(tcond) - len(tcond.value) -                self.offset += num_offset -                continue -            if cond is None: -                token = value[0] -            else: -                token = cond[0] -            tlist.insert_before(token, self.nl()) -        # Line breaks on group level are done. Now let's add an offset of -        # 5 (=length of "when", "then", "else") and process subgroups. -        self.offset += 5 -        self._process_default(tlist) -        self.offset -= 5 -        if num_offset is not None: -            self.offset -= num_offset -        end = tlist.token_next_match(0, T.Keyword, 'END') -        tlist.insert_before(end, self.nl()) -        self.offset -= outer_offset - -    def _process_default(self, tlist, stmts=True, kwds=True): -        if stmts: -            self._split_statements(tlist) -        if kwds: -            self._split_kwds(tlist) -        [self._process(sgroup) for sgroup in tlist.get_sublists()] - -    def process(self, stack, stmt): -        if isinstance(stmt, sql.Statement): -            self._curr_stmt = stmt -        self._process(stmt) -        if isinstance(stmt, sql.Statement): -            if self._last_stmt is not None: -                if self._last_stmt.to_unicode().endswith('\n'): -                    nl = '\n' -                else: -                    nl = '\n\n' -                stmt.tokens.insert(0, -                    sql.Token(T.Whitespace, nl)) -            if self._last_stmt != stmt: -                self._last_stmt = stmt - - -# FIXME: Doesn't work ;) -class RightMarginFilter(Filter): - -    keep_together = ( -#        sql.TypeCast, sql.Identifier, sql.Alias, -    ) - -    def __init__(self, width=79): -        self.width = width -        self.line = '' - -    def _process(self, stack, group, stream): -        for token in stream: -            if token.is_whitespace() and '\n' in token.value: -                if token.value.endswith('\n'): -                    self.line = '' -                else: -                    self.line = token.value.splitlines()[-1] -            elif (token.is_group() -                  and not token.__class__ in self.keep_together): -                token.tokens = self._process(stack, token, token.tokens) -            else: -                val = token.to_unicode() -                if len(self.line) + len(val) > self.width: -                    match = re.search('^ +', self.line) -                    if match is not None: -                        indent = match.group() -                    else: -                        indent = '' -                    yield sql.Token(T.Whitespace, '\n%s' % indent) -                    self.line = indent -                self.line += val -            yield token - -    def process(self, stack, group): -        return -        group.tokens = self._process(stack, group, group.tokens) - - -# --------------------------- -# postprocess - -class SerializerUnicode(Filter): - -    def process(self, stack, stmt): -        raw = stmt.to_unicode() -        add_nl = raw.endswith('\n') -        res = '\n'.join(line.rstrip() for line in raw.splitlines()) -        if add_nl: -            res += '\n' -        return res - - -class OutputPythonFilter(Filter): - -    def __init__(self, varname='sql'): -        self.varname = varname -        self.cnt = 0 - -    def _process(self, stream, varname, count, has_nl): -        if count > 1: -            yield sql.Token(T.Whitespace, '\n') -        yield sql.Token(T.Name, varname) -        yield sql.Token(T.Whitespace, ' ') -        yield sql.Token(T.Operator, '=') -        yield sql.Token(T.Whitespace, ' ') -        if has_nl: -            yield sql.Token(T.Operator, '(') -        yield sql.Token(T.Text, "'") -        cnt = 0 -        for token in stream: -            cnt += 1 -            if token.is_whitespace() and '\n' in token.value: -                if cnt == 1: -                    continue -                after_lb = token.value.split('\n', 1)[1] -                yield sql.Token(T.Text, " '") -                yield sql.Token(T.Whitespace, '\n') -                for i in range(len(varname) + 4): -                    yield sql.Token(T.Whitespace, ' ') -                yield sql.Token(T.Text, "'") -                if after_lb:  # it's the indendation -                    yield sql.Token(T.Whitespace, after_lb) -                continue -            elif token.value and "'" in token.value: -                token.value = token.value.replace("'", "\\'") -            yield sql.Token(T.Text, token.value or '') -        yield sql.Token(T.Text, "'") -        if has_nl: -            yield sql.Token(T.Operator, ')') - -    def process(self, stack, stmt): -        self.cnt += 1 -        if self.cnt > 1: -            varname = '%s%d' % (self.varname, self.cnt) -        else: -            varname = self.varname -        has_nl = len(stmt.to_unicode().strip().splitlines()) > 1 -        stmt.tokens = self._process(stmt.tokens, varname, self.cnt, has_nl) -        return stmt - - -class OutputPHPFilter(Filter): - -    def __init__(self, varname='sql'): -        self.varname = '$%s' % varname -        self.count = 0 - -    def _process(self, stream, varname): -        if self.count > 1: -            yield sql.Token(T.Whitespace, '\n') -        yield sql.Token(T.Name, varname) -        yield sql.Token(T.Whitespace, ' ') -        yield sql.Token(T.Operator, '=') -        yield sql.Token(T.Whitespace, ' ') -        yield sql.Token(T.Text, '"') -        for token in stream: -            if token.is_whitespace() and '\n' in token.value: -                after_lb = token.value.split('\n', 1)[1] -                yield sql.Token(T.Text, ' "') -                yield sql.Token(T.Operator, ';') -                yield sql.Token(T.Whitespace, '\n') -                yield sql.Token(T.Name, varname) -                yield sql.Token(T.Whitespace, ' ') -                yield sql.Token(T.Punctuation, '.') -                yield sql.Token(T.Operator, '=') -                yield sql.Token(T.Whitespace, ' ') -                yield sql.Token(T.Text, '"') -                if after_lb: -                    yield sql.Token(T.Text, after_lb) -                continue -            elif '"' in token.value: -                token.value = token.value.replace('"', '\\"') -            yield sql.Token(T.Text, token.value) -        yield sql.Token(T.Text, '"') -        yield sql.Token(T.Punctuation, ';') - -    def process(self, stack, stmt): -        self.count += 1 -        if self.count > 1: -            varname = '%s%d' % (self.varname, self.count) -        else: -            varname = self.varname -        stmt.tokens = tuple(self._process(stmt.tokens, varname)) -        return stmt - - -class BoldKeywordFilter(Filter): -    """sqlparse filter to bold SQL keywords""" -    def process(self, stack, stream): -        """Process the token stream""" -        for token_type, value in stream: -            is_keyword = token_type in T.Keyword -            if is_keyword: -                yield T.Text, '<strong>' -            yield token_type, escape(value) -            if is_keyword: -                yield T.Text, '</strong>' diff --git a/debug_toolbar/utils/sqlparse/formatter.py b/debug_toolbar/utils/sqlparse/formatter.py deleted file mode 100644 index 3acece9..0000000 --- a/debug_toolbar/utils/sqlparse/formatter.py +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com -# -# This module is part of python-sqlparse and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php. - -"""SQL formatter""" - -from debug_toolbar.utils.sqlparse import SQLParseError -from debug_toolbar.utils.sqlparse import filters - - -def validate_options(options): -    """Validates options.""" -    kwcase = options.get('keyword_case', None) -    if kwcase not in [None, 'upper', 'lower', 'capitalize']: -        raise SQLParseError('Invalid value for keyword_case: %r' % kwcase) - -    idcase = options.get('identifier_case', None) -    if idcase not in [None, 'upper', 'lower', 'capitalize']: -        raise SQLParseError('Invalid value for identifier_case: %r' % idcase) - -    ofrmt = options.get('output_format', None) -    if ofrmt not in [None, 'sql', 'python', 'php']: -        raise SQLParseError('Unknown output format: %r' % ofrmt) - -    strip_comments = options.get('strip_comments', False) -    if strip_comments not in [True, False]: -        raise SQLParseError('Invalid value for strip_comments: %r' -                            % strip_comments) - -    strip_ws = options.get('strip_whitespace', False) -    if strip_ws not in [True, False]: -        raise SQLParseError('Invalid value for strip_whitespace: %r' -                            % strip_ws) - -    reindent = options.get('reindent', False) -    if reindent not in [True, False]: -        raise SQLParseError('Invalid value for reindent: %r' -                            % reindent) -    elif reindent: -        options['strip_whitespace'] = True -    indent_tabs = options.get('indent_tabs', False) -    if indent_tabs not in [True, False]: -        raise SQLParseError('Invalid value for indent_tabs: %r' % indent_tabs) -    elif indent_tabs: -        options['indent_char'] = '\t' -    else: -        options['indent_char'] = ' ' -    indent_width = options.get('indent_width', 2) -    try: -        indent_width = int(indent_width) -    except (TypeError, ValueError): -        raise SQLParseError('indent_width requires an integer') -    if indent_width < 1: -        raise SQLParseError('indent_width requires an positive integer') -    options['indent_width'] = indent_width - -    right_margin = options.get('right_margin', None) -    if right_margin is not None: -        try: -            right_margin = int(right_margin) -        except (TypeError, ValueError): -            raise SQLParseError('right_margin requires an integer') -        if right_margin < 10: -            raise SQLParseError('right_margin requires an integer > 10') -    options['right_margin'] = right_margin - -    return options - - -def build_filter_stack(stack, options): -    """Setup and return a filter stack. - -    Args: -      stack: :class:`~sqlparse.filters.FilterStack` instance -      options: Dictionary with options validated by validate_options. -    """ -    # Token filter -    if options.get('keyword_case', None): -        stack.preprocess.append( -            filters.KeywordCaseFilter(options['keyword_case'])) - -    if options.get('identifier_case', None): -        stack.preprocess.append( -            filters.IdentifierCaseFilter(options['identifier_case'])) - -    # After grouping -    if options.get('strip_comments', False): -        stack.enable_grouping() -        stack.stmtprocess.append(filters.StripCommentsFilter()) - -    if (options.get('strip_whitespace', False) -        or options.get('reindent', False)): -        stack.enable_grouping() -        stack.stmtprocess.append(filters.StripWhitespaceFilter()) - -    if options.get('reindent', False): -        stack.enable_grouping() -        stack.stmtprocess.append( -            filters.ReindentFilter(char=options['indent_char'], -                                   width=options['indent_width'])) - -    if options.get('right_margin', False): -        stack.enable_grouping() -        stack.stmtprocess.append( -            filters.RightMarginFilter(width=options['right_margin'])) - -    # Serializer -    if options.get('output_format'): -        frmt = options['output_format'] -        if frmt.lower() == 'php': -            fltr = filters.OutputPHPFilter() -        elif frmt.lower() == 'python': -            fltr = filters.OutputPythonFilter() -        else: -            fltr = None -        if fltr is not None: -            stack.postprocess.append(fltr) - -    return stack diff --git a/debug_toolbar/utils/sqlparse/keywords.py b/debug_toolbar/utils/sqlparse/keywords.py deleted file mode 100644 index 4782cfe..0000000 --- a/debug_toolbar/utils/sqlparse/keywords.py +++ /dev/null @@ -1,565 +0,0 @@ -from debug_toolbar.utils.sqlparse import tokens - -KEYWORDS = { -    'ABORT': tokens.Keyword, -    'ABS': tokens.Keyword, -    'ABSOLUTE': tokens.Keyword, -    'ACCESS': tokens.Keyword, -    'ADA': tokens.Keyword, -    'ADD': tokens.Keyword, -    'ADMIN': tokens.Keyword, -    'AFTER': tokens.Keyword, -    'AGGREGATE': tokens.Keyword, -    'ALIAS': tokens.Keyword, -    'ALL': tokens.Keyword, -    'ALLOCATE': tokens.Keyword, -    'ANALYSE': tokens.Keyword, -    'ANALYZE': tokens.Keyword, -    'ANY': tokens.Keyword, -    'ARE': tokens.Keyword, -    'ASC': tokens.Keyword, -    'ASENSITIVE': tokens.Keyword, -    'ASSERTION': tokens.Keyword, -    'ASSIGNMENT': tokens.Keyword, -    'ASYMMETRIC': tokens.Keyword, -    'AT': tokens.Keyword, -    'ATOMIC': tokens.Keyword, -    'AUTHORIZATION': tokens.Keyword, -    'AVG': tokens.Keyword, - -    'BACKWARD': tokens.Keyword, -    'BEFORE': tokens.Keyword, -    'BEGIN': tokens.Keyword, -    'BETWEEN': tokens.Keyword, -    'BITVAR': tokens.Keyword, -    'BIT_LENGTH': tokens.Keyword, -    'BOTH': tokens.Keyword, -    'BREADTH': tokens.Keyword, - -#    'C': tokens.Keyword,  # most likely this is an alias -    'CACHE': tokens.Keyword, -    'CALL': tokens.Keyword, -    'CALLED': tokens.Keyword, -    'CARDINALITY': tokens.Keyword, -    'CASCADE': tokens.Keyword, -    'CASCADED': tokens.Keyword, -    'CAST': tokens.Keyword, -    'CATALOG': tokens.Keyword, -    'CATALOG_NAME': tokens.Keyword, -    'CHAIN': tokens.Keyword, -    'CHARACTERISTICS': tokens.Keyword, -    'CHARACTER_LENGTH': tokens.Keyword, -    'CHARACTER_SET_CATALOG': tokens.Keyword, -    'CHARACTER_SET_NAME': tokens.Keyword, -    'CHARACTER_SET_SCHEMA': tokens.Keyword, -    'CHAR_LENGTH': tokens.Keyword, -    'CHECK': tokens.Keyword, -    'CHECKED': tokens.Keyword, -    'CHECKPOINT': tokens.Keyword, -    'CLASS': tokens.Keyword, -    'CLASS_ORIGIN': tokens.Keyword, -    'CLOB': tokens.Keyword, -    'CLOSE': tokens.Keyword, -    'CLUSTER': tokens.Keyword, -    'COALSECE': tokens.Keyword, -    'COBOL': tokens.Keyword, -    'COLLATE': tokens.Keyword, -    'COLLATION': tokens.Keyword, -    'COLLATION_CATALOG': tokens.Keyword, -    'COLLATION_NAME': tokens.Keyword, -    'COLLATION_SCHEMA': tokens.Keyword, -    'COLUMN': tokens.Keyword, -    'COLUMN_NAME': tokens.Keyword, -    'COMMAND_FUNCTION': tokens.Keyword, -    'COMMAND_FUNCTION_CODE': tokens.Keyword, -    'COMMENT': tokens.Keyword, -    'COMMIT': tokens.Keyword, -    'COMMITTED': tokens.Keyword, -    'COMPLETION': tokens.Keyword, -    'CONDITION_NUMBER': tokens.Keyword, -    'CONNECT': tokens.Keyword, -    'CONNECTION': tokens.Keyword, -    'CONNECTION_NAME': tokens.Keyword, -    'CONSTRAINT': tokens.Keyword, -    'CONSTRAINTS': tokens.Keyword, -    'CONSTRAINT_CATALOG': tokens.Keyword, -    'CONSTRAINT_NAME': tokens.Keyword, -    'CONSTRAINT_SCHEMA': tokens.Keyword, -    'CONSTRUCTOR': tokens.Keyword, -    'CONTAINS': tokens.Keyword, -    'CONTINUE': tokens.Keyword, -    'CONVERSION': tokens.Keyword, -    'CONVERT': tokens.Keyword, -    'COPY': tokens.Keyword, -    'CORRESPONTING': tokens.Keyword, -    'COUNT': tokens.Keyword, -    'CREATEDB': tokens.Keyword, -    'CREATEUSER': tokens.Keyword, -    'CROSS': tokens.Keyword, -    'CUBE': tokens.Keyword, -    'CURRENT': tokens.Keyword, -    'CURRENT_DATE': tokens.Keyword, -    'CURRENT_PATH': tokens.Keyword, -    'CURRENT_ROLE': tokens.Keyword, -    'CURRENT_TIME': tokens.Keyword, -    'CURRENT_TIMESTAMP': tokens.Keyword, -    'CURRENT_USER': tokens.Keyword, -    'CURSOR': tokens.Keyword, -    'CURSOR_NAME': tokens.Keyword, -    'CYCLE': tokens.Keyword, - -    'DATA': tokens.Keyword, -    'DATABASE': tokens.Keyword, -    'DATETIME_INTERVAL_CODE': tokens.Keyword, -    'DATETIME_INTERVAL_PRECISION': tokens.Keyword, -    'DAY': tokens.Keyword, -    'DEALLOCATE': tokens.Keyword, -    'DECLARE': tokens.Keyword, -    'DEFAULT': tokens.Keyword, -    'DEFAULTS': tokens.Keyword, -    'DEFERRABLE': tokens.Keyword, -    'DEFERRED': tokens.Keyword, -    'DEFINED': tokens.Keyword, -    'DEFINER': tokens.Keyword, -    'DELIMITER': tokens.Keyword, -    'DELIMITERS': tokens.Keyword, -    'DEREF': tokens.Keyword, -    'DESC': tokens.Keyword, -    'DESCRIBE': tokens.Keyword, -    'DESCRIPTOR': tokens.Keyword, -    'DESTROY': tokens.Keyword, -    'DESTRUCTOR': tokens.Keyword, -    'DETERMINISTIC': tokens.Keyword, -    'DIAGNOSTICS': tokens.Keyword, -    'DICTIONARY': tokens.Keyword, -    'DISCONNECT': tokens.Keyword, -    'DISPATCH': tokens.Keyword, -    'DO': tokens.Keyword, -    'DOMAIN': tokens.Keyword, -    'DYNAMIC': tokens.Keyword, -    'DYNAMIC_FUNCTION': tokens.Keyword, -    'DYNAMIC_FUNCTION_CODE': tokens.Keyword, - -    'EACH': tokens.Keyword, -    'ENCODING': tokens.Keyword, -    'ENCRYPTED': tokens.Keyword, -    'END-EXEC': tokens.Keyword, -    'EQUALS': tokens.Keyword, -    'ESCAPE': tokens.Keyword, -    'EVERY': tokens.Keyword, -    'EXCEPT': tokens.Keyword, -    'ESCEPTION': tokens.Keyword, -    'EXCLUDING': tokens.Keyword, -    'EXCLUSIVE': tokens.Keyword, -    'EXEC': tokens.Keyword, -    'EXECUTE': tokens.Keyword, -    'EXISTING': tokens.Keyword, -    'EXISTS': tokens.Keyword, -    'EXTERNAL': tokens.Keyword, -    'EXTRACT': tokens.Keyword, - -    'FALSE': tokens.Keyword, -    'FETCH': tokens.Keyword, -    'FINAL': tokens.Keyword, -    'FIRST': tokens.Keyword, -    'FORCE': tokens.Keyword, -    'FOREIGN': tokens.Keyword, -    'FORTRAN': tokens.Keyword, -    'FORWARD': tokens.Keyword, -    'FOUND': tokens.Keyword, -    'FREE': tokens.Keyword, -    'FREEZE': tokens.Keyword, -    'FULL': tokens.Keyword, -    'FUNCTION': tokens.Keyword, - -#    'G': tokens.Keyword, -    'GENERAL': tokens.Keyword, -    'GENERATED': tokens.Keyword, -    'GET': tokens.Keyword, -    'GLOBAL': tokens.Keyword, -    'GO': tokens.Keyword, -    'GOTO': tokens.Keyword, -    'GRANT': tokens.Keyword, -    'GRANTED': tokens.Keyword, -    'GROUPING': tokens.Keyword, - -    'HANDLER': tokens.Keyword, -    'HAVING': tokens.Keyword, -    'HIERARCHY': tokens.Keyword, -    'HOLD': tokens.Keyword, -    'HOST': tokens.Keyword, - -    'IDENTITY': tokens.Keyword, -    'IGNORE': tokens.Keyword, -    'ILIKE': tokens.Keyword, -    'IMMEDIATE': tokens.Keyword, -    'IMMUTABLE': tokens.Keyword, - -    'IMPLEMENTATION': tokens.Keyword, -    'IMPLICIT': tokens.Keyword, -    'INCLUDING': tokens.Keyword, -    'INCREMENT': tokens.Keyword, -    'INDEX': tokens.Keyword, - -    'INDITCATOR': tokens.Keyword, -    'INFIX': tokens.Keyword, -    'INHERITS': tokens.Keyword, -    'INITIALIZE': tokens.Keyword, -    'INITIALLY': tokens.Keyword, -    'INOUT': tokens.Keyword, -    'INPUT': tokens.Keyword, -    'INSENSITIVE': tokens.Keyword, -    'INSTANTIABLE': tokens.Keyword, -    'INSTEAD': tokens.Keyword, -    'INTERSECT': tokens.Keyword, -    'INTO': tokens.Keyword, -    'INVOKER': tokens.Keyword, -    'IS': tokens.Keyword, -    'ISNULL': tokens.Keyword, -    'ISOLATION': tokens.Keyword, -    'ITERATE': tokens.Keyword, - -#    'K': tokens.Keyword, -    'KEY': tokens.Keyword, -    'KEY_MEMBER': tokens.Keyword, -    'KEY_TYPE': tokens.Keyword, - -    'LANCOMPILER': tokens.Keyword, -    'LANGUAGE': tokens.Keyword, -    'LARGE': tokens.Keyword, -    'LAST': tokens.Keyword, -    'LATERAL': tokens.Keyword, -    'LEADING': tokens.Keyword, -    'LENGTH': tokens.Keyword, -    'LESS': tokens.Keyword, -    'LEVEL': tokens.Keyword, -    'LIMIT': tokens.Keyword, -    'LISTEN': tokens.Keyword, -    'LOAD': tokens.Keyword, -    'LOCAL': tokens.Keyword, -    'LOCALTIME': tokens.Keyword, -    'LOCALTIMESTAMP': tokens.Keyword, -    'LOCATION': tokens.Keyword, -    'LOCATOR': tokens.Keyword, -    'LOCK': tokens.Keyword, -    'LOWER': tokens.Keyword, - -#    'M': tokens.Keyword, -    'MAP': tokens.Keyword, -    'MATCH': tokens.Keyword, -    'MAXVALUE': tokens.Keyword, -    'MESSAGE_LENGTH': tokens.Keyword, -    'MESSAGE_OCTET_LENGTH': tokens.Keyword, -    'MESSAGE_TEXT': tokens.Keyword, -    'METHOD': tokens.Keyword, -    'MINUTE': tokens.Keyword, -    'MINVALUE': tokens.Keyword, -    'MOD': tokens.Keyword, -    'MODE': tokens.Keyword, -    'MODIFIES': tokens.Keyword, -    'MODIFY': tokens.Keyword, -    'MONTH': tokens.Keyword, -    'MORE': tokens.Keyword, -    'MOVE': tokens.Keyword, -    'MUMPS': tokens.Keyword, - -    'NAMES': tokens.Keyword, -    'NATIONAL': tokens.Keyword, -    'NATURAL': tokens.Keyword, -    'NCHAR': tokens.Keyword, -    'NCLOB': tokens.Keyword, -    'NEW': tokens.Keyword, -    'NEXT': tokens.Keyword, -    'NO': tokens.Keyword, -    'NOCREATEDB': tokens.Keyword, -    'NOCREATEUSER': tokens.Keyword, -    'NONE': tokens.Keyword, -    'NOT': tokens.Keyword, -    'NOTHING': tokens.Keyword, -    'NOTIFY': tokens.Keyword, -    'NOTNULL': tokens.Keyword, -    'NULL': tokens.Keyword, -    'NULLABLE': tokens.Keyword, -    'NULLIF': tokens.Keyword, - -    'OBJECT': tokens.Keyword, -    'OCTET_LENGTH': tokens.Keyword, -    'OF': tokens.Keyword, -    'OFF': tokens.Keyword, -    'OFFSET': tokens.Keyword, -    'OIDS': tokens.Keyword, -    'OLD': tokens.Keyword, -    'ONLY': tokens.Keyword, -    'OPEN': tokens.Keyword, -    'OPERATION': tokens.Keyword, -    'OPERATOR': tokens.Keyword, -    'OPTION': tokens.Keyword, -    'OPTIONS': tokens.Keyword, -    'ORDINALITY': tokens.Keyword, -    'OUT': tokens.Keyword, -    'OUTPUT': tokens.Keyword, -    'OVERLAPS': tokens.Keyword, -    'OVERLAY': tokens.Keyword, -    'OVERRIDING': tokens.Keyword, -    'OWNER': tokens.Keyword, - -    'PAD': tokens.Keyword, -    'PARAMETER': tokens.Keyword, -    'PARAMETERS': tokens.Keyword, -    'PARAMETER_MODE': tokens.Keyword, -    'PARAMATER_NAME': tokens.Keyword, -    'PARAMATER_ORDINAL_POSITION': tokens.Keyword, -    'PARAMETER_SPECIFIC_CATALOG': tokens.Keyword, -    'PARAMETER_SPECIFIC_NAME': tokens.Keyword, -    'PARAMATER_SPECIFIC_SCHEMA': tokens.Keyword, -    'PARTIAL': tokens.Keyword, -    'PASCAL': tokens.Keyword, -    'PENDANT': tokens.Keyword, -    'PLACING': tokens.Keyword, -    'PLI': tokens.Keyword, -    'POSITION': tokens.Keyword, -    'POSTFIX': tokens.Keyword, -    'PRECISION': tokens.Keyword, -    'PREFIX': tokens.Keyword, -    'PREORDER': tokens.Keyword, -    'PREPARE': tokens.Keyword, -    'PRESERVE': tokens.Keyword, -    'PRIMARY': tokens.Keyword, -    'PRIOR': tokens.Keyword, -    'PRIVILEGES': tokens.Keyword, -    'PROCEDURAL': tokens.Keyword, -    'PROCEDURE': tokens.Keyword, -    'PUBLIC': tokens.Keyword, - -    'RAISE': tokens.Keyword, -    'READ': tokens.Keyword, -    'READS': tokens.Keyword, -    'RECHECK': tokens.Keyword, -    'RECURSIVE': tokens.Keyword, -    'REF': tokens.Keyword, -    'REFERENCES': tokens.Keyword, -    'REFERENCING': tokens.Keyword, -    'REINDEX': tokens.Keyword, -    'RELATIVE': tokens.Keyword, -    'RENAME': tokens.Keyword, -    'REPEATABLE': tokens.Keyword, -    'RESET': tokens.Keyword, -    'RESTART': tokens.Keyword, -    'RESTRICT': tokens.Keyword, -    'RESULT': tokens.Keyword, -    'RETURN': tokens.Keyword, -    'RETURNED_LENGTH': tokens.Keyword, -    'RETURNED_OCTET_LENGTH': tokens.Keyword, -    'RETURNED_SQLSTATE': tokens.Keyword, -    'RETURNS': tokens.Keyword, -    'REVOKE': tokens.Keyword, -    'RIGHT': tokens.Keyword, -    'ROLE': tokens.Keyword, -    'ROLLBACK': tokens.Keyword, -    'ROLLUP': tokens.Keyword, -    'ROUTINE': tokens.Keyword, -    'ROUTINE_CATALOG': tokens.Keyword, -    'ROUTINE_NAME': tokens.Keyword, -    'ROUTINE_SCHEMA': tokens.Keyword, -    'ROW': tokens.Keyword, -    'ROWS': tokens.Keyword, -    'ROW_COUNT': tokens.Keyword, -    'RULE': tokens.Keyword, - -    'SAVE_POINT': tokens.Keyword, -    'SCALE': tokens.Keyword, -    'SCHEMA': tokens.Keyword, -    'SCHEMA_NAME': tokens.Keyword, -    'SCOPE': tokens.Keyword, -    'SCROLL': tokens.Keyword, -    'SEARCH': tokens.Keyword, -    'SECOND': tokens.Keyword, -    'SECURITY': tokens.Keyword, -    'SELF': tokens.Keyword, -    'SENSITIVE': tokens.Keyword, -    'SERIALIZABLE': tokens.Keyword, -    'SERVER_NAME': tokens.Keyword, -    'SESSION': tokens.Keyword, -    'SESSION_USER': tokens.Keyword, -    'SETOF': tokens.Keyword, -    'SETS': tokens.Keyword, -    'SHARE': tokens.Keyword, -    'SHOW': tokens.Keyword, -    'SIMILAR': tokens.Keyword, -    'SIMPLE': tokens.Keyword, -    'SIZE': tokens.Keyword, -    'SOME': tokens.Keyword, -    'SOURCE': tokens.Keyword, -    'SPACE': tokens.Keyword, -    'SPECIFIC': tokens.Keyword, -    'SPECIFICTYPE': tokens.Keyword, -    'SPECIFIC_NAME': tokens.Keyword, -    'SQL': tokens.Keyword, -    'SQLCODE': tokens.Keyword, -    'SQLERROR': tokens.Keyword, -    'SQLEXCEPTION': tokens.Keyword, -    'SQLSTATE': tokens.Keyword, -    'SQLWARNING': tokens.Keyword, -    'STABLE': tokens.Keyword, -    'START': tokens.Keyword, -    'STATE': tokens.Keyword, -    'STATEMENT': tokens.Keyword, -    'STATIC': tokens.Keyword, -    'STATISTICS': tokens.Keyword, -    'STDIN': tokens.Keyword, -    'STDOUT': tokens.Keyword, -    'STORAGE': tokens.Keyword, -    'STRICT': tokens.Keyword, -    'STRUCTURE': tokens.Keyword, -    'STYPE': tokens.Keyword, -    'SUBCLASS_ORIGIN': tokens.Keyword, -    'SUBLIST': tokens.Keyword, -    'SUBSTRING': tokens.Keyword, -    'SUM': tokens.Keyword, -    'SYMMETRIC': tokens.Keyword, -    'SYSID': tokens.Keyword, -    'SYSTEM': tokens.Keyword, -    'SYSTEM_USER': tokens.Keyword, - -    'TABLE': tokens.Keyword, -    'TABLE_NAME': tokens.Keyword, -    ' TEMP': tokens.Keyword, -    'TEMPLATE': tokens.Keyword, -    'TEMPORARY': tokens.Keyword, -    'TERMINATE': tokens.Keyword, -    'THAN': tokens.Keyword, -    'TIMESTAMP': tokens.Keyword, -    'TIMEZONE_HOUR': tokens.Keyword, -    'TIMEZONE_MINUTE': tokens.Keyword, -    'TO': tokens.Keyword, -    'TOAST': tokens.Keyword, -    'TRAILING': tokens.Keyword, -    'TRANSATION': tokens.Keyword, -    'TRANSACTIONS_COMMITTED': tokens.Keyword, -    'TRANSACTIONS_ROLLED_BACK': tokens.Keyword, -    'TRANSATION_ACTIVE': tokens.Keyword, -    'TRANSFORM': tokens.Keyword, -    'TRANSFORMS': tokens.Keyword, -    'TRANSLATE': tokens.Keyword, -    'TRANSLATION': tokens.Keyword, -    'TREAT': tokens.Keyword, -    'TRIGGER': tokens.Keyword, -    'TRIGGER_CATALOG': tokens.Keyword, -    'TRIGGER_NAME': tokens.Keyword, -    'TRIGGER_SCHEMA': tokens.Keyword, -    'TRIM': tokens.Keyword, -    'TRUE': tokens.Keyword, -    'TRUNCATE': tokens.Keyword, -    'TRUSTED': tokens.Keyword, -    'TYPE': tokens.Keyword, - -    'UNCOMMITTED': tokens.Keyword, -    'UNDER': tokens.Keyword, -    'UNENCRYPTED': tokens.Keyword, -    'UNION': tokens.Keyword, -    'UNIQUE': tokens.Keyword, -    'UNKNOWN': tokens.Keyword, -    'UNLISTEN': tokens.Keyword, -    'UNNAMED': tokens.Keyword, -    'UNNEST': tokens.Keyword, -    'UNTIL': tokens.Keyword, -    'UPPER': tokens.Keyword, -    'USAGE': tokens.Keyword, -    'USER': tokens.Keyword, -    'USER_DEFINED_TYPE_CATALOG': tokens.Keyword, -    'USER_DEFINED_TYPE_NAME': tokens.Keyword, -    'USER_DEFINED_TYPE_SCHEMA': tokens.Keyword, -    'USING': tokens.Keyword, - -    'VACUUM': tokens.Keyword, -    'VALID': tokens.Keyword, -    'VALIDATOR': tokens.Keyword, -    'VALUES': tokens.Keyword, -    'VARIABLE': tokens.Keyword, -    'VERBOSE': tokens.Keyword, -    'VERSION': tokens.Keyword, -    'VIEW': tokens.Keyword, -    'VOLATILE': tokens.Keyword, - -    'WHENEVER': tokens.Keyword, -    'WITH': tokens.Keyword, -    'WITHOUT': tokens.Keyword, -    'WORK': tokens.Keyword, -    'WRITE': tokens.Keyword, - -    'YEAR': tokens.Keyword, - -    'ZONE': tokens.Keyword, - - -    'ARRAY': tokens.Name.Builtin, -    'BIGINT': tokens.Name.Builtin, -    'BINARY': tokens.Name.Builtin, -    'BIT': tokens.Name.Builtin, -    'BLOB': tokens.Name.Builtin, -    'BOOLEAN': tokens.Name.Builtin, -    'CHAR': tokens.Name.Builtin, -    'CHARACTER': tokens.Name.Builtin, -    'DATE': tokens.Name.Builtin, -    'DEC': tokens.Name.Builtin, -    'DECIMAL': tokens.Name.Builtin, -    'FLOAT': tokens.Name.Builtin, -    'INT': tokens.Name.Builtin, -    'INTEGER': tokens.Name.Builtin, -    'INTERVAL': tokens.Name.Builtin, -    'LONG': tokens.Name.Builtin, -    'NUMBER': tokens.Name.Builtin, -    'NUMERIC': tokens.Name.Builtin, -    'REAL': tokens.Name.Builtin, -    'SERIAL': tokens.Name.Builtin, -    'SMALLINT': tokens.Name.Builtin, -    'VARCHAR': tokens.Name.Builtin, -    'VARCHAR2': tokens.Name.Builtin, -    'VARYING': tokens.Name.Builtin, -    'INT8': tokens.Name.Builtin, -    'SERIAL8': tokens.Name.Builtin, -    'TEXT': tokens.Name.Builtin, -    } - - -KEYWORDS_COMMON = { -    'SELECT': tokens.Keyword.DML, -    'INSERT': tokens.Keyword.DML, -    'DELETE': tokens.Keyword.DML, -    'UPDATE': tokens.Keyword.DML, -    'REPLACE': tokens.Keyword.DML, -    'DROP': tokens.Keyword.DDL, -    'CREATE': tokens.Keyword.DDL, -    'ALTER': tokens.Keyword.DDL, - -    'WHERE': tokens.Keyword, -    'FROM': tokens.Keyword, -    'INNER': tokens.Keyword, -    'JOIN': tokens.Keyword, -    'AND': tokens.Keyword, -    'OR': tokens.Keyword, -    'LIKE': tokens.Keyword, -    'ON': tokens.Keyword, -    'IN': tokens.Keyword, -    'SET': tokens.Keyword, - -    'BY': tokens.Keyword, -    'GROUP': tokens.Keyword, -    'ORDER': tokens.Keyword, -    'LEFT': tokens.Keyword, -    'OUTER': tokens.Keyword, - -    'IF': tokens.Keyword, -    'END': tokens.Keyword, -    'THEN': tokens.Keyword, -    'LOOP': tokens.Keyword, -    'AS': tokens.Keyword, -    'ELSE': tokens.Keyword, -    'FOR': tokens.Keyword, - -    'CASE': tokens.Keyword, -    'WHEN': tokens.Keyword, -    'MIN': tokens.Keyword, -    'MAX': tokens.Keyword, -    'DISTINCT': tokens.Keyword, -    } diff --git a/debug_toolbar/utils/sqlparse/lexer.py b/debug_toolbar/utils/sqlparse/lexer.py deleted file mode 100644 index ae3fc2e..0000000 --- a/debug_toolbar/utils/sqlparse/lexer.py +++ /dev/null @@ -1,331 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com -# -# This module is part of python-sqlparse and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php. - -"""SQL Lexer""" - -# This code is based on the SqlLexer in pygments. -# http://pygments.org/ -# It's separated from the rest of pygments to increase performance -# and to allow some customizations. - -import re - -from debug_toolbar.utils.sqlparse import tokens -from debug_toolbar.utils.sqlparse.keywords import KEYWORDS, KEYWORDS_COMMON - - -class include(str): -    pass - - -class combined(tuple): -    """Indicates a state combined from multiple states.""" - -    def __new__(cls, *args): -        return tuple.__new__(cls, args) - -    def __init__(self, *args): -        # tuple.__init__ doesn't do anything -        pass - - -def is_keyword(value): -    test = value.upper() -    return KEYWORDS_COMMON.get(test, KEYWORDS.get(test, tokens.Name)), value - - -def apply_filters(stream, filters, lexer=None): -    """ -    Use this method to apply an iterable of filters to -    a stream. If lexer is given it's forwarded to the -    filter, otherwise the filter receives `None`. -    """ - -    def _apply(filter_, stream): -        for token in filter_.filter(lexer, stream): -            yield token - -    for filter_ in filters: -        stream = _apply(filter_, stream) -    return stream - - -class LexerMeta(type): -    """ -    Metaclass for Lexer, creates the self._tokens attribute from -    self.tokens on the first instantiation. -    """ - -    def _process_state(cls, unprocessed, processed, state): -        assert type(state) is str, "wrong state name %r" % state -        assert state[0] != '#', "invalid state name %r" % state -        if state in processed: -            return processed[state] -        tokenlist = processed[state] = [] -        rflags = cls.flags -        for tdef in unprocessed[state]: -            if isinstance(tdef, include): -                # it's a state reference -                assert tdef != state, "circular state reference %r" % state -                tokenlist.extend(cls._process_state( -                    unprocessed, processed, str(tdef))) -                continue - -            assert type(tdef) is tuple, "wrong rule def %r" % tdef - -            try: -                rex = re.compile(tdef[0], rflags).match -            except Exception, err: -                raise ValueError(("uncompilable regex %r in state" -                                  " %r of %r: %s" -                                  % (tdef[0], state, cls, err))) - -            assert type(tdef[1]) is tokens._TokenType or callable(tdef[1]), \ -                   ('token type must be simple type or callable, not %r' -                    % (tdef[1],)) - -            if len(tdef) == 2: -                new_state = None -            else: -                tdef2 = tdef[2] -                if isinstance(tdef2, str): -                    # an existing state -                    if tdef2 == '#pop': -                        new_state = -1 -                    elif tdef2 in unprocessed: -                        new_state = (tdef2,) -                    elif tdef2 == '#push': -                        new_state = tdef2 -                    elif tdef2[:5] == '#pop:': -                        new_state = -int(tdef2[5:]) -                    else: -                        assert False, 'unknown new state %r' % tdef2 -                elif isinstance(tdef2, combined): -                    # combine a new state from existing ones -                    new_state = '_tmp_%d' % cls._tmpname -                    cls._tmpname += 1 -                    itokens = [] -                    for istate in tdef2: -                        assert istate != state, \ -                               'circular state ref %r' % istate -                        itokens.extend(cls._process_state(unprocessed, -                                                          processed, istate)) -                    processed[new_state] = itokens -                    new_state = (new_state,) -                elif isinstance(tdef2, tuple): -                    # push more than one state -                    for state in tdef2: -                        assert (state in unprocessed or -                                state in ('#pop', '#push')), \ -                               'unknown new state ' + state -                    new_state = tdef2 -                else: -                    assert False, 'unknown new state def %r' % tdef2 -            tokenlist.append((rex, tdef[1], new_state)) -        return tokenlist - -    def process_tokendef(cls): -        cls._all_tokens = {} -        cls._tmpname = 0 -        processed = cls._all_tokens[cls.__name__] = {} -        #tokendefs = tokendefs or cls.tokens[name] -        for state in cls.tokens.keys(): -            cls._process_state(cls.tokens, processed, state) -        return processed - -    def __call__(cls, *args, **kwds): -        if not hasattr(cls, '_tokens'): -            cls._all_tokens = {} -            cls._tmpname = 0 -            if hasattr(cls, 'token_variants') and cls.token_variants: -                # don't process yet -                pass -            else: -                cls._tokens = cls.process_tokendef() - -        return type.__call__(cls, *args, **kwds) - - -class Lexer(object): - -    __metaclass__ = LexerMeta - -    encoding = 'utf-8' -    stripall = False -    stripnl = False -    tabsize = 0 -    flags = re.IGNORECASE - -    tokens = { -        'root': [ -            (r'--.*?(\r\n|\r|\n)', tokens.Comment.Single), -            # $ matches *before* newline, therefore we have two patterns -            # to match Comment.Single -            (r'--.*?$', tokens.Comment.Single), -            (r'(\r|\n|\r\n)', tokens.Newline), -            (r'\s+', tokens.Whitespace), -            (r'/\*', tokens.Comment.Multiline, 'multiline-comments'), -            (r':=', tokens.Assignment), -            (r'::', tokens.Punctuation), -            (r'[*]', tokens.Wildcard), -            (r'CASE\b', tokens.Keyword),  # extended CASE(foo) -            (r"`(``|[^`])*`", tokens.Name), -            (r"´(´´|[^´])*´", tokens.Name), -            (r'\$([a-zA-Z_][a-zA-Z0-9_]*)?\$', tokens.Name.Builtin), -            (r'\?{1}', tokens.Name.Placeholder), -            (r'[$:?%][a-zA-Z0-9_]+[^$:?%]?', tokens.Name.Placeholder), -            (r'@[a-zA-Z_][a-zA-Z0-9_]+', tokens.Name), -            (r'[a-zA-Z_][a-zA-Z0-9_]*(?=[.(])', tokens.Name),  # see issue39 -            (r'[<>=~!]+', tokens.Operator.Comparison), -            (r'[+/@#%^&|`?^-]+', tokens.Operator), -            (r'0x[0-9a-fA-F]+', tokens.Number.Hexadecimal), -            (r'[0-9]*\.[0-9]+', tokens.Number.Float), -            (r'[0-9]+', tokens.Number.Integer), -            # TODO: Backslash escapes? -            (r"(''|'.*?[^\\]')", tokens.String.Single), -            # not a real string literal in ANSI SQL: -            (r'(""|".*?[^\\]")', tokens.String.Symbol), -            (r'(\[.*[^\]]\])', tokens.Name), -            (r'(LEFT |RIGHT )?(INNER |OUTER )?JOIN\b', tokens.Keyword), -            (r'END( IF| LOOP)?\b', tokens.Keyword), -            (r'NOT NULL\b', tokens.Keyword), -            (r'CREATE( OR REPLACE)?\b', tokens.Keyword.DDL), -            (r'[a-zA-Z_][a-zA-Z0-9_]*', is_keyword), -            (r'[;:()\[\],\.]', tokens.Punctuation), -        ], -        'multiline-comments': [ -            (r'/\*', tokens.Comment.Multiline, 'multiline-comments'), -            (r'\*/', tokens.Comment.Multiline, '#pop'), -            (r'[^/\*]+', tokens.Comment.Multiline), -            (r'[/*]', tokens.Comment.Multiline) -        ]} - -    def __init__(self): -        self.filters = [] - -    def add_filter(self, filter_, **options): -        from debug_toolbar.utils.sqlparse.filters import Filter -        if not isinstance(filter_, Filter): -            filter_ = filter_(**options) -        self.filters.append(filter_) - -    def get_tokens(self, text, unfiltered=False): -        """ -        Return an iterable of (tokentype, value) pairs generated from -        `text`. If `unfiltered` is set to `True`, the filtering mechanism -        is bypassed even if filters are defined. - -        Also preprocess the text, i.e. expand tabs and strip it if -        wanted and applies registered filters. -        """ -        if not isinstance(text, unicode): -            if self.encoding == 'guess': -                try: -                    text = text.decode('utf-8') -                    if text.startswith(u'\ufeff'): -                        text = text[len(u'\ufeff'):] -                except UnicodeDecodeError: -                    text = text.decode('latin1') -            elif self.encoding == 'chardet': -                try: -                    import chardet -                except ImportError: -                    raise ImportError('To enable chardet encoding guessing, ' -                                      'please install the chardet library ' -                                      'from http://chardet.feedparser.org/') -                enc = chardet.detect(text) -                text = text.decode(enc['encoding']) -            else: -                text = text.decode(self.encoding) -        if self.stripall: -            text = text.strip() -        elif self.stripnl: -            text = text.strip('\n') -        if self.tabsize > 0: -            text = text.expandtabs(self.tabsize) -#        if not text.endswith('\n'): -#            text += '\n' - -        def streamer(): -            for i, t, v in self.get_tokens_unprocessed(text): -                yield t, v -        stream = streamer() -        if not unfiltered: -            stream = apply_filters(stream, self.filters, self) -        return stream - -    def get_tokens_unprocessed(self, text, stack=('root',)): -        """ -        Split ``text`` into (tokentype, text) pairs. - -        ``stack`` is the inital stack (default: ``['root']``) -        """ -        pos = 0 -        tokendefs = self._tokens -        statestack = list(stack) -        statetokens = tokendefs[statestack[-1]] -        known_names = {} -        while 1: -            for rexmatch, action, new_state in statetokens: -                m = rexmatch(text, pos) -                if m: -                    # print rex.pattern -                    value = m.group() -                    if value in known_names: -                        yield pos, known_names[value], value -                    elif type(action) is tokens._TokenType: -                        yield pos, action, value -                    elif hasattr(action, '__call__'): -                        ttype, value = action(value) -                        known_names[value] = ttype -                        yield pos, ttype, value -                    else: -                        for item in action(self, m): -                            yield item -                    pos = m.end() -                    if new_state is not None: -                        # state transition -                        if isinstance(new_state, tuple): -                            for state in new_state: -                                if state == '#pop': -                                    statestack.pop() -                                elif state == '#push': -                                    statestack.append(statestack[-1]) -                                else: -                                    statestack.append(state) -                        elif isinstance(new_state, int): -                            # pop -                            del statestack[new_state:] -                        elif new_state == '#push': -                            statestack.append(statestack[-1]) -                        else: -                            assert False, "wrong state def: %r" % new_state -                        statetokens = tokendefs[statestack[-1]] -                    break -            else: -                try: -                    if text[pos] == '\n': -                        # at EOL, reset state to "root" -                        pos += 1 -                        statestack = ['root'] -                        statetokens = tokendefs['root'] -                        yield pos, tokens.Text, u'\n' -                        continue -                    yield pos, tokens.Error, text[pos] -                    pos += 1 -                except IndexError: -                    break - - -def tokenize(sql): -    """Tokenize sql. - -    Tokenize *sql* using the :class:`Lexer` and return a 2-tuple stream -    of ``(token type, value)`` items. -    """ -    lexer = Lexer() -    return lexer.get_tokens(sql) diff --git a/debug_toolbar/utils/sqlparse/sql.py b/debug_toolbar/utils/sqlparse/sql.py deleted file mode 100644 index 2f9f538..0000000 --- a/debug_toolbar/utils/sqlparse/sql.py +++ /dev/null @@ -1,529 +0,0 @@ -# -*- coding: utf-8 -*- - -"""This module contains classes representing syntactical elements of SQL.""" - -import re - -from debug_toolbar.utils.sqlparse import tokens as T - - -class Token(object): -    """Base class for all other classes in this module. - -    It represents a single token and has two instance attributes: -    ``value`` is the unchange value of the token and ``ttype`` is -    the type of the token. -    """ - -    __slots__ = ('value', 'ttype', 'parent') - -    def __init__(self, ttype, value): -        self.value = value -        self.ttype = ttype -        self.parent = None - -    def __str__(self): -        return unicode(self).encode('utf-8') - -    def __repr__(self): -        short = self._get_repr_value() -        return '<%s \'%s\' at 0x%07x>' % (self._get_repr_name(), -                                          short, id(self)) - -    def __unicode__(self): -        return self.value or '' - -    def to_unicode(self): -        """Returns a unicode representation of this object.""" -        return unicode(self) - -    def _get_repr_name(self): -        return str(self.ttype).split('.')[-1] - -    def _get_repr_value(self): -        raw = unicode(self) -        if len(raw) > 7: -            short = raw[:6] + u'...' -        else: -            short = raw -        return re.sub('\s+', ' ', short) - -    def flatten(self): -        """Resolve subgroups.""" -        yield self - -    def match(self, ttype, values, regex=False): -        """Checks whether the token matches the given arguments. - -        *ttype* is a token type. If this token doesn't match the given token -        type. -        *values* is a list of possible values for this token. The values -        are OR'ed together so if only one of the values matches ``True`` -        is returned. Except for keyword tokens the comparison is -        case-sensitive. For convenience it's ok to pass in a single string. -        If *regex* is ``True`` (default is ``False``) the given values are -        treated as regular expressions. -        """ -        type_matched = self.ttype is ttype -        if not type_matched or values is None: -            return type_matched -        if isinstance(values, basestring): -            values = set([values]) -        if regex: -            if self.ttype is T.Keyword: -                values = set([re.compile(v, re.IGNORECASE) for v in values]) -            else: -                values = set([re.compile(v) for v in values]) -            for pattern in values: -                if pattern.search(self.value): -                    return True -            return False -        else: -            if self.ttype in T.Keyword: -                values = set([v.upper() for v in values]) -                return self.value.upper() in values -            else: -                return self.value in values - -    def is_group(self): -        """Returns ``True`` if this object has children.""" -        return False - -    def is_whitespace(self): -        """Return ``True`` if this token is a whitespace token.""" -        return self.ttype and self.ttype in T.Whitespace - -    def within(self, group_cls): -        """Returns ``True`` if this token is within *group_cls*. - -        Use this method for example to check if an identifier is within -        a function: ``t.within(sql.Function)``. -        """ -        parent = self.parent -        while parent: -            if isinstance(parent, group_cls): -                return True -            parent = parent.parent -        return False - -    def is_child_of(self, other): -        """Returns ``True`` if this token is a direct child of *other*.""" -        return self.parent == other - -    def has_ancestor(self, other): -        """Returns ``True`` if *other* is in this tokens ancestry.""" -        parent = self.parent -        while parent: -            if parent == other: -                return True -            parent = parent.parent -        return False - - -class TokenList(Token): -    """A group of tokens. - -    It has an additional instance attribute ``tokens`` which holds a -    list of child-tokens. -    """ - -    __slots__ = ('value', 'ttype', 'tokens') - -    def __init__(self, tokens=None): -        if tokens is None: -            tokens = [] -        self.tokens = tokens -        Token.__init__(self, None, None) - -    def __unicode__(self): -        return ''.join(unicode(x) for x in self.flatten()) - -    def __str__(self): -        return unicode(self).encode('utf-8') - -    def _get_repr_name(self): -        return self.__class__.__name__ - -    def _pprint_tree(self, max_depth=None, depth=0): -        """Pretty-print the object tree.""" -        indent = ' ' * (depth * 2) -        for idx, token in enumerate(self.tokens): -            if token.is_group(): -                pre = ' +-' -            else: -                pre = ' | ' -            print '%s%s%d %s \'%s\'' % (indent, pre, idx, -                                        token._get_repr_name(), -                                        token._get_repr_value()) -            if (token.is_group() and (max_depth is None or depth < max_depth)): -                token._pprint_tree(max_depth, depth + 1) - -    def flatten(self): -        """Generator yielding ungrouped tokens. - -        This method is recursively called for all child tokens. -        """ -        for token in self.tokens: -            if isinstance(token, TokenList): -                for item in token.flatten(): -                    yield item -            else: -                yield token - -    def is_group(self): -        return True - -    def get_sublists(self): -        return [x for x in self.tokens if isinstance(x, TokenList)] - -    @property -    def _groupable_tokens(self): -        return self.tokens - -    def token_first(self, ignore_whitespace=True): -        """Returns the first child token. - -        If *ignore_whitespace* is ``True`` (the default), whitespace -        tokens are ignored. -        """ -        for token in self.tokens: -            if ignore_whitespace and token.is_whitespace(): -                continue -            return token -        return None - -    def token_next_by_instance(self, idx, clss): -        """Returns the next token matching a class. - -        *idx* is where to start searching in the list of child tokens. -        *clss* is a list of classes the token should be an instance of. - -        If no matching token can be found ``None`` is returned. -        """ -        if isinstance(clss, (list, tuple)): -            clss = (clss,) -        if isinstance(clss, tuple): -            clss = tuple(clss) -        for token in self.tokens[idx:]: -            if isinstance(token, clss): -                return token -        return None - -    def token_next_by_type(self, idx, ttypes): -        """Returns next matching token by it's token type.""" -        if not isinstance(ttypes, (list, tuple)): -            ttypes = [ttypes] -        for token in self.tokens[idx:]: -            if token.ttype in ttypes: -                return token -        return None - -    def token_next_match(self, idx, ttype, value, regex=False): -        """Returns next token where it's ``match`` method returns ``True``.""" -        if not isinstance(idx, int): -            idx = self.token_index(idx) -        for token in self.tokens[idx:]: -            if token.match(ttype, value, regex): -                return token -        return None - -    def token_not_matching(self, idx, funcs): -        for token in self.tokens[idx:]: -            passed = False -            for func in funcs: -                if func(token): -                    passed = True -                    break -            if not passed: -                return token -        return None - -    def token_matching(self, idx, funcs): -        for token in self.tokens[idx:]: -            for i, func in enumerate(funcs): -                if func(token): -                    return token -        return None - -    def token_prev(self, idx, skip_ws=True): -        """Returns the previous token relative to *idx*. - -        If *skip_ws* is ``True`` (the default) whitespace tokens are ignored. -        ``None`` is returned if there's no previous token. -        """ -        if idx is None: -            return None -        if not isinstance(idx, int): -            idx = self.token_index(idx) -        while idx != 0: -            idx -= 1 -            if self.tokens[idx].is_whitespace() and skip_ws: -                continue -            return self.tokens[idx] - -    def token_next(self, idx, skip_ws=True): -        """Returns the next token relative to *idx*. - -        If *skip_ws* is ``True`` (the default) whitespace tokens are ignored. -        ``None`` is returned if there's no next token. -        """ -        if idx is None: -            return None -        if not isinstance(idx, int): -            idx = self.token_index(idx) -        while idx < len(self.tokens) - 1: -            idx += 1 -            if self.tokens[idx].is_whitespace() and skip_ws: -                continue -            return self.tokens[idx] - -    def token_index(self, token): -        """Return list index of token.""" -        return self.tokens.index(token) - -    def tokens_between(self, start, end, exclude_end=False): -        """Return all tokens between (and including) start and end. - -        If *exclude_end* is ``True`` (default is ``False``) the end token -        is included too. -        """ -        # FIXME(andi): rename exclude_end to inlcude_end -        if exclude_end: -            offset = 0 -        else: -            offset = 1 -        end_idx = self.token_index(end) + offset -        start_idx = self.token_index(start) -        return self.tokens[start_idx:end_idx] - -    def group_tokens(self, grp_cls, tokens, ignore_ws=False): -        """Replace tokens by an instance of *grp_cls*.""" -        idx = self.token_index(tokens[0]) -        if ignore_ws: -            while tokens and tokens[-1].is_whitespace(): -                tokens = tokens[:-1] -        for t in tokens: -            self.tokens.remove(t) -        grp = grp_cls(tokens) -        for token in tokens: -            token.parent = grp -        grp.parent = self -        self.tokens.insert(idx, grp) -        return grp - -    def insert_before(self, where, token): -        """Inserts *token* before *where*.""" -        self.tokens.insert(self.token_index(where), token) - - -class Statement(TokenList): -    """Represents a SQL statement.""" - -    __slots__ = ('value', 'ttype', 'tokens') - -    def get_type(self): -        """Returns the type of a statement. - -        The returned value is a string holding an upper-cased reprint of -        the first DML or DDL keyword. If the first token in this group -        isn't a DML or DDL keyword "UNKNOWN" is returned. -        """ -        first_token = self.token_first() -        if first_token is None: -            # An "empty" statement that either has not tokens at all -            # or only whitespace tokens. -            return 'UNKNOWN' -        elif first_token.ttype in (T.Keyword.DML, T.Keyword.DDL): -            return first_token.value.upper() -        else: -            return 'UNKNOWN' - - -class Identifier(TokenList): -    """Represents an identifier. - -    Identifiers may have aliases or typecasts. -    """ - -    __slots__ = ('value', 'ttype', 'tokens') - -    def has_alias(self): -        """Returns ``True`` if an alias is present.""" -        return self.get_alias() is not None - -    def get_alias(self): -        """Returns the alias for this identifier or ``None``.""" -        kw = self.token_next_match(0, T.Keyword, 'AS') -        if kw is not None: -            alias = self.token_next(self.token_index(kw)) -            if alias is None: -                return None -        else: -            next_ = self.token_next(0) -            if next_ is None or not isinstance(next_, Identifier): -                return None -            alias = next_ -        if isinstance(alias, Identifier): -            return alias.get_name() -        else: -            return alias.to_unicode() - -    def get_name(self): -        """Returns the name of this identifier. - -        This is either it's alias or it's real name. The returned valued can -        be considered as the name under which the object corresponding to -        this identifier is known within the current statement. -        """ -        alias = self.get_alias() -        if alias is not None: -            return alias -        return self.get_real_name() - -    def get_real_name(self): -        """Returns the real name (object name) of this identifier.""" -        # a.b -        dot = self.token_next_match(0, T.Punctuation, '.') -        if dot is None: -            return self.token_next_by_type(0, T.Name).value -        else: -            next_ = self.token_next_by_type(self.token_index(dot), -                                            (T.Name, T.Wildcard)) -            if next_ is None:  # invalid identifier, e.g. "a." -                return None -            return next_.value - -    def get_parent_name(self): -        """Return name of the parent object if any. - -        A parent object is identified by the first occuring dot. -        """ -        dot = self.token_next_match(0, T.Punctuation, '.') -        if dot is None: -            return None -        prev_ = self.token_prev(self.token_index(dot)) -        if prev_ is None:  # something must be verry wrong here.. -            return None -        return prev_.value - -    def is_wildcard(self): -        """Return ``True`` if this identifier contains a wildcard.""" -        token = self.token_next_by_type(0, T.Wildcard) -        return token is not None - -    def get_typecast(self): -        """Returns the typecast or ``None`` of this object as a string.""" -        marker = self.token_next_match(0, T.Punctuation, '::') -        if marker is None: -            return None -        next_ = self.token_next(self.token_index(marker), False) -        if next_ is None: -            return None -        return next_.to_unicode() - - -class IdentifierList(TokenList): -    """A list of :class:`~sqlparse.sql.Identifier`\'s.""" - -    __slots__ = ('value', 'ttype', 'tokens') - -    def get_identifiers(self): -        """Returns the identifiers. - -        Whitespaces and punctuations are not included in this list. -        """ -        return [x for x in self.tokens -                if not x.is_whitespace() and not x.match(T.Punctuation, ',')] - - -class Parenthesis(TokenList): -    """Tokens between parenthesis.""" -    __slots__ = ('value', 'ttype', 'tokens') - -    @property -    def _groupable_tokens(self): -        return self.tokens[1:-1] - - -class Assignment(TokenList): -    """An assignment like 'var := val;'""" -    __slots__ = ('value', 'ttype', 'tokens') - - -class If(TokenList): -    """An 'if' clause with possible 'else if' or 'else' parts.""" -    __slots__ = ('value', 'ttype', 'tokens') - - -class For(TokenList): -    """A 'FOR' loop.""" -    __slots__ = ('value', 'ttype', 'tokens') - - -class Comparison(TokenList): -    """A comparison used for example in WHERE clauses.""" -    __slots__ = ('value', 'ttype', 'tokens') - - -class Comment(TokenList): -    """A comment.""" -    __slots__ = ('value', 'ttype', 'tokens') - - -class Where(TokenList): -    """A WHERE clause.""" -    __slots__ = ('value', 'ttype', 'tokens') - - -class Case(TokenList): -    """A CASE statement with one or more WHEN and possibly an ELSE part.""" - -    __slots__ = ('value', 'ttype', 'tokens') - -    def get_cases(self): -        """Returns a list of 2-tuples (condition, value). - -        If an ELSE exists condition is None. -        """ -        ret = [] -        in_value = False -        in_condition = True -        for token in self.tokens: -            if token.match(T.Keyword, 'CASE'): -                continue -            elif token.match(T.Keyword, 'WHEN'): -                ret.append(([], [])) -                in_condition = True -                in_value = False -            elif token.match(T.Keyword, 'ELSE'): -                ret.append((None, [])) -                in_condition = False -                in_value = True -            elif token.match(T.Keyword, 'THEN'): -                in_condition = False -                in_value = True -            elif token.match(T.Keyword, 'END'): -                in_condition = False -                in_value = False -            if (in_condition or in_value) and not ret: -                # First condition withou preceding WHEN -                ret.append(([], [])) -            if in_condition: -                ret[-1][0].append(token) -            elif in_value: -                ret[-1][1].append(token) -        return ret - - -class Function(TokenList): -    """A function or procedure call.""" - -    __slots__ = ('value', 'ttype', 'tokens') - -    def get_parameters(self): -        """Return a list of parameters.""" -        parenthesis = self.tokens[-1] -        for t in parenthesis.tokens: -            if isinstance(t, IdentifierList): -                return t.get_identifiers() -        return [] diff --git a/debug_toolbar/utils/sqlparse/tokens.py b/debug_toolbar/utils/sqlparse/tokens.py deleted file mode 100644 index 01a9b89..0000000 --- a/debug_toolbar/utils/sqlparse/tokens.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (C) 2008 Andi Albrecht, albrecht.andi@gmail.com -# -# This module is part of python-sqlparse and is released under -# the BSD License: http://www.opensource.org/licenses/bsd-license.php. - -# The Token implementation is based on pygment's token system written -# by Georg Brandl. -# http://pygments.org/ - -"""Tokens""" - - -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, 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) -        new.parent = self -        return new - -    def __hash__(self): -        return hash(tuple(self)) - -    def __repr__(self): -        return 'Token' + (self and '.' or '') + '.'.join(self) - - -Token = _TokenType() - -# Special token types -Text = Token.Text -Whitespace = Text.Whitespace -Newline = Whitespace.Newline -Error = Token.Error -# Text that doesn't belong to this lexer (e.g. HTML in PHP) -Other = Token.Other - -# Common token types for source code -Keyword = Token.Keyword -Name = Token.Name -Literal = Token.Literal -String = Literal.String -Number = Literal.Number -Punctuation = Token.Punctuation -Operator = Token.Operator -Comparison = Operator.Comparison -Wildcard = Token.Wildcard -Comment = Token.Comment -Assignment = Token.Assignement - -# Generic types for non-source code -Generic = Token.Generic - -# String and some others are not direct childs of Token. -# alias them: -Token.Token = Token -Token.String = String -Token.Number = Number - -# SQL specific tokens -DML = Keyword.DML -DDL = Keyword.DDL -Command = Keyword.Command - -Group = Token.Group -Group.Parenthesis = Token.Group.Parenthesis -Group.Comment = Token.Group.Comment -Group.Where = Token.Group.Where @@ -12,8 +12,9 @@ setup(      download_url='https://github.com/django-debug-toolbar/django-debug-toolbar/downloads',      license='BSD',      packages=find_packages(exclude=('tests', 'example')), -    tests_require=[ +    install_requires=[          'django>=1.4,<1.6', +        'sqlparse',      ],      test_suite='runtests.runtests',      include_package_data=True, @@ -9,27 +9,41 @@ envlist =  [testenv]  commands = python runtests.py +deps = +    sqlparse  [testenv:py26-django14]  basepython = python2.6 -deps = Django>=1.4,<1.5 +deps = +    Django>=1.4,<1.5 +    {[testenv]deps}  [testenv:py27-django14]  basepython = python2.7 -deps = Django>=1.4,<1.5 +deps = +    Django>=1.4,<1.5 +    {[testenv]deps}  [testenv:py26-django15]  basepython = python2.6 -deps = Django>=1.5,<1.6 +deps = +    Django>=1.5,<1.6 +    {[testenv]deps}  [testenv:py27-django15]  basepython = python2.7 -deps = Django>=1.5,<1.6 +deps = +    Django>=1.5,<1.6 +    {[testenv]deps}  [testenv:py32-django15]  basepython = python3.2 -deps = Django>=1.5,<1.6 +deps = +    Django>=1.5,<1.6 +    {[testenv]deps}  [testenv:py33-django15]  basepython = python3.3 -deps = Django>=1.5,<1.6 +deps = +    Django>=1.5,<1.6 +    {[testenv]deps} | 
