{"id":5827,"library":"xenon","title":"Xenon Python Code Metrics Tool","description":"Xenon is a Python code complexity tool that analyzes source code for various metrics like cyclomatic complexity, raw LOC, and maintainability index, leveraging the `radon` library. It's designed for integration into CI pipelines to monitor code quality against defined thresholds. The current version is 0.9.3, with updates occurring periodically, often tied to `radon` releases.","status":"active","version":"0.9.3","language":"en","source_language":"en","source_url":"https://github.com/ruboc/xenon","tags":["code-quality","static-analysis","cli","complexity-metrics","ci-cd"],"install":[{"cmd":"pip install xenon","lang":"bash","label":"Install Xenon"}],"dependencies":[{"reason":"Core dependency for code analysis metrics.","package":"radon","optional":false}],"imports":[{"note":"Xenon is primarily a CLI tool. Its library usage involves calling `xenon.main.main` with an argument list similar to `sys.argv`. It does not expose a high-level Python object API for analysis, so attempting to `import xenon` and call methods directly will not work as expected.","wrong":"import xenon","symbol":"main","correct":"from xenon.main import main"}],"quickstart":{"code":"import sys\nfrom io import StringIO\nfrom contextlib import redirect_stdout\nfrom xenon.main import main\n\n# Simulate running xenon from the command line\n# This will write output to stdout, so we capture it.\nargs = [\n    '--max-complexity', '10', \n    '--max-blocks', '50', \n    '.'\n]\n\n# Capture stdout to see the results\nold_stdout = sys.stdout\nredirected_output = StringIO()\nsys.stdout = redirected_output\n\ntry:\n    # main() returns 0 for success, non-zero for failure (thresholds exceeded)\n    result_code = main(args)\n    output = redirected_output.getvalue()\n    print(\"Xenon Analysis Output:\")\n    print(output)\n    if result_code != 0:\n        print(f\"Xenon found issues (exit code: {result_code}).\")\n    else:\n        print(\"Xenon analysis passed all thresholds.\")\nexcept SystemExit as e:\n    # main() uses sys.exit(), which raises SystemExit in Python.\n    # The exit code is in e.code\n    output = redirected_output.getvalue()\n    print(\"Xenon Analysis Output:\")\n    print(output)\n    print(f\"Xenon exited with code: {e.code}\")\nfinally:\n    sys.stdout = old_stdout # Restore stdout\n\n# For a real-world scenario, you might run it on a specific file/directory.\n# Example: args = ['--max-complexity', '10', 'your_project_dir/your_file.py']","lang":"python","description":"Demonstrates how to run `xenon` programmatically by calling its `main` function, simulating a command-line invocation. This allows capturing its output and exit code for integration into Python scripts or build systems. Note that `main` can raise `SystemExit`, which should be handled."},"warnings":[{"fix":"Review release notes for 0.9.0 regarding configuration (`pyproject.toml`, `.xenon.ini`), file inclusions, and adapt any automated parsing of JSON reports. Explicitly specify `--include` or `--pattern` for non-Python files if needed.","message":"Version 0.9.0 introduced significant breaking changes in configuration handling, default file filtering (now only Python files by default), and the JSON report output format.","severity":"breaking","affected_versions":"0.9.0+"},{"fix":"Wrap calls to `xenon.main.main` in a `try...except SystemExit` block to handle its exit behavior. Process results by capturing `stdout` or parsing JSON reports saved to a file, rather than expecting direct return values.","message":"Xenon is primarily a command-line tool. Its Python 'library' usage involves calling `xenon.main.main(args)` directly, which mimics `sys.argv` and can call `sys.exit()` (raising `SystemExit`). It does not provide a high-level, object-oriented API for analysis results.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Add `--include` or `--pattern` arguments to your CLI command or configuration to match the desired files, for example, `--pattern '*.py,*.ipynb'`.","message":"Xenon's default behavior changed in 0.9.0 to only analyze Python files (`*.py`). If you need to analyze other file types (e.g., Jupyter notebooks with `--max-nb-complexity`), you must explicitly specify `--include` or `--pattern`.","severity":"gotcha","affected_versions":"0.9.0+"}],"env_vars":null,"last_verified":"2026-04-14T00:00:00.000Z","next_check":"2026-07-13T00:00:00.000Z"}