This repository has been archived on 2026-10-10. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2022-12-10 21:17:54 -06:00

216 lines
5.7 KiB
Python

#!/usr/bin/env python
#
# Copyright (C) 2009-2020 the sqlparse authors and contributors
# <see AUTHORS file>
#
# This module is part of python-sqlparse and is released under
# the BSD License: https://opensource.org/licenses/BSD-3-Clause
"""Module that contains the command line app.
Why does this file exist, and why not put this in __main__?
You might be tempted to import things from __main__ later, but that will
cause problems: the code will get executed twice:
- When you run `python -m sqlparse` python will execute
``__main__.py`` as a script. That means there won't be any
``sqlparse.__main__`` in ``sys.modules``.
- When you import __main__ it will get executed again (as a module) because
there's no ``sqlparse.__main__`` in ``sys.modules``.
Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration
"""
import argparse
import sys
from io import TextIOWrapper
import sqlparse
from sqlparse.exceptions import SQLParseError
# TODO: Add CLI Tests
# TODO: Simplify formatter by using argparse `type` arguments
def create_parser():
_CASE_CHOICES = ["upper", "lower", "capitalize"]
parser = argparse.ArgumentParser(
prog="sqlformat",
description='Format FILE according to OPTIONS. Use "-" as FILE '
"to read from stdin.",
usage="%(prog)s [OPTIONS] FILE, ...",
)
parser.add_argument("filename")
parser.add_argument(
"-o",
"--outfile",
dest="outfile",
metavar="FILE",
help="write output to FILE (defaults to stdout)",
)
parser.add_argument("--version", action="version", version=sqlparse.__version__)
group = parser.add_argument_group("Formatting Options")
group.add_argument(
"-k",
"--keywords",
metavar="CHOICE",
dest="keyword_case",
choices=_CASE_CHOICES,
help="change case of keywords, CHOICE is one of {}".format(
", ".join('"{}"'.format(x) for x in _CASE_CHOICES)
),
)
group.add_argument(
"-i",
"--identifiers",
metavar="CHOICE",
dest="identifier_case",
choices=_CASE_CHOICES,
help="change case of identifiers, CHOICE is one of {}".format(
", ".join('"{}"'.format(x) for x in _CASE_CHOICES)
),
)
group.add_argument(
"-l",
"--language",
metavar="LANG",
dest="output_format",
choices=["python", "php"],
help="output a snippet in programming language LANG, "
'choices are "python", "php"',
)
group.add_argument(
"--strip-comments",
dest="strip_comments",
action="store_true",
default=False,
help="remove comments",
)
group.add_argument(
"-r",
"--reindent",
dest="reindent",
action="store_true",
default=False,
help="reindent statements",
)
group.add_argument(
"--indent_width",
dest="indent_width",
default=2,
type=int,
help="indentation width (defaults to 2 spaces)",
)
group.add_argument(
"--indent_after_first",
dest="indent_after_first",
action="store_true",
default=False,
help="indent after first line of statement (e.g. SELECT)",
)
group.add_argument(
"--indent_columns",
dest="indent_columns",
action="store_true",
default=False,
help="indent all columns by indent_width instead of keyword length",
)
group.add_argument(
"-a",
"--reindent_aligned",
action="store_true",
default=False,
help="reindent statements to aligned format",
)
group.add_argument(
"-s",
"--use_space_around_operators",
action="store_true",
default=False,
help="place spaces around mathematical operators",
)
group.add_argument(
"--wrap_after",
dest="wrap_after",
default=0,
type=int,
help="Column after which lists should be wrapped",
)
group.add_argument(
"--comma_first",
dest="comma_first",
default=False,
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
def _error(msg):
"""Print msg and optionally exit with return code exit_."""
sys.stderr.write("[ERROR] {}\n".format(msg))
return 1
def main(args=None):
parser = create_parser()
args = parser.parse_args(args)
if args.filename == "-": # read from stdin
wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding)
try:
data = wrapper.read()
finally:
wrapper.detach()
else:
try:
with open(args.filename, encoding=args.encoding) as f:
data = "".join(f.readlines())
except OSError as e:
return _error("Failed to read {}: {}".format(args.filename, e))
close_stream = False
if args.outfile:
try:
stream = open(args.outfile, "w", encoding=args.encoding)
close_stream = True
except OSError as e:
return _error("Failed to open {}: {}".format(args.outfile, e))
else:
stream = sys.stdout
formatter_opts = vars(args)
try:
formatter_opts = sqlparse.formatter.validate_options(formatter_opts)
except SQLParseError as e:
return _error("Invalid options: {}".format(e))
s = sqlparse.format(data, **formatter_opts)
stream.write(s)
stream.flush()
if close_stream:
stream.close()
return 0