[Python-modules-commits] [sqlparse] 01/04: New upstream version 0.2.3
Andriy Senkovych
jollyroger-guest at moszumanska.debian.org
Sat Jul 15 00:02:55 UTC 2017
This is an automated email from the git hooks/post-receive script.
jollyroger-guest pushed a commit to branch master
in repository sqlparse.
commit 430a5996cdab9f3445331451bd4cbd7aa4e5efb1
Author: Andriy Senkovych <jolly_roger at itblog.org.ua>
Date: Sat Jul 15 02:21:39 2017 +0300
New upstream version 0.2.3
---
AUTHORS | 4 +++
CHANGELOG | 19 ++++++++++++
LICENSE | 25 ++++++++++++++++
MANIFEST.in | 4 +--
PKG-INFO | 3 +-
README.rst | 10 ++++++-
setup.cfg | 3 +-
setup.py | 1 +
sqlparse.egg-info/PKG-INFO | 3 +-
sqlparse.egg-info/SOURCES.txt | 3 ++
sqlparse/__init__.py | 2 +-
sqlparse/cli.py | 21 +++++++++----
sqlparse/engine/grouping.py | 2 +-
sqlparse/filters/reindent.py | 10 ++++---
sqlparse/keywords.py | 6 ++--
sqlparse/lexer.py | 11 +++----
sqlparse/sql.py | 2 +-
tests/files/encoding_gbk.sql | 3 ++
tests/files/encoding_utf8.sql | 3 ++
tests/test_cli.py | 68 +++++++++++++++++++++++++++++++++++++++++++
tests/test_grouping.py | 18 ++++++++++++
tests/test_regressions.py | 48 ++++++++++++++++++++++++++----
tox.ini | 16 +++++-----
23 files changed, 245 insertions(+), 40 deletions(-)
diff --git a/AUTHORS b/AUTHORS
index b8dd119..9019cb4 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -21,6 +21,7 @@ Alphabetical list of contributors:
* Gavin Wahl <gwahl at fusionbox.com>
* JacekPliszka <Jacek.Pliszka at gmail.com>
* Jesús Leganés Combarro "Piranna" <piranna at gmail.com>
+* Jon Dufresne <jon.dufresne at gmail.com>
* Kevin Jing Qiu <kevin.jing.qiu at gmail.com>
* koljonen <koljonen at outlook.com>
* Michael Schuller <chick at mschuller.net>
@@ -31,11 +32,14 @@ Alphabetical list of contributors:
* quest <quest at wonky.windwards.net>
* Robert Nix <com.github at rnix.org>
* Rocky Meza <rmeza at fusionbox.com>
+* Romain Rigaux <romain.rigaux at gmail.com>
+* Rowan Seymour <rowanseymour at gmail.com>
* Ryan Wooden <rygwdn at gmail.com>
* saaj <id at saaj.me>
* Shen Longxing <shenlongxing2012 at gmail.com>
* Sjoerd Job Postmus
* spigwitmer <itgpmc at gmail.com>
+* Tao Wang <twang2218 at gmail.com>
* Tenghuan <tenghuanhe at gmail.com>
* Tim Graham <timograham at gmail.com>
* Victor Hahn <info at victor-hahn.de>
diff --git a/CHANGELOG b/CHANGELOG
index 88e3a8b..9c75e7f 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,22 @@
+Release 0.2.3 (Mar 02, 2017)
+----------------------------
+
+Enhancements
+
+* New command line option "--encoding" (by twang2218, pr317).
+* Support CONCURRENTLY keyword (issue322, by rowanseymour).
+
+Bug Fixes
+
+* Fix some edge-cases when parsing invalid SQL statements.
+* Fix indentation of LIMIT (by romainr, issue320).
+* Fix parsing of INTO keyword (issue324).
+
+Internal Changes
+
+* Several improvements regarding encodings.
+
+
Release 0.2.2 (Oct 22, 2016)
----------------------------
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..de414c5
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2016, Andi Albrecht <albrecht.andi at gmail.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the authors nor the names of its contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
index 585ab3b..8043b35 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,10 +2,10 @@ recursive-include docs source/*
include docs/sqlformat.1
include docs/Makefile
recursive-include tests *.py *.sql
-include COPYING
+include LICENSE
include TODO
include AUTHORS
include CHANGELOG
include Makefile
-include pytest.ini
+include setup.cfg
include tox.ini
diff --git a/PKG-INFO b/PKG-INFO
index 79637ee..06d0e0d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: sqlparse
-Version: 0.2.2
+Version: 0.2.3
Summary: Non-validating SQL parser
Home-page: https://github.com/andialbrecht/sqlparse
Author: Andi Albrecht
@@ -68,5 +68,6 @@ Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Database
Classifier: Topic :: Software Development
diff --git a/README.rst b/README.rst
index f397c01..06b9e03 100644
--- a/README.rst
+++ b/README.rst
@@ -10,7 +10,15 @@ sqlparse is a non-validating SQL parser module for Python.
Install
-------
-Run::
+From pip, run::
+
+ $ pip install --upgrade sqlparse
+
+Consider using the ``--user`` option_.
+
+.. _option: https://pip.pypa.io/en/latest/user_guide/#user-installs
+
+From the repository, run::
python setup.py install
diff --git a/setup.cfg b/setup.cfg
index cb71d1c..b1b8a41 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,7 +1,7 @@
[wheel]
universal = 1
-[pytest]
+[tool:pytest]
xfail_strict = True
[flake8]
@@ -19,5 +19,4 @@ omit =
[egg_info]
tag_build =
tag_date = 0
-tag_svn_revision = 0
diff --git a/setup.py b/setup.py
index 3033305..c40ee71 100644
--- a/setup.py
+++ b/setup.py
@@ -95,6 +95,7 @@ setup(
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
'Topic :: Database',
'Topic :: Software Development',
],
diff --git a/sqlparse.egg-info/PKG-INFO b/sqlparse.egg-info/PKG-INFO
index 79637ee..06d0e0d 100644
--- a/sqlparse.egg-info/PKG-INFO
+++ b/sqlparse.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: sqlparse
-Version: 0.2.2
+Version: 0.2.3
Summary: Non-validating SQL parser
Home-page: https://github.com/andialbrecht/sqlparse
Author: Andi Albrecht
@@ -68,5 +68,6 @@ Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
Classifier: Topic :: Database
Classifier: Topic :: Software Development
diff --git a/sqlparse.egg-info/SOURCES.txt b/sqlparse.egg-info/SOURCES.txt
index e635c2f..b52c3a7 100644
--- a/sqlparse.egg-info/SOURCES.txt
+++ b/sqlparse.egg-info/SOURCES.txt
@@ -1,5 +1,6 @@
AUTHORS
CHANGELOG
+LICENSE
MANIFEST.in
Makefile
README.rst
@@ -57,6 +58,8 @@ tests/files/_Make_DirEntry.sql
tests/files/begintag.sql
tests/files/begintag_2.sql
tests/files/dashcomment.sql
+tests/files/encoding_gbk.sql
+tests/files/encoding_utf8.sql
tests/files/function.sql
tests/files/function_psql.sql
tests/files/function_psql2.sql
diff --git a/sqlparse/__init__.py b/sqlparse/__init__.py
index b8dbf48..261b367 100644
--- a/sqlparse/__init__.py
+++ b/sqlparse/__init__.py
@@ -17,7 +17,7 @@ from sqlparse import formatter
from sqlparse.compat import text_type
-__version__ = '0.2.2'
+__version__ = '0.2.3'
__all__ = ['engine', 'filters', 'formatter', 'sql', 'tokens', 'cli']
diff --git a/sqlparse/cli.py b/sqlparse/cli.py
index bd2e1b8..0b5c204 100755
--- a/sqlparse/cli.py
+++ b/sqlparse/cli.py
@@ -21,6 +21,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
@@ -125,6 +127,12 @@ def create_parser():
type=bool,
help='Insert linebreak before comma (default False)')
+ group.add_argument(
+ '--encoding',
+ dest='encoding',
+ default='utf-8',
+ help='Specify the input encoding (default utf-8)')
+
return parser
@@ -139,18 +147,21 @@ def main(args=None):
args = parser.parse_args(args)
if args.filename == '-': # read from stdin
- data = sys.stdin.read()
+ if PY2:
+ data = getreader(args.encoding)(sys.stdin).read()
+ else:
+ data = TextIOWrapper(
+ sys.stdin.buffer, encoding=args.encoding).read()
else:
try:
- # TODO: Needs to deal with encoding
- data = ''.join(open(args.filename).readlines())
+ data = ''.join(open(args.filename, 'r', args.encoding).readlines())
except IOError as e:
return _error(
u'Failed to read {0}: {1}'.format(args.filename, e))
if args.outfile:
try:
- stream = open(args.outfile, 'w')
+ stream = open(args.outfile, 'w', args.encoding)
except IOError as e:
return _error(u'Failed to open {0}: {1}'.format(args.outfile, e))
else:
@@ -163,8 +174,6 @@ def main(args=None):
return _error(u'Invalid options: {0}'.format(e))
s = sqlparse.format(data, **formatter_opts)
- if PY2:
- s = s.encode('utf-8', 'replace')
stream.write(s)
stream.flush()
return 0
diff --git a/sqlparse/engine/grouping.py b/sqlparse/engine/grouping.py
index 5fa3909..3c49201 100644
--- a/sqlparse/engine/grouping.py
+++ b/sqlparse/engine/grouping.py
@@ -380,7 +380,7 @@ def _group(tlist, cls, match,
if match(token):
nidx, next_ = tlist.token_next(tidx)
- if valid_prev(prev_) and valid_next(next_):
+ if prev_ and valid_prev(prev_) and valid_next(next_):
from_idx, to_idx = post(tlist, pidx, tidx, nidx)
grp = tlist.group_tokens(cls, from_idx, to_idx, extend=extend)
diff --git a/sqlparse/filters/reindent.py b/sqlparse/filters/reindent.py
index ff1b211..f077849 100644
--- a/sqlparse/filters/reindent.py
+++ b/sqlparse/filters/reindent.py
@@ -30,7 +30,7 @@ class ReindentFilter(object):
for t in self._curr_stmt.flatten():
if t == token:
- raise StopIteration
+ break
yield t
@property
@@ -51,7 +51,7 @@ class ReindentFilter(object):
def _next_token(self, tlist, idx=-1):
split_words = ('FROM', 'STRAIGHT_JOIN$', 'JOIN$', 'AND', 'OR',
'GROUP', 'ORDER', 'UNION', 'VALUES',
- 'SET', 'BETWEEN', 'EXCEPT', 'HAVING')
+ 'SET', 'BETWEEN', 'EXCEPT', 'HAVING', 'LIMIT')
m_split = T.Keyword, split_words, True
tidx, token = tlist.token_next_by(m=m_split, idx=idx)
@@ -162,12 +162,14 @@ class ReindentFilter(object):
with offset(self, len("WHEN ")):
self._process_default(tlist)
end_idx, end = tlist.token_next_by(m=sql.Case.M_CLOSE)
- tlist.insert_before(end_idx, self.nl())
+ if end_idx is not None:
+ tlist.insert_before(end_idx, self.nl())
def _process_default(self, tlist, stmts=True):
self._split_statements(tlist) if stmts else None
self._split_kwds(tlist)
- [self._process(sgroup) for sgroup in tlist.get_sublists()]
+ for sgroup in tlist.get_sublists():
+ self._process(sgroup)
def process(self, stmt):
self._curr_stmt = stmt
diff --git a/sqlparse/keywords.py b/sqlparse/keywords.py
index 48d37f0..d68b4ae 100644
--- a/sqlparse/keywords.py
+++ b/sqlparse/keywords.py
@@ -167,6 +167,7 @@ KEYWORDS = {
'COMMIT': tokens.Keyword.DML,
'COMMITTED': tokens.Keyword,
'COMPLETION': tokens.Keyword,
+ 'CONCURRENTLY': tokens.Keyword,
'CONDITION_NUMBER': tokens.Keyword,
'CONNECT': tokens.Keyword,
'CONNECTION': tokens.Keyword,
@@ -513,7 +514,7 @@ KEYWORDS = {
'SQLWARNING': tokens.Keyword,
'STABLE': tokens.Keyword,
'START': tokens.Keyword.DML,
- 'STATE': tokens.Keyword,
+ # 'STATE': tokens.Keyword,
'STATEMENT': tokens.Keyword,
'STATIC': tokens.Keyword,
'STATISTICS': tokens.Keyword,
@@ -721,7 +722,8 @@ KEYWORDS_ORACLE = {
'FREELIST': tokens.Keyword,
'FREELISTS': tokens.Keyword,
- 'GROUPS': tokens.Keyword,
+ # groups seems too common as table name
+ # 'GROUPS': tokens.Keyword,
'INDICATOR': tokens.Keyword,
'INITRANS': tokens.Keyword,
diff --git a/sqlparse/lexer.py b/sqlparse/lexer.py
index 914b520..60e43da 100644
--- a/sqlparse/lexer.py
+++ b/sqlparse/lexer.py
@@ -43,12 +43,13 @@ class Lexer(object):
if isinstance(text, text_type):
pass
elif isinstance(text, bytes_type):
- try:
- text = text.decode()
- except UnicodeDecodeError:
- if not encoding:
- encoding = 'unicode-escape'
+ if encoding:
text = text.decode(encoding)
+ else:
+ try:
+ text = text.decode('utf-8')
+ except UnicodeDecodeError:
+ text = text.decode('unicode-escape')
else:
raise TypeError(u"Expected text or file-like object, got {!r}".
format(type(text)))
diff --git a/sqlparse/sql.py b/sqlparse/sql.py
index c0f8306..f190de8 100644
--- a/sqlparse/sql.py
+++ b/sqlparse/sql.py
@@ -527,7 +527,7 @@ class Where(TokenList):
"""A WHERE clause."""
M_OPEN = T.Keyword, 'WHERE'
M_CLOSE = T.Keyword, ('ORDER', 'GROUP', 'LIMIT', 'UNION', 'EXCEPT',
- 'HAVING', 'RETURNING')
+ 'HAVING', 'RETURNING', 'INTO')
class Case(TokenList):
diff --git a/tests/files/encoding_gbk.sql b/tests/files/encoding_gbk.sql
new file mode 100644
index 0000000..a613229
--- /dev/null
+++ b/tests/files/encoding_gbk.sql
@@ -0,0 +1,3 @@
+select *
+from foo
+where bar = '������ϲ�����Լ���'
\ No newline at end of file
diff --git a/tests/files/encoding_utf8.sql b/tests/files/encoding_utf8.sql
new file mode 100644
index 0000000..26e7ad4
--- /dev/null
+++ b/tests/files/encoding_utf8.sql
@@ -0,0 +1,3 @@
+select *
+from foo
+where bar = '齐天大圣.カラフルな雲.사랑해요'
\ No newline at end of file
diff --git a/tests/test_cli.py b/tests/test_cli.py
index 77a764e..c1a5a75 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -73,3 +73,71 @@ def test_script():
# Call with the --help option as a basic sanity check.
cmd = "{0: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'])
+ 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')
+ 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')
+ old_stdin = sys.stdin
+ sys.stdin = open(path, 'r')
+ sys.stdout.encoding = 'utf-8'
+ sqlparse.cli.main(['-'])
+ 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
+ sys.stdin = open(path, 'r')
+ 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'
+ sqlparse.cli.main([path, '--encoding=cp1251'])
+ out, _ = capsys.readouterr()
+ assert out == expected
diff --git a/tests/test_grouping.py b/tests/test_grouping.py
index 20151a1..72f94f6 100644
--- a/tests/test_grouping.py
+++ b/tests/test_grouping.py
@@ -210,6 +210,14 @@ def test_returning_kw_ends_where_clause():
assert p.tokens[7].value == 'returning'
+def test_into_kw_ends_where_clause(): # issue324
+ s = 'select * from foo where a = 1 into baz'
+ p = sqlparse.parse(s)[0]
+ assert isinstance(p.tokens[8], sql.Where)
+ assert p.tokens[9].ttype == T.Keyword
+ assert p.tokens[9].value == 'into'
+
+
@pytest.mark.parametrize('sql, expected', [
# note: typecast needs to be 2nd token for this test
('select foo::integer from bar', 'integer'),
@@ -250,6 +258,16 @@ def test_grouping_alias_case():
assert p.tokens[0].get_alias() == 'foo'
+def test_grouping_subquery_no_parens():
+ # Not totally sure if this is the right approach...
+ # When a THEN clause contains a subquery w/o parens around it *and*
+ # a WHERE condition, the WHERE grouper consumes END too.
+ # This takes makes sure that it doesn't fail.
+ p = sqlparse.parse('CASE WHEN 1 THEN select 2 where foo = 1 end')[0]
+ assert len(p.tokens) == 1
+ assert isinstance(p.tokens[0], sql.Case)
+
+
def test_grouping_alias_returns_none():
# see issue185
p = sqlparse.parse('foo.bar')[0]
diff --git a/tests/test_regressions.py b/tests/test_regressions.py
index ba908d3..cc553c2 100644
--- a/tests/test_regressions.py
+++ b/tests/test_regressions.py
@@ -43,13 +43,14 @@ def test_issue34(value):
def test_issue35():
- # missing space before LIMIT
+ # missing space before LIMIT. Updated for #321
sql = sqlparse.format("select * from foo where bar = 1 limit 1",
reindent=True)
assert sql == "\n".join([
"select *",
"from foo",
- "where bar = 1 limit 1"])
+ "where bar = 1",
+ "limit 1"])
def test_issue38():
@@ -316,7 +317,42 @@ def test_token_next_doesnt_ignore_skip_cm():
assert tok.value == 'select'
-def test_issue284_as_grouping():
- sql = 'SELECT x AS'
- p = sqlparse.parse(sql)[0]
- assert sql == str(p)
+ at pytest.mark.parametrize('s', [
+ 'SELECT x AS',
+ 'AS'
+])
+def test_issue284_as_grouping(s):
+ p = sqlparse.parse(s)[0]
+ assert s == str(p)
+
+
+def test_issue315_utf8_by_default():
+ # Make sure the lexer can handle utf-8 string by default correctly
+ # digest = '齐天大圣.カラフルな雲.사랑해요'
+ # The digest contains Chinese, Japanese and Korean characters
+ # All in 'utf-8' encoding.
+ digest = (
+ '\xe9\xbd\x90\xe5\xa4\xa9\xe5\xa4\xa7\xe5\x9c\xa3.'
+ '\xe3\x82\xab\xe3\x83\xa9\xe3\x83\x95\xe3\x83\xab\xe3\x81\xaa\xe9'
+ '\x9b\xb2.'
+ '\xec\x82\xac\xeb\x9e\x91\xed\x95\xb4\xec\x9a\x94'
+ )
+ sql = "select * from foo where bar = '{0}'".format(digest)
+ formatted = sqlparse.format(sql, reindent=True)
+ tformatted = "select *\nfrom foo\nwhere bar = '{0}'".format(digest)
+ if PY2:
+ tformatted = tformatted.decode('utf-8')
+ assert formatted == tformatted
+
+
+def test_issue322_concurrently_is_keyword():
+ s = 'CREATE INDEX CONCURRENTLY myindex ON mytable(col1);'
+ p = sqlparse.parse(s)[0]
+
+ assert len(p.tokens) == 12
+ assert p.tokens[0].ttype is T.Keyword.DDL # CREATE
+ assert p.tokens[2].ttype is T.Keyword # INDEX
+ assert p.tokens[4].ttype is T.Keyword # CONCURRENTLY
+ assert p.tokens[4].value == 'CONCURRENTLY'
+ assert isinstance(p.tokens[6], sql.Identifier)
+ assert p.tokens[6].value == 'myindex'
diff --git a/tox.ini b/tox.ini
index 494246f..e22c808 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,12 +1,14 @@
[tox]
+skip_missing_interpreters = True
envlist =
- py27,
- py33,
- py34,
- py35,
- py36,
- pypy,
- pypy3,
+ py27
+ py33
+ py34
+ py35
+ py36
+ py37
+ pypy_54
+ pypy33
flake8
[testenv]
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/sqlparse.git
More information about the Python-modules-commits
mailing list