def __init__(self, cov, code_unit): self.coverage = cov self.code_unit = code_unit self.filename = self.code_unit.filename actual_filename, source = self.find_source(self.filename) self.parser = CodeParser( text=source, filename=actual_filename, exclude=self.coverage._exclude_regex('exclude')) self.statements, self.excluded = self.parser.parse_source() executed = self.coverage.data.executed_lines(self.filename) exec1 = self.parser.first_lines(executed) self.missing = sorted(set(self.statements) - set(exec1)) if self.coverage.data.has_arcs(): self.no_branch = self.parser.lines_matching( join_regex(self.coverage.config.partial_list), join_regex(self.coverage.config.partial_always_list)) n_branches = self.total_branches() mba = self.missing_branch_arcs() n_partial_branches = sum( [len(v) for k, v in iitems(mba) if k not in self.missing]) n_missing_branches = sum([len(v) for k, v in iitems(mba)]) else: n_branches = n_partial_branches = n_missing_branches = 0 self.no_branch = set() self.numbers = Numbers(n_files=1, n_statements=len(self.statements), n_excluded=len(self.excluded), n_missing=len(self.missing), n_branches=n_branches, n_partial_branches=n_partial_branches, n_missing_branches=n_missing_branches)
def collect(self, filename, line_no): if filename not in self.data: self.data[filename] = set() self.data[filename].add(line_no) if filename not in self.parse_cache: parser = CodeParser(filename=filename) statements, _ = parser.parse_source() self.parse_cache[filename] = {'parser': parser, 'code': statements}
def one_file(self, options, filename): """Process just one file.""" if options.dis or options.chunks: try: bp = ByteParser(filename=filename) except CoverageException: _, err, _ = sys.exc_info() print("%s" % (err,)) return if options.dis: print("Main code:") self.disassemble(bp) if options.chunks: chunks = bp._all_chunks() if options.recursive: print("%6d: %s" % (len(chunks), filename)) else: print("Chunks: %r" % chunks) arcs = bp._all_arcs() print("Arcs: %r" % sorted(arcs)) if options.source or options.tokens: cp = CodeParser(filename=filename, exclude=r"no\s*cover") cp.show_tokens = options.tokens cp._raw_parse() if options.source: if options.chunks: arc_width, arc_chars = self.arc_ascii_art(arcs) else: arc_width, arc_chars = 0, {} exit_counts = cp.exit_counts() for i, ltext in enumerate(cp.lines): lineno = i+1 m0 = m1 = m2 = m3 = a = ' ' if lineno in cp.statement_starts: m0 = '-' exits = exit_counts.get(lineno, 0) if exits > 1: m1 = str(exits) if lineno in cp.docstrings: m2 = '"' if lineno in cp.classdefs: m2 = 'C' if lineno in cp.excluded: m3 = 'x' a = arc_chars.get(lineno, '').ljust(arc_width) print("%4d %s%s%s%s%s %s" % (lineno, m0, m1, m2, m3, a, ltext) )
def _init_trace_file(self, filename, lineno): """ here comes a new file that need to trace :param filename: the name of the file :param lineno: first called line number :return: None """ if filename not in self.data: self.data[filename] = {} self.data[filename][lineno] = None if filename not in self.parse_cache: parser = CodeParser(filename=filename) statements, _ = parser.parse_source() self.parse_cache[filename] = { 'parser': parser, 'code': statements }
def __init__(self, cov, code_unit): self.coverage = cov self.code_unit = code_unit self.filename = self.code_unit.filename ext = os.path.splitext(self.filename)[1] source = None if ext == '.py': if not os.path.exists(self.filename): source = self.coverage.file_locator.get_zip_data(self.filename) if not source: raise NoSource("No source for code: '%s'" % self.filename) self.parser = CodeParser( text=source, filename=self.filename, exclude=self.coverage._exclude_regex('exclude')) self.statements, self.excluded = self.parser.parse_source() # Identify missing statements. executed = self.coverage.data.executed_lines(self.filename) exec1 = self.parser.first_lines(executed) self.missing = sorted(set(self.statements) - set(exec1)) if self.coverage.data.has_arcs(): self.no_branch = self.parser.lines_matching( join_regex(self.coverage.config.partial_list), join_regex(self.coverage.config.partial_always_list)) n_branches = self.total_branches() mba = self.missing_branch_arcs() n_partial_branches = sum( [len(v) for k, v in iitems(mba) if k not in self.missing]) n_missing_branches = sum([len(v) for k, v in iitems(mba)]) else: n_branches = n_partial_branches = n_missing_branches = 0 self.no_branch = set() self.numbers = Numbers( n_files=1, n_statements=len(self.statements), n_excluded=len(self.excluded), n_missing=len(self.missing), n_branches=n_branches, n_partial_branches=n_partial_branches, n_missing_branches=n_missing_branches, )
def _dfs(self, filename): stack = [] ret = [] stack.append(filename) while len(stack) > 0: tmp = stack.pop() if os.path.isdir(tmp): for item in os.listdir(tmp): # ignore .git .xxoo if not item.startswith('.'): # why not use path.join? because in windows we usually have a\\b and # in linux we usually have a/b, however, the path is the id of some # html element, which may cause conflicts stack.append(tmp + '/' + item) else: if not tmp.startswith('.') and tmp.endswith('.py'): # ignore .gitignore, *.pyc parser = CodeParser(filename=tmp) statements, _ = parser.parse_source() ret.append((tmp.replace(self.path, ''), len(statements))) return ret
def list_all_files(self): """ list all the files and directories for a given path. ignore .svn, .git, .gitignore, *.pyc :return: e.g.: { 'path': '/home/source' 'dirs': ['dir1', 'dir2', 'dir3'], 'files': ['file1', 'file2', 'file3'], 'dir1': ['dir1/f1.py', 'dir1/a/f2.py'], 'dir2': ['dir2/f1.py', 'dir2/f2.py', 'dir2/aa/bb/cc/dd.py'], 'dir3': [] } """ cache = file_db.query_dirs(self.path) if cache: return cache result = {'path': self.path, 'dirs': [], 'files': []} dirs = [] files = [] for filename in os.listdir(self.path): # ignore .git .ssh .svn, etc if not filename.startswith('.'): full_path = os.path.join(self.path, filename) if os.path.isdir(full_path): dirs.append(filename) else: # ignore .pyc if filename.endswith('.py'): parser = CodeParser(filename=full_path) statements, _ = parser.parse_source() files.append(("/" + filename, len(statements))) result['dirs'] = sorted(dirs) result['files'] = sorted(files) for dirname in result['dirs']: full_path = self.path + '/' + dirname result[dirname] = self._dfs(full_path) file_db.save_dirs(self.path, result) return result
def __init__(self, cov, code_unit): self.coverage = cov self.code_unit = code_unit self.filename = self.code_unit.filename ext = os.path.splitext(self.filename)[1] source = None if ext == '.py': if not os.path.exists(self.filename): source = self.coverage.file_locator.get_zip_data(self.filename) if not source: raise NoSource("No source for code: %r" % self.filename) self.parser = CodeParser(text=source, filename=self.filename, exclude=self.coverage.exclude_re) self.statements, self.excluded = self.parser.parse_source() # Identify missing statements. executed = self.coverage.data.executed_lines(self.filename) exec1 = self.parser.first_lines(executed) self.missing = sorted(set(self.statements) - set(exec1)) if self.coverage.data.has_arcs(): n_branches = self.total_branches() mba = self.missing_branch_arcs() n_missing_branches = sum([len(v) for v in mba.values()]) else: n_branches = n_missing_branches = 0 self.numbers = Numbers( n_files=1, n_statements=len(self.statements), n_excluded=len(self.excluded), n_missing=len(self.missing), n_branches=n_branches, n_missing_branches=n_missing_branches, )
def parse_source(self, text): """Parse `text` as source, and return the `CodeParser` used.""" text = textwrap.dedent(text) cp = CodeParser(text=text, exclude="nocover") cp.parse_source() return cp
def parse_file(self, filename): """Parse `text` as source, and return the `CodeParser` used.""" cp = CodeParser(filename=filename, exclude="nocover") cp.parse_source() return cp
def test_code_empty_file(self): cp = CodeParser(text="", filename="<code>")
def get_all_lines_from_path(self, path): from coverage.parser import CodeParser parser = CodeParser(filename=path) statements, excluded = parser.parse_source() return statements