### Example Mypy Configuration File Source: https://coatl-mypy.readthedocs.io/en/v0.971/config_file.html This example demonstrates a typical mypy.ini file with global options set. Place this file at the root of your repository to be used by mypy. ```ini # Global options: [mypy] python_version = 2.7 warn_return_any = True warn_unused_configs = True ``` -------------------------------- ### Install Development Mypy Build Source: https://coatl-mypy.readthedocs.io/en/v0.971/common_issues.html Instructions for installing the latest development version of mypy from source. This involves cloning the repository and using pip to install locally. ```bash git clone https://github.com/python/mypy.git cd mypy sudo python3 -m pip install --upgrade . ``` -------------------------------- ### Install mypy Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubtest.html Install the mypy package, which includes the stubtest tool, using pip. ```bash python3 -m pip install mypy ``` -------------------------------- ### Setup.py for Package with py.typed Source: https://coatl-mypy.readthedocs.io/en/v0.971/installed_packages.html Example `setup.py` configuration for a package that includes a `py.typed` file to distribute type information. ```python from distutils.core import setup setup( name="SuperPackageA", author="Me", version="0.1", package_data={"package_a": ["py.typed"]}, packages=["package_a"] ) ``` -------------------------------- ### Example pyproject.toml configuration for mypy Source: https://coatl-mypy.readthedocs.io/en/v0.971/config_file.html This example demonstrates a typical pyproject.toml file for mypy configuration, including global options, version specification, and exclusion patterns. Note the TOML string literal and basic string syntax for exclusion paths. ```toml # mypy global options: [tool.mypy] python_version = "2.7" warn_return_any = true warn_unused_configs = true exclude = [ '^file1\.py$', # TOML literal string (single-quotes, no escaping necessary) "^file2\\.py$", # TOML basic string (double-quotes, backslash and other characters need escaping) ] ``` -------------------------------- ### Setup.py for Stub-Only Package Source: https://coatl-mypy.readthedocs.io/en/v0.971/installed_packages.html Example `setup.py` configuration for a stub-only package, named with a `-stubs` suffix. ```python from distutils.core import setup setup( name="SuperPackageC", author="Me", version="0.1", package_data={"package_c-stubs": ["__init__.pyi", "lib.pyi"]}, packages=["package_c-stubs"] ) ``` -------------------------------- ### Install Mypy using pip Source: https://coatl-mypy.readthedocs.io/en/v0.971/getting_started.html Install mypy using pip. Requires Python 3.6 or later. ```bash $ python3 -m pip install mypy ``` -------------------------------- ### Install All Missing Stub Packages Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html Run this command to automatically install all missing stub packages that mypy detects. This is useful for quickly resolving multiple stub issues. ```bash mypy --install-types ``` -------------------------------- ### Install typing-extensions for Older Python Versions Source: https://coatl-mypy.readthedocs.io/en/v0.971/more_types.html For Python versions prior to the inclusion of `NoReturn` in the standard `typing` module, install the `typing-extensions` package. ```bash python3 -m pip install --upgrade typing-extensions ``` ```bash pip install --upgrade typing-extensions ``` -------------------------------- ### Setup.py for Package with Stubs and py.typed Source: https://coatl-mypy.readthedocs.io/en/v0.971/installed_packages.html Example `setup.py` configuration for a package that ships both runtime code and stub files, requiring `py.typed`. ```python from distutils.core import setup setup( name="SuperPackageB", author="Me", version="0.1", package_data={"package_b": ["py.typed", "lib.pyi"]}, packages=["package_b"] ) ``` -------------------------------- ### Example stub and implementation files Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubtest.html Create a Python implementation file (library.py) and a corresponding stub file (library.pyi) to demonstrate stubtest functionality. ```python x = "hello, stubtest" def foo(x=None): print(x) ``` ```python x: int def foo(x: int) -> None: ... ``` -------------------------------- ### Mypy Duck Type Compatibility Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/duck_type_compatibility.html Demonstrates how mypy allows an 'int' to be used where a 'float' is expected due to duck type compatibility. No special setup is required beyond standard Python. ```python import math def degrees_to_radians(degrees: float) -> float: return math.pi * degrees / 180 n = 90 # Inferred type 'int' print(degrees_to_radians(n)) # Okay! ``` -------------------------------- ### Install types-requests stub package Source: https://coatl-mypy.readthedocs.io/en/v0.971/getting_started.html Use this command to install stub files for the `requests` package, enabling Mypy to type-check code that uses it. This is useful for third-party libraries that do not ship with inline type annotations. ```bash $ python3 -m pip install types-requests ``` -------------------------------- ### Mypy Import Error Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html This example shows the output when using the --follow-imports=error flag and a module is not found or ignored. It indicates that the import was ignored and provides a note about the flag being used. ```text main.py:1: note: Import of "mycode.bar" ignored main.py:1: note: (Using --follow-imports=error, module not passed on command line) ``` -------------------------------- ### Defining a Simple User-Defined Protocol Source: https://coatl-mypy.readthedocs.io/en/v0.971/protocols.html Example of creating a `SupportsClose` protocol and a `Resource` class that implements it. This demonstrates nominal subtyping and how to use protocols for type checking. ```python from typing import Iterable from typing_extensions import Protocol class SupportsClose(Protocol): def close(self) -> None: ... # Empty method body (explicit '...') class Resource: # No SupportsClose base class! # ... some methods ... def close(self) -> None: self.resource.release() def close_all(items: Iterable[SupportsClose]) -> None: for item in items: item.close() close_all([Resource(), open('some/file')]) # Okay! ``` -------------------------------- ### Start Mypy Daemon with Fine-Grained Cache Source: https://coatl-mypy.readthedocs.io/en/v0.971/additional_features.html To utilize the fine-grained cache with the mypy daemon, start or restart the daemon using the `--use-fine-grained-cache` option. This allows the daemon to leverage the enhanced cache information for faster checks. ```bash $ dmypy start -- --use-fine-grained-cache ``` -------------------------------- ### Install Missing Stubs Non-Interactively Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html This command installs all suggested stub packages without confirmation and then type checks your code. It's suitable for CI environments where manual intervention is not possible. ```bash mypy --install-types --non-interactive src/ ``` -------------------------------- ### Install Missing Library Stubs with Pip Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html Use this command to install stubs for a specific library when mypy indicates they are missing. Ensure you replace 'yaml' with the actual library name. ```bash python3 -m pip install types-PyYAML ``` -------------------------------- ### Start Mypy Daemon Source: https://coatl-mypy.readthedocs.io/en/v0.971/mypy_daemon.html Starts the mypy daemon process without checking any files. Use this for workflows requiring more precise control over the daemon's lifetime. Arbitrary mypy flags can be provided after `--`. ```bash dmypy start -- ``` -------------------------------- ### Mypy: Fast Module Lookup Example Structure Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html Illustrates a directory structure that might trigger the quadratic worst-case behavior in mypy's default import scanning, where `--fast-module-lookup` can be beneficial. ```text foo/ company/ foo/ a.py bar/ company/ bar/ b.py baz/ company/ baz/ c.py ... ``` -------------------------------- ### Mypy Slot Checking Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/class_basics.html This example demonstrates mypy's behavior when an attribute assignment is attempted for a name not present in __slots__. Mypy will flag this as an error. ```python class Album: __slots__ = ('name', 'year') def __init__(self, name: str, year: int) -> None: self.name = name self.year = year # Error: Trying to assign name "released" that is not in "__slots__" of type "Album" self.released = True my_album = Album('Songs about Python', 2021) ``` -------------------------------- ### Basic Dictionary Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/more_types.html A typical Python dictionary with string keys and mixed value types. ```python movie = {'name': 'Blade Runner', 'year': 1982} ``` -------------------------------- ### Function and Callable Annotations Source: https://coatl-mypy.readthedocs.io/en/v0.971/cheat_sheet_py3.html Illustrates how to annotate function parameters, return types, and callable types using `typing.Callable`. Includes examples for generators and positional-only arguments. ```python from typing import Callable, Iterator, Union, Optional # This is how you annotate a function definition def stringify(num: int) -> str: return str(num) # And here's how you specify multiple arguments def plus(num1: int, num2: int) -> int: return num1 + num2 # Add default value for an argument after the type annotation def f(num1: int, my_float: float = 3.5) -> float: return num1 + my_float # This is how you annotate a callable (function) value x: Callable[[int, float], float] = f # A generator function that yields ints is secretly just a function that # returns an iterator of ints, so that's how we annotate it def g(n: int) -> Iterator[int]: i = 0 while i < n: yield i i += 1 # You can of course split a function annotation over multiple lines def send_email(address: Union[str, list[str]], sender: str, cc: Optional[list[str]], bcc: Optional[list[str]], subject='', body: Optional[list[str]] = None ) -> bool: ... # An argument can be declared positional-only by giving it a name # starting with two underscores: def quux(__x: int) -> None: pass quux(3) # Fine quux(__x=3) # Error ``` -------------------------------- ### Run Mypy in Python 2 Mode Source: https://coatl-mypy.readthedocs.io/en/v0.971/python2.html Use the --py2 option to enable Mypy's Python 2 compatibility mode. Ensure Mypy is installed with Python 2 support (`pip install 'mypy[python2]'`). ```bash $ mypy --py2 program.py ``` -------------------------------- ### Python module source code Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubgen.html This is an example of a Python source file for which `stubgen` can generate a stub file. ```python from other_module import dynamic BORDER_WIDTH = 15 class Window: parent = dynamic() def __init__(self, width, height): self.width = width self.height = height def create_empty() -> Window: return Window(0, 0) ``` -------------------------------- ### Mypy: Ignore Missing Imports Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html Demonstrates how `--ignore-missing-imports` prevents errors for missing imports but still flags missing attributes within resolved modules. ```text import package.unknown # No error, ignored x = package.unknown.func() # OK. 'func' is assumed to be of type 'Any' from package import unknown # No error, ignored from package.mod import NonExisting # Error: Module has no attribute 'NonExisting' ``` -------------------------------- ### Mypy Import Errors Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html Examples of mypy errors encountered when modules are not found or lack type information. ```text main.py:1: error: Skipping analyzing 'django': module is installed, but missing library stubs or py.typed marker main.py:2: error: Library stubs not installed for "requests" (or incompatible with Python 3.8) main.py:3: error: Cannot find implementation or library stub for module named "this_module_does_not_exist" ``` -------------------------------- ### Protocol Subtyping Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/common_issues.html Demonstrates a scenario where covariant subtyping of mutable protocol members is rejected by mypy due to potential unsafety. A workaround using @property is shown. ```python from typing_extensions import Protocol class P(Protocol): x: float def fun(arg: P) -> None: arg.x = 3.14 class C: x = 42 c = C() fun(c) # This is not safe c.x << 5 # Since this will fail! ``` ```python from typing_extensions import Protocol class P(Protocol): @property def x(self) -> float: pass def fun(arg: P) -> None: ... class C: x = 42 fun(C()) # OK ``` -------------------------------- ### Type Variable Binding Order Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Illustrates the rules for type variable binding order when inheriting from multiple generic classes, including explicit 'Generic' base classes. ```python from typing import Generic, TypeVar, Any T = TypeVar('T') S = TypeVar('S') U = TypeVar('U') class One(Generic[T]): ... class Another(Generic[T]): ... class First(One[T], Another[S]): ... class Second(One[T], Another[S], Generic[S, U, T]): ... x: First[int, str] # Here T is bound to int, S is bound to str y: Second[int, str, Any] # Here T is Any, S is int, and U is str ``` -------------------------------- ### TypedDict Inheritance Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/more_types.html Demonstrates how to use inheritance with class-based TypedDicts to create new types that include items from a parent TypedDict. The subclass automatically inherits all items from the parent. ```python class Movie(TypedDict): name: str year: int class BookBasedMovie(Movie): based_on: str ``` -------------------------------- ### Generated stub file Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubgen.html This is an example of a stub file automatically generated by `stubgen` based on a Python module. Note that types may default to `Any` and require manual refinement. ```python from typing import Any BORDER_WIDTH: int = ... class Window: parent: Any = ... width: Any = ... height: Any = ... def __init__(self, width, height) -> None: ... def create_empty() -> Window: ... ``` -------------------------------- ### Mypy Overload Variant Shadowing Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/more_types.html Demonstrates an anti-pattern where an earlier overload variant shadows a more specific subsequent one, preventing the latter from ever being matched. ```python from typing import overload, Union class Expression: # ...snip... class Literal(Expression): # ...snip... # Warning -- the first overload variant shadows the second! @overload def add(left: Expression, right: Expression) -> Expression: ... @overload def add(left: Literal, right: Literal) -> Literal: ... def add(left: Expression, right: Expression) -> Expression: # ...snip... ``` -------------------------------- ### Metaclass Usage Example with Mypy Source: https://coatl-mypy.readthedocs.io/en/v0.971/metaclasses.html Demonstrates Mypy's support for attribute lookup in metaclasses and how metaclass methods can be invoked. Note the type error on the second print statement due to incompatible types. ```python from typing import Type, TypeVar, ClassVar T = TypeVar('T') class M(type): count: ClassVar[int] = 0 def make(cls: Type[T]) -> T: M.count += 1 return cls() class A(metaclass=M): pass a: A = A.make() # make() is looked up at M; the result is an object of type A print(A.count) class B(A): pass b: B = B.make() # metaclasses are inherited print(B.count + " objects were created") # Error: Unsupported operand types for + ("int" and "str") ``` -------------------------------- ### Dynamic Attributes with __setattr__ Source: https://coatl-mypy.readthedocs.io/en/v0.971/cheat_sheet.html To enable dynamic attributes on a class, override the __setattr__ method. This example allows assignment to any attribute 'x' if its type matches 'value'. Use 'value: Any' for arbitrary types. ```python class A: # This will allow assignment to any A.x, if x is the same type as "value" # (use "value: Any" to allow arbitrary types) def __setattr__(self, name, value): # type: (str, int) -> None ... a.foo = 42 # Works a.bar = 'Ex-parrot' # Fails type checking ``` -------------------------------- ### Configure mypy for specific modules Source: https://coatl-mypy.readthedocs.io/en/v0.971/config_file.html Use `[tool.mypy.overrides]` to apply specific mypy settings to modules matching a pattern. This example disables untyped function definitions for all modules under `mycode.foo`. ```toml [[tool.mypy.overrides]] module = "mycode.foo.*" disallow_untyped_defs = true ``` -------------------------------- ### Configure mypy Plugins in Config File Source: https://coatl-mypy.readthedocs.io/en/v0.971/extending_mypy.html Specify plugin files in the `mypy.ini` configuration file using the `plugins` option. Paths can be relative or absolute, or module names if installed via pip. Multiple plugins can be listed, separated by commas. ```ini [mypy] plugins = /one/plugin.py, other.plugin ``` -------------------------------- ### Restart Mypy Daemon Source: https://coatl-mypy.readthedocs.io/en/v0.971/mypy_daemon.html Restarts the mypy daemon process. This is equivalent to stopping and then starting the daemon. Flags provided after `--` are the same as with `dmypy start`. ```bash dmypy restart -- ``` -------------------------------- ### Mypy Daemon Help Source: https://coatl-mypy.readthedocs.io/en/v0.971/mypy_daemon.html Displays help information for additional commands and command-line options for the mypy daemon client. ```bash dmypy --help ``` -------------------------------- ### Mypy Daemon Command-Specific Help Source: https://coatl-mypy.readthedocs.io/en/v0.971/mypy_daemon.html Displays help information for specific commands of the mypy daemon client. ```bash dmypy --help ``` -------------------------------- ### Defining Simple User-Defined Protocols Source: https://coatl-mypy.readthedocs.io/en/v0.971/protocols.html Demonstrates how to define a simple protocol by inheriting from `typing.Protocol` and how classes can conform to it. ```APIDOC ## Simple user-defined protocols# You can define your own protocol class by inheriting the special `Protocol` class: ```python from typing import Iterable from typing_extensions import Protocol class SupportsClose(Protocol): def close(self) -> None: ... # Empty method body (explicit '...') class Resource: # No SupportsClose base class! # ... some methods ... def close(self) -> None: self.resource.release() def close_all(items: Iterable[SupportsClose]) -> None: for item in items: item.close() close_all([Resource(), open('some/file')]) # Okay! ``` `Resource` is a subtype of the `SupportsClose` protocol since it defines a compatible `close` method. Regular file objects returned by `open()` are similarly compatible with the protocol, as they support `close()`. Note The `Protocol` base class is provided in the `typing_extensions` package for Python 2.7 and 3.4-3.7. Starting with Python 3.8, `Protocol` is included in the `typing` module. ``` -------------------------------- ### Defining Subprotocols and Subclassing Protocols Source: https://coatl-mypy.readthedocs.io/en/v0.971/protocols.html Illustrates how to extend existing protocols using multiple inheritance and the distinction between defining a protocol and implementing one. ```APIDOC ## Defining subprotocols and subclassing protocols# You can also define subprotocols. Existing protocols can be extended and merged using multiple inheritance. Example: ```python # ... continuing from the previous example class SupportsRead(Protocol): def read(self, amount: int) -> bytes: ... class TaggedReadableResource(SupportsClose, SupportsRead, Protocol): label: str class AdvancedResource(Resource): def __init__(self, label: str) -> None: self.label = label def read(self, amount: int) -> bytes: # some implementation ... resource: TaggedReadableResource resource = AdvancedResource('handle with care') # OK ``` Note that inheriting from an existing protocol does not automatically turn the subclass into a protocol – it just creates a regular (non-protocol) class or ABC that implements the given protocol (or protocols). The `Protocol` base class must always be explicitly present if you are defining a protocol: ``` class NotAProtocol(SupportsClose): # This is NOT a protocol new_attr: int class Concrete: new_attr: int = 0 def close(self) -> None: ... # Error: nominal subtyping used by default x: NotAProtocol = Concrete() # Error! ``` You can also include default implementations of methods in protocols. If you explicitly subclass these protocols you can inherit these default implementations. Explicitly including a protocol as a base class is also a way of documenting that your class implements a particular protocol, and it forces mypy to verify that your class implementation is actually compatible with the protocol. Note You can use Python 3.6 variable annotations (**PEP 526**) to declare protocol attributes. On Python 2.7 and earlier Python 3 versions you can use type comments and properties. ``` -------------------------------- ### Using a Generic Stack Instance Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Demonstrates the instantiation and usage of a generic `Stack` class. Type errors are shown when attempting to push an item of an incompatible type. ```python # Construct an empty Stack[int] instance stack = Stack[int]() stack.push(2) stack.pop() stack.push('x') # Type error ``` -------------------------------- ### Function using pathlib.Path with type hints Source: https://coatl-mypy.readthedocs.io/en/v0.971/getting_started.html Demonstrates how Mypy understands type hints for standard library modules like `pathlib`. Ensure `pathlib` is available in your environment. ```python from pathlib import Path def load_template(template_path: Path, name: str) -> str: # Mypy understands that 'file_path.read_text()' returns a str... template = template_path.read_text() # ...so understands this line type checks. return template.replace('USERNAME', name) ``` -------------------------------- ### Package Directory Structure with py.typed Source: https://coatl-mypy.readthedocs.io/en/v0.971/installed_packages.html Illustrates a typical directory structure for a package that includes type information via a `py.typed` file. ```text setup.py package_a/ __init__.py lib.py py.typed ``` -------------------------------- ### Python 2 Function Type Annotation Source: https://coatl-mypy.readthedocs.io/en/v0.971/python2.html Illustrates Python 2 function type annotation using comments as per PEP 484. Requires the 'typing' module to be installed (`pip install typing`). This syntax is also valid in Python 3. ```python from typing import List def hello(): # type: () -> None print 'hello' class Example: def method(self, lst, opt=0, *args, **kwargs): # type: (List[str], int, *str, **bool) -> int """Docstring comes after type comment.""" ... ``` -------------------------------- ### Run stubtest on library files Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubtest.html Execute stubtest to compare the stub file (library.pyi) against the implementation file (library.py) and report any inconsistencies. ```bash python3 -m mypy.stubtest library ``` -------------------------------- ### Import and Use Generic Type Aliases Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Shows how to import type aliases from modules and use them to define new types or generic classes. Also demonstrates aliasing an optional generic type. ```python from typing import TypeVar, Generic, Optional from example1 import AliasType from example2 import Vec # AliasType and Vec are type aliases (Vec as defined above) def fun() -> AliasType: ... T = TypeVar('T') class NewVec(Vec[T]): ... for i, j in NewVec[int](): ... OIntVec = Optional[Vec[int]] ``` -------------------------------- ### Example of mypy error without --show-error-context Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html This is the default error message format when --show-error-context is not enabled. ```text main.py:3: error: Unsupported operand types for + ("int" and "str") ``` -------------------------------- ### Use Generic Function 'first' Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Demonstrates calling the generic 'first' function with different sequence types (string and list) and shows how the return type is inferred. ```python # Assume first defined as above. s = first('foo') # s has type str. n = first([1, 2, 3]) # n has type int. ``` -------------------------------- ### Show Help Message Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html Use the `-h` or `--help` flag to display the help message and exit the mypy process. ```bash -h, --help# ``` -------------------------------- ### Import Literal from typing_extensions Source: https://coatl-mypy.readthedocs.io/en/v0.971/runtime_troubles.html Use this method to import Literal from `typing_extensions` for compatibility with older Python versions. Ensure `typing_extensions` is installed. ```python from typing_extensions import Literal x: Literal["open", "close"] ``` -------------------------------- ### Example of mypy error with --show-error-codes Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html This error message includes an error code in brackets when the --show-error-codes flag is enabled. ```text prog.py:1: error: "str" has no attribute "trim" [attr-defined] ``` -------------------------------- ### Example of mypy error with --show-column-numbers Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html This error message includes column offsets (0-based) when the --show-column-numbers flag is used. ```text main.py:12:9: error: Unsupported operand types for / ("int" and "str") ``` -------------------------------- ### Stubtest command-line options Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubtest.html Overview of common command-line flags available for the stubtest tool, including options for output conciseness, ignoring specific errors, and managing allowlists. ```bash stubtest --help ``` ```bash --concise Makes stubtest’s output more concise, one line per error ``` ```bash --ignore-missing-stub# Ignore errors for stub missing things that are present at runtime ``` ```bash --ignore-positional-only# Ignore errors for whether an argument should or shouldn’t be positional-only ``` ```bash --allowlist FILE# Use file as an allowlist. Can be passed multiple times to combine multiple allowlists. Allowlists can be created with –generate-allowlist. Allowlists support regular expressions. ``` ```bash --generate-allowlist# Print an allowlist (to stdout) to be used with –allowlist ``` ```bash --ignore-unused-allowlist# Ignore unused allowlist entries ``` ```bash --mypy-config-file FILE# Use specified mypy config file to determine mypy plugins and mypy path ``` ```bash --custom-typeshed-dir DIR# Use the custom typeshed in DIR ``` ```bash --check-typeshed# Check all stdlib modules in typeshed ``` ```bash --help# Show a help message :-) ``` -------------------------------- ### Decorated Function Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Apply a signature-preserving decorator to a function and demonstrate type checking. The decorated function retains its original type signature. ```python # A decorated function. @my_decorator def foo(a: int) -> str: return str(a) a = foo(12) reveal_type(a) # str foo('x') # Type check error: incompatible type "str"; expected "int" ``` -------------------------------- ### Specify files and directories for mypy Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html Provide specific Python files and directories for mypy to recursively type check. ```bash $ mypy file_1.py foo/file_2.py file_3.pyi some/directory ``` -------------------------------- ### Use SQLite for cache Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html Enable SQLite caching with the --sqlite-cache flag for potentially faster cache operations. ```bash mypy --sqlite-cache ``` -------------------------------- ### Check Attribute Existence in Class Source: https://coatl-mypy.readthedocs.io/en/v0.971/error_code_list.html Mypy verifies that attributes are defined in a class before they are accessed or assigned. This check applies to both getting and setting attributes. ```python class Resource: def __init__(self, name: str) -> None: self.name = name r = Resource('x') print(r.name) # OK print(r.id) # Error: "Resource" has no attribute "id" [attr-defined] r.id = 5 # Error: "Resource" has no attribute "id" [attr-defined] ``` -------------------------------- ### Show Program Version Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html Use the `-V` or `--version` flag to display the mypy program's version number and exit. ```bash -V, --version# ``` -------------------------------- ### Import not found error Source: https://coatl-mypy.readthedocs.io/en/v0.971/error_code_list.html Mypy cannot locate the source code or stub file for an imported module. Ensure the module is installed and accessible in your Python environment. ```python # Error: Cannot find implementation or library stub for module named 'acme' [import] import acme ``` -------------------------------- ### Mapping Duck Type Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/cheat_sheet.html Mapping describes a dict-like object (with "__getitem__") that will not be mutated. This function returns a list of keys from a mapping. ```python def f(my_dict): # type: (Mapping[int, str]) -> List[int] return list(my_dict.keys()) f({3: 'yes', 4: 'no'}) ``` -------------------------------- ### Stub-Only Package Directory Structure Source: https://coatl-mypy.readthedocs.io/en/v0.971/installed_packages.html Demonstrates the directory structure for a stub-only package, which does not require a `py.typed` file. ```text setup.py package_c-stubs/ __init__.pyi lib.pyi ``` -------------------------------- ### Package Directory Structure with Stubs and py.typed Source: https://coatl-mypy.readthedocs.io/en/v0.971/installed_packages.html Shows a directory structure for a package that includes both runtime Python files and stub files (`.pyi`), along with a `py.typed` file. ```text setup.py package_b/ __init__.py lib.py lib.pyi py.typed ``` -------------------------------- ### Specify multiple packages and modules Source: https://coatl-mypy.readthedocs.io/en/v0.971/running_mypy.html Combine -p and -m flags to specify multiple packages and modules for type checking. ```bash $ mypy --package p.a --package p.b --module c ``` -------------------------------- ### Example of mypy error with --show-error-context Source: https://coatl-mypy.readthedocs.io/en/v0.971/command_line.html This shows the enhanced error message format when the --show-error-context flag is enabled, providing additional contextual notes. ```text main.py: note: In member "foo" of class "Test": main.py:3: error: Unsupported operand types for + ("int" and "str") ``` -------------------------------- ### Correct Covariant Generic Protocol Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html This example correctly uses a covariant type variable in a generic protocol, allowing for assignment between types with different type arguments. ```python from typing import TypeVar from typing_extensions import Protocol T_co = TypeVar('T_co', covariant=True) class ReadOnlyBox(Protocol[T_co]): # OK def content(self) -> T_co: ... ax: ReadOnlyBox[float] = ... ay: ReadOnlyBox[int] = ... ax = ay # OK -- ReadOnlyBox is covariant ``` -------------------------------- ### Running mypy with a Configuration File Source: https://coatl-mypy.readthedocs.io/en/v0.971/existing_code.html Execute mypy with a specified configuration file to check a particular directory or set of files in your project. Ensure the config file is named appropriately or specified with `--config-file`. ```bash mypy --config-file mypy.ini mycode/ ``` -------------------------------- ### Generic Protocol Variance Error Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html This example demonstrates an error when a type variable in a generic protocol is used covariantly as a return type, but the type variable itself is invariant. ```python from typing import TypeVar from typing_extensions import Protocol T = TypeVar('T') class ReadOnlyBox(Protocol[T]): # Error: covariant type variable expected def content(self) -> T: ... ``` -------------------------------- ### Configure mypy overrides in pyproject.toml Source: https://coatl-mypy.readthedocs.io/en/v0.971/config_file.html Use the [[tool.mypy.overrides]] section in pyproject.toml to configure settings for specific modules. This example shows how to set options for a single module. ```toml [[tool.mypy.overrides]] module = 'packagename' ... ``` -------------------------------- ### Typing Regex Matches with typing.Match Source: https://coatl-mypy.readthedocs.io/en/v0.971/cheat_sheet.html The 'typing.Match' type describes regex matches obtained from the 're' module. This example shows how to annotate a variable with the result of 're.match'. ```python import sys import re from typing import Match, AnyStr, IO # "typing.Match" describes regex matches from the re module x = re.match(r'[0-9]+', "15") # type: Match[str] ``` -------------------------------- ### Defining Subprotocols and Subclassing Protocols Source: https://coatl-mypy.readthedocs.io/en/v0.971/protocols.html Demonstrates extending existing protocols using multiple inheritance to create more specific protocols like `TaggedReadableResource`. It also shows how a regular class can implement multiple protocols. ```python class SupportsRead(Protocol): def read(self, amount: int) -> bytes: ... class TaggedReadableResource(SupportsClose, SupportsRead, Protocol): label: str class AdvancedResource(Resource): def __init__(self, label: str) -> None: self.label = label def read(self, amount: int) -> bytes: # some implementation ... resource: TaggedReadableResource resource = AdvancedResource('handle with care') # OK ``` -------------------------------- ### Iterable Duck Type Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/cheat_sheet.html Use Iterable for generic iterables (anything usable in a 'for' loop). This function converts an iterable of integers to a list of strings. ```python from typing import Mapping, MutableMapping, Sequence, Iterable # Use Iterable for generic iterables (anything usable in "for"), # and Sequence where a sequence (supporting "len" and "__getitem__") is # required def f(iterable_of_ints): # type: (Iterable[int]) -> List[str] return [str(x) for x in iterator_of_ints] f(range(1, 3)) ``` -------------------------------- ### Generate stub file for a module Source: https://coatl-mypy.readthedocs.io/en/v0.971/stubgen.html Use `stubgen` with module names to generate stub files. This command generates stubs for 'foo' and 'bar' modules and recursively for 'my_pkg_dir' package. ```bash $ stubgen foo.py bar.py ``` ```bash $ stubgen my_pkg_dir ``` ```bash $ stubgen -m foo -m bar -p my_pkg_dir ``` -------------------------------- ### Type Guard with Non-Strict Narrowing Example Source: https://coatl-mypy.readthedocs.io/en/v0.971/type_narrowing.html Demonstrates that `TypeGuard` does not enforce strict narrowing; it's possible to narrow a `str` to an `int`, though this can break type safety. ```python def f(value: str) -> TypeGuard[int]: return True ``` -------------------------------- ### Annotating __init__ Methods Source: https://coatl-mypy.readthedocs.io/en/v0.971/class_basics.html The __init__ method should be annotated with '-> None'. Return type annotation can be omitted if at least one argument is annotated. ```python class C1: def __init__(self) -> None: self.var = 42 class C2: def __init__(self, arg: int): self.var = arg ``` -------------------------------- ### JSON Output for Programmatic Use Source: https://coatl-mypy.readthedocs.io/en/v0.971/mypy_daemon.html Use the `--json` flag to output the suggested signature in JSON format, which can be parsed by tools like PyAnnotate for automatic source file updates. ```json [{"func_name": "example.format_id", "line": 1, "path": "/absolute/path/to/example.py", "samples": 0, "signature": {"arg_types": ["int"], "return_type": "str"}}] ``` -------------------------------- ### Invariant List Example in Mypy Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Demonstrates why 'list' is invariant. Appending a 'Shape' to a 'list[Circle]' can lead to runtime errors if methods specific to 'Circle' are called on the appended 'Shape'. ```python class Shape: pass class Circle(Shape): def rotate(self): ... def add_one(things: list[Shape]) -> None: things.append(Shape()) my_things: list[Circle] = [] add_one(my_things) # This may appear safe, but... my_things[0].rotate() # ...this will fail ``` -------------------------------- ### Contravariant Callable Example in Mypy Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Illustrates contravariance with 'Callable'. A function expecting a 'Callable[[Manager], int]' can safely accept a 'Callable[[Employee], int]' because 'Manager' is a subtype of 'Employee'. ```python def salaries(staff: list[Manager], accountant: Callable[[Manager], int]) -> list[int]: ... ``` -------------------------------- ### Basic Literal Value Validation Source: https://coatl-mypy.readthedocs.io/en/v0.971/literal_types.html A simple function to validate if a value matches one of the specified Literal types. This example demonstrates a basic validation without exhaustiveness checking. ```python from typing import Literal PossibleValues = Literal['one', 'two'] def validate(x: PossibleValues) -> bool: if x == 'one': return True elif x == 'two': return False raise ValueError(f'Invalid value: {x}') assert validate('one') is True assert validate('two') is False ``` -------------------------------- ### Define Generic Type Aliases Source: https://coatl-mypy.readthedocs.io/en/v0.971/generics.html Demonstrates defining generic type aliases using TypeVar, Union, and Callable. Shows how subscripted and unsubscripted aliases behave and potential errors. ```python from typing import TypeVar, Iterable, Union, Callable S = TypeVar('S') TInt = tuple[int, S] UInt = Union[S, int] CBack = Callable[..., S] def response(query: str) -> UInt[str]: # Same as Union[str, int] ... def activate(cb: CBack[S]) -> S: # Same as Callable[..., S] ... table_entry: TInt # Same as tuple[int, Any] T = TypeVar('T', int, float, complex) Vec = Iterable[tuple[T, T]] def inproduct(v: Vec[T]) -> T: return sum(x*y for x, y in v) def dilate(v: Vec[T], scale: T) -> Vec[T]: return ((x * scale, y * scale) for x, y in v) v1: Vec[int] = [] # Same as Iterable[tuple[int, int]] v2: Vec = [] # Same as Iterable[tuple[Any, Any]] v3: Vec[int, int] = [] # Error: Invalid alias, too many type arguments! ```