diff options
41 files changed, 160 insertions, 308 deletions
diff --git a/.travis.yml b/.travis.yml index cbf7bf9..9f8fb77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,10 @@ language: python python: - - "2.7" - - "3.4" - "3.5" - "3.6" - "3.7" - "3.8" - "nightly" - - "pypy" - "pypy3" matrix: @@ -1,7 +1,10 @@ Development Version ------------------- -Nothing yet. ¯\_(ツ)_/¯ +Notable Changes + +* Remove support for end-of-life Python 2.7 and 3.4. Python 3.5+ is now + required. Release 0.3.1 (Feb 29, 2020) @@ -9,13 +9,8 @@ python-sqlparse - Parse SQL statements sqlparse is a non-validating SQL parser for Python. It provides support for parsing, splitting and formatting SQL statements. -The module is compatible with Python 2.7 and Python 3 (>= 3.4) -and released under the terms of the `New BSD license -<https://opensource.org/licenses/BSD-3-Clause>`_. - -.. note:: - - Support for Python<3.4 (including 2.x) will be dropped soon. +The module is compatible with Python 3.5+ and released under the terms of the +`New BSD license <https://opensource.org/licenses/BSD-3-Clause>`_. Visit the project page at https://github.com/andialbrecht/sqlparse for further information about this project. diff --git a/docs/source/conf.py b/docs/source/conf.py index 70bd69a..a5be640 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- -# # python-sqlparse documentation build configuration file, created by # sphinx-quickstart on Thu Feb 26 08:19:28 2009. # diff --git a/docs/source/intro.rst b/docs/source/intro.rst index 330184a..41e4d23 100644 --- a/docs/source/intro.rst +++ b/docs/source/intro.rst @@ -120,7 +120,7 @@ To check out the latest sources of this module run to check out the latest sources from the repository. -:mod:`sqlparse` is currently tested under Python 2.7, >=3.4 and pypy. Tests are +:mod:`sqlparse` is currently tested under Python 3.5+ and pypy. Tests are automatically run on each commit and for each pull request on Travis: https://travis-ci.org/andialbrecht/sqlparse diff --git a/examples/column_defs_lowlevel.py b/examples/column_defs_lowlevel.py index 6bd5072..2c5f3b8 100644 --- a/examples/column_defs_lowlevel.py +++ b/examples/column_defs_lowlevel.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/examples/extract_table_names.py b/examples/extract_table_names.py index 8f0065e..4f6b4b0 100644 --- a/examples/extract_table_names.py +++ b/examples/extract_table_names.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -32,8 +31,7 @@ def extract_from_part(parsed): for item in parsed.tokens: if from_seen: if is_subselect(item): - for x in extract_from_part(item): - yield x + yield from extract_from_part(item) elif item.ttype is Keyword: return else: @@ -67,4 +65,4 @@ if __name__ == '__main__': """ tables = ', '.join(extract_tables(sql)) - print('Tables: {0}'.format(tables)) + print('Tables: {}'.format(tables)) @@ -1,15 +1,7 @@ -[bdist_wheel] -universal = 1 - -[metadata] -license_file = LICENSE - [tool:pytest] xfail_strict = True [flake8] -exclude = - sqlparse/compat.py extend-ignore = E731 @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -84,21 +83,21 @@ setup( description='Non-validating SQL parser', long_description=LONG_DESCRIPTION, license='BSD', - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", + python_requires=">=3.5", classifiers=[ 'Development Status :: 5 - Production/Stable', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Database', 'Topic :: Software Development', ], diff --git a/sqlparse/__init__.py b/sqlparse/__init__.py index b475061..5dcd982 100644 --- a/sqlparse/__init__.py +++ b/sqlparse/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -16,7 +15,6 @@ from sqlparse import tokens from sqlparse import filters from sqlparse import formatter -from sqlparse.compat import text_type __version__ = '0.3.2.dev0' __all__ = ['engine', 'filters', 'formatter', 'sql', 'tokens', 'cli'] @@ -58,7 +56,7 @@ def format(sql, encoding=None, **options): options = formatter.validate_options(options) stack = formatter.build_filter_stack(stack, options) stack.postprocess.append(filters.SerializerUnicode()) - return u''.join(stack.run(sql, encoding)) + return ''.join(stack.run(sql, encoding)) def split(sql, encoding=None): @@ -69,4 +67,4 @@ def split(sql, encoding=None): :returns: A list of strings. """ stack = engine.FilterStack() - return [text_type(stmt).strip() for stmt in stack.run(sql, encoding)] + return [str(stmt).strip() for stmt in stack.run(sql, encoding)] diff --git a/sqlparse/__main__.py b/sqlparse/__main__.py index 867d75d..3e6d325 100644 --- a/sqlparse/__main__.py +++ b/sqlparse/__main__.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/cli.py b/sqlparse/cli.py index 25555a5..957d220 100755 --- a/sqlparse/cli.py +++ b/sqlparse/cli.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -23,10 +22,8 @@ Why does this file exist, and why not put this in __main__? import argparse import sys from io import TextIOWrapper -from codecs import open, getreader import sqlparse -from sqlparse.compat import PY2 from sqlparse.exceptions import SQLParseError @@ -62,16 +59,16 @@ def create_parser(): metavar='CHOICE', dest='keyword_case', choices=_CASE_CHOICES, - help='change case of keywords, CHOICE is one of {0}'.format( - ', '.join('"{0}"'.format(x) for x in _CASE_CHOICES))) + help='change case of keywords, CHOICE is one of {}'.format( + ', '.join('"{}"'.format(x) for x in _CASE_CHOICES))) group.add_argument( '-i', '--identifiers', metavar='CHOICE', dest='identifier_case', choices=_CASE_CHOICES, - help='change case of identifiers, CHOICE is one of {0}'.format( - ', '.join('"{0}"'.format(x) for x in _CASE_CHOICES))) + help='change case of identifiers, CHOICE is one of {}'.format( + ', '.join('"{}"'.format(x) for x in _CASE_CHOICES))) group.add_argument( '-l', '--language', @@ -153,7 +150,7 @@ def create_parser(): def _error(msg): """Print msg and optionally exit with return code exit_.""" - sys.stderr.write(u'[ERROR] {0}\n'.format(msg)) + sys.stderr.write('[ERROR] {}\n'.format(msg)) return 1 @@ -162,29 +159,26 @@ def main(args=None): args = parser.parse_args(args) if args.filename == '-': # read from stdin - if PY2: - data = getreader(args.encoding)(sys.stdin).read() - else: - wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding) - try: - data = wrapper.read() - finally: - wrapper.detach() + wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding) + try: + data = wrapper.read() + finally: + wrapper.detach() else: try: - with open(args.filename, 'r', args.encoding) as f: + with open(args.filename, encoding=args.encoding) as f: data = ''.join(f.readlines()) - except IOError as e: + except OSError as e: return _error( - u'Failed to read {0}: {1}'.format(args.filename, e)) + 'Failed to read {}: {}'.format(args.filename, e)) close_stream = False if args.outfile: try: - stream = open(args.outfile, 'w', args.encoding) + stream = open(args.outfile, 'w', encoding=args.encoding) close_stream = True - except IOError as e: - return _error(u'Failed to open {0}: {1}'.format(args.outfile, e)) + except OSError as e: + return _error('Failed to open {}: {}'.format(args.outfile, e)) else: stream = sys.stdout @@ -192,7 +186,7 @@ def main(args=None): try: formatter_opts = sqlparse.formatter.validate_options(formatter_opts) except SQLParseError as e: - return _error(u'Invalid options: {0}'.format(e)) + return _error('Invalid options: {}'.format(e)) s = sqlparse.format(data, **formatter_opts) stream.write(s) diff --git a/sqlparse/compat.py b/sqlparse/compat.py deleted file mode 100644 index d2214be..0000000 --- a/sqlparse/compat.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2009-2018 the sqlparse authors and contributors -# <see AUTHORS file> -# -# This module is part of python-sqlparse and is released under -# the BSD License: https://opensource.org/licenses/BSD-3-Clause - -"""Python 2/3 compatibility. - -This module only exists to avoid a dependency on six -for very trivial stuff. We only need to take care of -string types, buffers and metaclasses. - -Parts of the code is copied directly from six: -https://bitbucket.org/gutworth/six -""" - -import sys -from io import TextIOBase - -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 - - -if PY3: - def unicode_compatible(cls): - return cls - - text_type = str - string_types = (str,) - from io import StringIO - file_types = (StringIO, TextIOBase) - - -elif PY2: - def unicode_compatible(cls): - cls.__unicode__ = cls.__str__ - cls.__str__ = lambda x: x.__unicode__().encode('utf-8') - return cls - - text_type = unicode - string_types = (str, unicode,) - from StringIO import StringIO - file_types = (file, StringIO, TextIOBase) diff --git a/sqlparse/engine/__init__.py b/sqlparse/engine/__init__.py index 0b3f3eb..67ecc6e 100644 --- a/sqlparse/engine/__init__.py +++ b/sqlparse/engine/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/engine/filter_stack.py b/sqlparse/engine/filter_stack.py index fc77fd6..295c2c1 100644 --- a/sqlparse/engine/filter_stack.py +++ b/sqlparse/engine/filter_stack.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -13,7 +12,7 @@ from sqlparse.engine import grouping from sqlparse.engine.statement_splitter import StatementSplitter -class FilterStack(object): +class FilterStack: def __init__(self): self.preprocess = [] self.stmtprocess = [] diff --git a/sqlparse/engine/grouping.py b/sqlparse/engine/grouping.py index e7a4211..e895ce0 100644 --- a/sqlparse/engine/grouping.py +++ b/sqlparse/engine/grouping.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/engine/statement_splitter.py b/sqlparse/engine/statement_splitter.py index 1e9af3c..fb22c65 100644 --- a/sqlparse/engine/statement_splitter.py +++ b/sqlparse/engine/statement_splitter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -9,7 +8,7 @@ from sqlparse import sql, tokens as T -class StatementSplitter(object): +class StatementSplitter: """Filter that split stream at individual statements""" def __init__(self): diff --git a/sqlparse/exceptions.py b/sqlparse/exceptions.py index 01e60f7..687c20c 100644 --- a/sqlparse/exceptions.py +++ b/sqlparse/exceptions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/filters/__init__.py b/sqlparse/filters/__init__.py index c60d84d..ced03ea 100644 --- a/sqlparse/filters/__init__.py +++ b/sqlparse/filters/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/filters/aligned_indent.py b/sqlparse/filters/aligned_indent.py index 85b11e5..445d022 100644 --- a/sqlparse/filters/aligned_indent.py +++ b/sqlparse/filters/aligned_indent.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -7,11 +6,10 @@ # the BSD License: https://opensource.org/licenses/BSD-3-Clause from sqlparse import sql, tokens as T -from sqlparse.compat import text_type from sqlparse.utils import offset, indent -class AlignedIndentFilter(object): +class AlignedIndentFilter: join_words = (r'((LEFT\s+|RIGHT\s+|FULL\s+)?' r'(INNER\s+|OUTER\s+|STRAIGHT\s+)?|' r'(CROSS\s+|NATURAL\s+)?)?JOIN\b') @@ -73,7 +71,7 @@ class AlignedIndentFilter(object): end_token = tlist.token_next_by(m=(T.Keyword, 'END'))[1] cases.append((None, [end_token])) - condition_width = [len(' '.join(map(text_type, cond))) if cond else 0 + condition_width = [len(' '.join(map(str, cond))) if cond else 0 for cond, _ in cases] max_cond_width = max(condition_width) @@ -82,8 +80,7 @@ class AlignedIndentFilter(object): stmt = cond[0] if cond else value[0] if i > 0: - tlist.insert_before(stmt, self.nl( - offset_ - len(text_type(stmt)))) + tlist.insert_before(stmt, self.nl(offset_ - len(str(stmt)))) if cond: ws = sql.Token(T.Whitespace, self.char * ( max_cond_width - condition_width[i])) @@ -110,7 +107,7 @@ class AlignedIndentFilter(object): ): token_indent = token.value.split()[0] else: - token_indent = text_type(token) + token_indent = str(token) tlist.insert_before(token, self.nl(token_indent)) tidx += 1 tidx, token = self._next_token(tlist, tidx) diff --git a/sqlparse/filters/others.py b/sqlparse/filters/others.py index 52b8617..ff04b0e 100644 --- a/sqlparse/filters/others.py +++ b/sqlparse/filters/others.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -10,7 +9,7 @@ from sqlparse import sql, tokens as T from sqlparse.utils import split_unquoted_newlines -class StripCommentsFilter(object): +class StripCommentsFilter: @staticmethod def _process(tlist): def get_next_comment(): @@ -45,7 +44,7 @@ class StripCommentsFilter(object): return stmt -class StripWhitespaceFilter(object): +class StripWhitespaceFilter: def _stripws(self, tlist): func_name = '_stripws_{cls}'.format(cls=type(tlist).__name__) func = getattr(self, func_name.lower(), self._stripws_default) @@ -90,7 +89,7 @@ class StripWhitespaceFilter(object): return stmt -class SpacesAroundOperatorsFilter(object): +class SpacesAroundOperatorsFilter: @staticmethod def _process(tlist): @@ -118,7 +117,7 @@ class SpacesAroundOperatorsFilter(object): # --------------------------- # postprocess -class SerializerUnicode(object): +class SerializerUnicode: @staticmethod def process(stmt): lines = split_unquoted_newlines(stmt) diff --git a/sqlparse/filters/output.py b/sqlparse/filters/output.py index 3fbc46d..f34b29f 100644 --- a/sqlparse/filters/output.py +++ b/sqlparse/filters/output.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -7,10 +6,9 @@ # the BSD License: https://opensource.org/licenses/BSD-3-Clause from sqlparse import sql, tokens as T -from sqlparse.compat import text_type -class OutputFilter(object): +class OutputFilter: varname_prefix = '' def __init__(self, varname='sql'): @@ -23,11 +21,11 @@ class OutputFilter(object): def process(self, stmt): self.count += 1 if self.count > 1: - varname = u'{f.varname}{f.count}'.format(f=self) + varname = '{f.varname}{f.count}'.format(f=self) else: varname = self.varname - has_nl = len(text_type(stmt).strip().splitlines()) > 1 + has_nl = len(str(stmt).strip().splitlines()) > 1 stmt.tokens = self._process(stmt.tokens, varname, has_nl) return stmt diff --git a/sqlparse/filters/reindent.py b/sqlparse/filters/reindent.py index acec8ca..2b0f106 100644 --- a/sqlparse/filters/reindent.py +++ b/sqlparse/filters/reindent.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -7,11 +6,10 @@ # the BSD License: https://opensource.org/licenses/BSD-3-Clause from sqlparse import sql, tokens as T -from sqlparse.compat import text_type from sqlparse.utils import offset, indent -class ReindentFilter(object): +class ReindentFilter: def __init__(self, width=2, char=' ', wrap_after=0, n='\n', comma_first=False, indent_after_first=False, indent_columns=False): @@ -42,7 +40,7 @@ class ReindentFilter(object): return self.offset + self.indent * self.width def _get_offset(self, token): - raw = u''.join(map(text_type, self._flatten_up_to_token(token))) + raw = ''.join(map(str, self._flatten_up_to_token(token))) line = (raw or '\n').splitlines()[-1] # Now take current offset into account and return relative offset. return len(line) - len(self.char * self.leading_ws) @@ -71,7 +69,7 @@ class ReindentFilter(object): tidx, token = self._next_token(tlist) while token: pidx, prev_ = tlist.token_prev(tidx, skip_ws=False) - uprev = text_type(prev_) + uprev = str(prev_) if prev_ and prev_.is_whitespace: del tlist.tokens[pidx] @@ -234,7 +232,7 @@ class ReindentFilter(object): self._process(stmt) if self._last_stmt is not None: - nl = '\n' if text_type(self._last_stmt).endswith('\n') else '\n\n' + nl = '\n' if str(self._last_stmt).endswith('\n') else '\n\n' stmt.tokens.insert(0, sql.Token(T.Whitespace, nl)) self._last_stmt = stmt diff --git a/sqlparse/filters/right_margin.py b/sqlparse/filters/right_margin.py index 1658138..e263718 100644 --- a/sqlparse/filters/right_margin.py +++ b/sqlparse/filters/right_margin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -9,11 +8,10 @@ import re from sqlparse import sql, tokens as T -from sqlparse.compat import text_type # FIXME: Doesn't work -class RightMarginFilter(object): +class RightMarginFilter: keep_together = ( # sql.TypeCast, sql.Identifier, sql.Alias, ) @@ -32,14 +30,14 @@ class RightMarginFilter(object): elif token.is_group and type(token) not in self.keep_together: token.tokens = self._process(token, token.tokens) else: - val = text_type(token) + val = str(token) if len(self.line) + len(val) > self.width: match = re.search(r'^ +', self.line) if match is not None: indent = match.group() else: indent = '' - yield sql.Token(T.Whitespace, '\n{0}'.format(indent)) + yield sql.Token(T.Whitespace, '\n{}'.format(indent)) self.line = indent self.line += val yield token diff --git a/sqlparse/filters/tokens.py b/sqlparse/filters/tokens.py index 93182b1..a40f4b0 100644 --- a/sqlparse/filters/tokens.py +++ b/sqlparse/filters/tokens.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -7,15 +6,14 @@ # the BSD License: https://opensource.org/licenses/BSD-3-Clause from sqlparse import tokens as T -from sqlparse.compat import text_type -class _CaseFilter(object): +class _CaseFilter: ttype = None def __init__(self, case=None): case = case or 'upper' - self.convert = getattr(text_type, case) + self.convert = getattr(str, case) def process(self, stream): for ttype, value in stream: @@ -38,7 +36,7 @@ class IdentifierCaseFilter(_CaseFilter): yield ttype, value -class TruncateStringFilter(object): +class TruncateStringFilter: def __init__(self, width, char): self.width = width self.char = char diff --git a/sqlparse/formatter.py b/sqlparse/formatter.py index 8962759..8016f87 100644 --- a/sqlparse/formatter.py +++ b/sqlparse/formatter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -17,32 +16,32 @@ def validate_options(options): kwcase = options.get('keyword_case') if kwcase not in [None, 'upper', 'lower', 'capitalize']: raise SQLParseError('Invalid value for keyword_case: ' - '{0!r}'.format(kwcase)) + '{!r}'.format(kwcase)) idcase = options.get('identifier_case') if idcase not in [None, 'upper', 'lower', 'capitalize']: raise SQLParseError('Invalid value for identifier_case: ' - '{0!r}'.format(idcase)) + '{!r}'.format(idcase)) ofrmt = options.get('output_format') if ofrmt not in [None, 'sql', 'python', 'php']: raise SQLParseError('Unknown output format: ' - '{0!r}'.format(ofrmt)) + '{!r}'.format(ofrmt)) strip_comments = options.get('strip_comments', False) if strip_comments not in [True, False]: raise SQLParseError('Invalid value for strip_comments: ' - '{0!r}'.format(strip_comments)) + '{!r}'.format(strip_comments)) space_around_operators = options.get('use_space_around_operators', False) if space_around_operators not in [True, False]: raise SQLParseError('Invalid value for use_space_around_operators: ' - '{0!r}'.format(space_around_operators)) + '{!r}'.format(space_around_operators)) strip_ws = options.get('strip_whitespace', False) if strip_ws not in [True, False]: raise SQLParseError('Invalid value for strip_whitespace: ' - '{0!r}'.format(strip_ws)) + '{!r}'.format(strip_ws)) truncate_strings = options.get('truncate_strings') if truncate_strings is not None: @@ -50,17 +49,17 @@ def validate_options(options): truncate_strings = int(truncate_strings) except (ValueError, TypeError): raise SQLParseError('Invalid value for truncate_strings: ' - '{0!r}'.format(truncate_strings)) + '{!r}'.format(truncate_strings)) if truncate_strings <= 1: raise SQLParseError('Invalid value for truncate_strings: ' - '{0!r}'.format(truncate_strings)) + '{!r}'.format(truncate_strings)) options['truncate_strings'] = truncate_strings options['truncate_char'] = options.get('truncate_char', '[...]') indent_columns = options.get('indent_columns', False) if indent_columns not in [True, False]: raise SQLParseError('Invalid value for indent_columns: ' - '{0!r}'.format(indent_columns)) + '{!r}'.format(indent_columns)) elif indent_columns: options['reindent'] = True # enforce reindent options['indent_columns'] = indent_columns @@ -68,27 +67,27 @@ def validate_options(options): reindent = options.get('reindent', False) if reindent not in [True, False]: raise SQLParseError('Invalid value for reindent: ' - '{0!r}'.format(reindent)) + '{!r}'.format(reindent)) elif reindent: options['strip_whitespace'] = True reindent_aligned = options.get('reindent_aligned', False) if reindent_aligned not in [True, False]: raise SQLParseError('Invalid value for reindent_aligned: ' - '{0!r}'.format(reindent)) + '{!r}'.format(reindent)) elif reindent_aligned: options['strip_whitespace'] = True indent_after_first = options.get('indent_after_first', False) if indent_after_first not in [True, False]: raise SQLParseError('Invalid value for indent_after_first: ' - '{0!r}'.format(indent_after_first)) + '{!r}'.format(indent_after_first)) options['indent_after_first'] = indent_after_first indent_tabs = options.get('indent_tabs', False) if indent_tabs not in [True, False]: raise SQLParseError('Invalid value for indent_tabs: ' - '{0!r}'.format(indent_tabs)) + '{!r}'.format(indent_tabs)) elif indent_tabs: options['indent_char'] = '\t' else: diff --git a/sqlparse/keywords.py b/sqlparse/keywords.py index 9c37e50..3123531 100644 --- a/sqlparse/keywords.py +++ b/sqlparse/keywords.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/lexer.py b/sqlparse/lexer.py index fd007a4..836d53d 100644 --- a/sqlparse/lexer.py +++ b/sqlparse/lexer.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -13,13 +12,14 @@ # It's separated from the rest of pygments to increase performance # and to allow some customizations. +from io import TextIOBase + from sqlparse import tokens from sqlparse.keywords import SQL_REGEX -from sqlparse.compat import text_type, file_types from sqlparse.utils import consume -class Lexer(object): +class Lexer: """Lexer Empty class. Leaving for backwards-compatibility """ @@ -38,10 +38,10 @@ class Lexer(object): ``stack`` is the initial stack (default: ``['root']``) """ - if isinstance(text, file_types): + if isinstance(text, TextIOBase): text = text.read() - if isinstance(text, text_type): + if isinstance(text, str): pass elif isinstance(text, bytes): if encoding: @@ -52,7 +52,7 @@ class Lexer(object): except UnicodeDecodeError: text = text.decode('unicode-escape') else: - raise TypeError(u"Expected text or file-like object, got {!r}". + raise TypeError("Expected text or file-like object, got {!r}". format(type(text))) iterable = enumerate(text) diff --git a/sqlparse/sql.py b/sqlparse/sql.py index a942bcd..a9e11da 100644 --- a/sqlparse/sql.py +++ b/sqlparse/sql.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -7,12 +6,10 @@ # the BSD License: https://opensource.org/licenses/BSD-3-Clause """This module contains classes representing syntactical elements of SQL.""" -from __future__ import print_function import re from sqlparse import tokens as T -from sqlparse.compat import string_types, text_type, unicode_compatible from sqlparse.utils import imt, remove_quotes @@ -39,8 +36,7 @@ class NameAliasMixin: return self._get_first_name(reverse=True) -@unicode_compatible -class Token(object): +class Token: """Base class for all other classes in this module. It represents a single token and has two instance attributes: @@ -52,7 +48,7 @@ class Token(object): 'is_group', 'is_whitespace') def __init__(self, ttype, value): - value = text_type(value) + value = str(value) self.value = value self.ttype = ttype self.parent = None @@ -72,15 +68,15 @@ class Token(object): cls = self._get_repr_name() value = self._get_repr_value() - q = u'"' if value.startswith("'") and value.endswith("'") else u"'" - return u"<{cls} {q}{value}{q} at 0x{id:2X}>".format( + q = '"' if value.startswith("'") and value.endswith("'") else "'" + return "<{cls} {q}{value}{q} at 0x{id:2X}>".format( id=id(self), **locals()) def _get_repr_name(self): return str(self.ttype).split('.')[-1] def _get_repr_value(self): - raw = text_type(self) + raw = str(self) if len(raw) > 7: raw = raw[:6] + '...' return re.sub(r'\s+', ' ', raw) @@ -105,7 +101,7 @@ class Token(object): if not type_matched or values is None: return type_matched - if isinstance(values, string_types): + if isinstance(values, str): values = (values,) if regex: @@ -150,7 +146,6 @@ class Token(object): return False -@unicode_compatible class TokenList(Token): """A group of tokens. @@ -163,11 +158,11 @@ class TokenList(Token): def __init__(self, tokens=None): self.tokens = tokens or [] [setattr(token, 'parent', self) for token in self.tokens] - super(TokenList, self).__init__(None, text_type(self)) + super().__init__(None, str(self)) self.is_group = True def __str__(self): - return u''.join(token.value for token in self.flatten()) + return ''.join(token.value for token in self.flatten()) # weird bug # def __len__(self): @@ -190,14 +185,14 @@ class TokenList(Token): value = token._get_repr_value() last = idx == (token_count - 1) - pre = u'`- ' if last else u'|- ' + pre = '`- ' if last else '|- ' - q = u'"' if value.startswith("'") and value.endswith("'") else u"'" - print(u"{_pre}{pre}{idx} {cls} {q}{value}{q}" + q = '"' if value.startswith("'") and value.endswith("'") else "'" + print("{_pre}{pre}{idx} {cls} {q}{value}{q}" .format(**locals()), file=f) if token.is_group and (max_depth is None or depth < max_depth): - parent_pre = u' ' if last else u'| ' + parent_pre = ' ' if last else '| ' token._pprint_tree(max_depth, depth + 1, f, _pre + parent_pre) def get_token_at_offset(self, offset): @@ -216,8 +211,7 @@ class TokenList(Token): """ for token in self.tokens: if token.is_group: - for item in token.flatten(): - yield item + yield from token.flatten() else: yield token @@ -328,7 +322,7 @@ class TokenList(Token): grp = start grp.tokens.extend(subtokens) del self.tokens[start_idx + 1:end_idx] - grp.value = text_type(start) + grp.value = str(start) else: subtokens = self.tokens[start_idx:end_idx] grp = grp_cls(subtokens) diff --git a/sqlparse/tokens.py b/sqlparse/tokens.py index eefc0b4..193d100 100644 --- a/sqlparse/tokens.py +++ b/sqlparse/tokens.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> diff --git a/sqlparse/utils.py b/sqlparse/utils.py index 3283274..265378b 100644 --- a/sqlparse/utils.py +++ b/sqlparse/utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Copyright (C) 2009-2018 the sqlparse authors and contributors # <see AUTHORS file> @@ -10,7 +9,6 @@ import itertools import re from collections import deque from contextlib import contextmanager -from sqlparse.compat import text_type # This regular expression replaces the home-cooked parser that was here before. # It is much faster, but requires an extra post-processing step to get the @@ -40,7 +38,7 @@ def split_unquoted_newlines(stmt): Unlike str.splitlines(), this will ignore CR/LF/CR+LF if the requisite character is inside of a string.""" - text = text_type(stmt) + text = str(stmt) lines = SPLIT_REGEX.split(text) outputlines = [''] for line in lines: diff --git a/tests/conftest.py b/tests/conftest.py index f2473a4..939c481 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - """Helpers for testing.""" import io @@ -35,7 +33,7 @@ def load_file(filepath): # https://stackoverflow.com/questions/18011902/py-test-pass-a-parameter-to-a-fixture-function/33879151#33879151 # Syntax is noisy and requires specific variable names # And seems to be limited to only 1 argument. - with io.open(filepath(filename), encoding=encoding) as f: + with open(filepath(filename), encoding=encoding) as f: return f.read().strip() return make_load_file @@ -44,6 +42,6 @@ def load_file(filepath): @pytest.fixture() def get_stream(filepath): def make_stream(filename, encoding='utf-8'): - return io.open(filepath(filename), encoding=encoding) + return open(filepath(filename), encoding=encoding) return make_stream diff --git a/tests/test_cli.py b/tests/test_cli.py index 5f1ea0e..f1c005d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import subprocess import sys @@ -71,75 +69,56 @@ def test_stdout(filepath, load_file, capsys): def test_script(): # Call with the --help option as a basic sanity check. - cmd = "{0:s} -m sqlparse.cli --help".format(sys.executable) + cmd = "{:s} -m sqlparse.cli --help".format(sys.executable) assert subprocess.call(cmd.split()) == 0 -def test_encoding_utf8_stdout(filepath, load_file, capfd): - path = filepath('encoding_utf8.sql') - expected = load_file('encoding_utf8.sql', 'utf-8') - sys.stdout.encoding = 'utf-8' - sqlparse.cli.main([path]) - out, _ = capfd.readouterr() - assert out == expected - - -def test_encoding_utf8_output_file(filepath, load_file, tmpdir): - in_path = filepath('encoding_utf8.sql') - expected = load_file('encoding_utf8.sql', 'utf-8') - out_path = tmpdir.dirname + '/encoding_utf8.out.sql' - sqlparse.cli.main([in_path, '-o', out_path]) - out = load_file(out_path, 'utf-8') - assert out == expected - - -def test_encoding_gbk_stdout(filepath, load_file, capfd): - path = filepath('encoding_gbk.sql') - expected = load_file('encoding_gbk.sql', 'gbk') - sys.stdout.encoding = 'gbk' - sqlparse.cli.main([path, '--encoding', 'gbk']) +@pytest.mark.parametrize('fpath, encoding', ( + ('encoding_utf8.sql', 'utf-8'), + ('encoding_gbk.sql', 'gbk'), +)) +def test_encoding_stdout(fpath, encoding, filepath, load_file, capfd): + path = filepath(fpath) + expected = load_file(fpath, encoding) + sys.stdout.reconfigure(encoding=encoding) + sqlparse.cli.main([path, '--encoding', encoding]) out, _ = capfd.readouterr() assert out == expected -def test_encoding_gbk_output_file(filepath, load_file, tmpdir): - in_path = filepath('encoding_gbk.sql') - expected = load_file('encoding_gbk.sql', 'gbk') - out_path = tmpdir.dirname + '/encoding_gbk.out.sql' - sqlparse.cli.main([in_path, '--encoding', 'gbk', '-o', out_path]) - out = load_file(out_path, 'gbk') +@pytest.mark.parametrize('fpath, encoding', ( + ('encoding_utf8.sql', 'utf-8'), + ('encoding_gbk.sql', 'gbk'), +)) +def test_encoding_output_file(fpath, encoding, filepath, load_file, tmpdir): + in_path = filepath(fpath) + expected = load_file(fpath, encoding) + out_path = tmpdir.dirname + '/encoding_out.sql' + sqlparse.cli.main([in_path, '--encoding', encoding, '-o', out_path]) + out = load_file(out_path, encoding) assert out == expected -def test_encoding_stdin_utf8(filepath, load_file, capfd): - path = filepath('encoding_utf8.sql') - expected = load_file('encoding_utf8.sql', 'utf-8') +@pytest.mark.parametrize('fpath, encoding', ( + ('encoding_utf8.sql', 'utf-8'), + ('encoding_gbk.sql', 'gbk'), +)) +def test_encoding_stdin(fpath, encoding, filepath, load_file, capfd): + path = filepath(fpath) + expected = load_file(fpath, encoding) old_stdin = sys.stdin - with open(path, 'r') as f: + with open(path) as f: sys.stdin = f - sys.stdout.encoding = 'utf-8' - sqlparse.cli.main(['-']) + sys.stdout.reconfigure(encoding=encoding) + sqlparse.cli.main(['-', '--encoding', encoding]) sys.stdin = old_stdin out, _ = capfd.readouterr() assert out == expected -def test_encoding_stdin_gbk(filepath, load_file, capfd): - path = filepath('encoding_gbk.sql') - expected = load_file('encoding_gbk.sql', 'gbk') - old_stdin = sys.stdin - with open(path, 'r') as stream: - sys.stdin = stream - sys.stdout.encoding = 'gbk' - sqlparse.cli.main(['-', '--encoding', 'gbk']) - sys.stdin = old_stdin - out, _ = capfd.readouterr() - assert out == expected - - def test_encoding(filepath, capsys): path = filepath('test_cp1251.sql') - expected = u'insert into foo values (1); -- Песня про надежду\n' + expected = 'insert into foo values (1); -- Песня про надежду\n' sqlparse.cli.main([path, '--encoding=cp1251']) out, _ = capsys.readouterr() assert out == expected diff --git a/tests/test_format.py b/tests/test_format.py index 811e083..20390ff 100644 --- a/tests/test_format.py +++ b/tests/test_format.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- - import pytest import sqlparse from sqlparse.exceptions import SQLParseError -class TestFormat(object): +class TestFormat: def test_keywordcase(self): sql = 'select * from bar; -- select foo\n' res = sqlparse.format(sql, keyword_case='upper') @@ -123,7 +121,7 @@ class TestFormat(object): == "SELECT some_column LIKE 'value\\\\\\'\r' WHERE id = 1\n") -class TestFormatReindentAligned(object): +class TestFormatReindentAligned: @staticmethod def formatter(sql): return sqlparse.format(sql, reindent_aligned=True) @@ -294,7 +292,7 @@ class TestFormatReindentAligned(object): ' from table']) -class TestSpacesAroundOperators(object): +class TestSpacesAroundOperators: @staticmethod def formatter(sql): return sqlparse.format(sql, use_space_around_operators=True) @@ -321,7 +319,7 @@ class TestSpacesAroundOperators(object): assert self.formatter(sql) == 'select a * b - c from table' -class TestFormatReindent(object): +class TestFormatReindent: def test_option(self): with pytest.raises(SQLParseError): sqlparse.format('foo', reindent=2) @@ -598,7 +596,7 @@ class TestFormatReindent(object): ' , (5, 6)']) -class TestOutputFormat(object): +class TestOutputFormat: def test_python(self): sql = 'select * from foo;' f = lambda sql: sqlparse.format(sql, output_format='python') @@ -663,7 +661,7 @@ def test_format_column_ordering(): def test_truncate_strings(): - sql = "update foo set value = '{0}';".format('x' * 1000) + sql = "update foo set value = '{}';".format('x' * 1000) formatted = sqlparse.format(sql, truncate_strings=10) assert formatted == "update foo set value = 'xxxxxxxxxx[...]';" formatted = sqlparse.format(sql, truncate_strings=3, truncate_char='YYY') diff --git a/tests/test_grouping.py b/tests/test_grouping.py index 87dcf11..683954e 100644 --- a/tests/test_grouping.py +++ b/tests/test_grouping.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import pytest import sqlparse @@ -484,7 +482,7 @@ def test_comparison_with_parenthesis(): )) def test_comparison_with_strings(operator): # issue148 - p = sqlparse.parse("foo {0} 'bar'".format(operator))[0] + p = sqlparse.parse("foo {} 'bar'".format(operator))[0] assert len(p.tokens) == 1 assert isinstance(p.tokens[0], sql.Comparison) assert p.tokens[0].right.value == "'bar'" @@ -563,7 +561,7 @@ def test_comparison_with_typed_literal(): @pytest.mark.parametrize('start', ['FOR', 'FOREACH']) def test_forloops(start): - p = sqlparse.parse('{0} foo in bar LOOP foobar END LOOP'.format(start))[0] + p = sqlparse.parse('{} foo in bar LOOP foobar END LOOP'.format(start))[0] assert (len(p.tokens)) == 1 assert isinstance(p.tokens[0], sql.For) diff --git a/tests/test_keywords.py b/tests/test_keywords.py index c197f36..d4ded4b 100644 --- a/tests/test_keywords.py +++ b/tests/test_keywords.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pytest from sqlparse import tokens diff --git a/tests/test_parse.py b/tests/test_parse.py index c28cb06..6cce909 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -1,12 +1,10 @@ -# -*- coding: utf-8 -*- - """Tests sqlparse.parse().""" +from io import StringIO import pytest import sqlparse from sqlparse import sql, tokens as T -from sqlparse.compat import StringIO, text_type def test_parse_tokenize(): @@ -409,26 +407,26 @@ def test_dbldollar_as_literal(sql, is_literal): def test_non_ascii(): - _test_non_ascii = u"insert into test (id, name) values (1, 'тест');" + _test_non_ascii = "insert into test (id, name) values (1, 'тест');" s = _test_non_ascii stmts = sqlparse.parse(s) assert len(stmts) == 1 statement = stmts[0] - assert text_type(statement) == s + assert str(statement) == s assert statement._pprint_tree() is None s = _test_non_ascii.encode('utf-8') stmts = sqlparse.parse(s, 'utf-8') assert len(stmts) == 1 statement = stmts[0] - assert text_type(statement) == _test_non_ascii + assert str(statement) == _test_non_ascii assert statement._pprint_tree() is None def test_get_real_name(): # issue 369 - s = u"update a t set t.b=1" + s = "update a t set t.b=1" stmts = sqlparse.parse(s) assert len(stmts) == 1 assert 'a' == stmts[0].tokens[2].get_real_name() @@ -437,14 +435,14 @@ def test_get_real_name(): def test_from_subquery(): # issue 446 - s = u'from(select 1)' + s = 'from(select 1)' stmts = sqlparse.parse(s) assert len(stmts) == 1 assert len(stmts[0].tokens) == 2 assert stmts[0].tokens[0].value == 'from' assert stmts[0].tokens[0].ttype == T.Keyword - s = u'from (select 1)' + s = 'from (select 1)' stmts = sqlparse.parse(s) assert len(stmts) == 1 assert len(stmts[0].tokens) == 3 diff --git a/tests/test_regressions.py b/tests/test_regressions.py index 2ed0ff3..648cc4a 100644 --- a/tests/test_regressions.py +++ b/tests/test_regressions.py @@ -1,10 +1,7 @@ -# -*- coding: utf-8 -*- - import pytest import sqlparse from sqlparse import sql, tokens as T -from sqlparse.compat import PY2 def test_issue9(): @@ -20,9 +17,9 @@ def test_issue9(): def test_issue13(): - parsed = sqlparse.parse(("select 'one';\n" - "select 'two\\'';\n" - "select 'three';")) + parsed = sqlparse.parse("select 'one';\n" + "select 'two\\'';\n" + "select 'three';") assert len(parsed) == 3 assert str(parsed[1]).strip() == "select 'two\\'';" @@ -73,8 +70,8 @@ def test_issue39(): def test_issue40(): # make sure identifier lists in subselects are grouped - p = sqlparse.parse(('SELECT id, name FROM ' - '(SELECT id, name FROM bar) as foo'))[0] + p = sqlparse.parse('SELECT id, name FROM ' + '(SELECT id, name FROM bar) as foo')[0] assert len(p.tokens) == 7 assert p.tokens[2].__class__ == sql.IdentifierList assert p.tokens[-1].__class__ == sql.Identifier @@ -149,7 +146,7 @@ def test_issue83(): def test_comment_encoding_when_reindent(): # There was an UnicodeEncodeError in the reindent filter that # casted every comment followed by a keyword to str. - sql = u'select foo -- Comment containing Ümläuts\nfrom bar' + sql = 'select foo -- Comment containing Ümläuts\nfrom bar' formatted = sqlparse.format(sql, reindent=True) assert formatted == sql @@ -158,11 +155,9 @@ def test_parse_sql_with_binary(): # See https://github.com/andialbrecht/sqlparse/pull/88 # digest = '|ËêplL4¡høN{' digest = '\x82|\xcb\x0e\xea\x8aplL4\xa1h\x91\xf8N{' - sql = "select * from foo where bar = '{0}'".format(digest) + sql = "select * from foo where bar = '{}'".format(digest) formatted = sqlparse.format(sql, reindent=True) - tformatted = "select *\nfrom foo\nwhere bar = '{0}'".format(digest) - if PY2: - tformatted = tformatted.decode('unicode-escape') + tformatted = "select *\nfrom foo\nwhere bar = '{}'".format(digest) assert formatted == tformatted @@ -180,7 +175,7 @@ def test_format_accepts_encoding(load_file): # issue20 sql = load_file('test_cp1251.sql', 'cp1251') formatted = sqlparse.format(sql, reindent=True, encoding='cp1251') - tformatted = u'insert into foo\nvalues (1); -- Песня про надежду' + tformatted = 'insert into foo\nvalues (1); -- Песня про надежду' assert formatted == tformatted @@ -275,7 +270,7 @@ def test_issue186_get_type(): def test_issue212_py2unicode(): - t1 = sql.Token(T.String, u'schöner ') + t1 = sql.Token(T.String, 'schöner ') t2 = sql.Token(T.String, 'bug') token_list = sql.TokenList([t1, t2]) assert str(token_list) == 'schöner bug' @@ -337,11 +332,9 @@ def test_issue315_utf8_by_default(): '\x9b\xb2.' '\xec\x82\xac\xeb\x9e\x91\xed\x95\xb4\xec\x9a\x94' ) - sql = "select * from foo where bar = '{0}'".format(digest) + sql = "select * from foo where bar = '{}'".format(digest) formatted = sqlparse.format(sql, reindent=True) - tformatted = "select *\nfrom foo\nwhere bar = '{0}'".format(digest) - if PY2: - tformatted = tformatted.decode('utf-8') + tformatted = "select *\nfrom foo\nwhere bar = '{}'".format(digest) assert formatted == tformatted diff --git a/tests/test_split.py b/tests/test_split.py index a93e3d4..8214756 100644 --- a/tests/test_split.py +++ b/tests/test_split.py @@ -1,13 +1,11 @@ -# -*- coding: utf-8 -*- - # Tests splitting functions. import types +from io import StringIO import pytest import sqlparse -from sqlparse.compat import StringIO, text_type def test_split_semicolon(): @@ -33,7 +31,7 @@ def test_split_create_function(load_file, fn): sql = load_file(fn) stmts = sqlparse.parse(sql) assert len(stmts) == 1 - assert text_type(stmts[0]) == sql + assert str(stmts[0]) == sql def test_split_dashcomments(load_file): @@ -74,12 +72,12 @@ def test_split_dropif(): def test_split_comment_with_umlaut(): - sql = (u'select * from foo;\n' - u'-- Testing an umlaut: ä\n' - u'select * from bar;') + sql = ('select * from foo;\n' + '-- Testing an umlaut: ä\n' + 'select * from bar;') stmts = sqlparse.parse(sql) assert len(stmts) == 2 - assert ''.join(text_type(q) for q in stmts) == sql + assert ''.join(str(q) for q in stmts) == sql def test_split_comment_end_of_line(): @@ -125,11 +123,11 @@ def test_split_stream(): def test_split_encoding_parsestream(): stream = StringIO("SELECT 1; SELECT 2;") stmts = list(sqlparse.parsestream(stream)) - assert isinstance(stmts[0].tokens[0].value, text_type) + assert isinstance(stmts[0].tokens[0].value, str) def test_split_unicode_parsestream(): - stream = StringIO(u'SELECT ö') + stream = StringIO('SELECT ö') stmts = list(sqlparse.parsestream(stream)) assert str(stmts[0]) == 'SELECT ö' diff --git a/tests/test_tokenize.py b/tests/test_tokenize.py index 3e8831b..0d7f878 100644 --- a/tests/test_tokenize.py +++ b/tests/test_tokenize.py @@ -1,13 +1,11 @@ -# -*- coding: utf-8 -*- - import types +from io import StringIO import pytest import sqlparse from sqlparse import lexer from sqlparse import sql, tokens as T -from sqlparse.compat import StringIO def test_tokenize_simple(): @@ -152,7 +150,7 @@ def test_stream_error(): 'INNER JOIN', 'LEFT INNER JOIN']) def test_parse_join(expr): - p = sqlparse.parse('{0} foo'.format(expr))[0] + p = sqlparse.parse('{} foo'.format(expr))[0] assert len(p.tokens) == 3 assert p.tokens[0].ttype is T.Keyword @@ -1,22 +1,17 @@ [tox] skip_missing_interpreters = True envlist = - py27 - py34 py35 py36 py37 py38 - pypy_54 + pypy3 flake8 [testenv] deps = pytest pytest-cov - pytest-travis-fold -passenv = - TRAVIS commands = sqlformat --version pytest --cov=sqlparse {posargs} |
