[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