Skip to main content

Interrogate a codebase for docstring coverage.

Project description

Pink Sloth Logo

interrogate: explain yourself

Documentation Coverage Testing Coverage Documentation Status CI Status

Interrogate a codebase for docstring coverage.

Why Do I Need This?

interrogate checks your code base for missing docstrings.

Documentation should be as important as code itself. And it should live within code. Python standardized docstrings, allowing for developers to navigate libraries as simply as calling help() on objects, and with powerful tools like Sphinx, pydoc, and Docutils to automatically generate HTML, LaTeX, PDFs, etc.

Enter: interrogate.

interrogate will tell you which methods, functions, classes, and modules have docstrings, and which do not. Use interrogate to:

  • Get an understanding of how well your code is documented;

  • Add it to CI/CD checks to enforce documentation on newly-added code;

  • Assess a new code base for (one aspect of) code quality and maintainability.

Let’s get started.

Requirements

interrogate supports Python 3.5 and above.

Installation

interrogate is available on PyPI and GitHub. The recommended installation method is pip-installing into a virtualenv:

$ pip install interrogate

Usage

Try it out on a Python project:

$ interrogate [PATH]
RESULT: PASSED (minimum: 80.0%, actual: 100.0%)

Add verbosity to see a summary:

$ interrogate -v [PATH]

================== Coverage for /Users/lynn/dev/interrogate/ ====================
------------------------------------ Summary ------------------------------------
| Name                                  |   Total |   Miss |   Cover |   Cover% |
|---------------------------------------|---------|--------|---------|----------|
| src/interrogate/__init__.py           |       1 |      0 |       1 |     100% |
| src/interrogate/__main__.py           |       1 |      0 |       1 |     100% |
| src/interrogate/badge_gen.py          |       5 |      0 |       5 |     100% |
| src/interrogate/cli.py                |       2 |      0 |       2 |     100% |
| src/interrogate/config.py             |       6 |      0 |       6 |     100% |
| src/interrogate/coverage.py           |      25 |      0 |      25 |     100% |
| src/interrogate/utils.py              |      10 |      0 |      10 |     100% |
| src/interrogate/visit.py              |      15 |      0 |      15 |     100% |
| tests/functional/__init__.py          |       1 |      0 |       1 |     100% |
| tests/functional/test_cli.py          |       7 |      0 |       7 |     100% |
| tests/functional/test_coverage.py     |       6 |      0 |       6 |     100% |
| tests/unit/__init__.py                |       1 |      0 |       1 |     100% |
| tests/unit/test_badge_gen.py          |       6 |      0 |       6 |     100% |
| tests/unit/test_config.py             |       7 |      0 |       7 |     100% |
| tests/unit/test_utils.py              |      13 |      0 |      13 |     100% |
|---------------------------------------|---------|--------|---------|----------|
| TOTAL                                 |     106 |      0 |     106 |   100.0% |
---------------- RESULT: PASSED (minimum: 80.0%, actual: 100.0%) ----------------

Add even more verbosity:

$ interrogate -vv [PATH]

