The complexity PyCodeQual assigns to functions and methods is based on the Cyclomatic Complexity metric as proposed by McCabe. It essentially measures the number of paths through a piece of code. While this is useful, it gives the same complexity for very different pieces of code.

Consider the following example:

def fn_a(self, arg):
    if arg is None:
        return []
    return arg

def fn_b(self, a, b, c=1):
    if a is None:
        return (b + c ** b + b) / c
    d, e = a ** 2, b ** 2
    return math.acos(a) * math.log(d, e) + c

When we just count the number of ways through the body of the two functions, they both get the complexity 2. It is fair to assume that fn_b is harder to understand and on average has a higher likeliness of defects.

Simply put, the complexity of a piece of code is the amount of different things that you have to keep in mind in order to understand what it does. Thus, Code DB’s complexity measure is extended to account for

  • the number of arguments

  • the number of variables

  • the depth of expression trees (arithmetics, boolean expressions, etc.)

Those components are weighted and then added up.