summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDennis Taylor <dennis.taylor@clio.com>2016-06-02 15:28:27 -0700
committerDennis Taylor <dennis.taylor@clio.com>2016-06-02 15:28:27 -0700
commit9b84aac37a4099f4788508f98b7b1ed3010c424e (patch)
tree44c100cccbc104d1598cedc9c20baa664cb1abd7
parenta767c88b008d407d91b9118d124e2a9b579a7f12 (diff)
downloadsqlparse-9b84aac37a4099f4788508f98b7b1ed3010c424e.tar.gz
Add --wrap_after option for wrapping identifier lists.
-rwxr-xr-xbin/sqlformat2
-rw-r--r--docs/source/api.rst4
-rw-r--r--docs/sqlformat.14
-rw-r--r--sqlparse/filters.py9
-rw-r--r--sqlparse/formatter.py16
-rw-r--r--tests/test_format.py12
6 files changed, 43 insertions, 4 deletions
diff --git a/bin/sqlformat b/bin/sqlformat
index cecbed9..234393f 100755
--- a/bin/sqlformat
+++ b/bin/sqlformat
@@ -44,6 +44,8 @@ group.add_option('-r', '--reindent', dest='reindent',
help='reindent statements')
group.add_option('--indent_width', dest='indent_width', default=2,
help='indentation width (defaults to 2 spaces)')
+group.add_option('--wrap_after', dest='wrap_after', default=0,
+ help='Column after which lists should be wrapped')
_FORMATTING_GROUP = group
diff --git a/docs/source/api.rst b/docs/source/api.rst
index 518a428..e9fcdaa 100644
--- a/docs/source/api.rst
+++ b/docs/source/api.rst
@@ -52,6 +52,10 @@ The :meth:`~sqlparse.format` function accepts the following keyword arguments.
``indent_width``
The width of the indentation, defaults to 2.
+``wrap_after``
+ The column limit for wrapping comma-separated lists. If unspecified, it
+ puts every item in the list on its own line.
+
``output_format``
If given the output is additionally formatted to be used as a variable
in a programming language. Allowed values are "python" and "php".
diff --git a/docs/sqlformat.1 b/docs/sqlformat.1
index a42ea60..7d7987a 100644
--- a/docs/sqlformat.1
+++ b/docs/sqlformat.1
@@ -49,6 +49,10 @@ Set indent width to
.IR INDENT_WIDTH .
Default is 2 spaces.
.TP
+\fB\-\-wrap_after\fR=\fIWRAP_AFTER\fR
+The column limit for wrapping comma-separated lists. If unspecified, it
+puts every item in the list on its own line.
+.TP
\fB\-\-strip\-comments
Remove comments.
.TP
diff --git a/sqlparse/filters.py b/sqlparse/filters.py
index 72f17d0..4cb8a46 100644
--- a/sqlparse/filters.py
+++ b/sqlparse/filters.py
@@ -279,12 +279,13 @@ class StripWhitespaceFilter:
class ReindentFilter:
- def __init__(self, width=2, char=' ', line_width=None):
+ def __init__(self, width=2, char=' ', line_width=None, wrap_after=0):
self.width = width
self.char = char
self.indent = 0
self.offset = 0
self.line_width = line_width
+ self.wrap_after = wrap_after
self._curr_stmt = None
self._last_stmt = None
@@ -413,8 +414,12 @@ class ReindentFilter:
else:
num_offset = self._get_offset(first) - len(first.value)
self.offset += num_offset
+ position = self.offset
for token in identifiers[1:]:
- tlist.insert_before(token, self.nl())
+ position += len(token.value) + 1 # Add 1 for the "," separator
+ if position > self.wrap_after:
+ tlist.insert_before(token, self.nl())
+ position = self.offset
self.offset -= num_offset
self._process_default(tlist)
diff --git a/sqlparse/formatter.py b/sqlparse/formatter.py
index ab5f370..05ea327 100644
--- a/sqlparse/formatter.py
+++ b/sqlparse/formatter.py
@@ -52,6 +52,7 @@ def validate_options(options):
% 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)
@@ -59,15 +60,25 @@ def validate_options(options):
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')
+ raise SQLParseError('indent_width requires a positive integer')
options['indent_width'] = indent_width
+ wrap_after = options.get('wrap_after', 0)
+ try:
+ wrap_after = int(wrap_after)
+ except (TypeError, ValueError):
+ raise SQLParseError('wrap_after requires an integer')
+ if wrap_after < 0:
+ raise SQLParseError('wrap_after requires a positive integer')
+ options['wrap_after'] = wrap_after
+
right_margin = options.get('right_margin', None)
if right_margin is not None:
try:
@@ -115,7 +126,8 @@ def build_filter_stack(stack, options):
stack.enable_grouping()
stack.stmtprocess.append(
filters.ReindentFilter(char=options['indent_char'],
- width=options['indent_width']))
+ width=options['indent_width'],
+ wrap_after=options['wrap_after']))
if options.get('right_margin', False):
stack.enable_grouping()
diff --git a/tests/test_format.py b/tests/test_format.py
index e8875dd..9043e76 100644
--- a/tests/test_format.py
+++ b/tests/test_format.py
@@ -117,6 +117,10 @@ class TestFormatReindent(TestCaseBase):
reindent=True, indent_width='foo')
self.assertRaises(SQLParseError, sqlparse.format, 'foo',
reindent=True, indent_width=-12)
+ self.assertRaises(SQLParseError, sqlparse.format, 'foo',
+ reindent=True, wrap_after='foo')
+ self.assertRaises(SQLParseError, sqlparse.format, 'foo',
+ reindent=True, wrap_after=-12)
def test_stmts(self):
f = lambda sql: sqlparse.format(sql, reindent=True)
@@ -204,6 +208,14 @@ class TestFormatReindent(TestCaseBase):
'from a,',
' b']))
+ def test_identifier_list_with_wrap_after(self):
+ f = lambda sql: sqlparse.format(sql, reindent=True, wrap_after=14)
+ s = 'select foo, bar, baz from table1, table2 where 1 = 2'
+ self.ndiffAssertEqual(f(s), '\n'.join(['select foo, bar,',
+ ' baz',
+ 'from table1, table2',
+ 'where 1 = 2']))
+
def test_identifier_list_with_functions(self):
f = lambda sql: sqlparse.format(sql, reindent=True)
s = ("select 'abc' as foo, coalesce(col1, col2)||col3 as bar,"