first commit
This commit is contained in:
246
.venv/lib/python3.12/site-packages/sqlparse/cli.py
Normal file
246
.venv/lib/python3.12/site-packages/sqlparse/cli.py
Normal file
@@ -0,0 +1,246 @@
|
||||
# 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 [FILE ...]',
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
'filename',
|
||||
nargs='+',
|
||||
help='file(s) to format (use "-" for stdin)')
|
||||
|
||||
parser.add_argument(
|
||||
'-o', '--outfile',
|
||||
dest='outfile',
|
||||
metavar='FILE',
|
||||
help='write output to FILE (defaults to stdout)')
|
||||
|
||||
parser.add_argument(
|
||||
'--in-place',
|
||||
dest='inplace',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='format files in-place (overwrite existing files)')
|
||||
|
||||
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(f'"{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(f'"{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(
|
||||
'--compact',
|
||||
dest='compact',
|
||||
default=False,
|
||||
type=bool,
|
||||
help='Try to produce more compact output (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(f'[ERROR] {msg}\n')
|
||||
return 1
|
||||
|
||||
|
||||
def _process_file(filename, args):
|
||||
"""Process a single file with the given formatting options.
|
||||
|
||||
Returns 0 on success, 1 on error.
|
||||
"""
|
||||
# Check for incompatible option combinations first
|
||||
if filename == '-' and args.inplace:
|
||||
return _error('Cannot use --in-place with stdin')
|
||||
|
||||
# Read input
|
||||
if filename == '-': # read from stdin
|
||||
wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding)
|
||||
try:
|
||||
data = wrapper.read()
|
||||
finally:
|
||||
wrapper.detach()
|
||||
else:
|
||||
try:
|
||||
with open(filename, encoding=args.encoding) as f:
|
||||
data = ''.join(f.readlines())
|
||||
except OSError as e:
|
||||
return _error(f'Failed to read {filename}: {e}')
|
||||
|
||||
# Determine output destination
|
||||
close_stream = False
|
||||
if args.inplace:
|
||||
try:
|
||||
stream = open(filename, 'w', encoding=args.encoding)
|
||||
close_stream = True
|
||||
except OSError as e:
|
||||
return _error(f'Failed to open {filename}: {e}')
|
||||
elif args.outfile:
|
||||
try:
|
||||
stream = open(args.outfile, 'w', encoding=args.encoding)
|
||||
close_stream = True
|
||||
except OSError as e:
|
||||
return _error(f'Failed to open {args.outfile}: {e}')
|
||||
else:
|
||||
stream = sys.stdout
|
||||
|
||||
# Format the SQL
|
||||
formatter_opts = vars(args)
|
||||
try:
|
||||
formatter_opts = sqlparse.formatter.validate_options(formatter_opts)
|
||||
except SQLParseError as e:
|
||||
return _error(f'Invalid options: {e}')
|
||||
|
||||
s = sqlparse.format(data, **formatter_opts)
|
||||
stream.write(s)
|
||||
stream.flush()
|
||||
if close_stream:
|
||||
stream.close()
|
||||
return 0
|
||||
|
||||
|
||||
def main(args=None):
|
||||
parser = create_parser()
|
||||
args = parser.parse_args(args)
|
||||
|
||||
# Validate argument combinations
|
||||
if len(args.filename) > 1:
|
||||
if args.outfile:
|
||||
return _error('Cannot use -o/--outfile with multiple files')
|
||||
if not args.inplace:
|
||||
return _error('Multiple files require --in-place flag')
|
||||
|
||||
# Process all files
|
||||
exit_code = 0
|
||||
for filename in args.filename:
|
||||
result = _process_file(filename, args)
|
||||
if result != 0:
|
||||
exit_code = result
|
||||
# Continue processing remaining files even if one fails
|
||||
|
||||
return exit_code
|
||||
Reference in New Issue
Block a user