Skip to main content

A strict CLI + library API to report untyped variables, arguments, and function returns in Python code

Project description

Typecoverage Logo

๐Ÿ” Typecoverage - Python Type Annotation Analyzer

A strict CLI + library API to report untyped variables, arguments, and function returns in Python code

Python 3.11+ MIT License Code Style: Black

๐ŸŽฏ What is Typecoverage?

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.

โœจ Key Features

  • ๐Ÿ” 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: ignore and # noqa support
  • ๐Ÿš€ 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

๐Ÿš€ Quick Example

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

๐Ÿ“ฆ Installation

From Source (Current)

git clone <repository-url>
cd typecoverage-project
pip install -r requirements.txt

Using the Package

# Install in development mode
pip install -e .

# Or install directly
python setup.py install

๐Ÿ Quick Start

Command Line Usage

# 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.py

Python API Usage

from 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")

๐ŸŽฏ Supported Input Types

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

โš™๏ธ Configuration

Command Line Options

# 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 found

Configuration File

Create 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 = 50

๐Ÿšซ Issue Suppression

Use 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 + y

Supported 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

๐Ÿ“Š Understanding the Output

Text Format

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

JSON Format

{
  "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
  }
}

๐Ÿ”ง Advanced Usage

Analyzing Live Objects

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)}")

Batch Analysis

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)}")

๐Ÿ—๏ธ CI/CD Integration

GitHub Actions

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 Hook

# .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$

๐Ÿ“š Examples and Demos

Basic Usage Demo

python demos/basic_usage.py

Advanced Features Demo

python demos/advanced_usage.py

CLI Examples

python demos/cli_examples.py

Test the Library

# Run comprehensive test suite
pytest tests/ -v --cov=typecoverage --cov-report=term-missing

# Test specific functionality
pytest tests/test_core.py::TestTypeCoverage -v

๐Ÿ—๏ธ Project Structure

โ”œโ”€โ”€ 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

๐Ÿค Contributing

We welcome contributions! Here's how to get started:

  1. Fork the repository and clone your fork
  2. Install development dependencies: pip install -r requirements.txt
  3. Run tests: pytest tests/ -v
  4. Check code style: ruff check . && black . --check
  5. Make your changes and add tests
  6. Run the full test suite: pytest tests/ --cov=typecoverage
  7. Submit a pull request with a clear description

Development Workflow

# 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

๐Ÿ“ˆ Roadmap

  • 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

โ“ FAQ

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.

๐Ÿ“„ License

MIT License - see LICENSE file for details.

๐Ÿ™ Acknowledgments

  • Built with Python's ast module 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

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

typecoverage-1.0.1.tar.gz (47.1 kB view details)

Uploaded Source

Built Distribution

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

typecoverage-1.0.1-py3-none-any.whl (26.9 kB view details)

Uploaded Python 3

File details

Details for the file typecoverage-1.0.1.tar.gz.

File metadata

  • Download URL: typecoverage-1.0.1.tar.gz
  • Upload date:
  • Size: 47.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for typecoverage-1.0.1.tar.gz
Algorithm Hash digest
SHA256 5aaaf7157f4b3c34d149bf42cf53ae7623bcc133ab55af98b643188a91ed1d6a
MD5 8d2795a0fcb85438d609b796a4cabbe4
BLAKE2b-256 ab7435e69504a7f4d861e7cec0cc8d27949b32a4e9642a38b3f59bc5b05974ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for typecoverage-1.0.1.tar.gz:

Publisher: python-publish.yml on kairos-xx/typecoverage

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file typecoverage-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: typecoverage-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 26.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for typecoverage-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 1d87df4d681c694b6fcd73987a3d3857c3bc876fdc7eff1610c84b370b6c91d3
MD5 a082cb586002e61b56338a33d42265aa
BLAKE2b-256 8cbf51d924d317b8d568d440808c0b78efa4d6cd2caf9ea63c85d3f39c204870

See more details on using hashes here.

Provenance

The following attestation bundles were made for typecoverage-1.0.1-py3-none-any.whl:

Publisher: python-publish.yml on kairos-xx/typecoverage

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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