 
  
  A strict CLI + library API to report untyped variables, arguments, and function returns in Python code
Typecoverage is a comprehensive Python static analysis tool that identifies missing type annotations in your codebase. Unlike other type checkers that focus on type correctness, Typecoverage specifically targets type annotation coverage - ensuring your code has complete type hints for maintainability and clarity.
- π Comprehensive Detection - Finds missing annotations in functions, methods, variables, and returns
- π― Multiple Input Types - Analyze files, directories, code strings, live Python objects, and more
- π Rich Output Formats - Human-readable text with colors or machine-readable JSON
- βοΈ Flexible Filtering - Smart defaults with configurable rules for different coding patterns
- π« Comment Suppression - Standard # type: ignoreand# noqasupport
- π High Performance - Parallel processing for large codebases
- π οΈ CI/CD Ready - Exit codes and JSON output for continuous integration
- π Detailed Context - Source code snippets around issues for easy fixing
from typecoverage import detect_untyped
# Analyze code string
code = """
def calculate_total(items, tax_rate):
    subtotal = sum(item.price for item in items)
    return subtotal * (1 + tax_rate)
"""
result = detect_untyped(code, statistics=True)
print(result)Output:
Found 3 type annotation issues
π <string>
  <string>:2:20 - Missing type annotation for argument "items"
    1 β 
  βΊ 2 β def calculate_total(items, tax_rate):
    3 β     subtotal = sum(item.price for item in items)
  <string>:2:27 - Missing type annotation for argument "tax_rate"
    1 β 
  βΊ 2 β def calculate_total(items, tax_rate):
    3 β     subtotal = sum(item.price for item in items)
  <string>:2:1 - Missing return type annotation "calculate_total"
    1 β 
  βΊ 2 β def calculate_total(items, tax_rate):
    3 β     subtotal = sum(item.price for item in items)
π Summary
  Total issues: 3
  π΄ Missing argument types: 2
  π‘ Missing return types: 1
git clone <repository-url>
cd typecoverage-project
pip install -r requirements.txt# Install in development mode
pip install -e .
# Or install directly
python setup.py install# Using the module
python -m typecoverage myfile.py
# Using the installed command
typecoverage myfile.py
# Analyze entire project with statistics
typecoverage --recursive --statistics src/
# JSON output for CI/CD
typecoverage --format json --exit-nonzero-on-issues src/ > report.json
# Include context lines for easier fixing
typecoverage --context-lines 3 src/main.pyfrom typecoverage import TypeCoverage, detect_untyped
# Simple analysis
result = detect_untyped("def func(x): return x", statistics=True)
print(result)
# Advanced analysis
checker = TypeCoverage()
issues, errors = checker.analyze_targets(
    "src/",
    recursive=True,
    context_lines=2,
    exclude=["__pycache__", "tests"],
)
stats = checker.compute_stats(issues)
print(f"Found {stats.total} issues across {len(set(i.file for i in issues))} files")Typecoverage can analyze various types of targets:
| Input Type | Example | Description | 
|---|---|---|
| Files | main.py | Individual Python files | 
| Directories | src/ | Directory trees (with --recursive) | 
| Glob Patterns | **/*.py | Wildcard file matching | 
| Code Strings | "def func(x): pass" | Direct Python code | 
| Live Functions | my_function | Runtime function objects | 
| Classes | MyClass | Class objects | 
| Modules | import mymodule; mymodule | Module objects | 
| Paths | Path("src/main.py") | pathlib.Path objects | 
# Analysis options
--recursive              # Recurse into subdirectories
--context-lines N        # Show N lines of context around issues
--statistics             # Include summary statistics
# Output options  
--format json            # JSON output instead of text
--output FILE            # Write to file instead of stdout
--force-color            # Force ANSI colors even when piped
# File filtering
--extensions .py,.pyx    # File extensions to analyze
--exclude tests,docs     # Exclude paths containing substrings
# Variable filtering (default: ignore these)
--no-ignore-underscore-vars    # Include _private variables
--no-ignore-for-targets        # Include for loop variables
--no-ignore-except-vars        # Include exception variables  
--no-ignore-context-vars       # Include with statement variables
--no-ignore-comprehensions     # Include list/dict comprehension vars
# Exit behavior
--exit-nonzero-on-issues       # Exit 1 if any issues found
--fail-under N                 # Exit 1 if >= N issues foundCreate pyproject.toml configuration:
[tool.typecoverage]
recursive = true
statistics = true
context-lines = 2
exclude = ["tests", "__pycache__", "build"]
ignore-underscore-vars = true
exit-nonzero-on-issues = true
fail-under = 50Use standard Python suppression comments:
# Suppress all issues on this line
def my_function(x, y):  # type: ignore
    return x + y
# Suppress specific issue types
def another_function(x, y):  # noqa: ANN001,ANN201
    return x + y
# Suppress on previous line
# type: ignore
def third_function(x, y):
    return x + ySupported patterns:
- # type: ignore- Suppress all type checking issues
- # type: ignore[code]- Suppress specific error codes
- # noqa/- # noqa: code- Flake8-style suppression
- # mypy: ignore/- # pyright: ignore- Tool-specific suppression
Found 5 type annotation issues
π src/calculator.py
  src/calculator.py:15:8 - Missing type annotation for argument "value"
    14 β     def process_value(self, value, multiplier=1):
  βΊ 15 β         result = value * multiplier
    16 β         return result
π Summary
  Total issues: 5
  π΄ Missing argument types: 3
  π‘ Missing return types: 1  
  π΅ Missing variable types: 1
{
  "version": "0.1.8",
  "issues": [
    {
      "file": "src/calculator.py",
      "line": 15,
      "column": 8,
      "type": "untyped-argument", 
      "name": "value",
      "context": ["    def process_value(self, value, multiplier=1):", "        result = value * multiplier"]
    }
  ],
  "statistics": {
    "total": 5,
    "untyped-argument": 3,
    "untyped-return": 1,
    "untyped-variable": 1
  }
}from typecoverage import TypeCoverage
def my_function(x, y):
    return x + y
class MyClass:
    def method(self, value):
        return value * 2
checker = TypeCoverage()
# Analyze function
issues, _ = checker.analyze_object(my_function, context_lines=1)
print(f"Function issues: {len(issues)}")
# Analyze class
issues, _ = checker.analyze_object(MyClass, context_lines=1)
print(f"Class issues: {len(issues)}")from pathlib import Path
from typecoverage import analyze_targets
# Analyze multiple targets
issues, errors = analyze_targets(
    "src/main.py",           # Specific file
    Path("lib/"),            # Directory path
    "utils/**/*.py",         # Glob pattern
    my_function,             # Live object
    recursive=True,
    exclude=["test_", "__pycache__"],
    context_lines=1,
)
print(f"Total issues: {len(issues)}")
print(f"Errors: {len(errors)}")name: Type Annotation Coverage
on: [push, pull_request]
jobs:
  typecoverage:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'
    
    - name: Install dependencies
      run: pip install -r requirements.txt
    
    - name: Run typecoverage
      run: |
        typecoverage \
          --format json \
          --exit-nonzero-on-issues \
          --recursive \
          --output typecoverage-report.json \
          src/
    
    - name: Upload results
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: typecoverage-report
        path: typecoverage-report.json# .pre-commit-config.yaml
