Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cli.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright (C) 2016 Andi Albrecht, albrecht.andi@gmail.com
  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. """Module that contains the command line app.
  9. Why does this file exist, and why not put this in __main__?
  10. You might be tempted to import things from __main__ later, but that will
  11. cause problems: the code will get executed twice:
  12. - When you run `python -m sqlparse` python will execute
  13. ``__main__.py`` as a script. That means there won't be any
  14. ``sqlparse.__main__`` in ``sys.modules``.
  15. - When you import __main__ it will get executed again (as a module) because
  16. there's no ``sqlparse.__main__`` in ``sys.modules``.
  17. Also see (1) from http://click.pocoo.org/5/setuptools/#setuptools-integration
  18. """
  19. import argparse
  20. import sys
  21. from io import TextIOWrapper
  22. from codecs import open, getreader
  23. import sqlparse
  24. from sqlparse.compat import PY2
  25. from sqlparse.exceptions import SQLParseError
  26. # TODO: Add CLI Tests
  27. # TODO: Simplify formatter by using argparse `type` arguments
  28. def create_parser():
  29. _CASE_CHOICES = ['upper', 'lower', 'capitalize']
  30. parser = argparse.ArgumentParser(
  31. prog='sqlformat',
  32. description='Format FILE according to OPTIONS. Use "-" as FILE '
  33. 'to read from stdin.',
  34. usage='%(prog)s [OPTIONS] FILE, ...',
  35. )
  36. parser.add_argument('filename')
  37. parser.add_argument(
  38. '-o', '--outfile',
  39. dest='outfile',
  40. metavar='FILE',
  41. help='write output to FILE (defaults to stdout)')
  42. parser.add_argument(
  43. '--version',
  44. action='version',
  45. version=sqlparse.__version__)
  46. group = parser.add_argument_group('Formatting Options')
  47. group.add_argument(
  48. '-k', '--keywords',
  49. metavar='CHOICE',
  50. dest='keyword_case',
  51. choices=_CASE_CHOICES,
  52. help='change case of keywords, CHOICE is one of {0}'.format(
  53. ', '.join('"{0}"'.format(x) for x in _CASE_CHOICES)))
  54. group.add_argument(
  55. '-i', '--identifiers',
  56. metavar='CHOICE',
  57. dest='identifier_case',
  58. choices=_CASE_CHOICES,
  59. help='change case of identifiers, CHOICE is one of {0}'.format(
  60. ', '.join('"{0}"'.format(x) for x in _CASE_CHOICES)))
  61. group.add_argument(
  62. '-l', '--language',
  63. metavar='LANG',
  64. dest='output_format',
  65. choices=['python', 'php'],
  66. help='output a snippet in programming language LANG, '
  67. 'choices are "python", "php"')
  68. group.add_argument(
  69. '--strip-comments',
  70. dest='strip_comments',
  71. action='store_true',
  72. default=False,
  73. help='remove comments')
  74. group.add_argument(
  75. '-r', '--reindent',
  76. dest='reindent',
  77. action='store_true',
  78. default=False,
  79. help='reindent statements')
  80. group.add_argument(
  81. '--indent_width',
  82. dest='indent_width',
  83. default=2,
  84. type=int,
  85. help='indentation width (defaults to 2 spaces)')
  86. group.add_argument(
  87. '-a', '--reindent_aligned',
  88. action='store_true',
  89. default=False,
  90. help='reindent statements to aligned format')
  91. group.add_argument(
  92. '-s', '--use_space_around_operators',
  93. action='store_true',
  94. default=False,
  95. help='place spaces around mathematical operators')
  96. group.add_argument(
  97. '--wrap_after',
  98. dest='wrap_after',
  99. default=0,
  100. type=int,
  101. help='Column after which lists should be wrapped')
  102. group.add_argument(
  103. '--comma_first',
  104. dest='comma_first',
  105. default=False,
  106. type=bool,
  107. help='Insert linebreak before comma (default False)')
  108. group.add_argument(
  109. '--encoding',
  110. dest='encoding',
  111. default='utf-8',
  112. help='Specify the input encoding (default utf-8)')
  113. return parser
  114. def _error(msg):
  115. """Print msg and optionally exit with return code exit_."""
  116. sys.stderr.write(u'[ERROR] {0}\n'.format(msg))
  117. return 1
  118. def main(args=None):
  119. parser = create_parser()
  120. args = parser.parse_args(args)
  121. if args.filename == '-': # read from stdin
  122. if PY2:
  123. data = getreader(args.encoding)(sys.stdin).read()
  124. else:
  125. data = TextIOWrapper(
  126. sys.stdin.buffer, encoding=args.encoding).read()
  127. else:
  128. try:
  129. with open(args.filename, 'r', args.encoding) as f:
  130. data = ''.join(f.readlines())
  131. except IOError as e:
  132. return _error(
  133. u'Failed to read {0}: {1}'.format(args.filename, e))
  134. close_stream = False
  135. if args.outfile:
  136. try:
  137. stream = open(args.outfile, 'w', args.encoding)
  138. close_stream = True
  139. except IOError as e:
  140. return _error(u'Failed to open {0}: {1}'.format(args.outfile, e))
  141. else:
  142. stream = sys.stdout
  143. formatter_opts = vars(args)
  144. try:
  145. formatter_opts = sqlparse.formatter.validate_options(formatter_opts)
  146. except SQLParseError as e:
  147. return _error(u'Invalid options: {0}'.format(e))
  148. s = sqlparse.format(data, **formatter_opts)
  149. stream.write(s)
  150. stream.flush()
  151. if close_stream:
  152. stream.close()
  153. return 0