From cb100a4a573542af08695d178d726cc2b423daab Mon Sep 17 00:00:00 2001 From: xuu33030 <268775543+xuu33030@users.noreply.github.com> Date: Wed, 16 Sep 2026 20:03:42 +0800 Subject: [PATCH] Fix CLI boolean value parsing (fixes #638) --- CHANGELOG | 4 +++- sqlparse/cli.py | 20 ++++++++++++++++---- tests/test_cli.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 44d5938e..0041dba0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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) diff --git a/sqlparse/cli.py b/sqlparse/cli.py index 03ee86e3..bf7ad1a8 100644 --- a/sqlparse/cli.py +++ b/sqlparse/cli.py @@ -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(): @@ -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', diff --git a/tests/test_cli.py b/tests/test_cli.py index 4aec44d3..57f03651 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -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()