m2m模型翻译
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.

291 lines
9.6 KiB

6 months ago
  1. # Human friendly input/output in Python.
  2. #
  3. # Author: Peter Odding <peter@peterodding.com>
  4. # Last Change: March 1, 2020
  5. # URL: https://humanfriendly.readthedocs.io
  6. """
  7. Usage: humanfriendly [OPTIONS]
  8. Human friendly input/output (text formatting) on the command
  9. line based on the Python package with the same name.
  10. Supported options:
  11. -c, --run-command
  12. Execute an external command (given as the positional arguments) and render
  13. a spinner and timer while the command is running. The exit status of the
  14. command is propagated.
  15. --format-table
  16. Read tabular data from standard input (each line is a row and each
  17. whitespace separated field is a column), format the data as a table and
  18. print the resulting table to standard output. See also the --delimiter
  19. option.
  20. -d, --delimiter=VALUE
  21. Change the delimiter used by --format-table to VALUE (a string). By default
  22. all whitespace is treated as a delimiter.
  23. -l, --format-length=LENGTH
  24. Convert a length count (given as the integer or float LENGTH) into a human
  25. readable string and print that string to standard output.
  26. -n, --format-number=VALUE
  27. Format a number (given as the integer or floating point number VALUE) with
  28. thousands separators and two decimal places (if needed) and print the
  29. formatted number to standard output.
  30. -s, --format-size=BYTES
  31. Convert a byte count (given as the integer BYTES) into a human readable
  32. string and print that string to standard output.
  33. -b, --binary
  34. Change the output of -s, --format-size to use binary multiples of bytes
  35. (base-2) instead of the default decimal multiples of bytes (base-10).
  36. -t, --format-timespan=SECONDS
  37. Convert a number of seconds (given as the floating point number SECONDS)
  38. into a human readable timespan and print that string to standard output.
  39. --parse-length=VALUE
  40. Parse a human readable length (given as the string VALUE) and print the
  41. number of metres to standard output.
  42. --parse-size=VALUE
  43. Parse a human readable data size (given as the string VALUE) and print the
  44. number of bytes to standard output.
  45. --demo
  46. Demonstrate changing the style and color of the terminal font using ANSI
  47. escape sequences.
  48. -h, --help
  49. Show this message and exit.
  50. """
  51. # Standard library modules.
  52. import functools
  53. import getopt
  54. import pipes
  55. import subprocess
  56. import sys
  57. # Modules included in our package.
  58. from humanfriendly import (
  59. Timer,
  60. format_length,
  61. format_number,
  62. format_size,
  63. format_timespan,
  64. parse_length,
  65. parse_size,
  66. )
  67. from humanfriendly.tables import format_pretty_table, format_smart_table
  68. from humanfriendly.terminal import (
  69. ANSI_COLOR_CODES,
  70. ANSI_TEXT_STYLES,
  71. HIGHLIGHT_COLOR,
  72. ansi_strip,
  73. ansi_wrap,
  74. enable_ansi_support,
  75. find_terminal_size,
  76. output,
  77. usage,
  78. warning,
  79. )
  80. from humanfriendly.terminal.spinners import Spinner
  81. # Public identifiers that require documentation.
  82. __all__ = (
  83. 'demonstrate_256_colors',
  84. 'demonstrate_ansi_formatting',
  85. 'main',
  86. 'print_formatted_length',
  87. 'print_formatted_number',
  88. 'print_formatted_size',
  89. 'print_formatted_table',
  90. 'print_formatted_timespan',
  91. 'print_parsed_length',
  92. 'print_parsed_size',
  93. 'run_command',
  94. )
  95. def main():
  96. """Command line interface for the ``humanfriendly`` program."""
  97. enable_ansi_support()
  98. try:
  99. options, arguments = getopt.getopt(sys.argv[1:], 'cd:l:n:s:bt:h', [
  100. 'run-command', 'format-table', 'delimiter=', 'format-length=',
  101. 'format-number=', 'format-size=', 'binary', 'format-timespan=',
  102. 'parse-length=', 'parse-size=', 'demo', 'help',
  103. ])
  104. except Exception as e:
  105. warning("Error: %s", e)
  106. sys.exit(1)
  107. actions = []
  108. delimiter = None
  109. should_format_table = False
  110. binary = any(o in ('-b', '--binary') for o, v in options)
  111. for option, value in options:
  112. if option in ('-d', '--delimiter'):
  113. delimiter = value
  114. elif option == '--parse-size':
  115. actions.append(functools.partial(print_parsed_size, value))
  116. elif option == '--parse-length':
  117. actions.append(functools.partial(print_parsed_length, value))
  118. elif option in ('-c', '--run-command'):
  119. actions.append(functools.partial(run_command, arguments))
  120. elif option in ('-l', '--format-length'):
  121. actions.append(functools.partial(print_formatted_length, value))
  122. elif option in ('-n', '--format-number'):
  123. actions.append(functools.partial(print_formatted_number, value))
  124. elif option in ('-s', '--format-size'):
  125. actions.append(functools.partial(print_formatted_size, value, binary))
  126. elif option == '--format-table':
  127. should_format_table = True
  128. elif option in ('-t', '--format-timespan'):
  129. actions.append(functools.partial(print_formatted_timespan, value))
  130. elif option == '--demo':
  131. actions.append(demonstrate_ansi_formatting)
  132. elif option in ('-h', '--help'):
  133. usage(__doc__)
  134. return
  135. if should_format_table:
  136. actions.append(functools.partial(print_formatted_table, delimiter))
  137. if not actions:
  138. usage(__doc__)
  139. return
  140. for partial in actions:
  141. partial()
  142. def run_command(command_line):
  143. """Run an external command and show a spinner while the command is running."""
  144. timer = Timer()
  145. spinner_label = "Waiting for command: %s" % " ".join(map(pipes.quote, command_line))
  146. with Spinner(label=spinner_label, timer=timer) as spinner:
  147. process = subprocess.Popen(command_line)
  148. while True:
  149. spinner.step()
  150. spinner.sleep()
  151. if process.poll() is not None:
  152. break
  153. sys.exit(process.returncode)
  154. def print_formatted_length(value):
  155. """Print a human readable length."""
  156. if '.' in value:
  157. output(format_length(float(value)))
  158. else:
  159. output(format_length(int(value)))
  160. def print_formatted_number(value):
  161. """Print large numbers in a human readable format."""
  162. output(format_number(float(value)))
  163. def print_formatted_size(value, binary):
  164. """Print a human readable size."""
  165. output(format_size(int(value), binary=binary))
  166. def print_formatted_table(delimiter):
  167. """Read tabular data from standard input and print a table."""
  168. data = []
  169. for line in sys.stdin:
  170. line = line.rstrip()
  171. data.append(line.split(delimiter))
  172. output(format_pretty_table(data))
  173. def print_formatted_timespan(value):
  174. """Print a human readable timespan."""
  175. output(format_timespan(float(value)))
  176. def print_parsed_length(value):
  177. """Parse a human readable length and print the number of metres."""
  178. output(parse_length(value))
  179. def print_parsed_size(value):
  180. """Parse a human readable data size and print the number of bytes."""
  181. output(parse_size(value))
  182. def demonstrate_ansi_formatting():
  183. """Demonstrate the use of ANSI escape sequences."""
  184. # First we demonstrate the supported text styles.
  185. output('%s', ansi_wrap('Text styles:', bold=True))
  186. styles = ['normal', 'bright']
  187. styles.extend(ANSI_TEXT_STYLES.keys())
  188. for style_name in sorted(styles):
  189. options = dict(color=HIGHLIGHT_COLOR)
  190. if style_name != 'normal':
  191. options[style_name] = True
  192. style_label = style_name.replace('_', ' ').capitalize()
  193. output(' - %s', ansi_wrap(style_label, **options))
  194. # Now we demonstrate named foreground and background colors.
  195. for color_type, color_label in (('color', 'Foreground colors'),
  196. ('background', 'Background colors')):
  197. intensities = [
  198. ('normal', dict()),
  199. ('bright', dict(bright=True)),
  200. ]
  201. if color_type != 'background':
  202. intensities.insert(0, ('faint', dict(faint=True)))
  203. output('\n%s' % ansi_wrap('%s:' % color_label, bold=True))
  204. output(format_smart_table([
  205. [color_name] + [
  206. ansi_wrap(
  207. 'XXXXXX' if color_type != 'background' else (' ' * 6),
  208. **dict(list(kw.items()) + [(color_type, color_name)])
  209. ) for label, kw in intensities
  210. ] for color_name in sorted(ANSI_COLOR_CODES.keys())
  211. ], column_names=['Color'] + [
  212. label.capitalize() for label, kw in intensities
  213. ]))
  214. # Demonstrate support for 256 colors as well.
  215. demonstrate_256_colors(0, 7, 'standard colors')
  216. demonstrate_256_colors(8, 15, 'high-intensity colors')
  217. demonstrate_256_colors(16, 231, '216 colors')
  218. demonstrate_256_colors(232, 255, 'gray scale colors')
  219. def demonstrate_256_colors(i, j, group=None):
  220. """Demonstrate 256 color mode support."""
  221. # Generate the label.
  222. label = '256 color mode'
  223. if group:
  224. label += ' (%s)' % group
  225. output('\n' + ansi_wrap('%s:' % label, bold=True))
  226. # Generate a simple rendering of the colors in the requested range and
  227. # check if it will fit on a single line (given the terminal's width).
  228. single_line = ''.join(' ' + ansi_wrap(str(n), color=n) for n in range(i, j + 1))
  229. lines, columns = find_terminal_size()
  230. if columns >= len(ansi_strip(single_line)):
  231. output(single_line)
  232. else:
  233. # Generate a more complex rendering of the colors that will nicely wrap
  234. # over multiple lines without using too many lines.
  235. width = len(str(j)) + 1
  236. colors_per_line = int(columns / width)
  237. colors = [ansi_wrap(str(n).rjust(width), color=n) for n in range(i, j + 1)]
  238. blocks = [colors[n:n + colors_per_line] for n in range(0, len(colors), colors_per_line)]
  239. output('\n'.join(''.join(b) for b in blocks))