Various code metrics for Python code

Overview

Radon

Codacy badge Travis-CI badge Coveralls badge PyPI latest version badge Radon license

Radon is a Python tool that computes various metrics from the source code. Radon can compute:

  • McCabe's complexity, i.e. cyclomatic complexity
  • raw metrics (these include SLOC, comment lines, blank lines, &c.)
  • Halstead metrics (all of them)
  • Maintainability Index (the one used in Visual Studio)

Requirements

Radon will run from Python 2.7 to Python 3.8 (except Python versions from 3.0 to 3.3) with a single code base and without the need of tools like 2to3 or six. It can also run on PyPy without any problems (currently PyPy 3.5 v7.3.1 is used in tests).

Radon depends on as few packages as possible. Currently only mando is strictly required (for the CLI interface). colorama is also listed as a dependency but if Radon cannot import it, the output simply will not be colored.

Note: Python 2.6 was supported until version 1.5.0. Starting from version 2.0, it is not supported anymore.

Installation

With Pip:

$ pip install radon

Or download the source and run the setup file:

$ python setup.py install

Usage

Radon can be used either from the command line or programmatically. Documentation is at https://radon.readthedocs.org/.

Cyclomatic Complexity Example

Quick example:

$ radon cc sympy/solvers/solvers.py -a -nc
sympy/solvers/solvers.py
    F 346:0 solve - F
    F 1093:0 _solve - F
    F 1434:0 _solve_system - F
    F 2647:0 unrad - F
    F 110:0 checksol - F
    F 2238:0 _tsolve - F
    F 2482:0 _invert - F
    F 1862:0 solve_linear_system - E
    F 1781:0 minsolve_linear_system - D
    F 1636:0 solve_linear - D
    F 2382:0 nsolve - C

11 blocks (classes, functions, methods) analyzed.
Average complexity: F (61.0)

Explanation:

  • cc is the radon command to compute Cyclomatic Complexity
  • -a tells radon to calculate the average complexity at the end. Note that the average is computed among the shown blocks. If you want the total average, among all the blocks, regardless of what is being shown, you should use --total-average.
  • -nc tells radon to print only results with a complexity rank of C or worse. Other examples: -na (from A to F), or -nd (from D to F).
  • The letter in front of the line numbers represents the type of the block (F means function, M method and C class).

Actually it's even better: it's got colors!

A screen of Radon's cc command

Note about file encoding

On some systems, such as Windows, the default encoding is not UTF-8. If you are using Unicode characters in your Python file and want to analyze it with Radon, you'll have to set the RADONFILESENCODING environment variable to UTF-8.

On a Continuous Integration server

If you are looking to use radon on a CI server you may be better off with xenon. Although still experimental, it will fail (that means exiting with a non-zero exit code) when various thresholds are surpassed. radon is more of a reporting tool, while xenon is a monitoring one.

If you are looking for more complete solutions, read the following sections.

Codacy

Codacy uses Radon by default to calculate metrics from the source code.

Code Climate

Radon is available as a Code Climate Engine. To understand how to add Radon's checks to your Code Climate Platform, head over to their documentation: https://docs.codeclimate.com/v1.0/docs/radon

coala Analyzer

Radon is also supported in coala. To add Radon's checks to coala, simply add the RadonBear to one of the sections in your .coafile.

CodeFactor

CodeFactor uses Radon out-of-the-box to calculate Cyclomatic Complexity.

Usage with Jupyter Notebooks

Radon can be used with .ipynb files to inspect code metrics for Python cells. Any % macros will be ignored in the metrics.

Note

Jupyter Notebook support requires the optional nbformat package. To install, run pip install nbformat.

To enable scanning of Jupyter notebooks, add the --include-ipynb flag.

To enable reporting of individual cells, add the --ipynb-cells flag.

Quick example:

$ radon raw --include-ipynb --ipynb-cells .
example.ipynb
    LOC: 63
    LLOC: 37
    SLOC: 37
    Comments: 3
    Single comments: 2
    Multi: 10
    Blank: 14
    - Comment Stats
        (C % L): 5%
        (C % S): 8%
        (C + M % L): 21%
example.ipynb:[0]
    LOC: 0
    LLOC: 0
    SLOC: 0
    Comments: 0
    Single comments: 0
    Multi: 0
    Blank: 0
    - Comment Stats
        (C % L): 0%
        (C % S): 0%
        (C + M % L): 0%
