Overview of pytype traces library
mainpytype/tools/traces library is a flexible, lightweight tool designed to allow developers to access and interact with type information extracted from pytype's opcode traces.repository·main·Indexed 26 days ago
https://github.com/google/pytypeA static type checker for Python that uses bytecode-based inference. It includes tools such as analyze_project for analyzing Python code, merge-pyi for copying type annotations from stub files, and the pytype_extensions package. The project supports Python versions up to 3.12 and provides a developer-focused abstract value system for modeling Python objects and processing PEP 484 type annotations.
pytype/tools/traces library is a flexible, lightweight tool designed to allow developers to access and interact with type information extracted from pytype's opcode traces.pytype includes several non-standard behaviors that differ from other type checkers:
str from matching an iterable of strs to catch accidental string iteration bugs.pytype_extensions: A namespace containing various user-contributed extensions.None or ... without explicitly including them in the annotation (e.g., x: str = None or x: str = ... are valid).pytype_extensions package provides type system extensions designed specifically for use with the pytype type analyzer.pytype uses a Control Flow Graph (CFG) to represent the execution paths of a program. This graph is used to track variable types and scope during analysis.
Key concepts:
if statement) that restrict which paths can be taken.y = m * x + b).Pytype processes PEP 484 type annotations (type hints) by parsing them as part of the regular bytecode VM. Unlike type comments, annotations are compiled by the interpreter using SETUP_ANNOTATIONS and STORE_ANNOTATION opcodes.
Pytype maintains an abstract.AnnotationsDict (equivalent to Python's __annotations__) to store these annotations in locals for function variables or in __dict__ for class members. This dictionary is updated via:
vm._record_local(): Records an annotation on a local variable.vm._apply_annotation(): Applies an explicit AnnotationsDict (e.g., for class objects).byte_STORE_ATTRIBUTE: Handles attribute assignments that haven't been recorded as class-level annotations.Pytype uses special builtins to handle Python functions that have complex type-level side effects (like metaprogramming) or type effects that depend on argument values (e.g., super()). While standard functions are modeled via signatures, special builtins allow pytype to directly manipulate abstract values.
Note that these special functions still require type signatures in builtins.pytd to interoperate with the rest of pytype.
Pytype analyzes Python code by following these steps:
Opcodes, which are pytype's internal representation of Python bytecode instructions.vm.py/VirtualMachine interprets these Opcodes, manipulating types rather than actual values.pytype operates using a shadow bytecode interpreter that traces through a program's bytecode. It mimics the CPython interpreter but tracks types instead of values.
Key architectural components include:
mypy, pyre, and pyright, it may differ in areas not formally covered by PEPs. A primary driver for these differences is pytype's design goal to avoid breaking existing, unannotated code that follows valid Python idioms.analyze_project tool is used to analyze one or more files or directories of Python code. It automatically handles dependency ordering and the generation of .pyi files during the analysis process. For general usage and installation instructions for pytype, refer to the main project README.PyType uses an extended .pyi format called PyType Declaration (PyTD) to support mutations. A mutation allows describing how an unannotated parameterized class's contained type changes during an operation. In PyTD, mutations are expressed via assignments to self within a method body.
Example of a mutation in dict.update:
class dict(Dict[_K, _V]):
def update(self, other: dict[_K2, _V2]) -> None:
self = dict[_K | _K2, _V | _V2]