================== Coverage for /Users/lynn/dev/interrogate/ ====================
------------------------------- Detailed Coverage -------------------------------
| Name                                                                |  Status |
|---------------------------------------------------------------------|---------|
| src/interrogate/__init__.py (module)                                | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/__main__.py (module)                                | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/badge_gen.py (module)                               | COVERED |
|   save_badge (L33)                                                  | COVERED |
|   get_badge (L50)                                                   | COVERED |
|   get_color (L66)                                                   | COVERED |
|   create (L79)                                                      | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/cli.py (module)                                     | COVERED |
|   main (L18)                                                        | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/config.py (module)                                  | COVERED |
|   InterrogateConfig (L14)                                           | COVERED |
|   find_project_root (L49)                                           | COVERED |
|   find_pyproject_toml (L77)                                         | COVERED |
|   parse_pyproject_toml (L84)                                        | COVERED |
|   read_pyproject_toml (L100)                                        | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/coverage.py (module)                                | COVERED |
|   BaseInterrogateResult (L20)                                       | COVERED |
|     BaseInterrogateResult.perc_covered (L34)                        | COVERED |
|   InterrogateFileResult (L48)                                       | COVERED |
|     InterrogateFileResult.combine (L62)                             | COVERED |
|   InterrogateResults (L75)                                          | COVERED |
|     InterrogateResults.combine (L88)                                | COVERED |
|   InterrogateCoverage (L96)                                         | COVERED |
|     InterrogateCoverage._add_common_exclude (L115)                  | COVERED |
|     InterrogateCoverage._filter_files (L122)                        | COVERED |
|     InterrogateCoverage.get_filenames_from_paths (L139)             | COVERED |
|     InterrogateCoverage._filter_nodes (L166)                        | COVERED |
|     InterrogateCoverage._get_file_coverage (L192)                   | COVERED |
|     InterrogateCoverage._get_coverage (L218)                        | COVERED |
|     InterrogateCoverage.get_coverage (L235)                         | COVERED |
|     InterrogateCoverage._get_filename (L240)                        | COVERED |
|     InterrogateCoverage._get_detailed_row (L251)                    | COVERED |
|     InterrogateCoverage._create_detailed_table (L268)               | COVERED |
|       InterrogateCoverage._create_detailed_table._sort_nodes (L275) | COVERED |
|     InterrogateCoverage._print_detailed_table (L297)                | COVERED |
|     InterrogateCoverage._create_summary_table (L315)                | COVERED |
|     InterrogateCoverage._print_summary_table (L349)                 | COVERED |
|     InterrogateCoverage._sort_results (L366)                        | COVERED |
|     InterrogateCoverage._get_header_base (L397)                     | COVERED |
|     InterrogateCoverage.print_results (L406)                        | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/utils.py (module)                                   | COVERED |
|   parse_regex (L22)                                                 | COVERED |
|   smart_open (L40)                                                  | COVERED |
|   get_common_base (L61)                                             | COVERED |
|   OutputFormatter (L81)                                             | COVERED |
|     OutputFormatter.should_markup (L91)                             | COVERED |
|     OutputFormatter.set_detailed_markup (L106)                      | COVERED |
|     OutputFormatter.set_summary_markup (L130)                       | COVERED |
|     OutputFormatter._interrogate_line_formatter (L159)              | COVERED |
|     OutputFormatter.get_table_formatter (L222)                      | COVERED |
|---------------------------------------------------------------------|---------|
| src/interrogate/visit.py (module)                                   | COVERED |
|   CovNode (L10)                                                     | COVERED |
|   CoverageVisitor (L38)                                             | COVERED |
|     CoverageVisitor._has_doc (L51)                                  | COVERED |
|     CoverageVisitor._visit_helper (L59)                             | COVERED |
|     CoverageVisitor._is_nested (L99)                                | COVERED |
|     CoverageVisitor._is_private (L108)                              | COVERED |
|     CoverageVisitor._is_semiprivate (L116)                          | COVERED |
|     CoverageVisitor._is_ignored_common (L126)                       | COVERED |
|     CoverageVisitor._is_func_ignored (L143)                         | COVERED |
|     CoverageVisitor._is_class_ignored (L160)                        | COVERED |
|     CoverageVisitor.visit_Module (L164)                             | COVERED |
|     CoverageVisitor.visit_ClassDef (L171)                           | COVERED |
|     CoverageVisitor.visit_FunctionDef (L180)                        | COVERED |
|     CoverageVisitor.visit_AsyncFunctionDef (L189)                   | COVERED |
|---------------------------------------------------------------------|---------|
| tests/functional/__init__.py (module)                               | COVERED |
|---------------------------------------------------------------------|---------|
| tests/functional/test_cli.py (module)                               | COVERED |
|   runner (L20)                                                      | COVERED |
|   test_run_no_paths (L26)                                           | COVERED |
|   test_run_shortflags (L36)                                         | COVERED |
|   test_run_longflags (L73)                                          | COVERED |
|   test_run_multiple_flags (L98)                                     | COVERED |
|   test_generate_badge (L116)                                        | COVERED |
|---------------------------------------------------------------------|---------|
| tests/functional/test_coverage.py (module)                          | COVERED |
|   test_coverage_simple (L19)                                        | COVERED |
|   test_coverage_errors (L55)                                        | COVERED |
|   test_print_results (L75)                                          | COVERED |
|   test_print_results_ignore_module (L103)                           | COVERED |
|   test_print_results_single_file (L139)                             | COVERED |
|---------------------------------------------------------------------|---------|
| tests/unit/__init__.py (module)                                     | COVERED |
|---------------------------------------------------------------------|---------|
| tests/unit/test_badge_gen.py (module)                               | COVERED |
|   test_save_badge (L17)                                             | COVERED |
|   test_save_badge_windows (L39)                                     | COVERED |
|   test_get_badge (L61)                                              | COVERED |
|   test_get_color (L73)                                              | COVERED |
|   test_create (L90)                                                 | COVERED |
|---------------------------------------------------------------------|---------|
| tests/unit/test_config.py (module)                                  | COVERED |
|   test_find_project_root (L13)                                      | COVERED |
|   test_find_pyproject_toml (L40)                                    | COVERED |
|   test_parse_pyproject_toml (L53)                                   | COVERED |
|   test_read_pyproject_toml_none (L69)                               | COVERED |
|   test_read_pyproject_toml (L77)                                    | COVERED |
|   test_read_pyproject_toml_raises (L123)                            | COVERED |
|---------------------------------------------------------------------|---------|
| tests/unit/test_utils.py (module)                                   | COVERED |
|   test_parse_regex (L17)                                            | COVERED |
|   test_smart_open (L38)                                             | COVERED |
|   test_get_common_base (L55)                                        | COVERED |
|   test_get_common_base_windows (L77)                                | COVERED |
|   test_output_formatter_should_markup (L110)                        | COVERED |
|   test_output_formatter_set_detailed_markup (L146)                  | COVERED |
|   test_output_formatter_set_summary_markup (L176)                   | COVERED |
|   test_output_formatter_interrogate_line_formatter (L219)           | COVERED |
|   test_output_formatter_interrogate_line_formatter_windows (L280)   | COVERED |
|   test_output_formatter_get_table_formatter (L341)                  | COVERED |
|   test_output_formatter_get_table_formatter_py38 (L377)             | COVERED |
|   test_output_formatter_get_table_formatter_raises (L395)           | COVERED |
|---------------------------------------------------------------------|---------|

