# -*- coding: utf-8 -*- import os from metrics.metrics import process class CodeMetrics: """Handle source code metrics.""" def __init__(self, rootdir): """Init the code metrics.""" self._rootdir = rootdir self._languages = {} def __str__(self): """Display the collected metrics.""" desc = '' for l in self._languages: desc += l + ': ' + '%d' % self._languages[l]['sloc'] + '\n' return desc def process(self, msg): """Collect code metrics.""" # Get all files all_files = [] baselen = len(self._rootdir) + len(os.sep) for root, dirnames, filenames in os.walk(self._rootdir): if '.git' in root: continue for filename in filenames: full_access = os.path.join(root, filename) rel_access = full_access[baselen:] all_files.append(rel_access) # Compute metrics count = len(all_files) i = 0 for filename in all_files: print(msg + ' -> Collecting code metrics... %d%%' % ((i * 100) / count), end='') unsupported = { '.l' : 'Flex', '.y' : 'Bison' } supported = True lang = None for ext, lang in unsupported.items(): if filename.endswith(ext): supported = False break if supported: stats = self._analyse_supported_file(filename) if stats is None: i += 1 continue lang = stats['language'] else: stats = self._analyse_unsupported_file(os.path.join(self._rootdir, filename)) if not(lang in self._languages): self._languages[lang] = {} self._languages[lang]['sloc'] = 0 self._languages[lang]['comments'] = 0 self._languages[lang]['sloc'] += stats['sloc'] self._languages[lang]['comments'] += stats['comments'] i += 1 msg = msg + ' -> Collecting code metrics... %d%%' % ((i * 100) / count) print(msg, end='') return msg def _analyse_supported_file(self, filename): """Process a file supported by the Python module.""" context = {} context['include_metrics'] = [ ('sloc', 'SLOCMetric') ] context['quiet'] = True context['verbose'] = False context['root_dir'] = self._rootdir context['in_file_names'] = [ filename ] context['output_format'] = None stats = process(context) if filename in stats: stats = stats[filename] if stats['language'] == 'TASM': stats['language'] = 'Asm' if stats['language'] == 'Gettext Catalog': stats = None else: stats = None return stats def _analyse_unsupported_file(self, filename): """Process a file unsupported by the Python module.""" stats = {} stats['sloc'] = 0 stats['comments'] = 0 with open(filename, 'r') as fin: for line in fin: length = len(line) if not(length == 0 or (length == 1 and line == '\n') or (length == 2 and line == '\r\n')): stats['sloc'] += 1 return stats def count_all_lines(self): """Count all single lines of code.""" result = 0 for l in self._languages: result += self._languages[l]['sloc'] return result def get_most_used(self, count): """Compute the list of most used languages.""" max_count = len(self._languages.keys()) if count > max_count: count = max_count languages = [] for l in self._languages: languages.append((self._languages[l]['sloc'], l)) languages = sorted(languages, reverse=True) if count < max_count: selected = languages[:count - 1] remaining = 0 for n, _ in languages[count:]: remaining += n selected.append((remaining, 'Others')) else: selected = languages return selected