class MaintainabilityIndexOperator(BaseOperator): """MI Operator.""" name = "maintainability" defaults = { "exclude": None, "ignore": None, "min": "A", "max": "C", "multi": True, "show": False, "sort": False, } metrics = ( Metric( "rank", "Maintainability Ranking", str, MetricType.Informational, statistics.mode, ), Metric( "mi", "Maintainability Index", float, MetricType.AimLow, statistics.mean ), ) default_metric_index = 1 # MI def __init__(self, config): """ Instantiate a new MI operator. :param config: The wily configuration. :type config: :class:`WilyConfig` """ # TODO : Import config from wily.cfg logger.debug(f"Using {config.targets} with {self.defaults} for MI metrics") self.harvester = harvesters.MIHarvester( config.targets, config=Config(**self.defaults) ) def run(self, module, options): """ Run the operator. :param module: The target module path. :type module: ``str`` :param options: Any runtime options. :type options: ``dict`` :return: The operator results. :rtype: ``dict`` """ logger.debug("Running maintainability harvester") return dict(self.harvester.results)
class RawMetricsOperator(BaseOperator): """Raw Metrics Operator.""" name = "raw" defaults = { "exclude": None, "ignore": None, "summary": False, "include_ipynb": True, "ipynb_cells": True, } metrics = ( Metric("loc", "Lines of Code", int, MetricType.Informational, sum), Metric("lloc", "L Lines of Code", int, MetricType.AimLow, sum), Metric("sloc", "S Lines of Code", int, MetricType.AimLow, sum), Metric("comments", "Multi-line comments", int, MetricType.AimHigh, sum), Metric("multi", "Multi lines", int, MetricType.Informational, sum), Metric("blank", "blank lines", int, MetricType.Informational, sum), Metric( "single_comments", "Single comment lines", int, MetricType.Informational, sum, ), ) default_metric_index = 0 # LOC def __init__(self, config, targets): """ Instantiate a new raw operator. :param config: The wily configuration. :type config: :class:`WilyConfig` """ # TODO: Use config from wily.cfg for harvester logger.debug(f"Using {targets} with {self.defaults} for Raw metrics") self.harvester = harvesters.RawHarvester( targets, config=Config(**self.defaults)) def run(self, module, options): """ Run the operator. :param module: The target module path. :type module: ``str`` :param options: Any runtime options. :type options: ``dict`` :return: The operator results. :rtype: ``dict`` """ logger.debug("Running raw harvester") results = {} for filename, metrics in dict(self.harvester.results).items(): results[filename] = {"total": metrics} return results
class CyclomaticComplexityOperator(BaseOperator): """Cyclomatic complexity operator.""" name = "cyclomatic" defaults = { "exclude": None, "ignore": None, "min": "A", "max": "F", "no_assert": True, "show_closures": False, "order": radon.complexity.SCORE, } metrics = (Metric( "complexity", "Cyclomatic Complexity", float, MetricType.AimLow, statistics.mean, ), ) default_metric_index = 0 # MI def __init__(self, config): """ Instantiate a new Cyclomatic Complexity operator. :param config: The wily configuration. :type config: :class:`WilyConfig` """ # TODO: Import config for harvester from .wily.cfg logger.debug( f"Using {config.targets} with {self.defaults} for CC metrics") self.harvester = harvesters.CCHarvester(config.targets, config=Config(**self.defaults)) def run(self, module, options): """ Run the operator. :param module: The target module path. :type module: ``str`` :param options: Any runtime options. :type options: ``dict`` :return: The operator results. :rtype: ``dict`` """ logger.debug("Running CC harvester") results = {} for filename, details in dict(self.harvester.results).items(): results[filename] = {} total = 0 # running CC total for instance in details: if isinstance(instance, Class): i = self._dict_from_class(instance) elif isinstance(instance, Function): i = self._dict_from_function(instance) else: if isinstance(instance, str) and instance == "error": logger.warning( f"Failed to run CC harvester on {filename} : {details['error']}" ) continue else: logger.warning( f"Unexpected result from Radon : {instance} of {type(instance)}. Please report on Github." ) continue results[filename][i["fullname"]] = i del i["fullname"] total += i["complexity"] results[filename]["complexity"] = total return results @staticmethod def _dict_from_function(l): return { "name": l.name, "is_method": l.is_method, "classname": l.classname, "closures": l.closures, "complexity": l.complexity, "fullname": l.fullname, "loc": l.endline - l.lineno, } @staticmethod def _dict_from_class(l): return { "name": l.name, "inner_classes": l.inner_classes, "real_complexity": l.real_complexity, "complexity": l.complexity, "fullname": l.fullname, "loc": l.endline - l.lineno, }
class HalsteadOperator(BaseOperator): """Halstead Operator.""" name = "halstead" defaults = { "exclude": None, "ignore": None, "min": "A", "max": "C", "multi": True, "show": False, "sort": False, "by_function": True, } metrics = ( Metric("h1", "h1 metric", int, MetricType.AimLow, sum), Metric("h2", "h2 metric", int, MetricType.AimLow, sum), Metric("N1", "N1 metric", int, MetricType.AimLow, sum), Metric("N2", "N2 metric", int, MetricType.AimLow, sum), Metric("vocabulary", "Unique vocabulary (h1 + h2)", int, MetricType.AimLow, sum), Metric("length", "Length of application", int, MetricType.AimLow, sum), Metric("volume", "Code volume", float, MetricType.AimLow, sum), Metric("difficulty", "Difficulty", float, MetricType.AimLow, sum), Metric("effort", "Effort", float, MetricType.AimLow, sum), ) default_metric_index = 0 # MI def __init__(self, config): """ Instantiate a new HC operator. :param config: The wily configuration. :type config: :class:`WilyConfig` """ # TODO : Import config from wily.cfg logger.debug( f"Using {config.targets} with {self.defaults} for HC metrics") self.harvester = harvesters.HCHarvester(config.targets, config=Config(**self.defaults)) def run(self, module, options): """ Run the operator. :param module: The target module path. :type module: ``str`` :param options: Any runtime options. :type options: ``dict`` :return: The operator results. :rtype: ``dict`` """ logger.debug("Running halstead harvester") results = {} for filename, details in dict(self.harvester.results).items(): results[filename] = {} for instance in details: if isinstance(instance, list): for item in instance: function, report = item results[filename][function] = self._report_to_dict( report) else: results[filename] = self._report_to_dict(instance) return results def _report_to_dict(self, report): return { "h1": report.h1, "h2": report.h2, "N1": report.N1, "N2": report.N2, "vocabulary": report.vocabulary, "volume": report.volume, "length": report.length, "effort": report.effort, "difficulty": report.difficulty, }