Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
Development Version
-------------------

Nothing yet.
* Fix boolean value parsing for the sqlformat command's --comma_first and
--compact options. Accept true/false (case-insensitive) and 1/0, and reject
other values instead of treating every non-empty string as true (issue638).


Release 0.6.0 (Aug 13, 2026)
Expand Down
20 changes: 16 additions & 4 deletions sqlparse/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@
from sqlparse.exceptions import SQLParseError


def _parse_bool(value):
if value.lower() in ('true', '1'):
return True
if value.lower() in ('false', '0'):
return False
raise argparse.ArgumentTypeError('expected true, false, 1 or 0')


# TODO: Add CLI Tests
# TODO: Simplify formatter by using argparse `type` arguments
def create_parser():
Expand Down Expand Up @@ -144,15 +152,19 @@ def create_parser():
'--comma_first',
dest='comma_first',
default=False,
type=bool,
help='Insert linebreak before comma (default False)')
type=_parse_bool,
metavar='BOOL',
help='Insert linebreak before comma '
'(true/false or 1/0, case-insensitive; default false)')

group.add_argument(
'--compact',
dest='compact',
default=False,
type=bool,
help='Try to produce more compact output (default False)')
type=_parse_bool,
metavar='BOOL',
help='Try to produce more compact output '
'(true/false or 1/0, case-insensitive; default false)')

group.add_argument(
'--encoding',
Expand Down
47 changes: 47 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,53 @@ def test_cli_main_empty():
sqlparse.cli.main([])


@pytest.mark.parametrize('option', ['comma_first', 'compact'])
@pytest.mark.parametrize('value, expected', [
('True', True), ('true', True), ('TRUE', True), ('1', True),
('False', False), ('false', False), ('FALSE', False), ('0', False),
])
def test_parser_boolean_values(option, value, expected):
parser = sqlparse.cli.create_parser()
args = parser.parse_args(['-', '--' + option, value])
assert getattr(args, option) is expected


@pytest.mark.parametrize('option', ['comma_first', 'compact'])
def test_parser_boolean_default(option):
args = sqlparse.cli.create_parser().parse_args(['-'])
assert getattr(args, option) is False


@pytest.mark.parametrize('option', ['comma_first', 'compact'])
@pytest.mark.parametrize('value', ['xxx', '2', ''])
def test_parser_boolean_invalid(option, value, capsys):
with pytest.raises(SystemExit) as exc:
sqlparse.cli.create_parser().parse_args(['-', '--' + option, value])
assert exc.value.code == 2
out, err = capsys.readouterr()
assert out == ''
assert '--' + option in err
assert 'expected true, false, 1 or 0' in err


@pytest.mark.parametrize('option, sql, normal, enabled', [
('comma_first', 'select a, b from foo',
'select a,\n b\nfrom foo', 'select a\n , b\nfrom foo'),
('compact', 'case when foo then 1 else bar end',
'case\n when foo then 1\n else bar\nend',
'case when foo then 1 else bar end'),
])
@pytest.mark.parametrize('value', [None, 'False', '0', 'True', '1'])
def test_cli_boolean_formatting(option, sql, normal, enabled, value):
cmd = [sys.executable, '-m', 'sqlparse', '-', '--reindent']
if value is not None:
cmd.extend(['--' + option, value])
result = subprocess.run(cmd, input=sql, capture_output=True, text=True)
assert result.returncode == 0
assert result.stderr == ''
assert result.stdout == (enabled if value in ('True', '1') else normal)


def test_parser_empty():
with pytest.raises(SystemExit):
parser = sqlparse.cli.create_parser()
Expand Down