------------------------------------ Summary ------------------------------------
| Name                                  |   Total |   Miss |   Cover |   Cover% |
|---------------------------------------|---------|--------|---------|----------|
| src/interrogate/__init__.py           |       1 |      0 |       1 |     100% |
| src/interrogate/__main__.py           |       1 |      0 |       1 |     100% |
| src/interrogate/badge_gen.py          |       5 |      0 |       5 |     100% |
| src/interrogate/cli.py                |       2 |      0 |       2 |     100% |
| src/interrogate/config.py             |       6 |      0 |       6 |     100% |
| src/interrogate/coverage.py           |      25 |      0 |      25 |     100% |
| src/interrogate/utils.py              |      10 |      0 |      10 |     100% |
| src/interrogate/visit.py              |      15 |      0 |      15 |     100% |
| tests/functional/__init__.py          |       1 |      0 |       1 |     100% |
| tests/functional/test_cli.py          |       7 |      0 |       7 |     100% |
| tests/functional/test_coverage.py     |       6 |      0 |       6 |     100% |
| tests/unit/__init__.py                |       1 |      0 |       1 |     100% |
| tests/unit/test_badge_gen.py          |       6 |      0 |       6 |     100% |
| tests/unit/test_config.py             |       7 |      0 |       7 |     100% |
| tests/unit/test_utils.py              |      13 |      0 |      13 |     100% |
|---------------------------------------|---------|--------|---------|----------|
| TOTAL                                 |     106 |      0 |     106 |   100.0% |
---------------- RESULT: PASSED (minimum: 80.0%, actual: 100.0%) ----------------

Other Usage

Generate a shields.io badge (like this one! interrogate-badge ):

$ interrogate --generate-badge PATH
RESULT: PASSED (minimum: 80.0%, actual: 100.0%)
Generated badge to /Users/lynn/dev/interrogate/docs/_static/interrogate_badge.svg

Add it to your tox.ini file to enforce a level of coverage:

[testenv:doc]
deps = interrogate
skip_install = true
commands =
    interrogate --quiet --fail-under 95 src tests

Or use it with pre-commit:

repos:
  - repo: https://github.com/econchick/interrogate
    rev: 1.1.5  # or master if you're bold
    hooks:
      - id: interrogate
        args: [--quiet, --fail-under=95]

Use it within your code directly:

>>> from interrogate import coverage
>>> cov = coverage.InterrogateCoverage(paths=["src"])
>>> results = cov.get_coverage()
>>> results
InterrogateResults(total=68, covered=65, missing=3)

Configure within your pyproject.toml:

