
Security News
The Hidden Blast Radius of the Axios Compromise
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.
typecoverage
Advanced tools
A strict CLI + library API to report untyped variables, arguments, and function returns in Python code
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.
# type: ignore and # noqa supportfrom 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.py
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")
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 found
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
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 suppressionFound 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.py
python demos/advanced_usage.py
python 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:
pip install -r requirements.txtpytest tests/ -vruff check . && black . --checkpytest tests/ --cov=typecoverage# 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
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.
ast module for accurate source code analysisMade with ❤️ for the Python community
📚 Documentation • 🎯 Examples • 🐛 Report Issues • 💬 Discussions
FAQs
A strict CLI + library API to report untyped variables, arguments, and function returns in Python code
We found that typecoverage demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.

Research
A supply chain attack on Axios introduced a malicious dependency, plain-crypto-js@4.2.1, published minutes earlier and absent from the project’s GitHub releases.

Research
Malicious versions of the Telnyx Python SDK on PyPI delivered credential-stealing malware via a multi-stage supply chain attack.