def print_lines(console_printer, file_dict, sourcerange): """ Prints the lines between the current and the result line. If needed they will be shortened. :param console_printer: Object to print messages on the console. :param file_dict: A dictionary containing all files as values with filenames as key. :param sourcerange: The SourceRange object referring to the related lines to print. """ no_color = not console_printer.print_colored for i in range(sourcerange.start.line, sourcerange.end.line + 1): # Print affected file's line number in the sidebar. console_printer.print(format_lines(lines='', line_nr=i, symbol='['), color=FILE_LINES_COLOR, end='') line = file_dict[sourcerange.file][i - 1].rstrip('\n') try: lexer = get_lexer_for_filename(sourcerange.file) except ClassNotFound: lexer = TextLexer() lexer.add_filter( VisibleWhitespaceFilter(spaces=True, tabs=True, tabsize=SpacingHelper.DEFAULT_TAB_WIDTH)) # highlight() combines lexer and formatter to output a ``str`` # object. printed_chars = 0 if i == sourcerange.start.line and sourcerange.start.column: console_printer.print(highlight_text( no_color, line[:sourcerange.start.column - 1], BackgroundMessageStyle, lexer), end='') printed_chars = sourcerange.start.column - 1 if i == sourcerange.end.line and sourcerange.end.column: console_printer.print(highlight_text( no_color, line[printed_chars:sourcerange.end.column - 1], BackgroundSourceRangeStyle, lexer), end='') console_printer.print(highlight_text( no_color, line[sourcerange.end.column - 1:], BackgroundSourceRangeStyle, lexer), end='') console_printer.print('') else: console_printer.print(highlight_text(no_color, line[printed_chars:], BackgroundMessageStyle, lexer), end='') console_printer.print('')
def print_lines(console_printer, file_dict, sourcerange): """ Prints the lines between the current and the result line. If needed they will be shortened. :param console_printer: Object to print messages on the console. :param file_dict: A dictionary containing all files as values with filenames as key. :param sourcerange: The SourceRange object referring to the related lines to print. """ no_color = not console_printer.print_colored for i in range(sourcerange.start.line, sourcerange.end.line + 1): # Print affected file's line number in the sidebar. console_printer.print(format_lines(lines='', line_nr=i, symbol='['), color=FILE_LINES_COLOR, end='') line = file_dict[sourcerange.file][i - 1].rstrip('\n') try: lexer = get_lexer_for_filename(sourcerange.file) except ClassNotFound: lexer = TextLexer() lexer.add_filter(VisibleWhitespaceFilter( spaces=True, tabs=True, tabsize=SpacingHelper.DEFAULT_TAB_WIDTH)) # highlight() combines lexer and formatter to output a ``str`` # object. printed_chars = 0 if i == sourcerange.start.line and sourcerange.start.column: console_printer.print(highlight_text( no_color, line[:sourcerange.start.column - 1], BackgroundMessageStyle, lexer), end='') printed_chars = sourcerange.start.column - 1 if i == sourcerange.end.line and sourcerange.end.column: console_printer.print(highlight_text( no_color, line[printed_chars:sourcerange.end.column - 1], BackgroundSourceRangeStyle, lexer), end='') console_printer.print(highlight_text( no_color, line[sourcerange.end.column - 1:], BackgroundSourceRangeStyle, lexer), end='') console_printer.print('') else: console_printer.print(highlight_text( no_color, line[printed_chars:], BackgroundMessageStyle, lexer), end='') console_printer.print('')
def run(self): self.assert_has_content() try: lexer = get_lexer_by_name(self.arguments[0]) except ValueError: # no lexer found - use the text one instead of an exception lexer = TextLexer() lexer.add_filter(ctypes_types_highlighter) lexer.add_filter(custom_highlighters) # take an arbitrary option if more than one is given formatter = self.options and \ VARIANTS[self.options.keys()[0]] or \ DEFAULT print >>open('pygments.css', 'w'), formatter.get_style_defs('.highlight') parsed = highlight(u'\n'.join(self.content), lexer, formatter) return [nodes.raw('', parsed, format='html')]
def main(args=sys.argv): """ Main command line entry point. """ # pylint: disable-msg=R0911,R0912,R0915 usage = USAGE % ((args[0],) * 6) try: popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHgs") except getopt.GetoptError: print(usage, file=sys.stderr) return 2 opts = {} O_opts = [] P_opts = [] F_opts = [] for opt, arg in popts: if opt == "-O": O_opts.append(arg) elif opt == "-P": P_opts.append(arg) elif opt == "-F": F_opts.append(arg) opts[opt] = arg if opts.pop("-h", None) is not None: print(usage) return 0 if opts.pop("-V", None) is not None: print("Pygments version %s, (c) 2006-2014 by Georg Brandl." % __version__) return 0 # handle ``pygmentize -L`` L_opt = opts.pop("-L", None) if L_opt is not None: if opts: print(usage, file=sys.stderr) return 2 # print version main(["", "-V"]) if not args: args = ["lexer", "formatter", "filter", "style"] for arg in args: _print_list(arg.rstrip("s")) return 0 # handle ``pygmentize -H`` H_opt = opts.pop("-H", None) if H_opt is not None: if opts or len(args) != 2: print(usage, file=sys.stderr) return 2 what, name = args if what not in ("lexer", "formatter", "filter"): print(usage, file=sys.stderr) return 2 _print_help(what, name) return 0 # parse -O options parsed_opts = _parse_options(O_opts) opts.pop("-O", None) # parse -P options for p_opt in P_opts: try: name, value = p_opt.split("=", 1) except ValueError: parsed_opts[p_opt] = True else: parsed_opts[name] = value opts.pop("-P", None) # encodings inencoding = parsed_opts.get("inencoding", parsed_opts.get("encoding")) outencoding = parsed_opts.get("outencoding", parsed_opts.get("encoding")) # handle ``pygmentize -N`` infn = opts.pop("-N", None) if infn is not None: try: lexer = get_lexer_for_filename(infn, **parsed_opts) except ClassNotFound as err: lexer = TextLexer() except OptionError as err: print("Error:", err, file=sys.stderr) return 1 print(lexer.aliases[0]) return 0 # handle ``pygmentize -S`` S_opt = opts.pop("-S", None) a_opt = opts.pop("-a", None) if S_opt is not None: f_opt = opts.pop("-f", None) if not f_opt: print(usage, file=sys.stderr) return 2 if opts or args: print(usage, file=sys.stderr) return 2 try: parsed_opts["style"] = S_opt fmter = get_formatter_by_name(f_opt, **parsed_opts) except ClassNotFound as err: print(err, file=sys.stderr) return 1 arg = a_opt or "" try: print(fmter.get_style_defs(arg)) except Exception as err: print("Error:", err, file=sys.stderr) return 1 return 0 # if no -S is given, -a is not allowed if a_opt is not None: print(usage, file=sys.stderr) return 2 # parse -F options F_opts = _parse_filters(F_opts) opts.pop("-F", None) # select lexer lexer = opts.pop("-l", None) if lexer: try: lexer = get_lexer_by_name(lexer, **parsed_opts) except (OptionError, ClassNotFound) as err: print("Error:", err, file=sys.stderr) return 1 # read input code code = None if args: if len(args) > 1: print(usage, file=sys.stderr) return 2 if "-s" in opts: print("Error: -s option not usable when input file specified", file=sys.stderr) return 1 infn = args[0] try: with open(infn, "rb") as infp: code = infp.read() except Exception as err: print("Error: cannot read infile:", err, file=sys.stderr) return 1 if not inencoding: code, inencoding = guess_decode(code) # do we have to guess the lexer? if not lexer: try: lexer = get_lexer_for_filename(infn, code, **parsed_opts) except ClassNotFound as err: if "-g" in opts: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: print("Error:", err, file=sys.stderr) return 1 except OptionError as err: print("Error:", err, file=sys.stderr) return 1 elif "-s" not in opts: # treat stdin as full file (-s support is later) # read code from terminal, always in binary mode since we want to # decode ourselves and be tolerant with it if sys.version_info > (3,): # Python 3: we have to use .buffer to get a binary stream code = sys.stdin.buffer.read() else: code = sys.stdin.read() if not inencoding: code, inencoding = guess_decode_from_terminal(code, sys.stdin) # else the lexer will do the decoding if not lexer: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) # select formatter outfn = opts.pop("-o", None) fmter = opts.pop("-f", None) if fmter: try: fmter = get_formatter_by_name(fmter, **parsed_opts) except (OptionError, ClassNotFound) as err: print("Error:", err, file=sys.stderr) return 1 if outfn: if not fmter: try: fmter = get_formatter_for_filename(outfn, **parsed_opts) except (OptionError, ClassNotFound) as err: print("Error:", err, file=sys.stderr) return 1 try: outfile = open(outfn, "wb") except Exception as err: print("Error: cannot open outfile:", err, file=sys.stderr) return 1 else: if not fmter: fmter = TerminalFormatter(**parsed_opts) if sys.version_info > (3,): # Python 3: we have to use .buffer to get a binary stream outfile = sys.stdout.buffer else: outfile = sys.stdout # determine output encoding if not explicitly selected if not outencoding: if outfn: # output file? use lexer encoding for now (can still be None) fmter.encoding = inencoding else: # else use terminal encoding fmter.encoding = terminal_encoding(sys.stdout) # provide coloring under Windows, if possible if not outfn and sys.platform in ("win32", "cygwin") and fmter.name in ("Terminal", "Terminal256"): # unfortunately colorama doesn't support binary streams on Py3 if sys.version_info > (3,): import io outfile = io.TextIOWrapper(outfile, encoding=fmter.encoding) fmter.encoding = None try: import colorama.initialise except ImportError: pass else: outfile = colorama.initialise.wrap_stream(outfile, convert=None, strip=None, autoreset=False, wrap=True) # When using the LaTeX formatter and the option `escapeinside` is # specified, we need a special lexer which collects escaped text # before running the chosen language lexer. escapeinside = parsed_opts.get("escapeinside", "") if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter): left = escapeinside[0] right = escapeinside[1] lexer = LatexEmbeddedLexer(left, right, lexer) # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) if "-s" not in opts: # process whole input as per normal... highlight(code, lexer, fmter, outfile) else: if not lexer: print("Error: when using -s a lexer has to be selected with -l", file=sys.stderr) return 1 # line by line processing of stdin (eg: for 'tail -f')... try: while 1: if sys.version_info > (3,): # Python 3: we have to use .buffer to get a binary stream line = sys.stdin.buffer.readline() else: line = sys.stdin.readline() if not line: break if not inencoding: line = guess_decode_from_terminal(line, sys.stdin)[0] highlight(line, lexer, fmter, outfile) if hasattr(outfile, "flush"): outfile.flush() except KeyboardInterrupt: return 0 except Exception: raise import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += "\n (f%s)" % info[-2].split("\n")[0].strip()[1:] print(file=sys.stderr) print("*** Error while highlighting:", file=sys.stderr) print(msg, file=sys.stderr) return 1 return 0
else: if sys.version_info < (3, ): # use terminal encoding; Python 3's terminals already do that lexer.encoding = getattr(sys.stdin, 'encoding', None) or 'utf-8' fmter.encoding = getattr(sys.stdout, 'encoding', None) or 'utf-8' elif not outfn and sys.version_info > (3, ): # output to terminal with encoding -> use .buffer outfile = sys.stdout.buffer # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) highlight(code, lexer, fmter, outfile) except Exception, err: import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] print >> sys.stderr print >> sys.stderr, '*** Error while highlighting:' print >> sys.stderr, msg return 1 return 0
class ConsoleInteractionTest(unittest.TestCase): def setUp(self): self.log_printer = ListLogPrinter() self.console_printer = ConsolePrinter(print_colored=False) self.no_color = not self.console_printer.print_colored self.file_diff_dict = {} self.section = Section('t') self.local_bears = OrderedDict([('default', [SomelocalBear]), ('test', [SomelocalBear])]) self.global_bears = OrderedDict([('default', [SomeglobalBear]), ('test', [SomeglobalBear])]) self.old_open_editor_applicable = OpenEditorAction.is_applicable OpenEditorAction.is_applicable = staticmethod( lambda *args: 'OpenEditorAction cannot be applied') self.old_apply_patch_applicable = ApplyPatchAction.is_applicable ApplyPatchAction.is_applicable = staticmethod( lambda *args: 'ApplyPatchAction cannot be applied') self.lexer = TextLexer() self.lexer.add_filter(VisibleWhitespaceFilter( spaces=True, tabs=True, tabsize=SpacingHelper.DEFAULT_TAB_WIDTH)) def tearDown(self): OpenEditorAction.is_applicable = self.old_open_editor_applicable ApplyPatchAction.is_applicable = self.old_apply_patch_applicable def test_require_settings(self): curr_section = Section('') self.assertRaises(TypeError, acquire_settings, self.log_printer, 0, curr_section) with simulate_console_inputs(0, 1, 2) as generator: self.assertEqual(acquire_settings(self.log_printer, {'setting': ['help text', 'SomeBear']}, curr_section), {'setting': 0}) self.assertEqual(acquire_settings(self.log_printer, {'setting': ['help text', 'SomeBear', 'AnotherBear']}, curr_section), {'setting': 1}) self.assertEqual(acquire_settings(self.log_printer, {'setting': ['help text', 'SomeBear', 'AnotherBear', 'YetAnotherBear']}, curr_section), {'setting': 2}) self.assertEqual(generator.last_input, 2) def test_print_diffs_info(self): file_dict = {'a': ['a\n', 'b\n', 'c\n'], 'b': ['old_first\n']} diff_dict = {'a': Diff(file_dict['a']), 'b': Diff(file_dict['b'])} diff_dict['a'].add_lines(1, ['test\n']) diff_dict['a'].delete_line(3) diff_dict['b'].add_lines(0, ['first\n']) previous_diffs = {'a': Diff(file_dict['a'])} previous_diffs['a'].change_line(2, 'b\n', 'b_changed\n') with retrieve_stdout() as stdout: print_diffs_info(diff_dict, self.console_printer) self.assertEqual(stdout.getvalue(), '| | +1 -1 in a\n' '| | +1 -0 in b\n') @patch('coalib.output.ConsoleInteraction.acquire_actions_and_apply') @patch('coalib.output.ConsoleInteraction.ShowPatchAction.' 'apply_from_section') def test_print_result_interactive_small_patch(self, apply_from_section, _): file_dict = {'a': ['a\n', 'b\n', 'c\n'], 'b': ['old_first\n']} diff_dict = {'a': Diff(file_dict['a']), 'b': Diff(file_dict['b'])} diff_dict['a'].add_lines(1, ['test\n']) diff_dict['a'].delete_line(3) result = Result('origin', 'msg', diffs=diff_dict) section = Section('test') print_result(self.console_printer, section, self.file_diff_dict, result, file_dict, True) apply_from_section.assert_called_once_with( result, file_dict, self.file_diff_dict, section) @patch('coalib.output.ConsoleInteraction.acquire_actions_and_apply') @patch('coalib.output.ConsoleInteraction.print_diffs_info') def test_print_result_interactive_big_patch(self, diffs_info, _): file_dict = {'a': ['a\n', 'b\n', 'c\n'], 'b': ['old_first\n']} diff_dict = {'a': Diff(file_dict['a']), 'b': Diff(file_dict['b'])} diff_dict['a'].add_lines(1, ['test\n', 'test1\n', 'test2\n']) diff_dict['a'].delete_line(3) diff_dict['a'].add_lines(3, ['3test\n']) result = Result('origin', 'msg', diffs=diff_dict) section = Section('test') print_result(self.console_printer, section, self.file_diff_dict, result, file_dict, True) diffs_info.assert_called_once_with(diff_dict, self.console_printer) def test_print_result(self): print_result(self.console_printer, None, self.file_diff_dict, 'illegal value', {}) with simulate_console_inputs(0): print_result(self.console_printer, self.section, self.file_diff_dict, Result('origin', 'msg', diffs={}), {}) with make_temp() as testfile_path: file_dict = { testfile_path: ['1\n', '2\n', '3\n'], 'f_b': ['1', '2', '3'] } diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, '3\n', '3_changed\n') ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) # Interaction must be closed by the user with `0` if it's not a # param with simulate_console_inputs('INVALID', -1, 1, 0, 3) as input_generator: curr_section = Section('') print_section_beginning(self.console_printer, curr_section) print_result(self.console_printer, curr_section, self.file_diff_dict, Result('origin', 'msg', diffs={ testfile_path: diff}), file_dict) self.assertEqual(input_generator.last_input, 3) self.file_diff_dict.clear() with open(testfile_path) as f: self.assertEqual(f.readlines(), ['1\n', '3_changed\n']) os.remove(testfile_path + '.orig') name, section = get_action_info(curr_section, TestAction().get_metadata(), failed_actions=set()) self.assertEqual(input_generator.last_input, 4) self.assertEqual(str(section), " {param : '3'}") self.assertEqual(name, 'TestAction') # Check if the user is asked for the parameter only the first time. # Use OpenEditorAction that needs this parameter (editor command). with simulate_console_inputs(1, 'test_editor', 0, 1, 0) as generator: OpenEditorAction.is_applicable = staticmethod(lambda *args: True) patch_result = Result('origin', 'msg', diffs={testfile_path: diff}) patch_result.file = 'f_b' print_result(self.console_printer, curr_section, self.file_diff_dict, patch_result, file_dict) # choose action, choose editor, choose no action (-1 -> 2) self.assertEqual(generator.last_input, 2) # It shoudn't ask for parameter again print_result(self.console_printer, curr_section, self.file_diff_dict, patch_result, file_dict) self.assertEqual(generator.last_input, 4) def test_print_affected_files(self): with retrieve_stdout() as stdout, \ make_temp() as some_file: file_dict = {some_file: ['1\n', '2\n', '3\n']} affected_code = (SourceRange.from_values(some_file),) print_affected_files(self.console_printer, self.log_printer, Result('origin', 'message', affected_code=affected_code), file_dict) self.assertEqual(stdout.getvalue(), '\n'+relpath(some_file)+'\n') def test_acquire_actions_and_apply(self): with make_temp() as testfile_path: file_dict = {testfile_path: ['1\n', '2\n', '3\n']} diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, '3\n', '3_changed\n') with simulate_console_inputs(1, 0) as generator, \ retrieve_stdout() as sio: ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) acquire_actions_and_apply(self.console_printer, Section(''), self.file_diff_dict, Result('origin', 'message', diffs={ testfile_path: diff}), file_dict) self.assertEqual(generator.last_input, 1) self.assertIn(ApplyPatchAction.SUCCESS_MESSAGE, sio.getvalue()) class InvalidateTestAction(ResultAction): is_applicable = staticmethod(lambda *args: True) def apply(*args, **kwargs): ApplyPatchAction.is_applicable = staticmethod( lambda *args: 'ApplyPatchAction cannot be applied.') old_applypatch_is_applicable = ApplyPatchAction.is_applicable ApplyPatchAction.is_applicable = staticmethod(lambda *args: True) cli_actions = [ApplyPatchAction(), InvalidateTestAction()] with simulate_console_inputs(2, 1, 0) as generator, \ retrieve_stdout() as sio: acquire_actions_and_apply(self.console_printer, Section(''), self.file_diff_dict, Result('origin', 'message', diffs={testfile_path: diff}), file_dict, cli_actions=cli_actions) self.assertEqual(generator.last_input, 2) action_fail = 'Failed to execute the action' self.assertNotIn(action_fail, sio.getvalue()) apply_path_desc = ApplyPatchAction().get_metadata().desc self.assertEqual(sio.getvalue().count(apply_path_desc), 1) ApplyPatchAction.is_applicable = old_applypatch_is_applicable def test_ask_for_actions_and_apply(self): failed_actions = set() action = TestAction() args = [self.console_printer, Section(''), [action.get_metadata()], {'TestAction': action}, failed_actions, Result('origin', 'message'), {}, {}] with simulate_console_inputs(1, 'param1', 1, 'param2') as generator: action.apply = unittest.mock.Mock(side_effect=AssertionError) ask_for_action_and_apply(*args) self.assertEqual(generator.last_input, 1) self.assertIn('TestAction', failed_actions) action.apply = lambda *args, **kwargs: {} ask_for_action_and_apply(*args) self.assertEqual(generator.last_input, 3) self.assertNotIn('TestAction', failed_actions) def test_default_input(self): action = TestAction() args = [self.console_printer, Section(''), [action.get_metadata()], {'TestAction': action}, set(), Result('origin', 'message'), {}, {}] with simulate_console_inputs('') as generator: self.assertFalse(ask_for_action_and_apply(*args)) def test_print_result_no_input(self): with make_temp() as testfile_path: file_dict = {testfile_path: ['1\n', '2\n', '3\n']} diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, '3\n', '3_changed\n') with simulate_console_inputs(1, 2, 3) as generator, \ retrieve_stdout() as stdout: ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) print_results_no_input(self.log_printer, Section('someSection'), [Result('origin', 'message', diffs={ testfile_path: diff})], file_dict, self.file_diff_dict, self.console_printer) self.assertEqual(generator.last_input, -1) self.assertEqual(stdout.getvalue(), """ Project wide: | | [NORMAL] origin: | | {}\n""".format(highlight_text(self.no_color, 'message', style=BackgroundMessageStyle))) def test_print_section_beginning(self): with retrieve_stdout() as stdout: print_section_beginning(self.console_printer, Section('name')) self.assertEqual(stdout.getvalue(), 'Executing section name...\n') def test_nothing_done(self): nothing_done(self.log_printer) self.assertEqual(['No existent section was targeted or enabled. ' 'Nothing to do.'], [log.message for log in self.log_printer.logs]) def test_print_results_empty(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(''), [], {}, {}, self.console_printer) self.assertEqual(stdout.getvalue(), '') def test_print_results_project_wide(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(''), [Result('origin', 'message')], {}, {}, self.console_printer) self.assertEqual( '\n{}\n| | [NORMAL] origin:\n| | {}\n'.format( STR_PROJECT_WIDE, highlight_text(self.no_color, 'message', style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_for_file(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(''), [Result.from_values('SpaceConsistencyBear', 'Trailing whitespace found', file='filename', line=2)], {abspath('filename'): ['test line\n', 'line 2\n', 'line 3\n']}, {}, self.console_printer) self.assertEqual("""\nfilename | 2| {} | | [NORMAL] SpaceConsistencyBear: | | {}\n""".format(highlight_text(self.no_color, 'line 2', self.lexer), highlight_text(self.no_color, 'Trailing whitespace found', style=BackgroundMessageStyle)), stdout.getvalue()) with retrieve_stdout() as stdout: print_results( self.log_printer, Section(''), [Result.from_values('SpaceConsistencyBear', 'Trailing whitespace found', file='filename', line=5)], {abspath('filename'): ['test line\n', 'line 2\n', 'line 3\n', 'line 4\n', 'line 5\n']}, {}, self.console_printer) self.assertEqual("""\nfilename | 5| {} | | [NORMAL] SpaceConsistencyBear: | | {}\n""".format(highlight_text(self.no_color, 'line 5', self.lexer), highlight_text(self.no_color, 'Trailing whitespace found', style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_sorting(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(''), [Result.from_values('SpaceConsistencyBear', 'Trailing whitespace found', file='file', line=5), Result.from_values('SpaceConsistencyBear', 'Trailing whitespace found', file='file', line=2)], {abspath('file'): ['test line\n', '\t\n', 'line 3\n', 'line 4\n', 'line 5\t\n']}, {}, self.console_printer) self.assertEqual(""" file | 2| {0} | | [NORMAL] SpaceConsistencyBear: | | {1} file | 5| {2} | | [NORMAL] SpaceConsistencyBear: | | {1}\n""".format(highlight_text(self.no_color, '\t', self.lexer), highlight_text(self.no_color, 'Trailing whitespace found', style=BackgroundMessageStyle), highlight_text(self.no_color, 'line 5\t', self.lexer)), stdout.getvalue()) def test_print_results_multiple_ranges(self): affected_code = ( SourceRange.from_values('some_file', 5, end_line=7), SourceRange.from_values('another_file', 1, 3, 1, 5), SourceRange.from_values('another_file', 3, 3, 3, 5)) with retrieve_stdout() as stdout: print_results( self.log_printer, Section(''), [Result('ClangCloneDetectionBear', 'Clone Found', affected_code)], {abspath('some_file'): ['line ' + str(i + 1) + '\n' for i in range(10)], abspath('another_file'): ['line ' + str(i + 1) for i in range(10)]}, {}, self.console_printer) self.assertEqual(""" another_file | 1| li{0}{1} another_file | 3| li{0}{2} some_file | 5| {3} | 6| {4} | 7| {5} | | [NORMAL] ClangCloneDetectionBear: | | {6}\n""".format(highlight_text(self.no_color, 'ne', self.lexer, BackgroundSourceRangeStyle), highlight_text(self.no_color, ' 1', self.lexer), highlight_text(self.no_color, ' 3', self.lexer), highlight_text(self.no_color, 'line 5', self.lexer), highlight_text(self.no_color, 'line 6', self.lexer), highlight_text(self.no_color, 'line 7', self.lexer), highlight_text(self.no_color, 'Clone Found', style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_missing_file(self): self.log_printer.log_level = logging.CRITICAL with retrieve_stdout() as stdout: print_results( self.log_printer, Section(''), [Result('t', 'msg'), Result.from_values('t', 'msg', file='file', line=5)], {}, {}, self.console_printer) self.assertEqual('\n' + STR_PROJECT_WIDE + '\n' '| | [NORMAL] t:\n' '| | {0}\n' # Second results file isn't there, no context is # printed, only a warning log message which we # don't catch '| | [NORMAL] t:\n' '| | {0}\n'.format( highlight_text(self.no_color, 'msg', style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_missing_line(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(''), [Result.from_values('t', 'msg', file='file', line=5), Result.from_values('t', 'msg', file='file', line=6)], {abspath('file'): ['line ' + str(i + 1) for i in range(5)]}, {}, self.console_printer) self.assertEqual('\n' 'file\n' '| 5| {0}\n' '| | [NORMAL] t:\n' '| | {1}\n' '\n' 'file\n' '| 6| {2}\n' '| | [NORMAL] t:\n' '| | {1}\n'.format( highlight_text(self.no_color, 'line 5', self.lexer), highlight_text(self.no_color, 'msg', style=BackgroundMessageStyle), STR_LINE_DOESNT_EXIST), stdout.getvalue()) def test_print_results_without_line(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(''), [Result.from_values('t', 'msg', file='file')], {abspath('file'): []}, {}, self.console_printer) self.assertEqual( '\nfile\n' '| | [NORMAL] t:\n' '| | {}\n'.format(highlight_text( self.no_color, 'msg', style=BackgroundMessageStyle)), stdout.getvalue())
# stdin/stdout encoding otherwise. # (This is a compromise, I'm not too happy with it...) if 'encoding' not in parsed_opts and 'outencoding' not in parsed_opts: if outfn: # encoding pass-through fmter.encoding = 'latin1' else: # use terminal encoding lexer.encoding = getattr(sys.stdin, 'encoding', None) or 'ascii' fmter.encoding = getattr(sys.stdout, 'encoding', None) or 'ascii' # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) highlight(code, lexer, fmter, outfile) except Exception, err: import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] print >>sys.stderr print >>sys.stderr, '*** Error while highlighting:' print >>sys.stderr, msg return 1 return 0
def main(args=sys.argv): """ Main command line entry point. """ # pylint: disable-msg=R0911,R0912,R0915 usage = USAGE % ((args[0], ) * 6) try: popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHgs") except getopt.GetoptError: print(usage, file=sys.stderr) return 2 opts = {} O_opts = [] P_opts = [] F_opts = [] for opt, arg in popts: if opt == '-O': O_opts.append(arg) elif opt == '-P': P_opts.append(arg) elif opt == '-F': F_opts.append(arg) opts[opt] = arg if opts.pop('-h', None) is not None: print(usage) return 0 if opts.pop('-V', None) is not None: print('Pygments version %s, (c) 2006-2014 by Georg Brandl.' % __version__) return 0 # handle ``pygmentize -L`` L_opt = opts.pop('-L', None) if L_opt is not None: if opts: print(usage, file=sys.stderr) return 2 # print version main(['', '-V']) if not args: args = ['lexer', 'formatter', 'filter', 'style'] for arg in args: _print_list(arg.rstrip('s')) return 0 # handle ``pygmentize -H`` H_opt = opts.pop('-H', None) if H_opt is not None: if opts or len(args) != 2: print(usage, file=sys.stderr) return 2 what, name = args if what not in ('lexer', 'formatter', 'filter'): print(usage, file=sys.stderr) return 2 _print_help(what, name) return 0 # parse -O options parsed_opts = _parse_options(O_opts) opts.pop('-O', None) # parse -P options for p_opt in P_opts: try: name, value = p_opt.split('=', 1) except ValueError: parsed_opts[p_opt] = True else: parsed_opts[name] = value opts.pop('-P', None) # encodings inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding')) outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding')) # handle ``pygmentize -N`` infn = opts.pop('-N', None) if infn is not None: try: lexer = get_lexer_for_filename(infn, **parsed_opts) except ClassNotFound as err: lexer = TextLexer() except OptionError as err: print('Error:', err, file=sys.stderr) return 1 print(lexer.aliases[0]) return 0 # handle ``pygmentize -S`` S_opt = opts.pop('-S', None) a_opt = opts.pop('-a', None) if S_opt is not None: f_opt = opts.pop('-f', None) if not f_opt: print(usage, file=sys.stderr) return 2 if opts or args: print(usage, file=sys.stderr) return 2 try: parsed_opts['style'] = S_opt fmter = get_formatter_by_name(f_opt, **parsed_opts) except ClassNotFound as err: print(err, file=sys.stderr) return 1 arg = a_opt or '' try: print(fmter.get_style_defs(arg)) except Exception as err: print('Error:', err, file=sys.stderr) return 1 return 0 # if no -S is given, -a is not allowed if a_opt is not None: print(usage, file=sys.stderr) return 2 # parse -F options F_opts = _parse_filters(F_opts) opts.pop('-F', None) # select formatter outfn = opts.pop('-o', None) fmter = opts.pop('-f', None) if fmter: try: fmter = get_formatter_by_name(fmter, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 if outfn: if not fmter: try: fmter = get_formatter_for_filename(outfn, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 try: outfile = open(outfn, 'wb') except Exception as err: print('Error: cannot open outfile:', err, file=sys.stderr) return 1 else: if not fmter: fmter = TerminalFormatter(**parsed_opts) if sys.version_info > (3, ): # Python 3: we have to use .buffer to get a binary stream outfile = sys.stdout.buffer else: outfile = sys.stdout # determine output encoding if not explicitly selected if not outencoding: if outfn: # output file? -> encoding pass-through fmter.encoding = inencoding else: # else use terminal encoding fmter.encoding = terminal_encoding(sys.stdout) # provide coloring under Windows, if possible if not outfn and sys.platform in ('win32', 'cygwin') and \ fmter.name in ('Terminal', 'Terminal256'): # unfortunately colorama doesn't support binary streams on Py3 if sys.version_info > (3, ): import io outfile = io.TextIOWrapper(outfile, encoding=fmter.encoding) fmter.encoding = None try: import colorama.initialise except ImportError: pass else: outfile = colorama.initialise.wrap_stream(outfile, convert=None, strip=None, autoreset=False, wrap=True) # select lexer lexer = opts.pop('-l', None) if lexer: try: lexer = get_lexer_by_name(lexer, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 # read input code code = None if args: if len(args) > 1: print(usage, file=sys.stderr) return 2 if '-s' in opts: print('Error: -s option not usable when input file specified', file=sys.stderr) return 1 infn = args[0] try: with open(infn, 'rb') as infp: code = infp.read() except Exception as err: print('Error: cannot read infile:', err, file=sys.stderr) return 1 if not inencoding: code, inencoding = guess_decode(code) # do we have to guess the lexer? if not lexer: try: lexer = get_lexer_for_filename(infn, code, **parsed_opts) except ClassNotFound as err: if '-g' in opts: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: print('Error:', err, file=sys.stderr) return 1 except OptionError as err: print('Error:', err, file=sys.stderr) return 1 elif '-s' not in opts: # treat stdin as full file (-s support is later) # read code from terminal, always in binary mode since we want to # decode ourselves and be tolerant with it if sys.version_info > (3, ): # Python 3: we have to use .buffer to get a binary stream code = sys.stdin.buffer.read() else: code = sys.stdin.read() if not inencoding: code, inencoding = guess_decode_from_terminal(code, sys.stdin) # else the lexer will do the decoding if not lexer: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) # When using the LaTeX formatter and the option `escapeinside` is # specified, we need a special lexer which collects escaped text # before running the chosen language lexer. escapeinside = parsed_opts.get('escapeinside', '') if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter): left = escapeinside[0] right = escapeinside[1] lexer = LatexEmbeddedLexer(left, right, lexer) # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) if '-s' not in opts: # process whole input as per normal... highlight(code, lexer, fmter, outfile) else: if not lexer: print( 'Error: when using -s a lexer has to be selected with -l', file=sys.stderr) return 1 # line by line processing of stdin (eg: for 'tail -f')... try: while 1: if sys.version_info > (3, ): # Python 3: we have to use .buffer to get a binary stream line = sys.stdin.buffer.readline() else: line = sys.stdin.readline() if not line: break if not inencoding: line = guess_decode_from_terminal(line, sys.stdin)[0] highlight(line, lexer, fmter, outfile) if hasattr(outfile, 'flush'): outfile.flush() except KeyboardInterrupt: return 0 except Exception: import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] print(file=sys.stderr) print('*** Error while highlighting:', file=sys.stderr) print(msg, file=sys.stderr) return 1 return 0
class ConsoleInteractionTest(unittest.TestCase): def setUp(self): self.log_printer = LogPrinter(ConsolePrinter(print_colored=False)) self.console_printer = ConsolePrinter(print_colored=False) self.file_diff_dict = {} self.section = Section("t") self.local_bears = OrderedDict([("default", [SomelocalBear]), ("test", [SomelocalBear])]) self.global_bears = OrderedDict([("default", [SomeglobalBear]), ("test", [SomeglobalBear])]) self.old_open_editor_applicable = OpenEditorAction.is_applicable OpenEditorAction.is_applicable = staticmethod(lambda *args: False) self.old_apply_patch_applicable = ApplyPatchAction.is_applicable ApplyPatchAction.is_applicable = staticmethod(lambda *args: False) self.lexer = TextLexer() self.lexer.add_filter( VisibleWhitespaceFilter(spaces="•", tabs=True, tabsize=SpacingHelper.DEFAULT_TAB_WIDTH)) def tearDown(self): OpenEditorAction.is_applicable = self.old_open_editor_applicable ApplyPatchAction.is_applicable = self.old_apply_patch_applicable def test_require_settings(self): self.assertRaises(TypeError, acquire_settings, self.log_printer, 0) with simulate_console_inputs(0, 1, 2) as generator: self.assertEqual( acquire_settings(self.log_printer, {"setting": ["help text", "SomeBear"]}), {"setting": 0}) self.assertEqual( acquire_settings( self.log_printer, {"setting": ["help text", "SomeBear", "AnotherBear"]}), {"setting": 1}) self.assertEqual( acquire_settings( self.log_printer, { "setting": [ "help text", "SomeBear", "AnotherBear", "YetAnotherBear" ] }), {"setting": 2}) self.assertEqual(generator.last_input, 2) def test_print_diffs_info(self): file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]} diff_dict = {"a": Diff(file_dict['a']), "b": Diff(file_dict['b'])} diff_dict["a"].add_lines(1, ["test\n"]) diff_dict["a"].delete_line(3) diff_dict["b"].add_lines(0, ["first\n"]) previous_diffs = {"a": Diff(file_dict['a'])} previous_diffs["a"].change_line(2, "b\n", "b_changed\n") with retrieve_stdout() as stdout: print_diffs_info(diff_dict, self.console_printer) self.assertEqual(stdout.getvalue(), "| | +1 -1 in a\n" "| | +1 -0 in b\n") @patch("coalib.output.ConsoleInteraction.acquire_actions_and_apply") @patch("coalib.output.ConsoleInteraction.ShowPatchAction." "apply_from_section") def test_print_result_interactive_small_patch(self, apply_from_section, _): file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]} diff_dict = {"a": Diff(file_dict['a']), "b": Diff(file_dict['b'])} diff_dict["a"].add_lines(1, ["test\n"]) diff_dict["a"].delete_line(3) result = Result("origin", "msg", diffs=diff_dict) section = Section("test") print_result(self.console_printer, self.log_printer, section, self.file_diff_dict, result, file_dict, True) apply_from_section.assert_called_once_with(result, file_dict, self.file_diff_dict, section) @patch("coalib.output.ConsoleInteraction.acquire_actions_and_apply") @patch("coalib.output.ConsoleInteraction.print_diffs_info") def test_print_result_interactive_big_patch(self, diffs_info, _): file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]} diff_dict = {"a": Diff(file_dict['a']), "b": Diff(file_dict['b'])} diff_dict["a"].add_lines(1, ["test\n", "test1\n", "test2\n"]) diff_dict["a"].delete_line(3) diff_dict["a"].add_lines(3, ["3test\n"]) result = Result("origin", "msg", diffs=diff_dict) section = Section("test") print_result(self.console_printer, self.log_printer, section, self.file_diff_dict, result, file_dict, True) diffs_info.assert_called_once_with(diff_dict, self.console_printer) def test_print_result(self): print_result(self.console_printer, self.log_printer, None, self.file_diff_dict, "illegal value", {}) with simulate_console_inputs(0): print_result(self.console_printer, self.log_printer, self.section, self.file_diff_dict, Result("origin", "msg", diffs={}), {}) with make_temp() as testfile_path: file_dict = { testfile_path: ["1\n", "2\n", "3\n"], "f_b": ["1", "2", "3"] } diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, "3\n", "3_changed\n") ApplyPatchAction.is_applicable = staticmethod(lambda *args: True) # Interaction must be closed by the user with `0` if it's not a # param with simulate_console_inputs("INVALID", -1, 1, 0, 3) as input_generator: curr_section = Section("") print_section_beginning(self.console_printer, curr_section) print_result( self.console_printer, self.log_printer, curr_section, self.file_diff_dict, Result("origin", "msg", diffs={testfile_path: diff}), file_dict) self.assertEqual(input_generator.last_input, 3) self.file_diff_dict.clear() with open(testfile_path) as f: self.assertEqual(f.readlines(), ["1\n", "3_changed\n"]) os.remove(testfile_path + ".orig") name, section = get_action_info(curr_section, TestAction().get_metadata(), failed_actions=set()) self.assertEqual(input_generator.last_input, 4) self.assertEqual(str(section), " {param : '3'}") self.assertEqual(name, "TestAction") # Check if the user is asked for the parameter only the first time. # Use OpenEditorAction that needs this parameter (editor command). with simulate_console_inputs(1, "test_editor", 0, 1, 0) as generator: OpenEditorAction.is_applicable = staticmethod(lambda *args: True) patch_result = Result("origin", "msg", diffs={testfile_path: diff}) patch_result.file = "f_b" print_result(self.console_printer, self.log_printer, curr_section, self.file_diff_dict, patch_result, file_dict) # choose action, choose editor, choose no action (-1 -> 2) self.assertEqual(generator.last_input, 2) # It shoudn't ask for parameter again print_result(self.console_printer, self.log_printer, curr_section, self.file_diff_dict, patch_result, file_dict) self.assertEqual(generator.last_input, 4) def test_print_affected_files(self): with retrieve_stdout() as stdout, \ make_temp() as some_file: file_dict = {some_file: ["1\n", "2\n", "3\n"]} affected_code = (SourceRange.from_values(some_file), ) print_affected_files(self.console_printer, self.log_printer, Section(""), Result("origin", "message", affected_code=affected_code), file_dict, color=True) self.assertEqual(stdout.getvalue(), "\n" + relpath(some_file) + "\n") def test_acquire_actions_and_apply(self): with make_temp() as testfile_path: file_dict = {testfile_path: ["1\n", "2\n", "3\n"]} diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, "3\n", "3_changed\n") with simulate_console_inputs(1, 0) as generator, \ retrieve_stdout() as sio: ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) acquire_actions_and_apply( self.console_printer, self.log_printer, Section(""), self.file_diff_dict, Result("origin", "message", diffs={testfile_path: diff}), file_dict) self.assertEqual(generator.last_input, 1) self.assertIn(ApplyPatchAction.SUCCESS_MESSAGE, sio.getvalue()) class InvalidateTestAction(ResultAction): is_applicable = staticmethod(lambda *args: True) def apply(*args, **kwargs): ApplyPatchAction.is_applicable = staticmethod( lambda *args: False) old_applypatch_is_applicable = ApplyPatchAction.is_applicable ApplyPatchAction.is_applicable = staticmethod(lambda *args: True) cli_actions = [ApplyPatchAction(), InvalidateTestAction()] with simulate_console_inputs(2, 1, 0) as generator, \ retrieve_stdout() as sio: acquire_actions_and_apply(self.console_printer, self.log_printer, Section(""), self.file_diff_dict, Result("origin", "message", diffs={testfile_path: diff}), file_dict, cli_actions=cli_actions) self.assertEqual(generator.last_input, 2) action_fail = "Failed to execute the action" self.assertNotIn(action_fail, sio.getvalue()) apply_path_desc = ApplyPatchAction().get_metadata().desc self.assertEqual(sio.getvalue().count(apply_path_desc), 1) ApplyPatchAction.is_applicable = old_applypatch_is_applicable def test_ask_for_actions_and_apply(self): failed_actions = set() action = TestAction() args = [ self.log_printer, self.console_printer, Section(""), [action.get_metadata()], { 'TestAction': action }, failed_actions, Result("origin", "message"), {}, {} ] with simulate_console_inputs(1, 'param1', 1, 'param2') as generator: action.apply = unittest.mock.Mock(side_effect=AssertionError) ask_for_action_and_apply(*args) self.assertEqual(generator.last_input, 1) self.assertIn('TestAction', failed_actions) action.apply = lambda *args, **kwargs: {} ask_for_action_and_apply(*args) self.assertEqual(generator.last_input, 3) self.assertNotIn('TestAction', failed_actions) def test_default_input(self): action = TestAction() args = [ self.log_printer, self.console_printer, Section(""), [action.get_metadata()], { 'TestAction': action }, set(), Result("origin", "message"), {}, {} ] with simulate_console_inputs("") as generator: self.assertFalse(ask_for_action_and_apply(*args)) def test_print_result_no_input(self): with make_temp() as testfile_path: file_dict = {testfile_path: ["1\n", "2\n", "3\n"]} diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, "3\n", "3_changed\n") with simulate_console_inputs(1, 2, 3) as generator, \ retrieve_stdout() as stdout: ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) print_results_no_input( self.log_printer, Section("someSection"), [Result("origin", "message", diffs={testfile_path: diff})], file_dict, self.file_diff_dict, color=False) self.assertEqual(generator.last_input, -1) self.assertEqual( stdout.getvalue(), """ Project wide: | | [NORMAL] origin: | | {}\n""".format(highlight_text("message", style=BackgroundMessageStyle))) def test_print_section_beginning(self): with retrieve_stdout() as stdout: print_section_beginning(self.console_printer, Section("name")) self.assertEqual(stdout.getvalue(), "Executing section name...\n") def test_nothing_done(self): with retrieve_stdout() as stdout: nothing_done(self.log_printer) self.assertIn( "No existent section was targeted or enabled. " "Nothing to do.\n", stdout.getvalue()) def test_print_results_empty(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [], {}, {}) self.assertEqual(stdout.getvalue(), "") def test_print_results_project_wide(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [Result("origin", "message")], {}, {}, color=False) self.assertEqual( "\n{}\n| | [NORMAL] origin:\n| | {}\n".format( STR_PROJECT_WIDE, highlight_text("message", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_for_file(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [ Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="filename", line=2) ], {abspath("filename"): ["test line\n", "line 2\n", "line 3\n"]}, {}, color=False) self.assertEqual( """\nfilename | 2| {} | | [NORMAL] SpaceConsistencyBear: | | {}\n""".format( highlight_text('line 2', self.lexer), highlight_text("Trailing whitespace found", style=BackgroundMessageStyle)), stdout.getvalue()) with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [ Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="filename", line=5) ], { abspath("filename"): [ "test line\n", "line 2\n", "line 3\n", "line 4\n", "line 5\n" ] }, {}, color=False) self.assertEqual( """\nfilename | 5| {} | | [NORMAL] SpaceConsistencyBear: | | {}\n""".format( highlight_text('line 5', self.lexer), highlight_text("Trailing whitespace found", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_sorting(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [ Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="file", line=5), Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="file", line=2) ], { abspath("file"): [ "test line\n", "\t\n", "line 3\n", "line 4\n", "line 5\t\n" ] }, {}, color=False) self.assertEqual( """ file | 2| {0} | | [NORMAL] SpaceConsistencyBear: | | {1} file | 5| {2} | | [NORMAL] SpaceConsistencyBear: | | {1}\n""".format( highlight_text('\t', self.lexer), highlight_text("Trailing whitespace found", style=BackgroundMessageStyle), highlight_text('line 5\t', self.lexer)), stdout.getvalue()) def test_print_results_multiple_ranges(self): affected_code = (SourceRange.from_values("some_file", 5, end_line=7), SourceRange.from_values("another_file", 1, 3, 1, 5), SourceRange.from_values("another_file", 3, 3, 3, 5)) with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [ Result("ClangCloneDetectionBear", "Clone Found", affected_code) ], { abspath("some_file"): ["line " + str(i + 1) + "\n" for i in range(10)], abspath("another_file"): ["line " + str(i + 1) for i in range(10)] }, {}, color=False) self.assertEqual( """ another_file | 1| li{0}{1} another_file | 3| li{0}{2} some_file | 5| {3} | 6| {4} | 7| {5} | | [NORMAL] ClangCloneDetectionBear: | | {6}\n""".format( highlight_text('ne', self.lexer, BackgroundSourceRangeStyle), highlight_text(' 1', self.lexer), highlight_text(' 3', self.lexer), highlight_text('line 5', self.lexer), highlight_text('line 6', self.lexer), highlight_text('line 7', self.lexer), highlight_text("Clone Found", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_missing_file(self): self.log_printer = LogPrinter(NullPrinter()) with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [ Result("t", "msg"), Result.from_values("t", "msg", file="file", line=5) ], {}, {}, color=False) self.assertEqual( "\n" + STR_PROJECT_WIDE + "\n" "| | [NORMAL] t:\n" "| | {0}\n" # Second results file isn't there, no context is # printed, only a warning log message which we # don't catch "| | [NORMAL] t:\n" "| | {0}\n".format( highlight_text("msg", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_missing_line(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [ Result.from_values("t", "msg", file="file", line=5), Result.from_values("t", "msg", file="file", line=6) ], {abspath("file"): ["line " + str(i + 1) for i in range(5)]}, {}, color=False) self.assertEqual( "\n" "file\n" "| 5| {0}\n" "| | [NORMAL] t:\n" "| | {1}\n" "\n" "file\n" "| 6| {2}\n" "| | [NORMAL] t:\n" "| | {1}\n".format( highlight_text('line 5', self.lexer), highlight_text("msg", style=BackgroundMessageStyle), STR_LINE_DOESNT_EXIST), stdout.getvalue()) def test_print_results_without_line(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [Result.from_values("t", "msg", file="file")], {abspath("file"): []}, {}, color=False) self.assertEqual( "\nfile\n" "| | [NORMAL] t:\n" "| | {}\n".format( highlight_text("msg", style=BackgroundMessageStyle)), stdout.getvalue())
def main(args=sys.argv): """ Main command line entry point. """ # pylint: disable-msg=R0911,R0912,R0915 usage = USAGE % ((args[0],) * 6) if sys.platform in ['win32', 'cygwin']: try: # Provide coloring under Windows, if possible import colorama colorama.init() except ImportError: pass try: popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHg") except getopt.GetoptError: print(usage, file=sys.stderr) return 2 opts = {} O_opts = [] P_opts = [] F_opts = [] for opt, arg in popts: if opt == '-O': O_opts.append(arg) elif opt == '-P': P_opts.append(arg) elif opt == '-F': F_opts.append(arg) opts[opt] = arg if not opts and not args: print(usage) return 0 if opts.pop('-h', None) is not None: print(usage) return 0 if opts.pop('-V', None) is not None: print('Pygments version %s, (c) 2006-2014 by Georg Brandl.' % __version__) return 0 # handle ``pygmentize -L`` L_opt = opts.pop('-L', None) if L_opt is not None: if opts: print(usage, file=sys.stderr) return 2 # print version main(['', '-V']) if not args: args = ['lexer', 'formatter', 'filter', 'style'] for arg in args: _print_list(arg.rstrip('s')) return 0 # handle ``pygmentize -H`` H_opt = opts.pop('-H', None) if H_opt is not None: if opts or len(args) != 2: print(usage, file=sys.stderr) return 2 what, name = args if what not in ('lexer', 'formatter', 'filter'): print(usage, file=sys.stderr) return 2 _print_help(what, name) return 0 # parse -O options parsed_opts = _parse_options(O_opts) opts.pop('-O', None) # parse -P options for p_opt in P_opts: try: name, value = p_opt.split('=', 1) except ValueError: parsed_opts[p_opt] = True else: parsed_opts[name] = value opts.pop('-P', None) # handle ``pygmentize -N`` infn = opts.pop('-N', None) if infn is not None: try: lexer = get_lexer_for_filename(infn, **parsed_opts) except ClassNotFound as err: lexer = TextLexer() except OptionError as err: print('Error:', err, file=sys.stderr) return 1 print(lexer.aliases[0]) return 0 # handle ``pygmentize -S`` S_opt = opts.pop('-S', None) a_opt = opts.pop('-a', None) if S_opt is not None: f_opt = opts.pop('-f', None) if not f_opt: print(usage, file=sys.stderr) return 2 if opts or args: print(usage, file=sys.stderr) return 2 try: parsed_opts['style'] = S_opt fmter = get_formatter_by_name(f_opt, **parsed_opts) except ClassNotFound as err: print(err, file=sys.stderr) return 1 arg = a_opt or '' try: print(fmter.get_style_defs(arg)) except Exception as err: print('Error:', err, file=sys.stderr) return 1 return 0 # if no -S is given, -a is not allowed if a_opt is not None: print(usage, file=sys.stderr) return 2 # parse -F options F_opts = _parse_filters(F_opts) opts.pop('-F', None) # select formatter outfn = opts.pop('-o', None) fmter = opts.pop('-f', None) if fmter: try: fmter = get_formatter_by_name(fmter, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 if outfn: if not fmter: try: fmter = get_formatter_for_filename(outfn, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 try: outfile = open(outfn, 'wb') except Exception as err: print('Error: cannot open outfile:', err, file=sys.stderr) return 1 else: if not fmter: fmter = TerminalFormatter(**parsed_opts) outfile = sys.stdout # select lexer lexer = opts.pop('-l', None) if lexer: try: lexer = get_lexer_by_name(lexer, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 if args: if len(args) > 1: print(usage, file=sys.stderr) return 2 infn = args[0] try: code = open(infn, 'rb').read() except Exception as err: print('Error: cannot read infile:', err, file=sys.stderr) return 1 if not lexer: try: lexer = get_lexer_for_filename(infn, code, **parsed_opts) except ClassNotFound as err: if '-g' in opts: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: print('Error:', err, file=sys.stderr) return 1 except OptionError as err: print('Error:', err, file=sys.stderr) return 1 else: if '-g' in opts: code = sys.stdin.read() try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) elif not lexer: print('Error: no lexer name given and reading ' + \ 'from stdin (try using -g or -l <lexer>)', file=sys.stderr) return 2 else: code = sys.stdin.read() # No encoding given? Use latin1 if output file given, # stdin/stdout encoding otherwise. # (This is a compromise, I'm not too happy with it...) if 'encoding' not in parsed_opts and 'outencoding' not in parsed_opts: if outfn: # encoding pass-through fmter.encoding = 'latin1' else: if sys.version_info < (3,): # use terminal encoding; Python 3's terminals already do that lexer.encoding = getattr(sys.stdin, 'encoding', None) or 'ascii' fmter.encoding = getattr(sys.stdout, 'encoding', None) or 'ascii' elif not outfn and sys.version_info > (3,): # output to terminal with encoding -> use .buffer outfile = sys.stdout.buffer # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) highlight(code, lexer, fmter, outfile) except Exception: import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] print(file=sys.stderr) print('*** Error while highlighting:', file=sys.stderr) print(msg, file=sys.stderr) return 1 return 0
class ConsoleInteractionTest(unittest.TestCase): def setUp(self): self.log_printer = LogPrinter(ConsolePrinter(print_colored=False)) self.console_printer = ConsolePrinter(print_colored=False) self.file_diff_dict = {} self.section = Section("t") self.local_bears = OrderedDict([("default", [SomelocalBear]), ("test", [SomelocalBear])]) self.global_bears = OrderedDict([("default", [SomeglobalBear]), ("test", [SomeglobalBear])]) self.old_open_editor_applicable = OpenEditorAction.is_applicable OpenEditorAction.is_applicable = staticmethod(lambda *args: False) self.old_apply_patch_applicable = ApplyPatchAction.is_applicable ApplyPatchAction.is_applicable = staticmethod(lambda *args: False) self.lexer = TextLexer() self.lexer.add_filter(VisibleWhitespaceFilter( spaces="•", tabs=True, tabsize=SpacingHelper.DEFAULT_TAB_WIDTH)) def tearDown(self): OpenEditorAction.is_applicable = self.old_open_editor_applicable ApplyPatchAction.is_applicable = self.old_apply_patch_applicable def test_require_settings(self): self.assertRaises(TypeError, acquire_settings, self.log_printer, 0) with simulate_console_inputs(0, 1, 2) as generator: self.assertEqual(acquire_settings(self.log_printer, {"setting": ["help text", "SomeBear"]}), {"setting": 0}) self.assertEqual(acquire_settings(self.log_printer, {"setting": ["help text", "SomeBear", "AnotherBear"]}), {"setting": 1}) self.assertEqual(acquire_settings(self.log_printer, {"setting": ["help text", "SomeBear", "AnotherBear", "YetAnotherBear"]}), {"setting": 2}) self.assertEqual(generator.last_input, 2) def test_print_diffs_info(self): file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]} diff_dict = {"a": Diff(file_dict['a']), "b": Diff(file_dict['b'])} diff_dict["a"].add_lines(1, ["test\n"]) diff_dict["a"].delete_line(3) diff_dict["b"].add_lines(0, ["first\n"]) previous_diffs = {"a": Diff(file_dict['a'])} previous_diffs["a"].change_line(2, "b\n", "b_changed\n") with retrieve_stdout() as stdout: print_diffs_info(diff_dict, self.console_printer) self.assertEqual(stdout.getvalue(), "| | +1 -1 in a\n" "| | +1 -0 in b\n") @patch("coalib.output.ConsoleInteraction.acquire_actions_and_apply") @patch("coalib.output.ConsoleInteraction.ShowPatchAction." "apply_from_section") def test_print_result_interactive_small_patch(self, apply_from_section, _): file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]} diff_dict = {"a": Diff(file_dict['a']), "b": Diff(file_dict['b'])} diff_dict["a"].add_lines(1, ["test\n"]) diff_dict["a"].delete_line(3) result = Result("origin", "msg", diffs=diff_dict) section = Section("test") print_result(self.console_printer, self.log_printer, section, self.file_diff_dict, result, file_dict, True) apply_from_section.assert_called_once_with( result, file_dict, self.file_diff_dict, section) @patch("coalib.output.ConsoleInteraction.acquire_actions_and_apply") @patch("coalib.output.ConsoleInteraction.print_diffs_info") def test_print_result_interactive_big_patch(self, diffs_info, _): file_dict = {"a": ["a\n", "b\n", "c\n"], "b": ["old_first\n"]} diff_dict = {"a": Diff(file_dict['a']), "b": Diff(file_dict['b'])} diff_dict["a"].add_lines(1, ["test\n", "test1\n", "test2\n"]) diff_dict["a"].delete_line(3) diff_dict["a"].add_lines(3, ["3test\n"]) result = Result("origin", "msg", diffs=diff_dict) section = Section("test") print_result(self.console_printer, self.log_printer, section, self.file_diff_dict, result, file_dict, True) diffs_info.assert_called_once_with(diff_dict, self.console_printer) def test_print_result(self): print_result(self.console_printer, self.log_printer, None, self.file_diff_dict, "illegal value", {}) with simulate_console_inputs(0): print_result(self.console_printer, self.log_printer, self.section, self.file_diff_dict, Result("origin", "msg", diffs={}), {}) with make_temp() as testfile_path: file_dict = { testfile_path: ["1\n", "2\n", "3\n"], "f_b": ["1", "2", "3"] } diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, "3\n", "3_changed\n") ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) # Interaction must be closed by the user with `0` if it's not a # param with simulate_console_inputs("INVALID", -1, 1, 0, 3) as input_generator: curr_section = Section("") print_section_beginning(self.console_printer, curr_section) print_result(self.console_printer, self.log_printer, curr_section, self.file_diff_dict, Result("origin", "msg", diffs={ testfile_path: diff}), file_dict) self.assertEqual(input_generator.last_input, 3) self.file_diff_dict.clear() with open(testfile_path) as f: self.assertEqual(f.readlines(), ["1\n", "3_changed\n"]) os.remove(testfile_path + ".orig") name, section = get_action_info(curr_section, TestAction().get_metadata(), failed_actions=set()) self.assertEqual(input_generator.last_input, 4) self.assertEqual(str(section), " {param : '3'}") self.assertEqual(name, "TestAction") # Check if the user is asked for the parameter only the first time. # Use OpenEditorAction that needs this parameter (editor command). with simulate_console_inputs(1, "test_editor", 0, 1, 0) as generator: OpenEditorAction.is_applicable = staticmethod(lambda *args: True) patch_result = Result("origin", "msg", diffs={testfile_path: diff}) patch_result.file = "f_b" print_result(self.console_printer, self.log_printer, curr_section, self.file_diff_dict, patch_result, file_dict) # choose action, choose editor, choose no action (-1 -> 2) self.assertEqual(generator.last_input, 2) # It shoudn't ask for parameter again print_result(self.console_printer, self.log_printer, curr_section, self.file_diff_dict, patch_result, file_dict) self.assertEqual(generator.last_input, 4) def test_print_affected_files(self): with retrieve_stdout() as stdout, \ make_temp() as some_file: file_dict = {some_file: ["1\n", "2\n", "3\n"]} affected_code = (SourceRange.from_values(some_file),) print_affected_files(self.console_printer, self.log_printer, Section(""), Result("origin", "message", affected_code=affected_code), file_dict, color=True) self.assertEqual(stdout.getvalue(), "\n"+relpath(some_file)+"\n") def test_acquire_actions_and_apply(self): with make_temp() as testfile_path: file_dict = {testfile_path: ["1\n", "2\n", "3\n"]} diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, "3\n", "3_changed\n") with simulate_console_inputs(1, 0) as generator, \ retrieve_stdout() as sio: ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) acquire_actions_and_apply(self.console_printer, self.log_printer, Section(""), self.file_diff_dict, Result("origin", "message", diffs={ testfile_path: diff}), file_dict) self.assertEqual(generator.last_input, 1) self.assertIn(ApplyPatchAction.SUCCESS_MESSAGE, sio.getvalue()) class InvalidateTestAction(ResultAction): is_applicable = staticmethod(lambda *args: True) def apply(*args, **kwargs): ApplyPatchAction.is_applicable = staticmethod( lambda *args: False) old_applypatch_is_applicable = ApplyPatchAction.is_applicable ApplyPatchAction.is_applicable = staticmethod(lambda *args: True) cli_actions = [ApplyPatchAction(), InvalidateTestAction()] with simulate_console_inputs(2, 1, 0) as generator, \ retrieve_stdout() as sio: acquire_actions_and_apply(self.console_printer, self.log_printer, Section(""), self.file_diff_dict, Result("origin", "message", diffs={testfile_path: diff}), file_dict, cli_actions=cli_actions) self.assertEqual(generator.last_input, 2) action_fail = "Failed to execute the action" self.assertNotIn(action_fail, sio.getvalue()) apply_path_desc = ApplyPatchAction().get_metadata().desc self.assertEqual(sio.getvalue().count(apply_path_desc), 1) ApplyPatchAction.is_applicable = old_applypatch_is_applicable def test_ask_for_actions_and_apply(self): failed_actions = set() action = TestAction() args = [self.log_printer, self.console_printer, Section(""), [action.get_metadata()], {'TestAction': action}, failed_actions, Result("origin", "message"), {}, {}] with simulate_console_inputs(1, 'param1', 1, 'param2') as generator: action.apply = unittest.mock.Mock(side_effect=AssertionError) ask_for_action_and_apply(*args) self.assertEqual(generator.last_input, 1) self.assertIn('TestAction', failed_actions) action.apply = lambda *args, **kwargs: {} ask_for_action_and_apply(*args) self.assertEqual(generator.last_input, 3) self.assertNotIn('TestAction', failed_actions) def test_print_result_no_input(self): with make_temp() as testfile_path: file_dict = {testfile_path: ["1\n", "2\n", "3\n"]} diff = Diff(file_dict[testfile_path]) diff.delete_line(2) diff.change_line(3, "3\n", "3_changed\n") with simulate_console_inputs(1, 2, 3) as generator, \ retrieve_stdout() as stdout: ApplyPatchAction.is_applicable = staticmethod( lambda *args: True) print_results_no_input(self.log_printer, Section("someSection"), [Result("origin", "message", diffs={ testfile_path: diff})], file_dict, self.file_diff_dict, color=False) self.assertEqual(generator.last_input, -1) self.assertEqual(stdout.getvalue(), """ Project wide: | | [NORMAL] origin: | | {}\n""".format(highlight_text("message", style=BackgroundMessageStyle))) def test_print_section_beginning(self): with retrieve_stdout() as stdout: print_section_beginning(self.console_printer, Section("name")) self.assertEqual(stdout.getvalue(), "Executing section name...\n") def test_nothing_done(self): with retrieve_stdout() as stdout: nothing_done(self.log_printer) self.assertIn("No existent section was targeted or enabled. " "Nothing to do.\n", stdout.getvalue()) def test_print_results_empty(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [], {}, {}) self.assertEqual(stdout.getvalue(), "") def test_print_results_project_wide(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [Result("origin", "message")], {}, {}, color=False) self.assertEqual( "\n{}\n| | [NORMAL] origin:\n| | {}\n".format( STR_PROJECT_WIDE, highlight_text("message", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_for_file(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="filename", line=2)], {abspath("filename"): ["test line\n", "line 2\n", "line 3\n"]}, {}, color=False) self.assertEqual("""\nfilename | 2| {} | | [NORMAL] SpaceConsistencyBear: | | {}\n""".format(highlight_text('line 2', self.lexer), highlight_text("Trailing whitespace found", style=BackgroundMessageStyle)), stdout.getvalue()) with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="filename", line=5)], {abspath("filename"): ["test line\n", "line 2\n", "line 3\n", "line 4\n", "line 5\n"]}, {}, color=False) self.assertEqual("""\nfilename | 5| {} | | [NORMAL] SpaceConsistencyBear: | | {}\n""".format(highlight_text('line 5', self.lexer), highlight_text("Trailing whitespace found", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_sorting(self): with retrieve_stdout() as stdout: print_results(self.log_printer, Section(""), [Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="file", line=5), Result.from_values("SpaceConsistencyBear", "Trailing whitespace found", file="file", line=2)], {abspath("file"): ["test line\n", "\t\n", "line 3\n", "line 4\n", "line 5\t\n"]}, {}, color=False) self.assertEqual(""" file | 2| {0} | | [NORMAL] SpaceConsistencyBear: | | {1} file | 5| {2} | | [NORMAL] SpaceConsistencyBear: | | {1}\n""".format(highlight_text('\t', self.lexer), highlight_text("Trailing whitespace found", style=BackgroundMessageStyle), highlight_text('line 5\t', self.lexer)), stdout.getvalue()) def test_print_results_multiple_ranges(self): affected_code = ( SourceRange.from_values("some_file", 5, end_line=7), SourceRange.from_values("another_file", 1, 3, 1, 5), SourceRange.from_values("another_file", 3, 3, 3, 5)) with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [Result("ClangCloneDetectionBear", "Clone Found", affected_code)], {abspath("some_file"): ["line " + str(i + 1) + "\n" for i in range(10)], abspath("another_file"): ["line " + str(i + 1) for i in range(10)]}, {}, color=False) self.assertEqual(""" another_file | 1| li{0}{1} another_file | 3| li{0}{2} some_file | 5| {3} | 6| {4} | 7| {5} | | [NORMAL] ClangCloneDetectionBear: | | {6}\n""".format(highlight_text('ne', self.lexer, BackgroundSourceRangeStyle), highlight_text(' 1', self.lexer), highlight_text(' 3', self.lexer), highlight_text('line 5', self.lexer), highlight_text('line 6', self.lexer), highlight_text('line 7', self.lexer), highlight_text("Clone Found", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_missing_file(self): self.log_printer = LogPrinter(NullPrinter()) with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [Result("t", "msg"), Result.from_values("t", "msg", file="file", line=5)], {}, {}, color=False) self.assertEqual("\n" + STR_PROJECT_WIDE + "\n" "| | [NORMAL] t:\n" "| | {0}\n" # Second results file isn't there, no context is # printed, only a warning log message which we # don't catch "| | [NORMAL] t:\n" "| | {0}\n".format( highlight_text("msg", style=BackgroundMessageStyle)), stdout.getvalue()) def test_print_results_missing_line(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [Result.from_values("t", "msg", file="file", line=5), Result.from_values("t", "msg", file="file", line=6)], {abspath("file"): ["line " + str(i + 1) for i in range(5)]}, {}, color=False) self.assertEqual("\n" "file\n" "| 5| {0}\n" "| | [NORMAL] t:\n" "| | {1}\n" "\n" "file\n" "| 6| {2}\n" "| | [NORMAL] t:\n" "| | {1}\n".format( highlight_text('line 5', self.lexer), highlight_text("msg", style=BackgroundMessageStyle), STR_LINE_DOESNT_EXIST), stdout.getvalue()) def test_print_results_without_line(self): with retrieve_stdout() as stdout: print_results( self.log_printer, Section(""), [Result.from_values("t", "msg", file="file")], {abspath("file"): []}, {}, color=False) self.assertEqual( "\nfile\n" "| | [NORMAL] t:\n" "| | {}\n".format(highlight_text( "msg", style=BackgroundMessageStyle)), stdout.getvalue())
def main(args=sys.argv): """ Main command line entry point. """ # pylint: disable-msg=R0911,R0912,R0915 usage = USAGE % ((args[0],) * 6) if sys.platform in ['win32', 'cygwin']: try: # Provide coloring under Windows, if possible import colorama colorama.init() except ImportError: pass try: popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHg") except getopt.GetoptError as err: print(usage, file=sys.stderr) return 2 opts = {} O_opts = [] P_opts = [] F_opts = [] for opt, arg in popts: if opt == '-O': O_opts.append(arg) elif opt == '-P': P_opts.append(arg) elif opt == '-F': F_opts.append(arg) opts[opt] = arg if not opts and not args: print(usage) return 0 if opts.pop('-h', None) is not None: print(usage) return 0 if opts.pop('-V', None) is not None: print('Pygments version %s, (c) 2006-2013 by Georg Brandl.' % __version__) return 0 # handle ``pygmentize -L`` L_opt = opts.pop('-L', None) if L_opt is not None: if opts: print(usage, file=sys.stderr) return 2 # print version main(['', '-V']) if not args: args = ['lexer', 'formatter', 'filter', 'style'] for arg in args: _print_list(arg.rstrip('s')) return 0 # handle ``pygmentize -H`` H_opt = opts.pop('-H', None) if H_opt is not None: if opts or len(args) != 2: print(usage, file=sys.stderr) return 2 what, name = args if what not in ('lexer', 'formatter', 'filter'): print(usage, file=sys.stderr) return 2 _print_help(what, name) return 0 # parse -O options parsed_opts = _parse_options(O_opts) opts.pop('-O', None) # parse -P options for p_opt in P_opts: try: name, value = p_opt.split('=', 1) except ValueError: parsed_opts[p_opt] = True else: parsed_opts[name] = value opts.pop('-P', None) # handle ``pygmentize -N`` infn = opts.pop('-N', None) if infn is not None: try: lexer = get_lexer_for_filename(infn, **parsed_opts) except ClassNotFound as err: lexer = TextLexer() except OptionError as err: print('Error:', err, file=sys.stderr) return 1 print(lexer.aliases[0]) return 0 # handle ``pygmentize -S`` S_opt = opts.pop('-S', None) a_opt = opts.pop('-a', None) if S_opt is not None: f_opt = opts.pop('-f', None) if not f_opt: print(usage, file=sys.stderr) return 2 if opts or args: print(usage, file=sys.stderr) return 2 try: parsed_opts['style'] = S_opt fmter = get_formatter_by_name(f_opt, **parsed_opts) except ClassNotFound as err: print(err, file=sys.stderr) return 1 arg = a_opt or '' try: print(fmter.get_style_defs(arg)) except Exception as err: print('Error:', err, file=sys.stderr) return 1 return 0 # if no -S is given, -a is not allowed if a_opt is not None: print(usage, file=sys.stderr) return 2 # parse -F options F_opts = _parse_filters(F_opts) opts.pop('-F', None) # select formatter outfn = opts.pop('-o', None) fmter = opts.pop('-f', None) if fmter: try: fmter = get_formatter_by_name(fmter, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 if outfn: if not fmter: try: fmter = get_formatter_for_filename(outfn, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 try: outfile = open(outfn, 'wb') except Exception as err: print('Error: cannot open outfile:', err, file=sys.stderr) return 1 else: if not fmter: fmter = TerminalFormatter(**parsed_opts) outfile = sys.stdout # select lexer lexer = opts.pop('-l', None) if lexer: try: lexer = get_lexer_by_name(lexer, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 if args: if len(args) > 1: print(usage, file=sys.stderr) return 2 infn = args[0] try: code = open(infn, 'rb').read() except Exception as err: print('Error: cannot read infile:', err, file=sys.stderr) return 1 if not lexer: try: lexer = get_lexer_for_filename(infn, code, **parsed_opts) except ClassNotFound as err: if '-g' in opts: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: print('Error:', err, file=sys.stderr) return 1 except OptionError as err: print('Error:', err, file=sys.stderr) return 1 else: if '-g' in opts: code = sys.stdin.read() try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) elif not lexer: print('Error: no lexer name given and reading ' + \ 'from stdin (try using -g or -l <lexer>)', file=sys.stderr) return 2 else: code = sys.stdin.read() # No encoding given? Use latin1 if output file given, # stdin/stdout encoding otherwise. # (This is a compromise, I'm not too happy with it...) if 'encoding' not in parsed_opts and 'outencoding' not in parsed_opts: if outfn: # encoding pass-through fmter.encoding = 'latin1' else: if sys.version_info < (3,): # use terminal encoding; Python 3's terminals already do that lexer.encoding = getattr(sys.stdin, 'encoding', None) or 'ascii' fmter.encoding = getattr(sys.stdout, 'encoding', None) or 'ascii' elif not outfn and sys.version_info > (3,): # output to terminal with encoding -> use .buffer outfile = sys.stdout.buffer # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) highlight(code, lexer, fmter, outfile) except Exception as err: import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += '\n (f%s)' % info[-2].split('\n')[0].strip()[1:] print(file=sys.stderr) print('*** Error while highlighting:', file=sys.stderr) print(msg, file=sys.stderr) return 1 return 0
def main_inner(popts, args, usage): opts = {} O_opts = [] P_opts = [] F_opts = [] for opt, arg in popts: if opt == '-O': O_opts.append(arg) elif opt == '-P': P_opts.append(arg) elif opt == '-F': F_opts.append(arg) opts[opt] = arg if opts.pop('-h', None) is not None: print(usage) return 0 if opts.pop('-V', None) is not None: print('Pygments version %s, (c) 2006-2014 by Georg Brandl.' % __version__) return 0 # handle ``pygmentize -L`` L_opt = opts.pop('-L', None) if L_opt is not None: if opts: print(usage, file=sys.stderr) return 2 # print version main(['', '-V']) if not args: args = ['lexer', 'formatter', 'filter', 'style'] for arg in args: _print_list(arg.rstrip('s')) return 0 # handle ``pygmentize -H`` H_opt = opts.pop('-H', None) if H_opt is not None: if opts or len(args) != 2: print(usage, file=sys.stderr) return 2 what, name = args if what not in ('lexer', 'formatter', 'filter'): print(usage, file=sys.stderr) return 2 return _print_help(what, name) # parse -O options parsed_opts = _parse_options(O_opts) opts.pop('-O', None) # parse -P options for p_opt in P_opts: try: name, value = p_opt.split('=', 1) except ValueError: parsed_opts[p_opt] = True else: parsed_opts[name] = value opts.pop('-P', None) # encodings inencoding = parsed_opts.get('inencoding', parsed_opts.get('encoding')) outencoding = parsed_opts.get('outencoding', parsed_opts.get('encoding')) # handle ``pygmentize -N`` infn = opts.pop('-N', None) if infn is not None: lexer = find_lexer_class_for_filename(infn) if lexer is None: lexer = TextLexer print(lexer.aliases[0]) return 0 # handle ``pygmentize -S`` S_opt = opts.pop('-S', None) a_opt = opts.pop('-a', None) if S_opt is not None: f_opt = opts.pop('-f', None) if not f_opt: print(usage, file=sys.stderr) return 2 if opts or args: print(usage, file=sys.stderr) return 2 try: parsed_opts['style'] = S_opt fmter = get_formatter_by_name(f_opt, **parsed_opts) except ClassNotFound as err: print(err, file=sys.stderr) return 1 print(fmter.get_style_defs(a_opt or '')) return 0 # if no -S is given, -a is not allowed if a_opt is not None: print(usage, file=sys.stderr) return 2 # parse -F options F_opts = _parse_filters(F_opts) opts.pop('-F', None) # select lexer lexer = None # given by name? lexername = opts.pop('-l', None) if lexername: try: lexer = get_lexer_by_name(lexername, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 # read input code code = None if args: if len(args) > 1: print(usage, file=sys.stderr) return 2 if '-s' in opts: print('Error: -s option not usable when input file specified', file=sys.stderr) return 2 infn = args[0] try: with open(infn, 'rb') as infp: code = infp.read() except Exception as err: print('Error: cannot read infile:', err, file=sys.stderr) return 1 if not inencoding: code, inencoding = guess_decode(code) # do we have to guess the lexer? if not lexer: try: lexer = get_lexer_for_filename(infn, code, **parsed_opts) except ClassNotFound as err: if '-g' in opts: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: print('Error:', err, file=sys.stderr) return 1 except OptionError as err: print('Error:', err, file=sys.stderr) return 1 elif '-s' not in opts: # treat stdin as full file (-s support is later) # read code from terminal, always in binary mode since we want to # decode ourselves and be tolerant with it if sys.version_info > (3,): # Python 3: we have to use .buffer to get a binary stream code = sys.stdin.buffer.read() else: code = sys.stdin.read() if not inencoding: code, inencoding = guess_decode_from_terminal(code, sys.stdin) # else the lexer will do the decoding if not lexer: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: # -s option needs a lexer with -l if not lexer: print('Error: when using -s a lexer has to be selected with -l', file=sys.stderr) return 2 # process filters for fname, fopts in F_opts: try: lexer.add_filter(fname, **fopts) except ClassNotFound as err: print('Error:', err, file=sys.stderr) return 1 # select formatter outfn = opts.pop('-o', None) fmter = opts.pop('-f', None) if fmter: try: fmter = get_formatter_by_name(fmter, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 if outfn: if not fmter: try: fmter = get_formatter_for_filename(outfn, **parsed_opts) except (OptionError, ClassNotFound) as err: print('Error:', err, file=sys.stderr) return 1 try: outfile = open(outfn, 'wb') except Exception as err: print('Error: cannot open outfile:', err, file=sys.stderr) return 1 else: if not fmter: fmter = TerminalFormatter(**parsed_opts) if sys.version_info > (3,): # Python 3: we have to use .buffer to get a binary stream outfile = sys.stdout.buffer else: outfile = sys.stdout # determine output encoding if not explicitly selected if not outencoding: if outfn: # output file? use lexer encoding for now (can still be None) fmter.encoding = inencoding else: # else use terminal encoding fmter.encoding = terminal_encoding(sys.stdout) # provide coloring under Windows, if possible if not outfn and sys.platform in ('win32', 'cygwin') and \ fmter.name in ('Terminal', 'Terminal256'): # pragma: no cover # unfortunately colorama doesn't support binary streams on Py3 if sys.version_info > (3,): from pygments.util import UnclosingTextIOWrapper outfile = UnclosingTextIOWrapper(outfile, encoding=fmter.encoding) fmter.encoding = None try: import colorama.initialise except ImportError: pass else: outfile = colorama.initialise.wrap_stream( outfile, convert=None, strip=None, autoreset=False, wrap=True) # When using the LaTeX formatter and the option `escapeinside` is # specified, we need a special lexer which collects escaped text # before running the chosen language lexer. escapeinside = parsed_opts.get('escapeinside', '') if len(escapeinside) == 2 and isinstance(fmter, LatexFormatter): left = escapeinside[0] right = escapeinside[1] lexer = LatexEmbeddedLexer(left, right, lexer) # ... and do it! if '-s' not in opts: # process whole input as per normal... highlight(code, lexer, fmter, outfile) return 0 else: # line by line processing of stdin (eg: for 'tail -f')... try: while 1: if sys.version_info > (3,): # Python 3: we have to use .buffer to get a binary stream line = sys.stdin.buffer.readline() else: line = sys.stdin.readline() if not line: break if not inencoding: line = guess_decode_from_terminal(line, sys.stdin)[0] highlight(line, lexer, fmter, outfile) if hasattr(outfile, 'flush'): outfile.flush() return 0 except KeyboardInterrupt: # pragma: no cover return 0
def main(args=sys.argv): """ Main command line entry point. """ # pylint: disable-msg=R0911,R0912,R0915 usage = USAGE % ((args[0],) * 6) if sys.platform in ["win32", "cygwin"]: try: # Provide coloring under Windows, if possible import colorama colorama.init() except ImportError: pass try: popts, args = getopt.getopt(args[1:], "l:f:F:o:O:P:LS:a:N:hVHg") except getopt.GetoptError as err: print(usage, file=sys.stderr) return 2 opts = {} O_opts = [] P_opts = [] F_opts = [] for opt, arg in popts: if opt == "-O": O_opts.append(arg) elif opt == "-P": P_opts.append(arg) elif opt == "-F": F_opts.append(arg) opts[opt] = arg if not opts and not args: print(usage) return 0 if opts.pop("-h", None) is not None: print(usage) return 0 if opts.pop("-V", None) is not None: print("Pygments version %s, (c) 2006-2013 by Georg Brandl." % __version__) return 0 # handle ``pygmentize -L`` L_opt = opts.pop("-L", None) if L_opt is not None: if opts: print(usage, file=sys.stderr) return 2 # print version main(["", "-V"]) if not args: args = ["lexer", "formatter", "filter", "style"] for arg in args: _print_list(arg.rstrip("s")) return 0 # handle ``pygmentize -H`` H_opt = opts.pop("-H", None) if H_opt is not None: if opts or len(args) != 2: print(usage, file=sys.stderr) return 2 what, name = args if what not in ("lexer", "formatter", "filter"): print(usage, file=sys.stderr) return 2 _print_help(what, name) return 0 # parse -O options parsed_opts = _parse_options(O_opts) opts.pop("-O", None) # parse -P options for p_opt in P_opts: try: name, value = p_opt.split("=", 1) except ValueError: parsed_opts[p_opt] = True else: parsed_opts[name] = value opts.pop("-P", None) # handle ``pygmentize -N`` infn = opts.pop("-N", None) if infn is not None: try: lexer = get_lexer_for_filename(infn, **parsed_opts) except ClassNotFound as err: lexer = TextLexer() except OptionError as err: print("Error:", err, file=sys.stderr) return 1 print(lexer.aliases[0]) return 0 # handle ``pygmentize -S`` S_opt = opts.pop("-S", None) a_opt = opts.pop("-a", None) if S_opt is not None: f_opt = opts.pop("-f", None) if not f_opt: print(usage, file=sys.stderr) return 2 if opts or args: print(usage, file=sys.stderr) return 2 try: parsed_opts["style"] = S_opt fmter = get_formatter_by_name(f_opt, **parsed_opts) except ClassNotFound as err: print(err, file=sys.stderr) return 1 arg = a_opt or "" try: print(fmter.get_style_defs(arg)) except Exception as err: print("Error:", err, file=sys.stderr) return 1 return 0 # if no -S is given, -a is not allowed if a_opt is not None: print(usage, file=sys.stderr) return 2 # parse -F options F_opts = _parse_filters(F_opts) opts.pop("-F", None) # select formatter outfn = opts.pop("-o", None) fmter = opts.pop("-f", None) if fmter: try: fmter = get_formatter_by_name(fmter, **parsed_opts) except (OptionError, ClassNotFound) as err: print("Error:", err, file=sys.stderr) return 1 if outfn: if not fmter: try: fmter = get_formatter_for_filename(outfn, **parsed_opts) except (OptionError, ClassNotFound) as err: print("Error:", err, file=sys.stderr) return 1 try: outfile = open(outfn, "wb") except Exception as err: print("Error: cannot open outfile:", err, file=sys.stderr) return 1 else: if not fmter: fmter = TerminalFormatter(**parsed_opts) outfile = sys.stdout # select lexer lexer = opts.pop("-l", None) if lexer: try: lexer = get_lexer_by_name(lexer, **parsed_opts) except (OptionError, ClassNotFound) as err: print("Error:", err, file=sys.stderr) return 1 if args: if len(args) > 1: print(usage, file=sys.stderr) return 2 infn = args[0] try: code = open(infn, "rb").read() except Exception as err: print("Error: cannot read infile:", err, file=sys.stderr) return 1 if not lexer: try: lexer = get_lexer_for_filename(infn, code, **parsed_opts) except ClassNotFound as err: if "-g" in opts: try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) else: print("Error:", err, file=sys.stderr) return 1 except OptionError as err: print("Error:", err, file=sys.stderr) return 1 else: if "-g" in opts: code = sys.stdin.read() try: lexer = guess_lexer(code, **parsed_opts) except ClassNotFound: lexer = TextLexer(**parsed_opts) elif not lexer: print( "Error: no lexer name given and reading " + "from stdin (try using -g or -l <lexer>)", file=sys.stderr ) return 2 else: code = sys.stdin.read() # No encoding given? Use latin1 if output file given, # stdin/stdout encoding otherwise. # (This is a compromise, I'm not too happy with it...) if "encoding" not in parsed_opts and "outencoding" not in parsed_opts: if outfn: # encoding pass-through fmter.encoding = "latin1" else: if sys.version_info < (3,): # use terminal encoding; Python 3's terminals already do that lexer.encoding = getattr(sys.stdin, "encoding", None) or "ascii" fmter.encoding = getattr(sys.stdout, "encoding", None) or "ascii" elif not outfn and sys.version_info > (3,): # output to terminal with encoding -> use .buffer outfile = sys.stdout.buffer # ... and do it! try: # process filters for fname, fopts in F_opts: lexer.add_filter(fname, **fopts) highlight(code, lexer, fmter, outfile) except Exception as err: import traceback info = traceback.format_exception(*sys.exc_info()) msg = info[-1].strip() if len(info) >= 3: # extract relevant file and position info msg += "\n (f%s)" % info[-2].split("\n")[0].strip()[1:] print(file=sys.stderr) print("*** Error while highlighting:", file=sys.stderr) print(msg, file=sys.stderr) return 1 return 0