# Copyright (c) 2013 - present Facebook, Inc. # All rights reserved. # # This source code is licensed under the BSD style license found in the # LICENSE file in the root directory of this source tree. An additional grant # of patent rights can be found in the PATENTS file in the same directory. from __future__ import absolute_import from __future__ import division from __future__ import print_function from __future__ import unicode_literals import codecs from . import colorize, config BASE_INDENT = 2 # how many lines of context around each report SOURCE_CONTEXT = 2 class Indenter(str): def __init__(self): super(Indenter, self).__init__() self.text = '' self.indent = [] def indent_get(self): indent = '' for i in self.indent: indent += i return indent def indent_push(self, n=1): self.indent.append(n * BASE_INDENT * ' ') return self def indent_pop(self): return self.indent.pop() return self def newline(self): self.text += '\n' return self def add(self, x): if type(x) != unicode: x = x.decode(config.CODESET) lines = x.splitlines() indent = self.indent_get() lines = [indent + l for l in lines] self.text += '\n'.join(lines) return self def __unicode__(self): return self.text def __str__(self): return unicode(self).encode(config.CODESET) def build_source_context(source_name, mode, report_line): start_line = max(1, report_line - SOURCE_CONTEXT) # could go beyond last line, checked in the loop end_line = report_line + SOURCE_CONTEXT # get source excerpt line_number = 1 excerpt = '' with codecs.open(source_name, 'r', encoding=config.CODESET, errors="replace") as source_file: # avoid going past the end of the file for line in source_file: last_line = line_number if start_line <= line_number < end_line: excerpt += line elif line_number > end_line: # OPTIM: no need to read past the last line of the excerpt break line_number += 1 excerpt = colorize.syntax_highlighting(source_name, mode, excerpt) # number lines and add caret at the right position n_length = len(str(last_line)) s = '' line_number = start_line for line in excerpt.split('\n'): num = colorize.color((str(line_number) + '.').zfill(n_length), colorize.DIM, mode) caret = ' ' if line_number == report_line: caret = colorize.color('> ', colorize.HEADER, mode) s += '%s %s%s\n' % (num, caret, line) line_number += 1 return s