Skip to content

Commit 12d9aee

Browse files
committed
Merge pull request andialbrecht#248 from fimmtiu/add-wrap-after-option
Add --wrap_after option for wrapping identifier lists.
2 parents 88a9daf + 9b84aac commit 12d9aee

6 files changed

Lines changed: 43 additions & 4 deletions

File tree

bin/sqlformat

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ group.add_option('-r', '--reindent', dest='reindent',
4444
help='reindent statements')
4545
group.add_option('--indent_width', dest='indent_width', default=2,
4646
help='indentation width (defaults to 2 spaces)')
47+
group.add_option('--wrap_after', dest='wrap_after', default=0,
48+
help='Column after which lists should be wrapped')
4749

4850
_FORMATTING_GROUP = group
4951

docs/source/api.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ The :meth:`~sqlparse.format` function accepts the following keyword arguments.
5252
``indent_width``
5353
The width of the indentation, defaults to 2.
5454

55+
``wrap_after``
56+
The column limit for wrapping comma-separated lists. If unspecified, it
57+
puts every item in the list on its own line.
58+
5559
``output_format``
5660
If given the output is additionally formatted to be used as a variable
5761
in a programming language. Allowed values are "python" and "php".

docs/sqlformat.1

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ Set indent width to
4949
.IR INDENT_WIDTH .
5050
Default is 2 spaces.
5151
.TP
52+
\fB\-\-wrap_after\fR=\fIWRAP_AFTER\fR
53+
The column limit for wrapping comma-separated lists. If unspecified, it
54+
puts every item in the list on its own line.
55+
.TP
5256
\fB\-\-strip\-comments
5357
Remove comments.
5458
.TP

sqlparse/filters.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,12 +279,13 @@ def process(self, stack, stmt, depth=0):
279279

280280
class ReindentFilter(object):
281281

282-
def __init__(self, width=2, char=' ', line_width=None):
282+
def __init__(self, width=2, char=' ', line_width=None, wrap_after=0):
283283
self.width = width
284284
self.char = char
285285
self.indent = 0
286286
self.offset = 0
287287
self.line_width = line_width
288+
self.wrap_after = wrap_after
288289
self._curr_stmt = None
289290
self._last_stmt = None
290291

@@ -413,8 +414,12 @@ def _process_identifierlist(self, tlist):
413414
else:
414415
num_offset = self._get_offset(first) - len(first.value)
415416
self.offset += num_offset
417+
position = self.offset
416418
for token in identifiers[1:]:
417-
tlist.insert_before(token, self.nl())
419+
position += len(token.value) + 1 # Add 1 for the "," separator
420+
if position > self.wrap_after:
421+
tlist.insert_before(token, self.nl())
422+
position = self.offset
418423
self.offset -= num_offset
419424
self._process_default(tlist)
420425

sqlparse/formatter.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,33 @@ def validate_options(options):
5252
% reindent)
5353
elif reindent:
5454
options['strip_whitespace'] = True
55+
5556
indent_tabs = options.get('indent_tabs', False)
5657
if indent_tabs not in [True, False]:
5758
raise SQLParseError('Invalid value for indent_tabs: %r' % indent_tabs)
5859
elif indent_tabs:
5960
options['indent_char'] = '\t'
6061
else:
6162
options['indent_char'] = ' '
63+
6264
indent_width = options.get('indent_width', 2)
6365
try:
6466
indent_width = int(indent_width)
6567
except (TypeError, ValueError):
6668
raise SQLParseError('indent_width requires an integer')
6769
if indent_width < 1:
68-
raise SQLParseError('indent_width requires an positive integer')
70+
raise SQLParseError('indent_width requires a positive integer')
6971
options['indent_width'] = indent_width
7072

73+
wrap_after = options.get('wrap_after', 0)
74+
try:
75+
wrap_after = int(wrap_after)
76+
except (TypeError, ValueError):
77+
raise SQLParseError('wrap_after requires an integer')
78+
if wrap_after < 0:
79+
raise SQLParseError('wrap_after requires a positive integer')
80+
options['wrap_after'] = wrap_after
81+
7182
right_margin = options.get('right_margin', None)
7283
if right_margin is not None:
7384
try:
@@ -115,7 +126,8 @@ def build_filter_stack(stack, options):
115126
stack.enable_grouping()
116127
stack.stmtprocess.append(
117128
filters.ReindentFilter(char=options['indent_char'],
118-
width=options['indent_width']))
129+
width=options['indent_width'],
130+
wrap_after=options['wrap_after']))
119131

120132
if options.get('right_margin', False):
121133
stack.enable_grouping()

tests/test_format.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ def test_option(self):
117117
reindent=True, indent_width='foo')
118118
self.assertRaises(SQLParseError, sqlparse.format, 'foo',
119119
reindent=True, indent_width=-12)
120+
self.assertRaises(SQLParseError, sqlparse.format, 'foo',
121+
reindent=True, wrap_after='foo')
122+
self.assertRaises(SQLParseError, sqlparse.format, 'foo',
123+
reindent=True, wrap_after=-12)
120124

121125
def test_stmts(self):
122126
f = lambda sql: sqlparse.format(sql, reindent=True)
@@ -204,6 +208,14 @@ def test_identifier_list(self):
204208
'from a,',
205209
' b']))
206210

211+
def test_identifier_list_with_wrap_after(self):
212+
f = lambda sql: sqlparse.format(sql, reindent=True, wrap_after=14)
213+
s = 'select foo, bar, baz from table1, table2 where 1 = 2'
214+
self.ndiffAssertEqual(f(s), '\n'.join(['select foo, bar,',
215+
' baz',
216+
'from table1, table2',
217+
'where 1 = 2']))
218+
207219
def test_identifier_list_with_functions(self):
208220
f = lambda sql: sqlparse.format(sql, reindent=True)
209221
s = ("select 'abc' as foo, coalesce(col1, col2)||col3 as bar,"

0 commit comments

Comments
 (0)