Pyright is a fast, accurate static type checker for Python, designed to catch type errors before runtime. It's built by Microsoft and is the type checking engine behind Pylance, the Python language server for VS Code.
Pyright analyzes Python code without running it, using type annotations and type inference to detect potential type errors. It's designed to be:
- Fast and scalable, even for large codebases
- Highly configurable to match your project's needs
- Compatible with PEP 484, 526, 544, 561, and other typing-related PEPs
- Usable as a standalone tool or as a VS Code extension
Pyright is included as a development dependency:
# Install with other development dependencies
uv sync --devTo install it directly:
uv pip install pyrightIn this project, Pyright is used to:
- Verify type correctness of the codebase
- Catch potential type errors before runtime
- Enforce type safety standards
- Provide type information for IDE features
It's configured to run in strict mode, which enforces comprehensive type checking.
Pyright is configured in the pyproject.toml file:
[tool.pyright]
exclude = [
"**/__init__.py",
]
include = ["src", "tests"]
pythonVersion = "3.11"
reportUnknownParameterType = "none"
reportUnknownMemberType = "none"
reportUnknownVariableType = "none"
reportUnknownArgumentType = "none"
typeCheckingMode = "strict"This configuration:
- Excludes
__init__.pyfiles from type checking - Includes only the
srcandtestsdirectories - Specifies Python 3.11 as the target version
- Disables some specific error reports that might be too noisy
- Enables strict type checking mode
To run Pyright on the project:
# Run via poethepoet
uv run poe pyright
# Run directly
uv run pyright# Check specific files or directories
uv run pyright src/specific_module.py
# Show verbose output
uv run pyright --verbose
# Generate a stats file
uv run pyright --stats
# Use a specific Python version
uv run pyright --pythonversion 3.11
# Watch for changes
uv run pyright --watch# Variable annotations
name: str = "John"
age: int = 30
is_active: bool = True# Function with type annotations
def greet(name: str) -> str:
return f"Hello, {name}!"
# Function with optional parameters
def greet_optional(name: str, title: str | None = None) -> str:
if title:
return f"Hello, {title} {name}!"
return f"Hello, {name}!"# Class with type annotations
class User:
name: str
age: int
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
def is_adult(self) -> bool:
return self.age >= 18- Add type annotations to public APIs: At minimum, annotate function parameters and return types for public functions and methods.
- Use type aliases for complex types: Create type aliases for complex types to improve readability.
- Leverage Union types for flexibility: Use Union types (e.g.,
str | None) for parameters that can accept multiple types. - Use TypedDict for dictionary structures: Define TypedDict classes for dictionaries with specific structures.
- Add Generic types for containers: Use Generic types for collections to specify contained types.
- Gradually add types: Start with the most critical parts of your codebase and gradually add types to the rest.
If you get type errors from third-party libraries:
- Check if type stubs are available:
uv pip install types-package-name - Add the library to the exclude list in
pyproject.toml - Use
# type: ignorecomments for specific imports
If Pyright can't find a module:
- Ensure the module is installed
- Check your project structure
- Add the module to the Python path in your configuration
If you get "type is unknown" errors:
- Add type annotations to the relevant variables or functions
- Use
Anyas a last resort for truly dynamic types - Configure specific "reportUnknown*" settings in
pyproject.toml
- Pyright Documentation
- Python Type Hints Documentation
- PEP 484 - Type Hints
- mypy Type System Cheat Sheet (also applicable to Pyright)