repos:
  - repo: local
    hooks:
      - id: typecoverage
        name: typecoverage
        entry: typecoverage
        language: system
        args: [--exit-nonzero-on-issues, --recursive, src/]
        files: \.py$python demos/basic_usage.pypython demos/advanced_usage.pypython demos/cli_examples.py# Run comprehensive test suite
pytest tests/ -v --cov=typecoverage --cov-report=term-missing
# Test specific functionality
pytest tests/test_core.py::TestTypeCoverage -vβββ typecoverage/
β   βββ __init__.py          # Public API exports
β   βββ __main__.py          # CLI entry point
β   βββ core.py              # Main typecoverage implementation
βββ src/
β   βββ core.py              # Development version
βββ tests/
β   βββ test_core.py         # Comprehensive test suite  
β   βββ test_suppressions.py # Suppression functionality tests
βββ demos/
β   βββ basic_usage.py       # Basic usage examples
β   βββ advanced_usage.py    # Advanced features demo
β   βββ cli_examples.py      # CLI usage examples
βββ docs/
β   βββ wiki/               # Comprehensive documentation
β       βββ Home.md         # Wiki home page
β       βββ Quick-Start.md  # Getting started guide
β       βββ API-Reference.md# Complete API docs
β       βββ CLI-Guide.md    # Command-line reference
βββ scripts/                # Development utilities
βββ logs/                   # Analysis logs
βββ setup.py               # Package setup
βββ pyproject.toml         # Project configuration
βββ README.md              # This file
We welcome contributions! Here's how to get started:
- Fork the repository and clone your fork
- Install development dependencies: pip install -r requirements.txt
- Run tests: pytest tests/ -v
- Check code style: ruff check . && black . --check
- Make your changes and add tests
- Run the full test suite: pytest tests/ --cov=typecoverage
- Submit a pull request with a clear description
# Set up development environment
pip install -r requirements.txt
# Run code formatting
black . --line-length 79
isort . -l 79 -m 1
ruff format . --line-length 79
# Run linting
ruff check .
pyright
# Run tests with coverage
pytest tests/ --cov=typecoverage --cov-report=term-missing- Core Analysis Engine - AST-based type annotation detection
- CLI Interface - Full command-line interface
- Python API - Programmatic access
- Multiple Input Types - Files, directories, code strings, live objects
- Output Formats - Text and JSON with statistics
- Comment Suppression - Standard suppression patterns
- Configuration Files - pyproject.toml support
- IDE Extensions - VS Code, PyCharm plugin support
- Type Hint Suggestions - Automated type annotation suggestions
- Incremental Analysis - Only check changed files
- Custom Rules - User-defined annotation requirements
- HTML Reports - Rich web-based reporting
Q: How does this differ from mypy or pyright? A: Mypy and pyright focus on type correctness (catching type errors). Typecoverage focuses on type coverage (ensuring annotations exist). Use them together for comprehensive type safety.
Q: Can I use this with existing type checkers?
A: Absolutely! Typecoverage complements mypy, pyright, and other type checkers. Run typecoverage first to ensure annotations exist, then use other tools to verify type correctness.
Q: What about performance on large codebases?
A: Typecoverage uses parallel processing and is optimized for speed. For very large projects, use --exclude to skip unnecessary directories and --extensions to limit file types.
Q: How do I handle legacy code with many issues?
A: Start with --fail-under set to your current issue count, then gradually reduce it. Use suppression comments for intentionally untyped code.
MIT License - see LICENSE file for details.
- Built with Python's astmodule for accurate source code analysis
- Inspired by flake8, mypy, and other Python code quality tools
- Uses parallel processing for performance on large codebases
- Follows Google-style docstrings and modern Python practices
Made with β€οΈ for the Python community
π Documentation β’ π― Examples β’ π Report Issues β’ π¬ Discussions