example.ipynb:[1]
    LOC: 2
    LLOC: 2
    SLOC: 2
    Comments: 0
    Single comments: 0
    Multi: 0
    Blank: 0
    - Comment Stats
        (C % L): 0%
        (C % S): 0%
        (C + M % L): 0%

Links

Comments
  • ERROR: invalid syntax (<unknown>, line 1404)

    ERROR: invalid syntax (, line 1404)

    Cloned the repository. Did sudo python radon/setup.py install with apparent success. Installed Baker module.

    [21:48 ~/Documents/Dprojects/Python/CoBro] radon cc cobro.py
    cobro.py
        ERROR: invalid syntax (<unknown>, line 1404)
    [21:48 ~/Documents/Dprojects/Python/CoBro] radon mi cobro.py
    cobro.py
        ERROR: invalid syntax (<unknown>, line 1404)
    [21:49 ~/Documents/Dprojects/Python/CoBro] radon raw  cobro.py
    cobro.py
        LOC: 1404
        LLOC: 688
        SLOC: 1323
        Comments: 491
        Multi: 82
        Blank: 81
        - Comment Stats
            (C % L): 35%
            (C % S): 37%
            (C + M % L): 41%
    

    Noting "1404" as size of input -- that line of cobro.py was: # c'est tout! a comment indented 4 ending in ! -- deleted that line and appropriate output appeared. Restoring line 1404 as #! returned the error.

    opened by tallforasmurf 15
  • CC for lambda functions (and, more generally, nested functions)

    CC for lambda functions (and, more generally, nested functions)

    In the documentation on ReadTheDocs (https://radon.readthedocs.org/en/latest/intro.html#cyclomatic-complexity), the reasoning behind increasing CC by one when encountering a lambda function is that it is a regular function. This raises a couple of questions:

    1. Why should a lambda function in itself increase the cyclomatic complexity? Surely, it does not in itself add any linearly independent paths.
    2. Why should it make a difference in the CC of a function if the lambda function is defined inside the function or not? The lambda function could be replaced by a regular function which would either be nested or not. This replacement-function would have a CC of its own but why should it add to the CC of the other function?

    To make an example:

    lambda1 = lambda var: var
    lambda2 = lambda var: var if type(var) is str else str(var)
    
    def f1(var):
        return lambda1(var)
    
    def f2(var):
        return lambda2(var)
    
    def f3(var):
        lambda1 = lambda var: var
        return lambda1(var)
    
    def f4(var):
        lambda2 = lambda var: var if type(var) is str else str(var)
        return lambda2(var)
    

    When calling radon cc -s with the above saved in a script, the following output is obtained:

        F 14:0 f4 - A (3)
        F 10:0 f3 - A (2)
        F 4:0 f1 - A (1)
        F 7:0 f2 - A (1)
    

    ... where the argument made in this post is that all four functions should have CC = 1.

    bug 
    opened by ppeder08 13
  • Return a non-zero exit code for results below a certain threshold

    Return a non-zero exit code for results below a certain threshold

    There should be an option to set a threshold so that this tool will be used during the CI process. For example radon cc --min=B -a --min-average=A will fail if there are modules with cyclic complexity of C and below and if the average is below A.

    feature 
    opened by thedrow 13
  • ERROR: super() takes at least 1 argument (0 given)

    ERROR: super() takes at least 1 argument (0 given)

    I'm running radon hal myfile.py, but got this: ERROR: super() takes at least 1 argument (0 given). Any idea why? thanks!

    OS: macOS Majove 10.14.5 radon==3.0.1

    opened by kimi-p 12
  • Fixing versions of required libs

    Fixing versions of required libs

    Hey! It's us again from coala.

    Seems you just did a release with this line: https://github.com/rubik/radon/blob/master/setup.py#L21

    And it's giving us a lot of headaches (and CI failures) because you fix the colorama version to 0.3.6. So we have had long discussions last night and first off we don't know what's the best way to handle dependencies.

    We totally see that it's a huge value to fix the dependencies to a certain version as your stability increases, you can rely on your program to not have any issues due to any new releases of your dependency. OTOH if you have users that possibly want to use coala/radon on their python application you don't want to require them to

    a) Fix their requirements to yours if they overlap or b) Make an own virtualenv just for code checking.

    In general you'd rather want your requirements a bit more flexible because otherwise the user will be spending half of his workday working around clashing dependencies.

    What is your stand on that discussion?

    opened by sils 11
  • Separate

    Separate "flake8-polifyll" to extra requirement

    When installing radon, it requires flake8-polyfill, which, in turn, requires flake8.

    IMO, this should be an option provided though extra requirement (something like radon[flake8]) since not everyone want flake8 installed when using just radon alone.

    opened by tribals 9
  • Ensure that loc = sloc + multi + single-line comments + blank.

    Ensure that loc = sloc + multi + single-line comments + blank.

    This PR tries to address https://github.com/rubik/radon/issues/109. It fixes loc to genuinely be the sum of sloc, multi-line comments (including blank lines), single-line comments and blank lines (outside of comments). This requires a lot of test changes.

    There is a TODO on one case where the tokenizer approach seemed to be getting tripped up:

    def func():
        """ my comment """ \
       
        pass
    

    In this case, the tokenizer is reporting an error until it joins the line containing pass. Not sure if this is a bug with the tokenizer or not.

    I'm also not sure what the intermediate values in the comments should be for the second_mi example.

    opened by ashanbrown 9
  • Support configuration file

    Support configuration file

    I use radon on CodeClimate, and it's the only engine that requires configuration inside my .codeclimate.yml file. It would be much more straightforward to have a .radon.yml or .radon.txt file with the configurations, so I could run codeclimate analyze -r radon and/or radon itself and have the same output without having to figure which parameters codeclimate passes for each configuration on .codeclimate.yml.

    opened by caiofbpa 9
  • Installing radon breaks flake8

    Installing radon breaks flake8

    Issue

    The radon setup.py configures entry_points for flake8. When used by flake8, this entry point attempts to unconditionally import flake8_polyfill, causing flake8 to crash due to an ImportError if flake8-polyfill is not installed.

    The radon library should either specify flake8-polyfill as a required dependency, or guard against this error condition.

    Steps to reproduce

    1. Create a new virtualenv (pyenv-virtualenv used in this example):

      $ pyenv virtualenv 3.6.13 radon-issue
      $ pyenv activate radon-issue
      
    2. Install flake8 and observe only flake8 and dependencies are installed:

      $ pip install flake8
      $ pip freeze
      flake8==3.9.2
      importlib-metadata==4.0.1
      mccabe==0.6.1
      pycodestyle==2.7.0
      pyflakes==2.3.1
      typing-extensions==3.10.0.0
      zipp==3.4.1
      
    3. Confirm flake8 works (--version option used for this purpose):

      $ flake8 --version
      3.9.2 (mccabe: 0.6.1, pycodestyle: 2.7.0, pyflakes: 2.3.1) CPython 3.6.13 on
      Linux
      
    4. Install radon and observe new installed libraries:

      $ pip install radon
      $ pip freeze
      colorama==0.4.4
      flake8==3.9.2
      future==0.18.2
      importlib-metadata==4.0.1
      mando==0.6.4
      mccabe==0.6.1
      pycodestyle==2.7.0
      pyflakes==2.3.1
      radon==4.5.1
      six==1.16.0
      typing-extensions==3.10.0.0
      zipp==3.4.1
      
    5. Run flake8 again:

      $ flake8 --version
      Traceback (most recent call last):
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/plugins/manager.py", line 157, in load_plugin
          self._load()
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/plugins/manager.py", line 134, in _load
          self._plugin = self.entry_point.load()
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/importlib_metadata/__init__.py", line 166, in load
          module = import_module(match.group('module'))
      File "/home/user/.pyenv/versions/3.6.13/lib/python3.6/importlib/__init__.py", line 126, in import_module
          return _bootstrap._gcd_import(name[level:], package, level)
      File "<frozen importlib._bootstrap>", line 994, in _gcd_import
      File "<frozen importlib._bootstrap>", line 971, in _find_and_load
      File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
      File "<frozen importlib._bootstrap_external>", line 678, in exec_module
      File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/radon/contrib/flake8.py", line 1, in <module>
          from flake8_polyfill import options
      ModuleNotFoundError: No module named 'flake8_polyfill'
      
      During handling of the above exception, another exception occurred:
      
      Traceback (most recent call last):
      File "/home/user/.pyenv/versions/radon-issue/bin/flake8", line 11, in <module>
          sys.exit(main())
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/main/cli.py", line 22, in main
          app.run(argv)
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/main/application.py", line 363, in run
          self._run(argv)
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/main/application.py", line 350, in _run
          self.initialize(argv)
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/main/application.py", line 330, in initialize
          self.find_plugins(config_finder)
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/main/application.py", line 159, in find_plugins
          self.check_plugins.load_plugins()
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/plugins/manager.py", line 415, in load_plugins
          plugins = list(self.manager.map(load_plugin))
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/plugins/manager.py", line 302, in map
          yield func(self.plugins[name], *args, **kwargs)
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/plugins/manager.py", line 413, in load_plugin
          return plugin.load_plugin()
      File "/home/user/.pyenv/versions/3.6.13/envs/radon-issue/lib/python3.6/site-packages/flake8/plugins/manager.py", line 164, in load_plugin
          raise failed_to_load
      flake8.exceptions.FailedToLoadPlugin: Flake8 failed to load plugin "R70" due to No module named 'flake8_polyfill'.
      

    Observe

    Command flake8 --version crashes due to ImportError when radon is installed.

    Expected

    Command flake8 --version outputs version information and exits cleanly.

    opened by joxl 8
  • Add support for Code Climate

    Add support for Code Climate

    This PR creates a native Code Climate integration in Radon by adding:

    1. Dockerfile to run Radon as an engine
    2. --codeclimate report format
    3. get_content and get_remediation_point methods that provide informational issue content and a measure of the amount of effort needed to repair an engineering problem.
    opened by mrb 8
  • Radon doesn't work with utf-8 encoded files

    Radon doesn't work with utf-8 encoded files

    $ radon --version
    1.1.1
    $ echo 'print("Olá Açúcar Lâmpada")' > /tmp/test.py
    $ radon cc /tmp/test.py
    /tmp/test.py
        ERROR: 'ascii' codec can't decode byte 0xc3 in position 9: ordinal not in range(128)
    
    bug 
    opened by andredias 8
  • New release to drop future package

    New release to drop future package

    I can see that future has already been dropped in this pull request https://github.com/rubik/radon/pull/234

    but can we also release this now to resolve security scan failures that use this project? Thanks!

    opened by donfiguerres 0
  • pyproject.toml support

    pyproject.toml support

    Fixes: https://github.com/rubik/radon/issues/220

    This enables pyproject.toml support for radon.

    Decisions I made the maintainer should be aware of before merging:

    • Automatic pyproject.toml support for python 3.11+
    • Optional pyproject.toml support for python <3.11 if you install with:
      pip install radon[toml]
      
    • Silently ignores pyproject.toml if:
      • no pyproject.toml file is found
      • no toml parsing library is available
    • Raises an exception if:
      • toml file is found and is parsed incorrectly.

    I'm happy to change anything that isn't quite in the spirit of radon.

    opened by ajslater 0
  • Documentation link outdated

    Documentation link outdated

    According to https://pypi.org/project/radon/ the latest version is 5.1.0. However, the link to the documentation page https://radon.readthedocs.org/ redirects to an outdated version of 4.1.0. Please fix!

    E.g. the --codeclimate option is not documented for the 4.1.0 version but the command line help shows it.

    opened by ghpqans 2
  • Python 3.10: match-case syntax not yet supported by radon?

    Python 3.10: match-case syntax not yet supported by radon?

    I have analyzed cyclomatic complexity of a function that has this new Python 3.10 match-case syntax. The result of that function was A (1). That's not correct. The function had a lot of case statements in it.

    Is there any undergoing work yet to have radon analyze and correctly report cyclomatic complexity where there's match-case syntax in Python 3.10 code?

    opened by PedanticHacker 1
  • Radon struggles to collect statistics from large files

    Radon struggles to collect statistics from large files

    I have some large files that radon struggles to analyse. I created an example to demonstrate the problem: https://gist.githubusercontent.com/Sam152/50e8ef27cceb899084b42a069237a7b8/raw/bb21870395df86a0062c22353b532b45d31bd3f5/sample.py (~800 lines)

    In my case running radon raw big-package takes 28.38s. In reality the module I'm trying to analyse has ~ 5000 lines with a similar amount of AST per line.

    If I double my 800 line example, the script takes roughly 115.50s to run, so my feeling is that there might be something which scales worse than O(n) per-AST.

    Any pointers if there might be something that can be optimised here, or if the nature of the analysis is such that speeding this process up is simply not possible?

    Thanks in advance, if anyone can share their experience.

    Cheers, Sam


    On a side note, while researching this issue, I found radon cited in an academic paper, which I thought was interesting and worth sharing (https://arxiv.org/pdf/2007.08978.pdf).

    opened by Sam152 2
An extensible and friendly code review tool for projects and companies of all sizes.

Review Board Review Board is an open source, web-based code and document review tool built to help companies, open source projects, and other organiza

Review Board 1.5k Jan 2, 2023
Code Review, hosted on Google App Engine

Welcome to Rietveld GitHub Wiki: https://github.com/rietveld-codereview/rietveld/wiki Google Group: http://groups.google.com/group/codereview-discuss

null 531 Dec 24, 2022
Inspects Python source files and provides information about type and location of classes, methods etc

prospector About Prospector is a tool to analyse Python code and output information about errors, potential problems, convention violations and comple

Python Code Quality Authority 1.7k Dec 31, 2022
McCabe complexity checker for Python

McCabe complexity checker Ned's script to check McCabe complexity. This module provides a plugin for flake8, the Python code checker. Installation You

Python Code Quality Authority 527 Dec 21, 2022
A tool for measuring Python class cohesion.

Cohesion Cohesion is a tool for measuring Python class cohesion. In computer programming, cohesion refers to the degree to which the elements of a mod

null 177 Jan 4, 2023
FAIR Enough Metrics is an API for various FAIR Metrics Tests, written in python

☑️ FAIR Enough metrics for research FAIR Enough Metrics is an API for various FAIR Metrics Tests, written in python, conforming to the specifications

Maastricht University IDS 3 Jul 6, 2022
Pytorch Lightning 1.2k Jan 6, 2023
Metrics-advisor - Analyze reshaped metrics from TiDB cluster Prometheus and give some advice about anomalies and correlation.

metrics-advisor Analyze reshaped metrics from TiDB cluster Prometheus and give some advice about anomalies and correlation. Team freedeaths mashenjun

null 3 Jan 7, 2022
Various code metrics for Python code

Radon Radon is a Python tool that computes various metrics from the source code. Radon can compute: McCabe's complexity, i.e. cyclomatic complexity ra

Michele Lacchia 1.4k Jan 7, 2023
Simple tool/toolkit for evaluating NLG (Natural Language Generation) offering various automated metrics.

Simple tool/toolkit for evaluating NLG (Natural Language Generation) offering various automated metrics. Jury offers a smooth and easy-to-use interface. It uses datasets for underlying metric computation, and hence adding custom metric is easy as adopting datasets.Metric.

Open Business Software Solutions 129 Jan 6, 2023
A collection of automation aids to connect various database systems into Lookout for Metrics

A collection of automation aids to connect various database systems into Lookout for Metrics

AWS Samples 3 Apr 28, 2022
A python based tool that executes various CVEs to gain root privileges as root on various MAC OS platforms.

MacPer A python based tool that executes various CVEs to gain root privileges as root on various MAC OS platforms. Not all of the exploits directly sp

null 20 Nov 30, 2022
Code for reproducing our analysis in the paper titled: Image Cropping on Twitter: Fairness Metrics, their Limitations, and the Importance of Representation, Design, and Agency

Image Crop Analysis This is a repo for the code used for reproducing our Image Crop Analysis paper as shared on our blog post. If you plan to use this

Twitter Research 239 Jan 2, 2023
Metrinome is an all-purpose tool for working with code complexity metrics.

Overview Metrinome is an all-purpose tool for working with code complexity metrics. It can be used as both a REPL and API, and includes: Converters to

null 26 Dec 26, 2022
Machine learning evaluation metrics, implemented in Python, R, Haskell, and MATLAB / Octave

Note: the current releases of this toolbox are a beta release, to test working with Haskell's, Python's, and R's code repositories. Metrics provides i

Ben Hamner 1.6k Dec 26, 2022
whm also known as wifi-heat-mapper is a Python library for benchmarking Wi-Fi networks and gather useful metrics that can be converted into meaningful easy-to-understand heatmaps.

whm also known as wifi-heat-mapper is a Python library for benchmarking Wi-Fi networks and gather useful metrics that can be converted into meaningful easy-to-understand heatmaps.

Nischay Mamidi 128 Dec 16, 2022
A python toolbox for predictive uncertainty quantification, calibration, metrics, and visualization

Website, Tutorials, and Docs    Uncertainty Toolbox A python toolbox for predictive uncertainty quantification, calibration, metrics, and visualizatio

Uncertainty Toolbox 1.4k Dec 28, 2022
A Python application that helps users determine their calorie intake, and automatically generates customized weekly meal and workout plans based on metrics computed using their physical parameters

A Python application that helps users determine their calorie intake, and automatically generates customized weekly meal and workout plans based on metrics computed using their physical parameters

Anam Iqbal 1 Jan 13, 2022