wily\operators\halstead.py
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | Halstead operator.
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | Measures all of the halstead metrics (volume, vocab, difficulty)
-- -- --- --- --- --- --- --- ------- ------- ------- | """
-- -- --- --- --- --- --- --- ------- ------- ------- | import radon.cli.harvest as harvesters
-- -- --- --- --- --- --- --- ------- ------- ------- | from radon.cli import Config
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily import logger
-- -- --- --- --- --- --- --- ------- ------- ------- | from wily.operators import BaseOperator, MetricType, Metric
-- -- --- --- --- --- --- --- ------- ------- ------- |
-- -- --- --- --- --- --- --- ------- ------- ------- |
04 -- --- --- --- --- --- --- ------- ------- ------- | class HalsteadOperator(BaseOperator):
04 -- --- --- --- --- --- --- ------- ------- ------- | """Halstead Operator."""
04 -- --- --- --- --- --- --- ------- ------- ------- |
04 -- --- --- --- --- --- --- ------- ------- ------- | name = "halstead"
04 -- --- --- --- --- --- --- ------- ------- ------- | defaults = {
04 -- --- --- --- --- --- --- ------- ------- ------- | "exclude": None,
04 -- --- --- --- --- --- --- ------- ------- ------- | "ignore": None,
04 -- --- --- --- --- --- --- ------- ------- ------- | "min": "A",
04 -- --- --- --- --- --- --- ------- ------- ------- | "max": "C",
04 -- --- --- --- --- --- --- ------- ------- ------- | "multi": True,
04 -- --- --- --- --- --- --- ------- ------- ------- | "show": False,
04 -- --- --- --- --- --- --- ------- ------- ------- | "sort": False,
04 -- --- --- --- --- --- --- ------- ------- ------- | "by_function": True,
04 -- --- --- --- --- --- --- ------- ------- ------- | "include_ipynb": True,
04 -- --- --- --- --- --- --- ------- ------- ------- | "ipynb_cells": True,
04 -- --- --- --- --- --- --- ------- ------- ------- | }
04 -- --- --- --- --- --- --- ------- ------- ------- |
04 -- --- --- --- --- --- --- ------- ------- ------- | metrics = (
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("h1", "Unique Operands", int, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("h2", "Unique Operators", int, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("N1", "Number of Operands", int, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("N2", "Number of Operators", int, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric(
04 -- --- --- --- --- --- --- ------- ------- ------- | "vocabulary", "Unique vocabulary (h1 + h2)", int, MetricType.AimLow, sum
04 -- --- --- --- --- --- --- ------- ------- ------- | ),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("length", "Length of application", int, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("volume", "Code volume", float, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("difficulty", "Difficulty", float, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | Metric("effort", "Effort", float, MetricType.AimLow, sum),
04 -- --- --- --- --- --- --- ------- ------- ------- | )
04 -- --- --- --- --- --- --- ------- ------- ------- |
04 -- --- --- --- --- --- --- ------- ------- ------- | default_metric_index = 0 # MI
04 -- --- --- --- --- --- --- ------- ------- ------- |
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def __init__(self, config, targets):
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | Instantiate a new HC operator.
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | :param config: The wily configuration.
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | :type config: :class:`WilyConfig`
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | """
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | # TODO : Import config from wily.cfg
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | logger.debug(f"Using {targets} with {self.defaults} for HC metrics")
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 |
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | self.harvester = harvesters.HCHarvester(targets, config=Config(**self.defaults))
04 -- --- --- --- --- --- --- ------- ------- ------- |
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | def run(self, module, options):
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | """
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | Run the operator.
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 |
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | :param module: The target module path.
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | :type module: ``str``
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 |
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | :param options: Any runtime options.
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | :type options: ``dict``
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 |
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | :return: The operator results.
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | :rtype: ``dict``
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | """
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | logger.debug("Running halstead harvester")
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | results = {}
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | for filename, details in dict(self.harvester.results).items():
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | results[filename] = {"detailed": {}, "total": {}}
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | for instance in details:
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if isinstance(instance, list):
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | for item in instance:
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | function, report = item
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | results[filename]["detailed"][function] = self._report_to_dict(
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | report
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | )
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | else:
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | if isinstance(instance, str) and instance == "error":
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | logger.warning(
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | f"Failed to run Halstead harvester on {filename} : {details['error']}"
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | )
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | continue
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | results[filename]["total"] = self._report_to_dict(instance)
04 07 002 004 002 004 006 006 0015.51 0015.51 0001.00 | return results
04 -- --- --- --- --- --- --- ------- ------- ------- |
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | def _report_to_dict(self, report):
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | return {
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "h1": report.h1,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "h2": report.h2,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "N1": report.N1,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "N2": report.N2,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "vocabulary": report.vocabulary,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "volume": report.volume,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "length": report.length,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "effort": report.effort,
04 01 000 000 000 000 000 000 0000.00 0000.00 0000.00 | "difficulty": report.difficulty,
-- -- 000 000 000 000 000 000 0000.00 0000.00 0000.00 | }