carocad/CodeInk

View on GitHub
codeink/atelier/scientist.py

Summary

Maintainability
A
0 mins
Test Coverage
"""General mathematic related functions"""

import math
from radon import metrics
from codeink.atelier import secretary
from codeink.parchment import tools
filterfalse = tools.safe_import(origin='itertools', funk1='filterfalse', funk2='ifilterfalse')

def get_size_color(strcode, initsize=50):
    """base on the `strcode` string, calculate its complexity
    and maintainabiliy indexes and transform those into size and
    color values.

    Args:
        strcode (str): source code to use for the calculations.
        initsize (Optional[int]): minimum value of size.
    Returns:
        tuple(int): size and color of the passed source code.

    """
    size = initsize # minimum size
    cyclom, maintainability = calculate_complexity(strcode)
    size += math.pow(cyclom, 2)

    hsl = secretary.value_to_HSL(maintainability)
    color = secretary.hsl_to_str(*hsl)
    return size, color

def calculate_complexity(sourcecode):
    """calculate the ciclomatic and maintainability index of the
    provided `source code`.

    Args:
        sourcecode (str): source code to use for the calculations.
    Returns:
        Tuple[int]: cyclomatic and maintainability index.

    """
    halstead, cyclom, lloc, pcom = metrics.mi_parameters(sourcecode, count_multi=False)
    maintainability = metrics.mi_compute(halstead, cyclom, lloc, pcom)
    return cyclom, maintainability

def compute_edges(filepath, base, found_imports, missing_imports=None):
    """base on `found_imports` list, determine which of the imported modules
    are related to each other.

    Args:
        filepath (str): absolute filepath of the module under analysis.
        base (str): The most basic node. Every unknown import will be treated
          as related to this node.
        found_imports (List[modulefinder.Module]): list of modules imported
        missing_imports (List[str]): list of names of modules not found.
    Yields:
        Tuple[str, str]: module filepath and import filepath. Note that `base`
          is used in case the module filepath is unknown.
    """
    for module in found_imports:
        if include_module(module):
            yield (filepath, module.__file__)
    if missing_imports:
        yield (filepath, base)

def include_module(module):
    """nice wrapper around a set of ugly comparison neccessary to determine
    if a module should be included in the list of related modules.

    Args:
        module (modulefinder.Module): Module information gathered by modulefinder.
    Returns:
        bool: True if the module should be included, False otherwise.
    """
    return (module.__file__ is not None # builtin import
            and not module.__file__.endswith('__init__.py') # pkg import
            #and filepath != module.__file__
            and module.__name__ != '__main__') # self module

def filtertype(objtype, sequence, filterfalse=False):
    """filter a list of objects base on their type. Currently two types of filtering
    are allowed, those that have the same type as `objtype` and those that doesnt.
    `filterfalse` should be set to `True` if negative filtering is desired.

    Args:
        objtype (Any): Type of the objects that are used as comparison.
        sequence (Sequence[Any]): A sequence of objects to be filtered.
        filterfalse (Optional[bool]): whether or not to filter those objects that
          are not of type `objtype`.
    Returns:
        Iterator[Any]: iterator over the sequence of objects that conform to the
          desired filtering process.
    """
    filterfn = filter if not filterfalse else filterfalse
    return filterfn(lambda element: isinstance(element, objtype), sequence)