$ interrogate -c pyproject.toml [OPTIONS] [PATHS]...
[tool.interrogate]
ignore-init-method = true
ignore-init-module = false
ignore-magic = false
ignore-semiprivate = false
ignore-private = false
ignore-module = false
fail-under = 95
exclude = ["setup.py", "docs", "build"]
ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"]
verbose = 0
quiet = false
whitelist-regex = []
color = true

To view all options available, run interrogate --help:

interrogate -h
Usage: interrogate [OPTIONS] [PATHS]...

  Measure and report on documentation coverage in Python modules.

Options:
  --version                      Show the version and exit.
  -v, --verbose                  Level of verbosity  [default: 0]
  -q, --quiet                    Do not print output  [default: False]
  -f, --fail-under INT | FLOAT   Fail when coverage % is less than a given
                                 amount.  [default: 80.0]

  -e, --exclude PATH             Exclude PATHs of files and/or directories.
                                 Multiple `-e/--exclude` invocations
                                 supported.

  -i, --ignore-init-method       Ignore `__init__` method of classes.
                                 [default: False]

  -I, --ignore-init-module       Ignore `__init__.py` modules.  [default:
                                 False]

  -m, --ignore-magic             Ignore all magic methods of classes.
                                 [default: False]

                                 NOTE: This does not include the `__init__`
                                 method. To ignore `__init__` methods, use
                                 `--ignore-init-method`.

  -M, --ignore-module            Ignore module-level docstrings.  [default:
                                 False]

  -n, --ignore-nested-functions  Ignore nested functions and methods.
                                 [default: False]

  -p, --ignore-private           Ignore private classes, methods, and
                                 functions starting with two underscores.
                                 [default:False]

                                 NOTE: This does not include magic methods;
                                 use `--ignore-magic` and/or `--ignore-init-
                                 method` instead.

  -s, --ignore-semiprivate       Ignore semiprivate classes, methods, and
                                 functions starting with a single underscore.
                                 [default: False]

  -r, --ignore-regex STR         Regex identifying class, method, and function
                                 names to ignore. Multiple `-r/--ignore-regex`
                                 invocations supported.

  -w, --whitelist-regex STR      Regex identifying class, method, and function
                                 names to include. Multiple `-w/--whitelist-
                                 regex` invocations supported.

  -o, --output FILE              Write output to a given FILE.  [default:
                                 stdout]

  -c, --config FILE              Read configuration from `pyproject.toml`.
  --color / --no-color           Toggle color output on/off when printing to
                                 stdout.  [default: True]
  -g, --generate-badge PATH      Generate a 'shields.io' status badge (an SVG
                                 image) in at a given file or directory.

  -h, --help                     Show this message and exit.

Credits

interrogate was inspired by docstr-coverage, which was forked from Alexey “DataGreed” Strelkov’s docstring-coverage, which was inspired by a 2004 recipe from James Harlow (turtles…).

The cute sloth logo is by JustineW purchased via the Noun Project (but also available under the Creative Commons License with attribution).

Release Information

1.2.0 (2020-05-19)

Added

  • Add -n / --ignore-nested-functions flag to ignore nested functions and methods (#11).

  • Add color output for stdout via --color/--no-color (#25).

Fixed

  • Output now alpha-sorts by directory.

Full changelog.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

interrogate-1.2.0.tar.gz (65.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

interrogate-1.2.0-py3-none-any.whl (21.9 kB view details)

Uploaded Python 3

File details

Details for the file interrogate-1.2.0.tar.gz.

File metadata

  • Download URL: interrogate-1.2.0.tar.gz
  • Upload date:
  • Size: 65.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.2

File hashes

Hashes for interrogate-1.2.0.tar.gz
Algorithm Hash digest
SHA256 c69410f4bcefe98349942aa84824d2f811e6e9a7674d350ccc01da93f584b4af
MD5 fccd9094236dd72cdaa8d9d0b3d65815
BLAKE2b-256 34424f50c6bcc9fd84a8b7d7370fb4141e54ad233dd5398d0ce3f82ab103d4df

See more details on using hashes here.

File details

Details for the file interrogate-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: interrogate-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 21.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.23.0 setuptools/46.1.3 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.2

File hashes

Hashes for interrogate-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 daba87d40cf8742534a61bd190d9986f7b4b1364f71023cbfae5323c4ebe6042
MD5 530528f7c55515e9431abbf9b2635aee
BLAKE2b-256 8f8fd89d19078d05c48843d385caf0d9c67466691142318552cab72d5a3b54d3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page