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

64 statements  

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 

8 

9"""Module that contains the command line app. 

10 

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""" 

21 

22import argparse 

23import sys 

24from io import TextIOWrapper 

25 

26import sqlparse 

27from sqlparse.exceptions import SQLParseError 

28 

29 

30# TODO: Add CLI Tests 

31# TODO: Simplify formatter by using argparse `type` arguments 

32def create_parser(): 

33 _CASE_CHOICES = ['upper', 'lower', 'capitalize'] 

34 

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 ) 

41 

42 parser.add_argument('filename') 

43 

44 parser.add_argument( 

45 '-o', '--outfile', 

46 dest='outfile', 

47 metavar='FILE', 

48 help='write output to FILE (defaults to stdout)') 

49 

50 parser.add_argument( 

51 '--version', 

52 action='version', 

53 version=sqlparse.__version__) 

54 

55 group = parser.add_argument_group('Formatting Options') 

56 

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))) 

64 

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))) 

72 

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"') 

80 

81 group.add_argument( 

82 '--strip-comments', 

83 dest='strip_comments', 

84 action='store_true', 

85 default=False, 

86 help='remove comments') 

87 

88 group.add_argument( 

89 '-r', '--reindent', 

90 dest='reindent', 

91 action='store_true', 

92 default=False, 

93 help='reindent statements') 

94 

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)') 

101 

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)') 

108 

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') 

115 

116 group.add_argument( 

117 '-a', '--reindent_aligned', 

118 action='store_true', 

119 default=False, 

120 help='reindent statements to aligned format') 

121 

122 group.add_argument( 

123 '-s', '--use_space_around_operators', 

124 action='store_true', 

125 default=False, 

126 help='place spaces around mathematical operators') 

127 

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') 

134 

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)') 

141 

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)') 

148 

149 group.add_argument( 

150 '--encoding', 

151 dest='encoding', 

152 default='utf-8', 

153 help='Specify the input encoding (default utf-8)') 

154 

155 return parser 

156 

157 

158def _error(msg): 

159 """Print msg and optionally exit with return code exit_.""" 

160 sys.stderr.write(f'[ERROR] {msg}\n') 

161 return 1 

162 

163 

164def main(args=None): 

165 parser = create_parser() 

166 args = parser.parse_args(args) 

167 

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}') 

181 

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 

191 

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}') 

197 

198 s = sqlparse.format(data, **formatter_opts) 

199 stream.write(s) 

200 stream.flush() 

201 if close_stream: 

202 stream.close() 

203 return 0