Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/sqlparse/cli.py: 14%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1#!/usr/bin/env python
2#
3# Copyright (C) 2009-2020 the sqlparse authors and contributors
4# <see AUTHORS file>
5#
6# This module is part of python-sqlparse and is released under
7# the BSD License: https://opensource.org/licenses/BSD-3-Clause
9"""Module that contains the command line app.
11Why does this file exist, and why not put this in __main__?
12 You might be tempted to import things from __main__ later, but that will
13 cause problems: the code will get executed twice:
14 - When you run `python -m sqlparse` python will execute
15 ``__main__.py`` as a script. That means there won't be any
16 ``sqlparse.__main__`` in ``sys.modules``.
17 - When you import __main__ it will get executed again (as a module) because
18 there's no ``sqlparse.__main__`` in ``sys.modules``.
19 Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration
20"""
22import argparse
23import sys
24from io import TextIOWrapper
26import sqlparse
27from sqlparse.exceptions import SQLParseError
30# TODO: Add CLI Tests
31# TODO: Simplify formatter by using argparse `type` arguments
32def create_parser():
33 _CASE_CHOICES = ['upper', 'lower', 'capitalize']
35 parser = argparse.ArgumentParser(
36 prog='sqlformat',
37 description='Format FILE according to OPTIONS. Use "-" as FILE '
38 'to read from stdin.',
39 usage='%(prog)s [OPTIONS] FILE, ...',
40 )
42 parser.add_argument('filename')
44 parser.add_argument(
45 '-o', '--outfile',
46 dest='outfile',
47 metavar='FILE',
48 help='write output to FILE (defaults to stdout)')
50 parser.add_argument(
51 '--version',
52 action='version',
53 version=sqlparse.__version__)
55 group = parser.add_argument_group('Formatting Options')
57 group.add_argument(
58 '-k', '--keywords',
59 metavar='CHOICE',
60 dest='keyword_case',
61 choices=_CASE_CHOICES,
62 help='change case of keywords, CHOICE is one of {}'.format(
63 ', '.join(f'"{x}"' for x in _CASE_CHOICES)))
65 group.add_argument(
66 '-i', '--identifiers',
67 metavar='CHOICE',
68 dest='identifier_case',
69 choices=_CASE_CHOICES,
70 help='change case of identifiers, CHOICE is one of {}'.format(
71 ', '.join(f'"{x}"' for x in _CASE_CHOICES)))
73 group.add_argument(
74 '-l', '--language',
75 metavar='LANG',
76 dest='output_format',
77 choices=['python', 'php'],
78 help='output a snippet in programming language LANG, '
79 'choices are "python", "php"')
81 group.add_argument(
82 '--strip-comments',
83 dest='strip_comments',
84 action='store_true',
85 default=False,
86 help='remove comments')
88 group.add_argument(
89 '-r', '--reindent',
90 dest='reindent',
91 action='store_true',
92 default=False,
93 help='reindent statements')
95 group.add_argument(
96 '--indent_width',
97 dest='indent_width',
98 default=2,
99 type=int,
100 help='indentation width (defaults to 2 spaces)')
102 group.add_argument(
103 '--indent_after_first',
104 dest='indent_after_first',
105 action='store_true',
106 default=False,
107 help='indent after first line of statement (e.g. SELECT)')
109 group.add_argument(
110 '--indent_columns',
111 dest='indent_columns',
112 action='store_true',
113 default=False,
114 help='indent all columns by indent_width instead of keyword length')
116 group.add_argument(
117 '-a', '--reindent_aligned',
118 action='store_true',
119 default=False,
120 help='reindent statements to aligned format')
122 group.add_argument(
123 '-s', '--use_space_around_operators',
124 action='store_true',
125 default=False,
126 help='place spaces around mathematical operators')
128 group.add_argument(
129 '--wrap_after',
130 dest='wrap_after',
131 default=0,
132 type=int,
133 help='Column after which lists should be wrapped')
135 group.add_argument(
136 '--comma_first',
137 dest='comma_first',
138 default=False,
139 type=bool,
140 help='Insert linebreak before comma (default False)')
142 group.add_argument(
143 '--compact',
144 dest='compact',
145 default=False,
146 type=bool,
147 help='Try to produce more compact output (default False)')
149 group.add_argument(
150 '--encoding',
151 dest='encoding',
152 default='utf-8',
153 help='Specify the input encoding (default utf-8)')
155 return parser
158def _error(msg):
159 """Print msg and optionally exit with return code exit_."""
160 sys.stderr.write(f'[ERROR] {msg}\n')
161 return 1
164def main(args=None):
165 parser = create_parser()
166 args = parser.parse_args(args)
168 if args.filename == '-': # read from stdin
169 wrapper = TextIOWrapper(sys.stdin.buffer, encoding=args.encoding)
170 try:
171 data = wrapper.read()
172 finally:
173 wrapper.detach()
174 else:
175 try:
176 with open(args.filename, encoding=args.encoding) as f:
177 data = ''.join(f.readlines())
178 except OSError as e:
179 return _error(
180 f'Failed to read {args.filename}: {e}')
182 close_stream = False
183 if args.outfile:
184 try:
185 stream = open(args.outfile, 'w', encoding=args.encoding)
186 close_stream = True
187 except OSError as e:
188 return _error(f'Failed to open {args.outfile}: {e}')
189 else:
190 stream = sys.stdout
192 formatter_opts = vars(args)
193 try:
194 formatter_opts = sqlparse.formatter.validate_options(formatter_opts)
195 except SQLParseError as e:
196 return _error(f'Invalid options: {e}')
198 s = sqlparse.format(data, **formatter_opts)
199 stream.write(s)
200 stream.flush()
201 if close_stream:
202 stream.close()
203 return 0