diff --git a/info/Mypy.info b/info/Mypy.info
new file mode 100644
index 00000000..7b79edf5
--- /dev/null
+++ b/info/Mypy.info
@@ -0,0 +1,18112 @@
+This is Mypy.info, produced by makeinfo version 6.7 from Mypy.texi.
+
+     Mypy 0.942, Apr 07, 2022
+
+     Jukka
+
+     Copyright © 2016, Jukka Lehtosalo
+
+INFO-DIR-SECTION Miscellaneous
+START-INFO-DIR-ENTRY
+* Mypy: (Mypy.info). One line description of project.
+END-INFO-DIR-ENTRY
+
+
+   Generated by Sphinx 4.5.0.
+
+
+File: Mypy.info,  Node: Top,  Next: Introduction,  Up: (dir)
+
+Mypy Documentation
+******************
+
+     Mypy 0.942, Apr 07, 2022
+
+     Jukka
+
+     Copyright © 2016, Jukka Lehtosalo
+
+Mypy is a static type checker for Python 3 and Python 2.7.
+
+* Menu:
+
+* Introduction::
+* Getting started::
+* Using mypy with an existing codebase::
+* Type hints cheat sheet (Python 3): Type hints cheat sheet Python 3.
+* Type hints cheat sheet (Python 2): Type hints cheat sheet Python 2.
+* Built-in types: Built-in types<3>.
+* Type inference and type annotations::
+* Kinds of types::
+* Class basics::
+* Annotation issues at runtime::
+* Protocols and structural subtyping::
+* Dynamically typed code::
+* Type checking Python 2 code::
+* Type narrowing::
+* Duck type compatibility::
+* Stub files::
+* Generics::
+* More types::
+* Literal types and Enums::
+* Final names, methods and classes: Final names methods and classes.
+* Metaclasses::
+* Running mypy and managing imports::
+* The mypy command line::
+* The mypy configuration file::
+* Inline configuration::
+* Mypy daemon (mypy server): Mypy daemon mypy server.
+* Using installed packages::
+* Extending and integrating mypy::
+* Automatic stub generation (stubgen): Automatic stub generation stubgen.
+* Automatic stub testing (stubtest): Automatic stub testing stubtest.
+* Common issues and solutions::
+* Supported Python features::
+* Error codes::
+* Error codes enabled by default::
+* Error codes for optional checks::
+* Additional features::
+* Frequently Asked Questions::
+* Indices and tables::
+* Index::
+
+
+File: Mypy.info,  Node: Introduction,  Next: Getting started,  Prev: Top,  Up: Top
+
+1 Introduction
+**************
+
+Mypy is a static type checker for Python 3 and Python 2.7.  If you
+sprinkle your code with type annotations, mypy can type check your code
+and find common bugs.  As mypy is a static analyzer, or a lint-like
+tool, the type annotations are just hints for mypy and don’t interfere
+when running your program.  You run your program with a standard Python
+interpreter, and the annotations are treated effectively as comments.
+
+Using the Python 3 annotation syntax (using PEP 484(1) and PEP 526(2)
+notation) or a comment-based annotation syntax for Python 2 code, you
+will be able to efficiently annotate your code and use mypy to check the
+code for common errors.  Mypy has a powerful and easy-to-use type system
+with modern features such as type inference, generics, callable types,
+tuple types, union types, and structural subtyping.
+
+As a developer, you decide how to use mypy in your workflow.  You can
+always escape to dynamic typing as mypy’s approach to static typing
+doesn’t restrict what you can do in your programs.  Using mypy will make
+your programs easier to understand, debug, and maintain.
+
+This documentation provides a short introduction to mypy.  It will help
+you get started writing statically typed code.  Knowledge of Python and
+a statically typed object-oriented language, such as Java, are assumed.
+
+     Note: Mypy is used in production by many companies and projects,
+     but mypy is officially beta software.  There will be occasional
+     changes that break backward compatibility.  The mypy development
+     team tries to minimize the impact of changes to user code.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+   (2) https://peps.python.org/pep-0526/
+
+
+File: Mypy.info,  Node: Getting started,  Next: Using mypy with an existing codebase,  Prev: Introduction,  Up: Top
+
+2 Getting started
+*****************
+
+This chapter introduces some core concepts of mypy, including function
+annotations, the typing(1) module, library stubs, and more.
+
+Be sure to read this chapter carefully, as the rest of the documentation
+may not make much sense otherwise.
+
+* Menu:
+
+* Installing and running mypy::
+* Function signatures and dynamic vs static typing::
+* More function signatures::
+* Additional types, and the typing module: Additional types and the typing module.
+* Local type inference::
+* Library stubs and typeshed::
+* Configuring mypy::
+* Next steps::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Installing and running mypy,  Next: Function signatures and dynamic vs static typing,  Up: Getting started
+
+2.1 Installing and running mypy
+===============================
+
+Mypy requires Python 3.6 or later to run.  Once you’ve installed Python
+3(1), install mypy using pip:
+
+     $ python3 -m pip install mypy
+
+Once mypy is installed, run it by using the ‘mypy’ tool:
+
+     $ mypy program.py
+
+This command makes mypy `type check' your ‘program.py’ file and print
+out any errors it finds.  Mypy will type check your code `statically':
+this means that it will check for errors without ever running your code,
+just like a linter.
+
+This means that you are always free to ignore the errors mypy reports
+and treat them as just warnings, if you so wish: mypy runs independently
+from Python itself.
+
+However, if you try directly running mypy on your existing Python code,
+it will most likely report little to no errors: you must add `type
+annotations' to your code to take full advantage of mypy.  See the
+section below for details.
+
+     Note: Although you must install Python 3 to run mypy, mypy is fully
+     capable of type checking Python 2 code as well: just pass in the
+     *note –py2: 8. flag.  See *note Type checking Python 2 code: 9. for
+     more details.
+
+          $ mypy --py2 program.py
+
+   ---------- Footnotes ----------
+
+   (1) https://www.python.org/downloads/
+
+
+File: Mypy.info,  Node: Function signatures and dynamic vs static typing,  Next: More function signatures,  Prev: Installing and running mypy,  Up: Getting started
+
+2.2 Function signatures and dynamic vs static typing
+====================================================
+
+A function without type annotations is considered to be `dynamically
+typed' by mypy:
+
+     def greeting(name):
+         return 'Hello ' + name
+
+By default, mypy will `not' type check dynamically typed functions.
+This means that with a few exceptions, mypy will not report any errors
+with regular unannotated Python.
+
+This is the case even if you misuse the function: for example, mypy
+would currently not report any errors if you tried running ‘greeting(3)’
+or ‘greeting(b"Alice")’ even though those function calls would result in
+errors at runtime.
+
+You can teach mypy to detect these kinds of bugs by adding `type
+annotations' (also known as `type hints').  For example, you can teach
+mypy that ‘greeting’ both accepts and returns a string like so:
+
+     def greeting(name: str) -> str:
+         return 'Hello ' + name
+
+This function is now `statically typed': mypy can use the provided type
+hints to detect incorrect usages of the ‘greeting’ function.  For
+example, it will reject the following calls since the arguments have
+invalid types:
+
+     def greeting(name: str) -> str:
+         return 'Hello ' + name
+
+     greeting(3)         # Argument 1 to "greeting" has incompatible type "int"; expected "str"
+     greeting(b'Alice')  # Argument 1 to "greeting" has incompatible type "bytes"; expected "str"
+
+Note that this is all still valid Python 3 code!  The function
+annotation syntax shown above was added to Python as a part of Python
+3.0(1).
+
+If you are trying to type check Python 2 code, you can add type hints
+using a comment-based syntax instead of the Python 3 annotation syntax.
+See our section on *note typing Python 2 code: 9. for more details.
+
+Being able to pick whether you want a function to be dynamically or
+statically typed can be very helpful.  For example, if you are migrating
+an existing Python codebase to use static types, it’s usually easier to
+migrate by incrementally adding type hints to your code rather than
+adding them all at once.  Similarly, when you are prototyping a new
+feature, it may be convenient to initially implement the code using
+dynamic typing and only add type hints later once the code is more
+stable.
+
+Once you are finished migrating or prototyping your code, you can make
+mypy warn you if you add a dynamic function by mistake by using the
+*note –disallow-untyped-defs: b. flag.  See *note The mypy command line:
+c. for more information on configuring mypy.
+
+     Note: The earlier stages of analysis performed by mypy may report
+     errors even for dynamically typed functions.  However, you should
+     not rely on this, as this may change in the future.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-3107/
+
+
+File: Mypy.info,  Node: More function signatures,  Next: Additional types and the typing module,  Prev: Function signatures and dynamic vs static typing,  Up: Getting started
+
+2.3 More function signatures
+============================
+
+Here are a few more examples of adding type hints to function
+signatures.
+
+If a function does not explicitly return a value, give it a return type
+of ‘None’.  Using a ‘None’ result in a statically typed context results
+in a type check error:
+
+     def p() -> None:
+         print('hello')
+
+     a = p()  # Error: "p" does not return a value
+
+Make sure to remember to include ‘None’: if you don’t, the function will
+be dynamically typed.  For example:
+
+     def f():
+         1 + 'x'  # No static type error (dynamically typed)
+
+     def g() -> None:
+         1 + 'x'  # Type check error (statically typed)
+
+Arguments with default values can be annotated like so:
+
+     def greeting(name: str, excited: bool = False) -> str:
+         message = 'Hello, {}'.format(name)
+         if excited:
+             message += '!!!'
+         return message
+
+‘*args’ and ‘**kwargs’ arguments can be annotated like so:
+
+     def stars(*args: int, **kwargs: float) -> None:
+         # 'args' has type 'tuple[int, ...]' (a tuple of ints)
+         # 'kwargs' has type 'dict[str, float]' (a dict of strs to floats)
+         for arg in args:
+             print(arg)
+         for key, value in kwargs:
+             print(key, value)
+
+
+File: Mypy.info,  Node: Additional types and the typing module,  Next: Local type inference,  Prev: More function signatures,  Up: Getting started
+
+2.4 Additional types, and the typing module
+===========================================
+
+So far, we’ve added type hints that use only basic concrete types like
+‘str’ and ‘float’.  What if we want to express more complex types, such
+as “a list of strings” or “an iterable of ints”?
+
+For example, to indicate that some function can accept a list of
+strings, use the ‘list[str]’ type (Python 3.9 and later):
+
+     def greet_all(names: list[str]) -> None:
+         for name in names:
+             print('Hello ' + name)
+
+     names = ["Alice", "Bob", "Charlie"]
+     ages = [10, 20, 30]
+
+     greet_all(names)   # Ok!
+     greet_all(ages)    # Error due to incompatible types
+
+The list(1) type is an example of something called a `generic type': it
+can accept one or more `type parameters'.  In this case, we
+`parameterized' list(2) by writing ‘list[str]’.  This lets mypy know
+that ‘greet_all’ accepts specifically lists containing strings, and not
+lists containing ints or any other type.
+
+In Python 3.8 and earlier, you can instead import the List(3) type from
+the typing(4) module:
+
+     from typing import List  # Python 3.8 and earlier
+
+     def greet_all(names: List[str]) -> None:
+         for name in names:
+             print('Hello ' + name)
+
+     ...
+
+You can find many of these more complex static types in the typing(5)
+module.
+
+In the above examples, the type signature is perhaps a little too rigid.
+After all, there’s no reason why this function must accept
+`specifically' a list – it would run just fine if you were to pass in a
+tuple, a set, or any other custom iterable.
+
+You can express this idea using the collections.abc.Iterable(6) (or
+typing.Iterable(7) in Python 3.8 and earlier) type instead of list(8) :
+
+     from collections.abc import Iterable  # or "from typing import Iterable"
+
+     def greet_all(names: Iterable[str]) -> None:
+         for name in names:
+             print('Hello ' + name)
+
+As another example, suppose you want to write a function that can accept
+`either' ints or strings, but no other types.  You can express this
+using the Union(9) type:
+
+     from typing import Union
+
+     def normalize_id(user_id: Union[int, str]) -> str:
+         if isinstance(user_id, int):
+             return 'user-{}'.format(100000 + user_id)
+         else:
+             return user_id
+
+Similarly, suppose that you want the function to accept only strings or
+‘None’.  You can again use Union(10) and use ‘Union[str, None]’ – or
+alternatively, use the type ‘Optional[str]’.  These two types are
+identical and interchangeable: ‘Optional[str]’ is just a shorthand or
+`alias' for ‘Union[str, None]’.  It exists mostly as a convenience to
+help function signatures look a little cleaner:
+
+     from typing import Optional
+
+     def greeting(name: Optional[str] = None) -> str:
+         # Optional[str] means the same thing as Union[str, None]
+         if name is None:
+             name = 'stranger'
+         return 'Hello, ' + name
+
+The typing(11) module contains many other useful types.  You can find a
+quick overview by looking through the *note mypy cheatsheets: f. and a
+more detailed overview (including information on how to make your own
+generic types or your own type aliases) by looking through the *note
+type system reference: 10.
+
+     Note: When adding types, the convention is to import types using
+     the form ‘from typing import Union’ (as opposed to doing just
+     ‘import typing’ or ‘import typing as t’ or ‘from typing import *’).
+
+     For brevity, we often omit imports from typing(12) or
+     collections.abc(13) in code examples, but mypy will give an error
+     if you use types such as Iterable(14) without first importing them.
+
+     Note: In some examples we use capitalized variants of types, such
+     as ‘List’, and sometimes we use plain ‘list’.  They are equivalent,
+     but the prior variant is needed if you are using Python 3.8 or
+     earlier.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#list
+
+   (2) https://docs.python.org/3/library/stdtypes.html#list
+
+   (3) https://docs.python.org/3/library/typing.html#typing.List
+
+   (4) https://docs.python.org/3/library/typing.html#module-typing
+
+   (5) https://docs.python.org/3/library/typing.html#module-typing
+
+   (6) 
+https://docs.python.org/3/library/collections.abc.html#collections.abc.Iterable
+
+   (7) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (8) https://docs.python.org/3/library/stdtypes.html#list
+
+   (9) https://docs.python.org/3/library/typing.html#typing.Union
+
+   (10) https://docs.python.org/3/library/typing.html#typing.Union
+
+   (11) https://docs.python.org/3/library/typing.html#module-typing
+
+   (12) https://docs.python.org/3/library/typing.html#module-typing
+
+   (13) 
+https://docs.python.org/3/library/collections.abc.html#module-collections.abc
+
+   (14) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+
+File: Mypy.info,  Node: Local type inference,  Next: Library stubs and typeshed,  Prev: Additional types and the typing module,  Up: Getting started
+
+2.5 Local type inference
+========================
+
+Once you have added type hints to a function (i.e.  made it statically
+typed), mypy will automatically type check that function’s body.  While
+doing so, mypy will try and `infer' as many details as possible.
+
+We saw an example of this in the ‘normalize_id’ function above – mypy
+understands basic isinstance(1) checks and so can infer that the
+‘user_id’ variable was of type ‘int’ in the if-branch and of type ‘str’
+in the else-branch.  Similarly, mypy was able to understand that ‘name’
+could not possibly be ‘None’ in the ‘greeting’ function above, based
+both on the ‘name is None’ check and the variable assignment in that if
+statement.
+
+As another example, consider the following function.  Mypy can type
+check this function without a problem: it will use the available context
+and deduce that ‘output’ must be of type ‘list[float]’ and that ‘num’
+must be of type ‘float’:
+
+     def nums_below(numbers: Iterable[float], limit: float) -> list[float]:
+         output = []
+         for num in numbers:
+             if num < limit:
+                 output.append(num)
+         return output
+
+Mypy will warn you if it is unable to determine the type of some
+variable – for example, when assigning an empty dictionary to some
+global value:
+
+     my_global_dict = {}  # Error: Need type annotation for "my_global_dict"
+
+You can teach mypy what type ‘my_global_dict’ is meant to have by giving
+it a type hint.  For example, if you knew this variable is supposed to
+be a dict of ints to floats, you could annotate it using either variable
+annotations (introduced in Python 3.6 by PEP 526(2)) or using a
+comment-based syntax like so:
+
+     # If you're using Python 3.9+
+     my_global_dict: dict[int, float] = {}
+
+     # If you're using Python 3.6+
+     my_global_dict: Dict[int, float] = {}
+
+     # If you want compatibility with even older versions of Python
+     my_global_dict = {}  # type: Dict[int, float]
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+   (2) https://peps.python.org/pep-0526/
+
+
+File: Mypy.info,  Node: Library stubs and typeshed,  Next: Configuring mypy,  Prev: Local type inference,  Up: Getting started
+
+2.6 Library stubs and typeshed
+==============================
+
+Mypy uses library `stubs' to type check code interacting with library
+modules, including the Python standard library.  A library stub defines
+a skeleton of the public interface of the library, including classes,
+variables and functions, and their types.  Mypy ships with stubs for the
+standard library from the typeshed(1) project, which contains library
+stubs for the Python builtins, the standard library, and selected
+third-party packages.
+
+For example, consider this code:
+
+     x = chr(4)
+
+Without a library stub, mypy would have no way of inferring the type of
+‘x’ and checking that the argument to chr()(2) has a valid type.
+
+Mypy complains if it can’t find a stub (or a real module) for a library
+module that you import.  Some modules ship with stubs or inline
+annotations that mypy can automatically find, or you can install
+additional stubs using pip (see *note Missing imports: 14. and *note
+Using installed packages: 15. for the details).  For example, you can
+install the stubs for the ‘requests’ package like this:
+
+     python3 -m pip install types-requests
+
+The stubs are usually packaged in a distribution named
+‘types-<distribution>’.  Note that the distribution name may be
+different from the name of the package that you import.  For example,
+‘types-PyYAML’ contains stubs for the ‘yaml’ package.  Mypy can often
+suggest the name of the stub distribution:
+
+     prog.py:1: error: Library stubs not installed for "yaml" (or incompatible with Python 3.8)
+     prog.py:1: note: Hint: "python3 -m pip install types-PyYAML"
+     ...
+
+     Note: Starting in mypy 0.900, most third-party package stubs must
+     be installed explicitly.  This decouples mypy and stub versioning,
+     allowing stubs to updated without updating mypy.  This also allows
+     stubs not originally included with mypy to be installed.  Earlier
+     mypy versions included a fixed set of stubs for third-party
+     packages.
+
+You can also *note create stubs: 16. easily.  We discuss ways of
+silencing complaints about missing stubs in *note Missing imports: 17.
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/typeshed
+
+   (2) https://docs.python.org/3/library/functions.html#chr
+
+
+File: Mypy.info,  Node: Configuring mypy,  Next: Next steps,  Prev: Library stubs and typeshed,  Up: Getting started
+
+2.7 Configuring mypy
+====================
+
+Mypy supports many command line options that you can use to tweak how
+mypy behaves: see *note The mypy command line: c. for more details.
+
+For example, suppose you want to make sure `all' functions within your
+codebase are using static typing and make mypy report an error if you
+add a dynamically-typed function by mistake.  You can make mypy do this
+by running mypy with the *note –disallow-untyped-defs: b. flag.
+
+Another potentially useful flag is *note –strict: 19, which enables many
+(though not all) of the available strictness options – including *note
+–disallow-untyped-defs: b.
+
+This flag is mostly useful if you’re starting a new project from scratch
+and want to maintain a high degree of type safety from day one.
+However, this flag will probably be too aggressive if you either plan on
+using many untyped third party libraries or are trying to add static
+types to a large, existing codebase.  See *note Using mypy with an
+existing codebase: 1a. for more suggestions on how to handle the latter
+case.
+
+
+File: Mypy.info,  Node: Next steps,  Prev: Configuring mypy,  Up: Getting started
+
+2.8 Next steps
+==============
+
+If you are in a hurry and don’t want to read lots of documentation
+before getting started, here are some pointers to quick learning
+resources:
+
+   * Read the *note mypy cheatsheet: 1c. (also for *note Python 2: 1d.).
+
+   * Read *note Using mypy with an existing codebase: 1a. if you have a
+     significant existing codebase without many type annotations.
+
+   * Read the blog post(1) about the Zulip project’s experiences with
+     adopting mypy.
+
+   * If you prefer watching talks instead of reading, here are some
+     ideas:
+
+        * Carl Meyer: Type Checked Python in the Real World(2) (PyCon
+          2018)
+
+        * Greg Price: Clearer Code at Scale: Static Types at Zulip and
+          Dropbox(3) (PyCon 2018)
+
+   * Look at *note solutions to common issues: 1e. with mypy if you
+     encounter problems.
+
+   * You can ask questions about mypy in the mypy issue tracker(4) and
+     typing Gitter chat(5).
+
+You can also continue reading this document and skip sections that
+aren’t relevant for you.  You don’t need to read sections in order.
+
+   ---------- Footnotes ----------
+
+   (1) https://blog.zulip.org/2016/10/13/static-types-in-python-oh-mypy/
+
+   (2) https://www.youtube.com/watch?v=pMgmKJyWKn8
+
+   (3) https://www.youtube.com/watch?v=0c46YHS3RY8
+
+   (4) https://github.com/python/mypy/issues
+
+   (5) https://gitter.im/python/typing
+
+
+File: Mypy.info,  Node: Using mypy with an existing codebase,  Next: Type hints cheat sheet Python 3,  Prev: Getting started,  Up: Top
+
+3 Using mypy with an existing codebase
+**************************************
+
+This section explains how to get started using mypy with an existing,
+significant codebase that has little or no type annotations.  If you are
+a beginner, you can skip this section.
+
+These steps will get you started with mypy on an existing codebase:
+
+  1. Start small – get a clean mypy build for some files, with few
+     annotations
+
+  2. Write a mypy runner script to ensure consistent results
+
+  3. Run mypy in Continuous Integration to prevent type errors
+
+  4. Gradually annotate commonly imported modules
+
+  5. Write annotations as you modify existing code and write new code
+
+  6. Use MonkeyType(1) or PyAnnotate(2) to automatically annotate legacy
+     code
+
+We discuss all of these points in some detail below, and a few optional
+follow-up steps.
+
+* Menu:
+
+* Start small::
+* Mypy runner script::
+* Continuous Integration::
+* Annotate widely imported modules::
+* Write annotations as you go::
+* Automate annotation of legacy code::
+* Speed up mypy runs::
+* Introduce stricter options::
+
+   ---------- Footnotes ----------
+
+   (1) https://monkeytype.readthedocs.io/en/latest/index.html
+
+   (2) https://github.com/dropbox/pyannotate
+
+
+File: Mypy.info,  Node: Start small,  Next: Mypy runner script,  Up: Using mypy with an existing codebase
+
+3.1 Start small
+===============
+
+If your codebase is large, pick a subset of your codebase (say, 5,000 to
+50,000 lines) and run mypy only on this subset at first, `without any
+annotations'.  This shouldn’t take more than a day or two to implement,
+so you start enjoying benefits soon.
+
+You’ll likely need to fix some mypy errors, either by inserting
+annotations requested by mypy or by adding ‘# type: ignore’ comments to
+silence errors you don’t want to fix now.
+
+In particular, mypy often generates errors about modules that it can’t
+find or that don’t have stub files:
+
+     core/config.py:7: error: Cannot find implementation or library stub for module named 'frobnicate'
+     core/model.py:9: error: Cannot find implementation or library stub for module named 'acme'
+     ...
+
+This is normal, and you can easily ignore these errors.  For example,
+here we ignore an error about a third-party module ‘frobnicate’ that
+doesn’t have stubs using ‘# type: ignore’:
+
+     import frobnicate  # type: ignore
+     ...
+     frobnicate.initialize()  # OK (but not checked)
+
+You can also use a mypy configuration file, which is convenient if there
+are a large number of errors to ignore.  For example, to disable errors
+about importing ‘frobnicate’ and ‘acme’ everywhere in your codebase, use
+a config like this:
+
+     [mypy-frobnicate.*]
+     ignore_missing_imports = True
+
+     [mypy-acme.*]
+     ignore_missing_imports = True
+
+You can add multiple sections for different modules that should be
+ignored.
+
+If your config file is named ‘mypy.ini’, this is how you run mypy:
+
+     mypy --config-file mypy.ini mycode/
+
+If you get a large number of errors, you may want to ignore all errors
+about missing imports.  This can easily cause problems later on and hide
+real errors, and it’s only recommended as a last resort.  For more
+details, look *note here: 22.
+
+Mypy follows imports by default.  This can result in a few files passed
+on the command line causing mypy to process a large number of imported
+files, resulting in lots of errors you don’t want to deal with at the
+moment.  There is a config file option to disable this behavior, but
+since this can hide errors, it’s not recommended for most users.
+
+
+File: Mypy.info,  Node: Mypy runner script,  Next: Continuous Integration,  Prev: Start small,  Up: Using mypy with an existing codebase
+
+3.2 Mypy runner script
+======================
+
+Introduce a mypy runner script that runs mypy, so that every developer
+will use mypy consistently.  Here are some things you may want to do in
+the script:
+
+   * Ensure that the correct version of mypy is installed.
+
+   * Specify mypy config file or command-line options.
+
+   * Provide set of files to type check.  You may want to implement
+     inclusion and exclusion filters for full control of the file list.
+
+
+File: Mypy.info,  Node: Continuous Integration,  Next: Annotate widely imported modules,  Prev: Mypy runner script,  Up: Using mypy with an existing codebase
+
+3.3 Continuous Integration
+==========================
+
+Once you have a clean mypy run and a runner script for a part of your
+codebase, set up your Continuous Integration (CI) system to run mypy to
+ensure that developers won’t introduce bad annotations.  A simple CI
+script could look something like this:
+
+     python3 -m pip install mypy==0.790  # Pinned version avoids surprises
+     scripts/mypy  # Run the mypy runner script you set up
+
+
+File: Mypy.info,  Node: Annotate widely imported modules,  Next: Write annotations as you go,  Prev: Continuous Integration,  Up: Using mypy with an existing codebase
+
+3.4 Annotate widely imported modules
+====================================
+
+Most projects have some widely imported modules, such as utilities or
+model classes.  It’s a good idea to annotate these pretty early on,
+since this allows code using these modules to be type checked more
+effectively.  Since mypy supports gradual typing, it’s okay to leave
+some of these modules unannotated.  The more you annotate, the more
+useful mypy will be, but even a little annotation coverage is useful.
+
+
+File: Mypy.info,  Node: Write annotations as you go,  Next: Automate annotation of legacy code,  Prev: Annotate widely imported modules,  Up: Using mypy with an existing codebase
+
+3.5 Write annotations as you go
+===============================
+
+Now you are ready to include type annotations in your development
+workflows.  Consider adding something like these in your code style
+conventions:
+
+  1. Developers should add annotations for any new code.
+
+  2. It’s also encouraged to write annotations when you modify existing
+     code.
+
+This way you’ll gradually increase annotation coverage in your codebase
+without much effort.
+
+
+File: Mypy.info,  Node: Automate annotation of legacy code,  Next: Speed up mypy runs,  Prev: Write annotations as you go,  Up: Using mypy with an existing codebase
+
+3.6 Automate annotation of legacy code
+======================================
+
+There are tools for automatically adding draft annotations based on type
+profiles collected at runtime.  Tools include MonkeyType(1) (Python 3)
+and PyAnnotate(2).
+
+A simple approach is to collect types from test runs.  This may work
+well if your test coverage is good (and if your tests aren’t very slow).
+
+Another approach is to enable type collection for a small, random
+fraction of production network requests.  This clearly requires more
+care, as type collection could impact the reliability or the performance
+of your service.
+
+   ---------- Footnotes ----------
+
+   (1) https://monkeytype.readthedocs.io/en/latest/index.html
+
+   (2) https://github.com/dropbox/pyannotate
+
+
+File: Mypy.info,  Node: Speed up mypy runs,  Next: Introduce stricter options,  Prev: Automate annotation of legacy code,  Up: Using mypy with an existing codebase
+
+3.7 Speed up mypy runs
+======================
+
+You can use *note mypy daemon: 29. to get much faster incremental mypy
+runs.  The larger your project is, the more useful this will be.  If
+your project has at least 100,000 lines of code or so, you may also want
+to set up *note remote caching: 2a. for further speedups.
+
+
+File: Mypy.info,  Node: Introduce stricter options,  Prev: Speed up mypy runs,  Up: Using mypy with an existing codebase
+
+3.8 Introduce stricter options
+==============================
+
+Mypy is very configurable.  Once you get started with static typing, you
+may want to explore the various strictness options mypy provides to
+catch more bugs.  For example, you can ask mypy to require annotations
+for all functions in certain modules to avoid accidentally introducing
+code that won’t be type checked using *note disallow_untyped_defs: 2c,
+or type check code without annotations as well with *note
+check_untyped_defs: 2d.  Refer to *note The mypy configuration file: 2e.
+for the details.
+
+
+File: Mypy.info,  Node: Type hints cheat sheet Python 3,  Next: Type hints cheat sheet Python 2,  Prev: Using mypy with an existing codebase,  Up: Top
+
+4 Type hints cheat sheet (Python 3)
+***********************************
+
+This document is a quick cheat sheet showing how the PEP 484(1) type
+annotation notation represents various common types in Python 3.
+
+     Note: Technically many of the type annotations shown below are
+     redundant, because mypy can derive them from the type of the
+     expression.  So many of the examples have a dual purpose: show how
+     to write the annotation, and show the inferred types.
+
+* Menu:
+
+* Variables::
+* Built-in types::
+* Functions::
+* When you’re puzzled or when things are complicated::
+* Standard “duck types”::
+* Classes::
+* Coroutines and asyncio::
+* Miscellaneous::
+* Decorators::
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+
+File: Mypy.info,  Node: Variables,  Next: Built-in types,  Up: Type hints cheat sheet Python 3
+
+4.1 Variables
+=============
+
+Python 3.6 introduced a syntax for annotating variables in PEP 526(1)
+and we use it in most examples.
+
+     # This is how you declare the type of a variable type in Python 3.6
+     age: int = 1
+
+     # In Python 3.5 and earlier you can use a type comment instead
+     # (equivalent to the previous definition)
+     age = 1  # type: int
+
+     # You don't need to initialize a variable to annotate it
+     a: int  # Ok (no value at runtime until assigned)
+
+     # The latter is useful in conditional branches
+     child: bool
+     if age < 18:
+         child = True
+     else:
+         child = False
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0526/
+
+
+File: Mypy.info,  Node: Built-in types,  Next: Functions,  Prev: Variables,  Up: Type hints cheat sheet Python 3
+
+4.2 Built-in types
+==================
+
+     from typing import List, Set, Dict, Tuple, Optional
+
+     # For simple built-in types, just use the name of the type
+     x: int = 1
+     x: float = 1.0
+     x: bool = True
+     x: str = "test"
+     x: bytes = b"test"
+
+     # For collections, the type of the collection item is in brackets
+     # (Python 3.9+)
+     x: list[int] = [1]
+     x: set[int] = {6, 7}
+
+     # In Python 3.8 and earlier, the name of the collection type is
+     # capitalized, and the type is imported from the 'typing' module
+     x: List[int] = [1]
+     x: Set[int] = {6, 7}
+
+     # Same as above, but with type comment syntax (Python 3.5 and earlier)
+     x = [1]  # type: List[int]
+
+     # For mappings, we need the types of both keys and values
+     x: dict[str, float] = {"field": 2.0}  # Python 3.9+
+     x: Dict[str, float] = {"field": 2.0}
+
+     # For tuples of fixed size, we specify the types of all the elements
+     x: tuple[int, str, float] = (3, "yes", 7.5)  # Python 3.9+
+     x: Tuple[int, str, float] = (3, "yes", 7.5)
+
+     # For tuples of variable size, we use one type and ellipsis
+     x: tuple[int, ...] = (1, 2, 3)  # Python 3.9+
+     x: Tuple[int, ...] = (1, 2, 3)
+
+     # Use Optional[] for values that could be None
+     x: Optional[str] = some_function()
+     # Mypy understands a value can't be None in an if-statement
+     if x is not None:
+         print(x.upper())
+     # If a value can never be None due to some invariants, use an assert
+     assert x is not None
+     print(x.upper())
+
+
+File: Mypy.info,  Node: Functions,  Next: When you’re puzzled or when things are complicated,  Prev: Built-in types,  Up: Type hints cheat sheet Python 3
+
+4.3 Functions
+=============
+
+Python 3 supports an annotation syntax for function declarations.
+
+     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
+
+
+File: Mypy.info,  Node: When you’re puzzled or when things are complicated,  Next: Standard “duck types”,  Prev: Functions,  Up: Type hints cheat sheet Python 3
+
+4.4 When you’re puzzled or when things are complicated
+======================================================
+
+     from typing import Union, Any, Optional, cast
+
+     # To find out what type mypy infers for an expression anywhere in
+     # your program, wrap it in reveal_type().  Mypy will print an error
+     # message with the type; remove it again before running the code.
+     reveal_type(1)  # -> Revealed type is "builtins.int"
+
+     # Use Union when something could be one of a few types
+     x: list[Union[int, str]] = [3, 5, "test", "fun"]
+
+     # Use Any if you don't know the type of something or it's too
+     # dynamic to write a type for
+     x: Any = mystery_function()
+
+     # If you initialize a variable with an empty container or "None"
+     # you may have to help mypy a bit by providing a type annotation
+     x: list[str] = []
+     x: Optional[str] = None
+
+     # This makes each positional arg and each keyword arg a "str"
+     def call(self, *args: str, **kwargs: str) -> str:
+         request = make_request(*args, **kwargs)
+         return self.do_api_query(request)
+
+     # Use a "type: ignore" comment to suppress errors on a given line,
+     # when your code confuses mypy or runs into an outright bug in mypy.
+     # Good practice is to comment every "ignore" with a bug link
+     # (in mypy, typeshed, or your own code) or an explanation of the issue.
+     x = confusing_function()  # type: ignore  # https://github.com/python/mypy/issues/1167
+
+     # "cast" is a helper function that lets you override the inferred
+     # type of an expression. It's only for mypy -- there's no runtime check.
+     a = [4]
+     b = cast(list[int], a)  # Passes fine
+     c = cast(list[str], a)  # Passes fine (no runtime check)
+     reveal_type(c)  # -> Revealed type is "builtins.list[builtins.str]"
+     print(c)  # -> [4]; the object is not cast
+
+     # If you want dynamic attributes on your class, have it override "__setattr__"
+     # or "__getattr__" in a stub or in your source code.
+     #
+     # "__setattr__" allows for dynamic assignment to names
+     # "__getattr__" allows for dynamic access to names
+     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: str, value: int) -> None: ...
+
+         # This will allow access to any A.x, if x is compatible with the return type
+         def __getattr__(self, name: str) -> int: ...
+
+     a.foo = 42  # Works
+     a.bar = 'Ex-parrot'  # Fails type checking
+
+
+File: Mypy.info,  Node: Standard “duck types”,  Next: Classes,  Prev: When you’re puzzled or when things are complicated,  Up: Type hints cheat sheet Python 3
+
+4.5 Standard “duck types”
+=========================
+
+In typical Python code, many functions that can take a list or a dict as
+an argument only need their argument to be somehow “list-like” or
+“dict-like”.  A specific meaning of “list-like” or “dict-like” (or
+something-else-like) is called a “duck type”, and several duck types
+that are common in idiomatic Python are standardized.
+
+     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(ints: Iterable[int]) -> list[str]:
+         return [str(x) for x in ints]
+
+     f(range(1, 3))
+
+     # Mapping describes a dict-like object (with "__getitem__") that we won't
+     # mutate, and MutableMapping one (with "__setitem__") that we might
+     def f(my_mapping: Mapping[int, str]) -> list[int]:
+         my_mapping[5] = 'maybe'  # if we try this, mypy will throw an error...
+         return list(my_mapping.keys())
+
+     f({3: 'yes', 4: 'no'})
+
+     def f(my_mapping: MutableMapping[int, str]) -> set[str]:
+         my_mapping[5] = 'maybe'  # ...but mypy is OK with this.
+         return set(my_mapping.values())
+
+     f({3: 'yes', 4: 'no'})
+
+You can even make your own duck types using *note Protocols and
+structural subtyping: 37.
+
+
+File: Mypy.info,  Node: Classes,  Next: Coroutines and asyncio,  Prev: Standard “duck types”,  Up: Type hints cheat sheet Python 3
+
+4.6 Classes
+===========
+
+     class MyClass:
+         # You can optionally declare instance variables in the class body
+         attr: int
+         # This is an instance variable with a default value
+         charge_percent: int = 100
+
+         # The "__init__" method doesn't return anything, so it gets return
+         # type "None" just like any other method that doesn't return anything
+         def __init__(self) -> None:
+             ...
+
+         # For instance methods, omit type for "self"
+         def my_method(self, num: int, str1: str) -> str:
+             return num * str1
+
+     # User-defined classes are valid as types in annotations
+     x: MyClass = MyClass()
+
+     # You can use the ClassVar annotation to declare a class variable
+     class Car:
+         seats: ClassVar[int] = 4
+         passengers: ClassVar[list[str]]
+
+     # You can also declare the type of an attribute in "__init__"
+     class Box:
+         def __init__(self) -> None:
+             self.items: list[str] = []
+
+
+File: Mypy.info,  Node: Coroutines and asyncio,  Next: Miscellaneous,  Prev: Classes,  Up: Type hints cheat sheet Python 3
+
+4.7 Coroutines and asyncio
+==========================
+
+See *note Typing async/await: 3a. for the full detail on typing
+coroutines and asynchronous code.
+
+     import asyncio
+
+     # A coroutine is typed like a normal function
+     async def countdown35(tag: str, count: int) -> str:
+         while count > 0:
+             print('T-minus {} ({})'.format(count, tag))
+             await asyncio.sleep(0.1)
+             count -= 1
+         return "Blastoff!"
+
+
+File: Mypy.info,  Node: Miscellaneous,  Next: Decorators,  Prev: Coroutines and asyncio,  Up: Type hints cheat sheet Python 3
+
+4.8 Miscellaneous
+=================
+
+     import sys
+     import re
+     from typing import Match, AnyStr, IO
+
+     # "typing.Match" describes regex matches from the re module
+     x: Match[str] = re.match(r'[0-9]+', "15")
+
+     # Use IO[] for functions that should accept or return any
+     # object that comes from an open() call (IO[] does not
+     # distinguish between reading, writing or other modes)
+     def get_sys_IO(mode: str = 'w') -> IO[str]:
+         if mode == 'w':
+             return sys.stdout
+         elif mode == 'r':
+             return sys.stdin
+         else:
+             return sys.stdout
+
+     # Forward references are useful if you want to reference a class before
+     # it is defined
+     def f(foo: A) -> int:  # This will fail
+         ...
+
+     class A:
+         ...
+
+     # If you use the string literal 'A', it will pass as long as there is a
+     # class of that name later on in the file
+     def f(foo: 'A') -> int:  # Ok
+         ...
+
+
+File: Mypy.info,  Node: Decorators,  Prev: Miscellaneous,  Up: Type hints cheat sheet Python 3
+
+4.9 Decorators
+==============
+
+Decorator functions can be expressed via generics.  See *note Declaring
+decorators: 3d. for more details.
+
+     from typing import Any, Callable, TypeVar
+
+     F = TypeVar('F', bound=Callable[..., Any])
+
+     def bare_decorator(func: F) -> F:
+         ...
+
+     def decorator_args(url: str) -> Callable[[F], F]:
+         ...
+
+
+File: Mypy.info,  Node: Type hints cheat sheet Python 2,  Next: Built-in types<3>,  Prev: Type hints cheat sheet Python 3,  Up: Top
+
+5 Type hints cheat sheet (Python 2)
+***********************************
+
+This document is a quick cheat sheet showing how the PEP 484(1) type
+language represents various common types in Python 2.
+
+     Note: Technically many of the type annotations shown below are
+     redundant, because mypy can derive them from the type of the
+     expression.  So many of the examples have a dual purpose: show how
+     to write the annotation, and show the inferred types.
+
+     Note: To check Python 2 code with mypy, you’ll need to install mypy
+     with ‘pip install 'mypy[python2]'’.
+
+* Menu:
+
+* Built-in types: Built-in types<2>.
+* Functions: Functions<2>.
+* When you’re puzzled or when things are complicated: When you’re puzzled or when things are complicated<2>.
+* Standard “duck types”: Standard “duck types”<2>.
+* Classes: Classes<2>.
+* Miscellaneous: Miscellaneous<2>.
+* Decorators: Decorators<2>.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+
+File: Mypy.info,  Node: Built-in types<2>,  Next: Functions<2>,  Up: Type hints cheat sheet Python 2
+
+5.1 Built-in types
+==================
+
+     from typing import List, Set, Dict, Tuple, Text, Optional
+
+     # For simple built-in types, just use the name of the type
+     x = 1  # type: int
+     x = 1.0  # type: float
+     x = True  # type: bool
+     x = "test"  # type: str
+     x = u"test"  # type: unicode
+
+     # For collections, the name of the type is capitalized, and the
+     # name of the type inside the collection is in brackets
+     x = [1]  # type: List[int]
+     x = {6, 7}  # type: Set[int]
+
+     # For mappings, we need the types of both keys and values
+     x = {'field': 2.0}  # type: Dict[str, float]
+
+     # For tuples, we specify the types of all the elements
+     x = (3, "yes", 7.5)  # type: Tuple[int, str, float]
+
+     # For textual data, use Text
+     # ("Text" means  "unicode" in Python 2 and "str" in Python 3)
+     x = [u"one", u"two"]  # type: List[Text]
+
+     # Use Optional[] for values that could be None
+     x = some_function()  # type: Optional[str]
+     # Mypy understands a value can't be None in an if-statement
+     if x is not None:
+         print x.upper()
+     # If a value can never be None due to some invariants, use an assert
+     assert x is not None
+     print x.upper()
+
+
+File: Mypy.info,  Node: Functions<2>,  Next: When you’re puzzled or when things are complicated<2>,  Prev: Built-in types<2>,  Up: Type hints cheat sheet Python 2
+
+5.2 Functions
+=============
+
+     from typing import Callable, Iterator, Union, Optional, List
+
+     # This is how you annotate a function definition
+     def stringify(num):
+         # type: (int) -> str
+         """Your function docstring goes here after the type definition."""
+         return str(num)
+
+     # This function has no parameters and also returns nothing. Annotations
+     # can also be placed on the same line as their function headers.
+     def greet_world(): # type: () -> None
+         print "Hello, world!"
+
+     # And here's how you specify multiple arguments
+     def plus(num1, num2):
+         # type: (int, int) -> int
+         return num1 + num2
+
+     # Add type annotations for arguments with default values as though they
+     # had no defaults
+     def f(num1, my_float=3.5):
+         # type: (int, float) -> float
+         return num1 + my_float
+
+     # An argument can be declared positional-only by giving it a name
+     # starting with two underscores
+     def quux(__x):
+         # type: (int) -> None
+         pass
+
+     quux(3)  # Fine
+     quux(__x=3)  # Error
+
+     # This is how you annotate a callable (function) value
+     x = f  # type: Callable[[int, float], float]
+
+     # 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):
+         # type: (int) -> Iterator[int]
+         i = 0
+         while i < n:
+             yield i
+             i += 1
+
+     # There's an alternative syntax for functions with many arguments
+     def send_email(address,     # type: Union[str, List[str]]
+                    sender,      # type: str
+                    cc,          # type: Optional[List[str]]
+                    bcc,         # type: Optional[List[str]]
+                    subject='',
+                    body=None    # type: List[str]
+                    ):
+         # type: (...) -> bool
+         ...
+
+
+File: Mypy.info,  Node: When you’re puzzled or when things are complicated<2>,  Next: Standard “duck types”<2>,  Prev: Functions<2>,  Up: Type hints cheat sheet Python 2
+
+5.3 When you’re puzzled or when things are complicated
+======================================================
+
+     from typing import Union, Any, List, Optional, cast
+
+     # To find out what type mypy infers for an expression anywhere in
+     # your program, wrap it in reveal_type().  Mypy will print an error
+     # message with the type; remove it again before running the code.
+     reveal_type(1) # -> Revealed type is "builtins.int"
+
+     # Use Union when something could be one of a few types
+     x = [3, 5, "test", "fun"]  # type: List[Union[int, str]]
+
+     # Use Any if you don't know the type of something or it's too
+     # dynamic to write a type for
+     x = mystery_function()  # type: Any
+
+     # If you initialize a variable with an empty container or "None"
+     # you may have to help mypy a bit by providing a type annotation
+     x = []  # type: List[str]
+     x = None  # type: Optional[str]
+
+     # This makes each positional arg and each keyword arg a "str"
+     def call(self, *args, **kwargs):
+         # type: (*str, **str) -> str
+         request = make_request(*args, **kwargs)
+         return self.do_api_query(request)
+
+     # Use a "type: ignore" comment to suppress errors on a given line,
+     # when your code confuses mypy or runs into an outright bug in mypy.
+     # Good practice is to comment every "ignore" with a bug link
+     # (in mypy, typeshed, or your own code) or an explanation of the issue.
+     x = confusing_function() # type: ignore # https://github.com/python/mypy/issues/1167
+
+     # "cast" is a helper function that lets you override the inferred
+     # type of an expression. It's only for mypy -- there's no runtime check.
+     a = [4]
+     b = cast(List[int], a)  # Passes fine
+     c = cast(List[str], a)  # Passes fine (no runtime check)
+     reveal_type(c)  # -> Revealed type is "builtins.list[builtins.str]"
+     print c  # -> [4]; the object is not cast
+
+     # If you want dynamic attributes on your class, have it override "__setattr__"
+     # or "__getattr__" in a stub or in your source code.
+     #
+     # "__setattr__" allows for dynamic assignment to names
+     # "__getattr__" allows for dynamic access to names
+     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
+
+
+File: Mypy.info,  Node: Standard “duck types”<2>,  Next: Classes<2>,  Prev: When you’re puzzled or when things are complicated<2>,  Up: Type hints cheat sheet Python 2
+
+5.4 Standard “duck types”
+=========================
+
+In typical Python code, many functions that can take a list or a dict as
+an argument only need their argument to be somehow “list-like” or
+“dict-like”.  A specific meaning of “list-like” or “dict-like” (or
+something-else-like) is called a “duck type”, and several duck types
+that are common in idiomatic Python are standardized.
+
+     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))
+
+     # Mapping describes a dict-like object (with "__getitem__") that we won't
+     # mutate, and MutableMapping one (with "__setitem__") that we might
+     def f(my_dict):
+         # type: (Mapping[int, str]) -> List[int]
+         return list(my_dict.keys())
+
+     f({3: 'yes', 4: 'no'})
+
+     def f(my_mapping):
+         # type: (MutableMapping[int, str]) -> Set[str]
+         my_mapping[5] = 'maybe'
+         return set(my_mapping.values())
+
+     f({3: 'yes', 4: 'no'})
+
+
+File: Mypy.info,  Node: Classes<2>,  Next: Miscellaneous<2>,  Prev: Standard “duck types”<2>,  Up: Type hints cheat sheet Python 2
+
+5.5 Classes
+===========
+
+     class MyClass(object):
+         # For instance methods, omit type for "self"
+         def my_method(self, num, str1):
+             # type: (int, str) -> str
+             return num * str1
+
+         # The "__init__" method doesn't return anything, so it gets return
+         # type "None" just like any other method that doesn't return anything
+         def __init__(self):
+             # type: () -> None
+             pass
+
+     # User-defined classes are valid as types in annotations
+     x = MyClass()  # type: MyClass
+
+
+File: Mypy.info,  Node: Miscellaneous<2>,  Next: Decorators<2>,  Prev: Classes<2>,  Up: Type hints cheat sheet Python 2
+
+5.6 Miscellaneous
+=================
+
+     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]
+
+     # Use IO[] for functions that should accept or return any
+     # object that comes from an open() call (IO[] does not
+     # distinguish between reading, writing or other modes)
+     def get_sys_IO(mode='w'):
+         # type: (str) -> IO[str]
+         if mode == 'w':
+             return sys.stdout
+         elif mode == 'r':
+             return sys.stdin
+         else:
+             return sys.stdout
+
+
+File: Mypy.info,  Node: Decorators<2>,  Prev: Miscellaneous<2>,  Up: Type hints cheat sheet Python 2
+
+5.7 Decorators
+==============
+
+Decorator functions can be expressed via generics.  See *note Declaring
+decorators: 3d. for the more details.
+
+     from typing import Any, Callable, TypeVar
+
+     F = TypeVar('F', bound=Callable[..., Any])
+
+     def bare_decorator(func):  # type: (F) -> F
+         ...
+
+     def decorator_args(url):  # type: (str) -> Callable[[F], F]
+         ...
+
+
+File: Mypy.info,  Node: Built-in types<3>,  Next: Type inference and type annotations,  Prev: Type hints cheat sheet Python 2,  Up: Top
+
+6 Built-in types
+****************
+
+This chapter introduces some commonly used built-in types.  We will
+cover many other kinds of types later.
+
+* Menu:
+
+* Simple types::
+* Any type::
+* Generic types::
+
+
+File: Mypy.info,  Node: Simple types,  Next: Any type,  Up: Built-in types<3>
+
+6.1 Simple types
+================
+
+Here are examples of some common built-in types:
+
+Type                       Description
+                           
+-----------------------------------------------------------------------------------------
+                           
+‘int’                      integer
+                           
+                           
+‘float’                    floating point number
+                           
+                           
+‘bool’                     boolean value (subclass of ‘int’)
+                           
+                           
+‘str’                      string (unicode in Python 3)
+                           
+                           
+‘bytes’                    8-bit string
+                           
+                           
+‘object’                   an arbitrary object (‘object’ is the common base class)
+                           
+
+All built-in classes can be used as types.
+
+
+File: Mypy.info,  Node: Any type,  Next: Generic types,  Prev: Simple types,  Up: Built-in types<3>
+
+6.2 Any type
+============
+
+If you can’t find a good type for some value, you can always fall back
+to ‘Any’:
+
+Type                       Description
+                           
+------------------------------------------------------------------------------
+                           
+‘Any’                      dynamically typed value with an arbitrary type
+                           
+
+The type ‘Any’ is defined in the typing(1) module.  See *note
+Dynamically typed code: 4b. for more details.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Generic types,  Prev: Any type,  Up: Built-in types<3>
+
+6.3 Generic types
+=================
+
+In Python 3.9 and later, built-in collection type objects support
+indexing:
+
+Type                       Description
+                           
+-----------------------------------------------------------------------------------------------
+                           
+‘list[str]’                list of ‘str’ objects
+                           
+                           
+‘tuple[int, int]’          tuple of two ‘int’ objects (‘tuple[()]’ is the empty tuple)
+                           
+                           
+‘tuple[int, ...]’          tuple of an arbitrary number of ‘int’ objects
+                           
+                           
+‘dict[str, int]’           dictionary from ‘str’ keys to ‘int’ values
+                           
+                           
+‘Iterable[int]’            iterable object containing ints
+                           
+                           
+‘Sequence[bool]’           sequence of booleans (read-only)
+                           
+                           
+‘Mapping[str, int]’        mapping from ‘str’ keys to ‘int’ values (read-only)
+                           
+
+The type ‘dict’ is a `generic' class, signified by type arguments within
+‘[...]’.  For example, ‘dict[int, str]’ is a dictionary from integers to
+strings and ‘dict[Any, Any]’ is a dictionary of dynamically typed
+(arbitrary) values and keys.  ‘list’ is another generic class.
+
+‘Iterable’, ‘Sequence’, and ‘Mapping’ are generic types that correspond
+to Python protocols.  For example, a ‘str’ object or a ‘list[str]’
+object is valid when ‘Iterable[str]’ or ‘Sequence[str]’ is expected.
+You can import them from collections.abc(1) instead of importing from
+typing(2) in Python 3.9.
+
+See *note Using generic builtins: 4d. for more details, including how
+you can use these in annotations also in Python 3.7 and 3.8.
+
+These legacy types defined in typing(3) are needed if you need to
+support Python 3.8 and earlier:
+
+Type                       Description
+                           
+-----------------------------------------------------------------------------------------------
+                           
+‘List[str]’                list of ‘str’ objects
+                           
+                           
+‘Tuple[int, int]’          tuple of two ‘int’ objects (‘Tuple[()]’ is the empty tuple)
+                           
+                           
+‘Tuple[int, ...]’          tuple of an arbitrary number of ‘int’ objects
+                           
+                           
+‘Dict[str, int]’           dictionary from ‘str’ keys to ‘int’ values
+                           
+                           
+‘Iterable[int]’            iterable object containing ints
+                           
+                           
+‘Sequence[bool]’           sequence of booleans (read-only)
+                           
+                           
+‘Mapping[str, int]’        mapping from ‘str’ keys to ‘int’ values (read-only)
+                           
+
+‘List’ is an alias for the built-in type ‘list’ that supports indexing
+(and similarly for ‘dict’/‘Dict’ and ‘tuple’/‘Tuple’).
+
+Note that even though ‘Iterable’, ‘Sequence’ and ‘Mapping’ look similar
+to abstract base classes defined in collections.abc(4) (formerly
+‘collections’), they are not identical, since the latter don’t support
+indexing prior to Python 3.9.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/collections.abc.html#module-collections.abc
+
+   (2) https://docs.python.org/3/library/typing.html#module-typing
+
+   (3) https://docs.python.org/3/library/typing.html#module-typing
+
+   (4) 
+https://docs.python.org/3/library/collections.abc.html#module-collections.abc
+
+
+File: Mypy.info,  Node: Type inference and type annotations,  Next: Kinds of types,  Prev: Built-in types<3>,  Up: Top
+
+7 Type inference and type annotations
+*************************************
+
+* Menu:
+
+* Type inference::
+* Explicit types for variables::
+* Explicit types for collections::
+* Compatibility of container types::
+* Context in type inference::
+* Declaring multiple variable types at a time::
+* Starred expressions::
+* Silencing type errors::
+
+
+File: Mypy.info,  Node: Type inference,  Next: Explicit types for variables,  Up: Type inference and type annotations
+
+7.1 Type inference
+==================
+
+Mypy considers the initial assignment as the definition of a variable.
+If you do not explicitly specify the type of the variable, mypy infers
+the type based on the static type of the value expression:
+
+     i = 1           # Infer type "int" for i
+     l = [1, 2]      # Infer type "list[int]" for l
+
+Type inference is not used in dynamically typed functions (those without
+a function type annotation) — every local variable type defaults to
+‘Any’ in such functions.  ‘Any’ is discussed later in more detail.
+
+
+File: Mypy.info,  Node: Explicit types for variables,  Next: Explicit types for collections,  Prev: Type inference,  Up: Type inference and type annotations
+
+7.2 Explicit types for variables
+================================
+
+You can override the inferred type of a variable by using a variable
+type annotation:
+
+     from typing import Union
+
+     x: Union[int, str] = 1
+
+Without the type annotation, the type of ‘x’ would be just ‘int’.  We
+use an annotation to give it a more general type ‘Union[int, str]’ (this
+type means that the value can be either an ‘int’ or a ‘str’).  Mypy
+checks that the type of the initializer is compatible with the declared
+type.  The following example is not valid, since the initializer is a
+floating point number, and this is incompatible with the declared type:
+
+     x: Union[int, str] = 1.1  # Error!
+
+The variable annotation syntax is available starting from Python 3.6.
+In earlier Python versions, you can use a special comment after an
+assignment statement to declare the type of a variable:
+
+     x = 1  # type: Union[int, str]
+
+We’ll use both syntax variants in examples.  The syntax variants are
+mostly interchangeable, but the variable annotation syntax allows
+defining the type of a variable without initialization, which is not
+possible with the comment syntax:
+
+     x: str  # Declare type of 'x' without initialization
+
+     Note: The best way to think about this is that the type annotation
+     sets the type of the variable, not the type of the expression.  To
+     force the type of an expression you can use cast(<type>,
+     <expression>)(1).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.cast
+
+
+File: Mypy.info,  Node: Explicit types for collections,  Next: Compatibility of container types,  Prev: Explicit types for variables,  Up: Type inference and type annotations
+
+7.3 Explicit types for collections
+==================================
+
+The type checker cannot always infer the type of a list or a dictionary.
+This often arises when creating an empty list or dictionary and
+assigning it to a new variable that doesn’t have an explicit variable
+type.  Here is an example where mypy can’t infer the type without some
+help:
+
+     l = []  # Error: Need type annotation for "l"
+
+In these cases you can give the type explicitly using a type annotation:
+
+     l: list[int] = []       # Create empty list with type list[int]
+     d: dict[str, int] = {}  # Create empty dictionary (str -> int)
+
+Similarly, you can also give an explicit type when creating an empty
+set:
+
+     s: set[int] = set()
+
+     Note: Using type arguments (e.g.  ‘list[int]’) on builtin
+     collections like list(1), dict(2), tuple(3), and set(4) only works
+     in Python 3.9 and later.  For Python 3.8 and earlier, you must use
+     List(5) (e.g.  ‘List[int]’), Dict(6), and so on.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#list
+
+   (2) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (3) https://docs.python.org/3/library/stdtypes.html#tuple
+
+   (4) https://docs.python.org/3/library/stdtypes.html#set
+
+   (5) https://docs.python.org/3/library/typing.html#typing.List
+
+   (6) https://docs.python.org/3/library/typing.html#typing.Dict
+
+
+File: Mypy.info,  Node: Compatibility of container types,  Next: Context in type inference,  Prev: Explicit types for collections,  Up: Type inference and type annotations
+
+7.4 Compatibility of container types
+====================================
+
+The following program generates a mypy error, since ‘list[int]’ is not
+compatible with ‘list[object]’:
+
+     def f(l: list[object], k: list[int]) -> None:
+         l = k  # Type check error: incompatible types in assignment
+
+The reason why the above assignment is disallowed is that allowing the
+assignment could result in non-int values stored in a list of ‘int’:
+
+     def f(l: list[object], k: list[int]) -> None:
+         l = k
+         l.append('x')
+         print(k[-1])  # Ouch; a string in list[int]
+
+Other container types like dict(1) and set(2) behave similarly.  We will
+discuss how you can work around this in *note Invariance vs covariance:
+55.
+
+You can still run the above program; it prints ‘x’.  This illustrates
+the fact that static types are used during type checking, but they do
+not affect the runtime behavior of programs.  You can run programs with
+type check failures, which is often very handy when performing a large
+refactoring.  Thus you can always ‘work around’ the type system, and it
+doesn’t really limit what you can do in your program.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (2) https://docs.python.org/3/library/stdtypes.html#set
+
+
+File: Mypy.info,  Node: Context in type inference,  Next: Declaring multiple variable types at a time,  Prev: Compatibility of container types,  Up: Type inference and type annotations
+
+7.5 Context in type inference
+=============================
+
+Type inference is `bidirectional' and takes context into account.  For
+example, the following is valid:
+
+     def f(l: list[object]) -> None:
+         l = [1, 2]  # Infer type list[object] for [1, 2], not list[int]
+
+In an assignment, the type context is determined by the assignment
+target.  In this case this is ‘l’, which has the type ‘list[object]’.
+The value expression ‘[1, 2]’ is type checked in this context and given
+the type ‘list[object]’.  In the previous example we introduced a new
+variable ‘l’, and here the type context was empty.
+
+Declared argument types are also used for type context.  In this program
+mypy knows that the empty list ‘[]’ should have type ‘list[int]’ based
+on the declared type of ‘arg’ in ‘foo’:
+
+     def foo(arg: list[int]) -> None:
+         print('Items:', ''.join(str(a) for a in arg))
+
+     foo([])  # OK
+
+However, context only works within a single statement.  Here mypy
+requires an annotation for the empty list, since the context would only
+be available in the following statement:
+
+     def foo(arg: list[int]) -> None:
+         print('Items:', ', '.join(arg))
+
+     a = []  # Error: Need type annotation for "a"
+     foo(a)
+
+Working around the issue is easy by adding a type annotation:
+
+     ...
+     a: list[int] = []  # OK
+     foo(a)
+
+
+File: Mypy.info,  Node: Declaring multiple variable types at a time,  Next: Starred expressions,  Prev: Context in type inference,  Up: Type inference and type annotations
+
+7.6 Declaring multiple variable types at a time
+===============================================
+
+You can declare more than a single variable at a time, but only with a
+type comment.  In order to nicely work with multiple assignment, you
+must give each variable a type separately:
+
+     i, found = 0, False  # type: int, bool
+
+You can optionally use parentheses around the types, assignment targets
+and assigned expression:
+
+     i, found = 0, False  # type: (int, bool)      # OK
+     (i, found) = 0, False  # type: int, bool      # OK
+     i, found = (0, False)  # type: int, bool      # OK
+     (i, found) = (0, False)  # type: (int, bool)  # OK
+
+
+File: Mypy.info,  Node: Starred expressions,  Next: Silencing type errors,  Prev: Declaring multiple variable types at a time,  Up: Type inference and type annotations
+
+7.7 Starred expressions
+=======================
+
+In most cases, mypy can infer the type of starred expressions from the
+right-hand side of an assignment, but not always:
+
+     a, *bs = 1, 2, 3   # OK
+     p, q, *rs = 1, 2   # Error: Type of rs cannot be inferred
+
+On first line, the type of ‘bs’ is inferred to be ‘list[int]’.  However,
+on the second line, mypy cannot infer the type of ‘rs’, because there is
+no right-hand side value for ‘rs’ to infer the type from.  In cases like
+these, the starred expression needs to be annotated with a starred type:
+
+     p, q, *rs = 1, 2  # type: int, int, list[int]
+
+Here, the type of ‘rs’ is set to ‘list[int]’.
+
+
+File: Mypy.info,  Node: Silencing type errors,  Prev: Starred expressions,  Up: Type inference and type annotations
+
+7.8 Silencing type errors
+=========================
+
+You might want to disable type checking on specific lines, or within
+specific files in your codebase.  To do that, you can use a ‘# type:
+ignore’ comment.
+
+For example, say that the web framework that you use now takes an
+integer argument to ‘run()’, which starts it on localhost on that port.
+Like so:
+
+     # Starting app on http://localhost:8000
+     app.run(8000)
+
+However, the type stubs that the package uses is not up-to-date, and it
+still expects only ‘str’ types for ‘run()’.  This would give you the
+following error:
+
+     error: Argument 1 to "run" of "A" has incompatible type "int"; expected "str"
+
+If you cannot directly fix the type stubs yourself, you can temporarily
+disable type checking on that line, by adding a ‘# type: ignore’:
+
+     # Starting app on http://localhost:8000
+     app.run(8000)  # type: ignore
+
+This will suppress any mypy errors that would have raised on that
+specific line.
+
+You should probably add some more information on the ‘# type: ignore’
+comment, to explain why the ignore was added in the first place.  This
+could be a link to an issue on the repository responsible for the type
+stubs, or it could be a short explanation of the bug.  To do that, use
+this format:
+
+     # Starting app on http://localhost:8000
+     app.run(8000)  # type: ignore  # `run()` now accepts an `int`, as a port
+
+Mypy displays an error code for each error if you use *note
+–show-error-codes: 5a.:
+
+     error: "str" has no attribute "trim"  [attr-defined]
+
+It is possible to add a specific error-code in your ignore comment (e.g.
+‘# type: ignore[attr-defined]’) to clarify what’s being silenced.  You
+can find more information about error codes *note here: 5b.
+
+Similarly, you can also ignore all mypy checks in a file, by adding a ‘#
+type: ignore’ at the top of the file:
+
+     # type: ignore
+     # This is a test file, skipping type checking in it.
+     import unittest
+     ...
+
+
+File: Mypy.info,  Node: Kinds of types,  Next: Class basics,  Prev: Type inference and type annotations,  Up: Top
+
+8 Kinds of types
+****************
+
+We’ve mostly restricted ourselves to built-in types until now.  This
+section introduces several additional kinds of types.  You are likely to
+need at least some of them to type check any non-trivial programs.
+
+* Menu:
+
+* Class types::
+* The Any type::
+* Tuple types::
+* Callable types (and lambdas): Callable types and lambdas.
+* Union types::
+* Optional types and the None type::
+* Disabling strict optional checking::
+* Type aliases::
+* Named tuples::
+* The type of class objects::
+* Text and AnyStr::
+* Generators::
+
+
+File: Mypy.info,  Node: Class types,  Next: The Any type,  Up: Kinds of types
+
+8.1 Class types
+===============
+
+Every class is also a valid type.  Any instance of a subclass is also
+compatible with all superclasses – it follows that every value is
+compatible with the object(1) type (and incidentally also the ‘Any’
+type, discussed below).  Mypy analyzes the bodies of classes to
+determine which methods and attributes are available in instances.  This
+example uses subclassing:
+
+     class A:
+         def f(self) -> int:  # Type of self inferred (A)
+             return 2
+
+     class B(A):
+         def f(self) -> int:
+              return 3
+         def g(self) -> int:
+             return 4
+
+     def foo(a: A) -> None:
+         print(a.f())  # 3
+         a.g()         # Error: "A" has no attribute "g"
+
+     foo(B())  # OK (B is a subclass of A)
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#object
+
+
+File: Mypy.info,  Node: The Any type,  Next: Tuple types,  Prev: Class types,  Up: Kinds of types
+
+8.2 The Any type
+================
+
+A value with the ‘Any’ type is dynamically typed.  Mypy doesn’t know
+anything about the possible runtime types of such value.  Any operations
+are permitted on the value, and the operations are only checked at
+runtime.  You can use ‘Any’ as an “escape hatch” when you can’t use a
+more precise type for some reason.
+
+‘Any’ is compatible with every other type, and vice versa.  You can
+freely assign a value of type ‘Any’ to a variable with a more precise
+type:
+
+     a: Any = None
+     s: str = ''
+     a = 2     # OK (assign "int" to "Any")
+     s = a     # OK (assign "Any" to "str")
+
+Declared (and inferred) types are ignored (or `erased') at runtime.
+They are basically treated as comments, and thus the above code does not
+generate a runtime error, even though ‘s’ gets an ‘int’ value when the
+program is run, while the declared type of ‘s’ is actually ‘str’!  You
+need to be careful with ‘Any’ types, since they let you lie to mypy, and
+this could easily hide bugs.
+
+If you do not define a function return value or argument types, these
+default to ‘Any’:
+
+     def show_heading(s) -> None:
+         print('=== ' + s + ' ===')  # No static type checking, as s has type Any
+
+     show_heading(1)  # OK (runtime error only; mypy won't generate an error)
+
+You should give a statically typed function an explicit ‘None’ return
+type even if it doesn’t return a value, as this lets mypy catch
+additional type errors:
+
+     def wait(t: float):  # Implicit Any return value
+         print('Waiting...')
+         time.sleep(t)
+
+     if wait(2) > 1:   # Mypy doesn't catch this error!
+         ...
+
+If we had used an explicit ‘None’ return type, mypy would have caught
+the error:
+
+     def wait(t: float) -> None:
+         print('Waiting...')
+         time.sleep(t)
+
+     if wait(2) > 1:   # Error: can't compare None and int
+         ...
+
+The ‘Any’ type is discussed in more detail in section *note Dynamically
+typed code: 4b.
+
+     Note: A function without any types in the signature is dynamically
+     typed.  The body of a dynamically typed function is not checked
+     statically, and local variables have implicit ‘Any’ types.  This
+     makes it easier to migrate legacy Python code to mypy, as mypy
+     won’t complain about dynamically typed functions.
+
+
+File: Mypy.info,  Node: Tuple types,  Next: Callable types and lambdas,  Prev: The Any type,  Up: Kinds of types
+
+8.3 Tuple types
+===============
+
+The type ‘tuple[T1, ..., Tn]’ represents a tuple with the item types
+‘T1’, …, ‘Tn’:
+
+     # Use `typing.Tuple` in Python 3.8 and earlier
+     def f(t: tuple[int, str]) -> None:
+         t = 1, 'foo'    # OK
+         t = 'foo', 1    # Type check error
+
+A tuple type of this kind has exactly a specific number of items (2 in
+the above example).  Tuples can also be used as immutable,
+varying-length sequences.  You can use the type ‘tuple[T, ...]’ (with a
+literal ‘...’ – it’s part of the syntax) for this purpose.  Example:
+
+     def print_squared(t: tuple[int, ...]) -> None:
+         for n in t:
+             print(n, n ** 2)
+
+     print_squared(())           # OK
+     print_squared((1, 3, 5))    # OK
+     print_squared([1, 2])       # Error: only a tuple is valid
+
+     Note: Usually it’s a better idea to use ‘Sequence[T]’ instead of
+     ‘tuple[T, ...]’, as Sequence(1) is also compatible with lists and
+     other non-tuple sequences.
+
+     Note: ‘tuple[...]’ is valid as a base class in Python 3.6 and
+     later, and always in stub files.  In earlier Python versions you
+     can sometimes work around this limitation by using a named tuple as
+     a base class (see section *note Named tuples: 62.).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Sequence
+
+
+File: Mypy.info,  Node: Callable types and lambdas,  Next: Union types,  Prev: Tuple types,  Up: Kinds of types
+
+8.4 Callable types (and lambdas)
+================================
+
+You can pass around function objects and bound methods in statically
+typed code.  The type of a function that accepts arguments ‘A1’, …, ‘An’
+and returns ‘Rt’ is ‘Callable[[A1, ..., An], Rt]’.  Example:
+
+     from typing import Callable
+
+     def twice(i: int, next: Callable[[int], int]) -> int:
+         return next(next(i))
+
+     def add(i: int) -> int:
+         return i + 1
+
+     print(twice(3, add))   # 5
+
+You can only have positional arguments, and only ones without default
+values, in callable types.  These cover the vast majority of uses of
+callable types, but sometimes this isn’t quite enough.  Mypy recognizes
+a special form ‘Callable[..., T]’ (with a literal ‘...’) which can be
+used in less typical cases.  It is compatible with arbitrary callable
+objects that return a type compatible with ‘T’, independent of the
+number, types or kinds of arguments.  Mypy lets you call such callable
+values with arbitrary arguments, without any checking – in this respect
+they are treated similar to a ‘(*args: Any, **kwargs: Any)’ function
+signature.  Example:
+
+     from typing import Callable
+
+     def arbitrary_call(f: Callable[..., int]) -> int:
+         return f('x') + f(y=2)  # OK
+
+     arbitrary_call(ord)   # No static error, but fails at runtime
+     arbitrary_call(open)  # Error: does not return an int
+     arbitrary_call(1)     # Error: 'int' is not callable
+
+In situations where more precise or complex types of callbacks are
+necessary one can use flexible *note callback protocols: 65.  Lambdas
+are also supported.  The lambda argument and return value types cannot
+be given explicitly; they are always inferred based on context using
+bidirectional type inference:
+
+     l = map(lambda x: x + 1, [1, 2, 3])   # Infer x as int and l as list[int]
+
+If you want to give the argument or return value types explicitly, use
+an ordinary, perhaps nested function definition.
+
+
+File: Mypy.info,  Node: Union types,  Next: Optional types and the None type,  Prev: Callable types and lambdas,  Up: Kinds of types
+
+8.5 Union types
+===============
+
+Python functions often accept values of two or more different types.
+You can use *note overloading: 68. to represent this, but union types
+are often more convenient.
+
+Use the ‘Union[T1, ..., Tn]’ type constructor to construct a union type.
+For example, if an argument has type ‘Union[int, str]’, both integers
+and strings are valid argument values.
+
+You can use an isinstance()(1) check to narrow down a union type to a
+more specific type:
+
+     from typing import Union
+
+     def f(x: Union[int, str]) -> None:
+         x + 1     # Error: str + int is not valid
+         if isinstance(x, int):
+             # Here type of x is int.
+             x + 1      # OK
+         else:
+             # Here type of x is str.
+             x + 'a'    # OK
+
+     f(1)    # OK
+     f('x')  # OK
+     f(1.1)  # Error
+
+     Note: Operations are valid for union types only if they are valid
+     for `every' union item.  This is why it’s often necessary to use an
+     isinstance()(2) check to first narrow down a union type to a
+     non-union type.  This also means that it’s recommended to avoid
+     union types as function return types, since the caller may have to
+     use isinstance()(3) before doing anything interesting with the
+     value.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+   (2) https://docs.python.org/3/library/functions.html#isinstance
+
+   (3) https://docs.python.org/3/library/functions.html#isinstance
+
+
+File: Mypy.info,  Node: Optional types and the None type,  Next: Disabling strict optional checking,  Prev: Union types,  Up: Kinds of types
+
+8.6 Optional types and the None type
+====================================
+
+You can use the Optional(1) type modifier to define a type variant that
+allows ‘None’, such as ‘Optional[int]’ (‘Optional[X]’ is the preferred
+shorthand for ‘Union[X, None]’):
+
+     from typing import Optional
+
+     def strlen(s: str) -> Optional[int]:
+         if not s:
+             return None  # OK
+         return len(s)
+
+     def strlen_invalid(s: str) -> int:
+         if not s:
+             return None  # Error: None not compatible with int
+         return len(s)
+
+Most operations will not be allowed on unguarded ‘None’ or Optional(2)
+values:
+
+     def my_inc(x: Optional[int]) -> int:
+         return x + 1  # Error: Cannot add None and int
+
+Instead, an explicit ‘None’ check is required.  Mypy has powerful type
+inference that lets you use regular Python idioms to guard against
+‘None’ values.  For example, mypy recognizes ‘is None’ checks:
+
+     def my_inc(x: Optional[int]) -> int:
+         if x is None:
+             return 0
+         else:
+             # The inferred type of x is just int here.
+             return x + 1
+
+Mypy will infer the type of ‘x’ to be ‘int’ in the else block due to the
+check against ‘None’ in the if condition.
+
+Other supported checks for guarding against a ‘None’ value include ‘if x
+is not None’, ‘if x’ and ‘if not x’.  Additionally, mypy understands
+‘None’ checks within logical expressions:
+
+     def concat(x: Optional[str], y: Optional[str]) -> Optional[str]:
+         if x is not None and y is not None:
+             # Both x and y are not None here
+             return x + y
+         else:
+             return None
+
+Sometimes mypy doesn’t realize that a value is never ‘None’.  This
+notably happens when a class instance can exist in a partially defined
+state, where some attribute is initialized to ‘None’ during object
+construction, but a method assumes that the attribute is no longer
+‘None’.  Mypy will complain about the possible ‘None’ value.  You can
+use ‘assert x is not None’ to work around this in the method:
+
+     class Resource:
+         path: Optional[str] = None
+
+         def initialize(self, path: str) -> None:
+             self.path = path
+
+         def read(self) -> str:
+             # We require that the object has been initialized.
+             assert self.path is not None
+             with open(self.path) as f:  # OK
+                return f.read()
+
+     r = Resource()
+     r.initialize('/foo/bar')
+     r.read()
+
+When initializing a variable as ‘None’, ‘None’ is usually an empty
+place-holder value, and the actual value has a different type.  This is
+why you need to annotate an attribute in cases like the class ‘Resource’
+above:
+
+     class Resource:
+         path: Optional[str] = None
+         ...
+
+This also works for attributes defined within methods:
+
+     class Counter:
+         def __init__(self) -> None:
+             self.count: Optional[int] = None
+
+As a special case, you can use a non-optional type when initializing an
+attribute to ‘None’ inside a class body `and' using a type comment,
+since when using a type comment, an initializer is syntactically
+required, and ‘None’ is used as a dummy, placeholder initializer:
+
+     class Container:
+         items = None  # type: list[str]  # OK (only with type comment)
+
+This is not a problem when using variable annotations, since no
+initializer is needed:
+
+     class Container:
+         items: list[str]  # No initializer
+
+Mypy generally uses the first assignment to a variable to infer the type
+of the variable.  However, if you assign both a ‘None’ value and a
+non-‘None’ value in the same scope, mypy can usually do the right thing
+without an annotation:
+
+     def f(i: int) -> None:
+         n = None  # Inferred type Optional[int] because of the assignment below
+         if i > 0:
+              n = i
+         ...
+
+Sometimes you may get the error “Cannot determine type of <something>”.
+In this case you should add an explicit ‘Optional[...]’ annotation (or
+type comment).
+
+     Note: ‘None’ is a type with only one value, ‘None’.  ‘None’ is also
+     used as the return type for functions that don’t return a value,
+     i.e.  functions that implicitly return ‘None’.
+
+     Note: The Python interpreter internally uses the name ‘NoneType’
+     for the type of ‘None’, but ‘None’ is always used in type
+     annotations.  The latter is shorter and reads better.  (Besides,
+     ‘NoneType’ is not even defined in the standard library.)
+
+     Note: ‘Optional[...]’ `does not' mean a function argument with a
+     default value.  However, if the default value of an argument is
+     ‘None’, you can use an optional type for the argument, but it’s not
+     enforced by default.  You can use the *note –no-implicit-optional:
+     6b. command-line option to stop treating arguments with a ‘None’
+     default value as having an implicit ‘Optional[...]’ type.  It’s
+     possible that this will become the default behavior in the future.
+
+* Menu:
+
+* X | Y syntax for Unions::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Optional
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Optional
+
+
+File: Mypy.info,  Node: X | Y syntax for Unions,  Up: Optional types and the None type
+
+8.6.1 X | Y syntax for Unions
+-----------------------------
+
+PEP 604(1) introduced an alternative way for spelling union types.  In
+Python 3.10 and later, you can write ‘Union[int, str]’ as ‘int | str’.
+It is possible to use this syntax in versions of Python where it isn’t
+supported by the runtime with some limitations (see *note Annotation
+issues at runtime: 6e.).
+
+     t1: int | str  # equivalent to Union[int, str]
+
+     t2: int | None  # equivalent to Optional[int]
+
+     # Usable in type comments
+     t3 = 42  # type: int | str
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0604/
+
+
+File: Mypy.info,  Node: Disabling strict optional checking,  Next: Type aliases,  Prev: Optional types and the None type,  Up: Kinds of types
+
+8.7 Disabling strict optional checking
+======================================
+
+Mypy also has an option to treat ‘None’ as a valid value for every type
+(in case you know Java, it’s useful to think of it as similar to the
+Java ‘null’).  In this mode ‘None’ is also valid for primitive types
+such as ‘int’ and ‘float’, and Optional(1) types are not required.
+
+The mode is enabled through the *note –no-strict-optional: 71.
+command-line option.  In mypy versions before 0.600 this was the default
+mode.  You can enable this option explicitly for backward compatibility
+with earlier mypy versions, in case you don’t want to introduce optional
+types to your codebase yet.
+
+It will cause mypy to silently accept some buggy code, such as this
+example – it’s not recommended if you can avoid it:
+
+     def inc(x: int) -> int:
+         return x + 1
+
+     x = inc(None)  # No error reported by mypy if strict optional mode disabled!
+
+However, making code “optional clean” can take some work!  You can also
+use *note the mypy configuration file: 2e. to migrate your code to
+strict optional checking one file at a time, since there exists the
+per-module flag *note strict_optional: 72. to control strict optional
+mode.
+
+Often it’s still useful to document whether a variable can be ‘None’.
+For example, this function accepts a ‘None’ argument, but it’s not
+obvious from its signature:
+
+     def greeting(name: str) -> str:
+         if name:
+             return 'Hello, {}'.format(name)
+         else:
+             return 'Hello, stranger'
+
+     print(greeting('Python'))  # Okay!
+     print(greeting(None))      # Also okay!
+
+You can still use Optional[t](2) to document that ‘None’ is a valid
+argument type, even if strict ‘None’ checking is not enabled:
+
+     from typing import Optional
+
+     def greeting(name: Optional[str]) -> str:
+         if name:
+             return 'Hello, {}'.format(name)
+         else:
+             return 'Hello, stranger'
+
+Mypy treats this as semantically equivalent to the previous example if
+strict optional checking is disabled, since ‘None’ is implicitly valid
+for any type, but it’s much more useful for a programmer who is reading
+the code.  This also makes it easier to migrate to strict ‘None’
+checking in the future.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Optional
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Optional
+
+
+File: Mypy.info,  Node: Type aliases,  Next: Named tuples,  Prev: Disabling strict optional checking,  Up: Kinds of types
+
+8.8 Type aliases
+================
+
+In certain situations, type names may end up being long and painful to
+type:
+
+     def f() -> Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]]:
+         ...
+
+When cases like this arise, you can define a type alias by simply
+assigning the type to a variable:
+
+     AliasType = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]]
+
+     # Now we can use AliasType in place of the full name:
+
+     def f() -> AliasType:
+         ...
+
+     Note: A type alias does not create a new type.  It’s just a
+     shorthand notation for another type – it’s equivalent to the target
+     type except for *note generic aliases: 75.
+
+Since Mypy 0.930 you can also use `explicit type aliases', which were
+introduced in PEP 613(1).
+
+There can be confusion about exactly when an assignment defines an
+implicit type alias – for example, when the alias contains forward
+references, invalid types, or violates some other restrictions on type
+alias declarations.  Because the distinction between an unannotated
+variable and a type alias is implicit, ambiguous or incorrect type alias
+declarations default to defining a normal variable instead of a type
+alias.
+
+Explicit type aliases are unambiguous and can also improve readability
+by making the intent clear:
+
+     from typing import TypeAlias  # "from typing_extensions" in Python 3.9 and earlier
+
+     AliasType: TypeAlias = Union[list[dict[tuple[int, str], set[int]]], tuple[str, list[str]]]
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0613/
+
+
+File: Mypy.info,  Node: Named tuples,  Next: The type of class objects,  Prev: Type aliases,  Up: Kinds of types
+
+8.9 Named tuples
+================
+
+Mypy recognizes named tuples and can type check code that defines or
+uses them.  In this example, we can detect code trying to access a
+missing attribute:
+
+     Point = namedtuple('Point', ['x', 'y'])
+     p = Point(x=1, y=2)
+     print(p.z)  # Error: Point has no attribute 'z'
+
+If you use namedtuple(1) to define your named tuple, all the items are
+assumed to have ‘Any’ types.  That is, mypy doesn’t know anything about
+item types.  You can use NamedTuple(2) to also define item types:
+
+     from typing import NamedTuple
+
+     Point = NamedTuple('Point', [('x', int),
+                                  ('y', int)])
+     p = Point(x=1, y='x')  # Argument has incompatible type "str"; expected "int"
+
+Python 3.6 introduced an alternative, class-based syntax for named
+tuples with types:
+
+     from typing import NamedTuple
+
+     class Point(NamedTuple):
+         x: int
+         y: int
+
+     p = Point(x=1, y='x')  # Argument has incompatible type "str"; expected "int"
+
+     Note: You can use the raw ‘NamedTuple’ “pseudo-class” in type
+     annotations if any ‘NamedTuple’ object is valid.
+
+     For example, it can be useful for deserialization:
+
+          def deserialize_named_tuple(arg: NamedTuple) -> Dict[str, Any]:
+              return arg._asdict()
+
+          Point = namedtuple('Point', ['x', 'y'])
+          Person = NamedTuple('Person', [('name', str), ('age', int)])
+
+          deserialize_named_tuple(Point(x=1, y=2))  # ok
+          deserialize_named_tuple(Person(name='Nikita', age=18))  # ok
+
+          # Error: Argument 1 to "deserialize_named_tuple" has incompatible type
+          # "Tuple[int, int]"; expected "NamedTuple"
+          deserialize_named_tuple((1, 2))
+
+     Note that this behavior is highly experimental, non-standard, and
+     may not be supported by other type checkers and IDEs.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/collections.html#collections.namedtuple
+
+   (2) https://docs.python.org/3/library/typing.html#typing.NamedTuple
+
+
+File: Mypy.info,  Node: The type of class objects,  Next: Text and AnyStr,  Prev: Named tuples,  Up: Kinds of types
+
+8.10 The type of class objects
+==============================
+
+(Freely after PEP 484: The type of class objects(1).)
+
+Sometimes you want to talk about class objects that inherit from a given
+class.  This can be spelled as Type[C](2) where ‘C’ is a class.  In
+other words, when ‘C’ is the name of a class, using ‘C’ to annotate an
+argument declares that the argument is an instance of ‘C’ (or of a
+subclass of ‘C’), but using Type[C](3) as an argument annotation
+declares that the argument is a class object deriving from ‘C’ (or ‘C’
+itself).
+
+For example, assume the following classes:
+
+     class User:
+         # Defines fields like name, email
+
+     class BasicUser(User):
+         def upgrade(self):
+             """Upgrade to Pro"""
+
+     class ProUser(User):
+         def pay(self):
+             """Pay bill"""
+
+Note that ‘ProUser’ doesn’t inherit from ‘BasicUser’.
+
+Here’s a function that creates an instance of one of these classes if
+you pass it the right class object:
+
+     def new_user(user_class):
+         user = user_class()
+         # (Here we could write the user object to a database)
+         return user
+
+How would we annotate this function?  Without Type(4) the best we could
+do would be:
+
+     def new_user(user_class: type) -> User:
+         # Same  implementation as before
+
+This seems reasonable, except that in the following example, mypy
+doesn’t see that the ‘buyer’ variable has type ‘ProUser’:
+
+     buyer = new_user(ProUser)
+     buyer.pay()  # Rejected, not a method on User
+
+However, using Type(5) and a type variable with an upper bound (see
+*note Type variables with upper bounds: 79.) we can do better:
+
+     U = TypeVar('U', bound=User)
+
+     def new_user(user_class: Type[U]) -> U:
+         # Same  implementation as before
+
+Now mypy will infer the correct type of the result when we call
+‘new_user()’ with a specific subclass of ‘User’:
+
+     beginner = new_user(BasicUser)  # Inferred type is BasicUser
+     beginner.upgrade()  # OK
+
+     Note: The value corresponding to Type[C](6) must be an actual class
+     object that’s a subtype of ‘C’.  Its constructor must be compatible
+     with the constructor of ‘C’.  If ‘C’ is a type variable, its upper
+     bound must be a class object.
+
+For more details about ‘Type[]’ see PEP 484: The type of class
+objects(7).
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/#the-type-of-class-objects
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Type
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Type
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Type
+
+   (5) https://docs.python.org/3/library/typing.html#typing.Type
+
+   (6) https://docs.python.org/3/library/typing.html#typing.Type
+
+   (7) https://peps.python.org/pep-0484/#the-type-of-class-objects
+
+
+File: Mypy.info,  Node: Text and AnyStr,  Next: Generators,  Prev: The type of class objects,  Up: Kinds of types
+
+8.11 Text and AnyStr
+====================
+
+Sometimes you may want to write a function which will accept only
+unicode strings.  This can be challenging to do in a codebase intended
+to run in both Python 2 and Python 3 since ‘str’ means something
+different in both versions and ‘unicode’ is not a keyword in Python 3.
+
+To help solve this issue, use Text(1) which is aliased to ‘unicode’ in
+Python 2 and to ‘str’ in Python 3.  This allows you to indicate that a
+function should accept only unicode strings in a cross-compatible way:
+
+     from typing import Text
+
+     def unicode_only(s: Text) -> Text:
+         return s + u'\u2713'
+
+In other cases, you may want to write a function that will work with any
+kind of string but will not let you mix two different string types.  To
+do so use AnyStr(2):
+
+     from typing import AnyStr
+
+     def concat(x: AnyStr, y: AnyStr) -> AnyStr:
+         return x + y
+
+     concat('foo', 'foo')     # Okay
+     concat(b'foo', b'foo')   # Okay
+     concat('foo', b'foo')    # Error: cannot mix bytes and unicode
+
+For more details, see *note Type variables with value restriction: 7c.
+
+     Note: How ‘bytes’, ‘str’, and ‘unicode’ are handled between Python
+     2 and Python 3 may change in future versions of mypy.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Text
+
+   (2) https://docs.python.org/3/library/typing.html#typing.AnyStr
+
+
+File: Mypy.info,  Node: Generators,  Prev: Text and AnyStr,  Up: Kinds of types
+
+8.12 Generators
+===============
+
+A basic generator that only yields values can be succinctly annotated as
+having a return type of either Iterator[YieldType](1) or
+Iterable[YieldType](2).  For example:
+
+     def squares(n: int) -> Iterator[int]:
+         for i in range(n):
+             yield i * i
+
+A good rule of thumb is to annotate functions with the most specific
+return type possible.  However, you should also take care to avoid
+leaking implementation details into a function’s public API. In keeping
+with these two principles, prefer Iterator[YieldType](3) over
+Iterable[YieldType](4) as the return-type annotation for a generator
+function, as it lets mypy know that users are able to call next()(5) on
+the object returned by the function.  Nonetheless, bear in mind that
+‘Iterable’ may sometimes be the better option, if you consider it an
+implementation detail that ‘next()’ can be called on the object returned
+by your function.
+
+If you want your generator to accept values via the send()(6) method or
+return a value, on the other hand, you should use the
+Generator[YieldType, SendType, ReturnType](7) generic type instead of
+either ‘Iterator’ or ‘Iterable’.  For example:
+
+     def echo_round() -> Generator[int, float, str]:
+         sent = yield 0
+         while sent >= 0:
+             sent = yield round(sent)
+         return 'Done'
+
+Note that unlike many other generics in the typing module, the
+‘SendType’ of Generator(8) behaves contravariantly, not covariantly or
+invariantly.
+
+If you do not plan on receiving or returning values, then set the
+‘SendType’ or ‘ReturnType’ to ‘None’, as appropriate.  For example, we
+could have annotated the first example as the following:
+
+     def squares(n: int) -> Generator[int, None, None]:
+         for i in range(n):
+             yield i * i
+
+This is slightly different from using ‘Iterator[int]’ or
+‘Iterable[int]’, since generators have close()(9), send()(10), and
+throw()(11) methods that generic iterators and iterables don’t.  If you
+plan to call these methods on the returned generator, use the
+Generator(12) type instead of Iterator(13) or Iterable(14).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Iterator
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Iterator
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (5) https://docs.python.org/3/library/functions.html#next
+
+   (6) 
+https://docs.python.org/3/reference/expressions.html#generator.send
+
+   (7) https://docs.python.org/3/library/typing.html#typing.Generator
+
+   (8) https://docs.python.org/3/library/typing.html#typing.Generator
+
+   (9) 
+https://docs.python.org/3/reference/expressions.html#generator.close
+
+   (10) 
+https://docs.python.org/3/reference/expressions.html#generator.send
+
+   (11) 
+https://docs.python.org/3/reference/expressions.html#generator.throw
+
+   (12) https://docs.python.org/3/library/typing.html#typing.Generator
+
+   (13) https://docs.python.org/3/library/typing.html#typing.Iterator
+
+   (14) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+
+File: Mypy.info,  Node: Class basics,  Next: Annotation issues at runtime,  Prev: Kinds of types,  Up: Top
+
+9 Class basics
+**************
+
+This section will help get you started annotating your classes.
+Built-in classes such as ‘int’ also follow these same rules.
+
+* Menu:
+
+* Instance and class attributes::
+* Annotating __init__ methods::
+* Class attribute annotations::
+* Overriding statically typed methods::
+* Abstract base classes and multiple inheritance::
+* Slots::
+
+
+File: Mypy.info,  Node: Instance and class attributes,  Next: Annotating __init__ methods,  Up: Class basics
+
+9.1 Instance and class attributes
+=================================
+
+The mypy type checker detects if you are trying to access a missing
+attribute, which is a very common programming error.  For this to work
+correctly, instance and class attributes must be defined or initialized
+within the class.  Mypy infers the types of attributes:
+
+     class A:
+         def __init__(self, x: int) -> None:
+             self.x = x  # Aha, attribute 'x' of type 'int'
+
+     a = A(1)
+     a.x = 2  # OK!
+     a.y = 3  # Error: "A" has no attribute "y"
+
+This is a bit like each class having an implicitly defined __slots__(1)
+attribute.  This is only enforced during type checking and not when your
+program is running.
+
+You can declare types of variables in the class body explicitly using a
+type annotation:
+
+     class A:
+         x: list[int]  # Declare attribute 'x' of type list[int]
+
+     a = A()
+     a.x = [1]     # OK
+
+As in Python generally, a variable defined in the class body can be used
+as a class or an instance variable.  (As discussed in the next section,
+you can override this with a ClassVar(2) annotation.)
+
+Type comments work as well, if you need to support Python versions
+earlier than 3.6:
+
+     class A:
+         x = None  # type: list[int]  # Declare attribute 'x' of type list[int]
+
+Note that attribute definitions in the class body that use a type
+comment are special: a ‘None’ value is valid as the initializer, even
+though the declared type is not optional.  This should be used
+sparingly, as this can result in ‘None’-related runtime errors that mypy
+can’t detect.
+
+Similarly, you can give explicit types to instance variables defined in
+a method:
+
+     class A:
+         def __init__(self) -> None:
+             self.x: list[int] = []
+
+         def f(self) -> None:
+             self.y: Any = 0
+
+You can only define an instance variable within a method if you assign
+to it explicitly using ‘self’:
+
+     class A:
+         def __init__(self) -> None:
+             self.y = 1   # Define 'y'
+             a = self
+             a.x = 1      # Error: 'x' not defined
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__slots__
+
+   (2) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+
+File: Mypy.info,  Node: Annotating __init__ methods,  Next: Class attribute annotations,  Prev: Instance and class attributes,  Up: Class basics
+
+9.2 Annotating __init__ methods
+===============================
+
+The __init__(1) method is somewhat special – it doesn’t return a value.
+This is best expressed as ‘-> None’.  However, since many feel this is
+redundant, it is allowed to omit the return type declaration on
+__init__(2) methods `if at least one argument is annotated'.  For
+example, in the following classes __init__(3) is considered fully
+annotated:
+
+     class C1:
+         def __init__(self) -> None:
+             self.var = 42
+
+     class C2:
+         def __init__(self, arg: int):
+             self.var = arg
+
+However, if __init__(4) has no annotated arguments and no return type
+annotation, it is considered an untyped method:
+
+     class C3:
+         def __init__(self):
+             # This body is not type checked
+             self.var = 42 + 'abc'
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (2) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (3) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (4) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+
+File: Mypy.info,  Node: Class attribute annotations,  Next: Overriding statically typed methods,  Prev: Annotating __init__ methods,  Up: Class basics
+
+9.3 Class attribute annotations
+===============================
+
+You can use a ClassVar[t](1) annotation to explicitly declare that a
+particular attribute should not be set on instances:
+
+     from typing import ClassVar
+
+     class A:
+         x: ClassVar[int] = 0  # Class variable only
+
+     A.x += 1  # OK
+
+     a = A()
+     a.x = 1  # Error: Cannot assign to class variable "x" via instance
+     print(a.x)  # OK -- can be read through an instance
+
+It’s not necessary to annotate all class variables using ClassVar(2).
+An attribute without the ClassVar(3) annotation can still be used as a
+class variable.  However, mypy won’t prevent it from being used as an
+instance variable, as discussed previously:
+
+     class A:
+         x = 0  # Can be used as a class or instance variable
+
+     A.x += 1  # OK
+
+     a = A()
+     a.x = 1  # Also OK
+
+Note that ClassVar(4) is not a class, and you can’t use it with
+isinstance()(5) or issubclass()(6).  It does not change Python runtime
+behavior – it’s only for type checkers such as mypy (and also helpful
+for human readers).
+
+You can also omit the square brackets and the variable type in a
+ClassVar(7) annotation, but this might not do what you’d expect:
+
+     class A:
+         y: ClassVar = 0  # Type implicitly Any!
+
+In this case the type of the attribute will be implicitly ‘Any’.  This
+behavior will change in the future, since it’s surprising.
+
+     Note: A ClassVar(8) type parameter cannot include type variables:
+     ‘ClassVar[T]’ and ‘ClassVar[list[T]]’ are both invalid if ‘T’ is a
+     type variable (see *note Defining generic classes: 84. for more
+     about type variables).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+   (2) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+   (3) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+   (4) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+   (5) https://docs.python.org/3/library/functions.html#isinstance
+
+   (6) https://docs.python.org/3/library/functions.html#issubclass
+
+   (7) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+   (8) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+
+File: Mypy.info,  Node: Overriding statically typed methods,  Next: Abstract base classes and multiple inheritance,  Prev: Class attribute annotations,  Up: Class basics
+
+9.4 Overriding statically typed methods
+=======================================
+
+When overriding a statically typed method, mypy checks that the override
+has a compatible signature:
+
+     class Base:
+         def f(self, x: int) -> None:
+             ...
+
+     class Derived1(Base):
+         def f(self, x: str) -> None:   # Error: type of 'x' incompatible
+             ...
+
+     class Derived2(Base):
+         def f(self, x: int, y: int) -> None:  # Error: too many arguments
+             ...
+
+     class Derived3(Base):
+         def f(self, x: int) -> None:   # OK
+             ...
+
+     class Derived4(Base):
+         def f(self, x: float) -> None:   # OK: mypy treats int as a subtype of float
+             ...
+
+     class Derived5(Base):
+         def f(self, x: int, y: int = 0) -> None:   # OK: accepts more than the base
+             ...                                    #     class method
+
+     Note: You can also vary return types `covariantly' in overriding.
+     For example, you could override the return type ‘Iterable[int]’
+     with a subtype such as ‘list[int]’.  Similarly, you can vary
+     argument types `contravariantly' – subclasses can have more general
+     argument types.
+
+You can also override a statically typed method with a dynamically typed
+one.  This allows dynamically typed code to override methods defined in
+library classes without worrying about their type signatures.
+
+As always, relying on dynamically typed code can be unsafe.  There is no
+runtime enforcement that the method override returns a value that is
+compatible with the original return type, since annotations have no
+effect at runtime:
+
+     class Base:
+         def inc(self, x: int) -> int:
+             return x + 1
+
+     class Derived(Base):
+         def inc(self, x):   # Override, dynamically typed
+             return 'hello'  # Incompatible with 'Base', but no mypy error
+
+
+File: Mypy.info,  Node: Abstract base classes and multiple inheritance,  Next: Slots,  Prev: Overriding statically typed methods,  Up: Class basics
+
+9.5 Abstract base classes and multiple inheritance
+==================================================
+
+Mypy supports Python abstract base classes(1) (ABCs).  Abstract classes
+have at least one abstract method or property that must be implemented
+by any `concrete' (non-abstract) subclass.  You can define abstract base
+classes using the abc.ABCMeta(2) metaclass and the
+@abc.abstractmethod(3) function decorator.  Example:
+
+     from abc import ABCMeta, abstractmethod
+
+     class Animal(metaclass=ABCMeta):
+         @abstractmethod
+         def eat(self, food: str) -> None: pass
+
+         @property
+         @abstractmethod
+         def can_walk(self) -> bool: pass
+
+     class Cat(Animal):
+         def eat(self, food: str) -> None:
+             ...  # Body omitted
+
+         @property
+         def can_walk(self) -> bool:
+             return True
+
+     x = Animal()  # Error: 'Animal' is abstract due to 'eat' and 'can_walk'
+     y = Cat()     # OK
+
+     Note: In Python 2.7 you have to use @abc.abstractproperty(4) to
+     define an abstract property.
+
+Note that mypy performs checking for unimplemented abstract methods even
+if you omit the ABCMeta(5) metaclass.  This can be useful if the
+metaclass would cause runtime metaclass conflicts.
+
+Since you can’t create instances of ABCs, they are most commonly used in
+type annotations.  For example, this method accepts arbitrary iterables
+containing arbitrary animals (instances of concrete ‘Animal’
+subclasses):
+
+     def feed_all(animals: Iterable[Animal], food: str) -> None:
+         for animal in animals:
+             animal.eat(food)
+
+There is one important peculiarity about how ABCs work in Python –
+whether a particular class is abstract or not is somewhat implicit.  In
+the example below, ‘Derived’ is treated as an abstract base class since
+‘Derived’ inherits an abstract ‘f’ method from ‘Base’ and doesn’t
+explicitly implement it.  The definition of ‘Derived’ generates no
+errors from mypy, since it’s a valid ABC:
+
+     from abc import ABCMeta, abstractmethod
+
+     class Base(metaclass=ABCMeta):
+         @abstractmethod
+         def f(self, x: int) -> None: pass
+
+     class Derived(Base):  # No error -- Derived is implicitly abstract
+         def g(self) -> None:
+             ...
+
+Attempting to create an instance of ‘Derived’ will be rejected, however:
+
+     d = Derived()  # Error: 'Derived' is abstract
+
+     Note: It’s a common error to forget to implement an abstract
+     method.  As shown above, the class definition will not generate an
+     error in this case, but any attempt to construct an instance will
+     be flagged as an error.
+
+A class can inherit any number of classes, both abstract and concrete.
+As with normal overrides, a dynamically typed method can override or
+implement a statically typed method defined in any base class, including
+an abstract method defined in an abstract base class.
+
+You can implement an abstract property using either a normal property or
+an instance variable.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/abc.html
+
+   (2) https://docs.python.org/3/library/abc.html#abc.ABCMeta
+
+   (3) https://docs.python.org/3/library/abc.html#abc.abstractmethod
+
+   (4) https://docs.python.org/3/library/abc.html#abc.abstractproperty
+
+   (5) https://docs.python.org/3/library/abc.html#abc.ABCMeta
+
+
+File: Mypy.info,  Node: Slots,  Prev: Abstract base classes and multiple inheritance,  Up: Class basics
+
+9.6 Slots
+=========
+
+When a class has explicitly defined __slots__(1), mypy will check that
+all attributes assigned to are members of ‘__slots__’:
+
+     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)
+
+Mypy will only check attribute assignments against ‘__slots__’ when the
+following conditions hold:
+
+  1. All base classes (except builtin ones) must have explicit
+     ‘__slots__’ defined (this mirrors Python semantics).
+
+  2. ‘__slots__’ does not include ‘__dict__’.  If ‘__slots__’ includes
+     ‘__dict__’, arbitrary attributes can be set, similar to when
+     ‘__slots__’ is not defined (this mirrors Python semantics).
+
+  3. All values in ‘__slots__’ must be string literals.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/reference/datamodel.html#slots
+
+
+File: Mypy.info,  Node: Annotation issues at runtime,  Next: Protocols and structural subtyping,  Prev: Class basics,  Up: Top
+
+10 Annotation issues at runtime
+*******************************
+
+Idiomatic use of type annotations can sometimes run up against what a
+given version of Python considers legal code.  This section describes
+these scenarios and explains how to get your code running again.
+Generally speaking, we have three tools at our disposal:
+
+   * For Python 3.7 through 3.9, use of ‘from __future__ import
+     annotations’ ( PEP 563(1)), made the default in Python 3.11 and
+     later
+
+   * Use of string literal types or type comments
+
+   * Use of ‘typing.TYPE_CHECKING’
+
+We provide a description of these before moving onto discussion of
+specific problems you may encounter.
+
+* Menu:
+
+* String literal types::
+* Future annotations import (PEP 563): Future annotations import PEP 563.
+* typing.TYPE_CHECKING: typing TYPE_CHECKING.
+* Class name forward references::
+* Import cycles::
+* Using classes that are generic in stubs but not at runtime::
+* Using types defined in stubs but not at runtime::
+* Using generic builtins::
+* Using X | Y syntax for Unions::
+* Using new additions to the typing module::
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0563/
+
+
+File: Mypy.info,  Node: String literal types,  Next: Future annotations import PEP 563,  Up: Annotation issues at runtime
+
+10.1 String literal types
+=========================
+
+Type comments can’t cause runtime errors because comments are not
+evaluated by Python.  In a similar way, using string literal types
+sidesteps the problem of annotations that would cause runtime errors.
+
+Any type can be entered as a string literal, and you can combine
+string-literal types with non-string-literal types freely:
+
+     def f(a: list['A']) -> None: ...  # OK
+     def g(n: 'int') -> None: ...      # OK, though not useful
+
+     class A: pass
+
+String literal types are never needed in ‘# type:’ comments and *note
+stub files: 16.
+
+String literal types must be defined (or imported) later `in the same
+module'.  They cannot be used to leave cross-module references
+unresolved.  (For dealing with import cycles, see *note Import cycles:
+8c.)
+
+
+File: Mypy.info,  Node: Future annotations import PEP 563,  Next: typing TYPE_CHECKING,  Prev: String literal types,  Up: Annotation issues at runtime
+
+10.2 Future annotations import (PEP 563)
+========================================
+
+Many of the issues described here are caused by Python trying to
+evaluate annotations.  From Python 3.11 on, Python will no longer
+attempt to evaluate function and variable annotations.  This behaviour
+is made available in Python 3.7 and later through the use of ‘from
+__future__ import annotations’.
+
+This can be thought of as automatic string literal-ification of all
+function and variable annotations.  Note that function and variable
+annotations are still required to be valid Python syntax.  For more
+details, see PEP 563(1).
+
+     Note: Even with the ‘__future__’ import, there are some scenarios
+     that could still require string literals or result in errors,
+     typically involving use of forward references or generics in:
+
+        * *note type aliases: 74.;
+
+        * *note type narrowing: 8f.;
+
+        * type definitions (see TypeVar(2), ‘NewType()’, NamedTuple(3));
+
+        * base classes.
+
+          # base class example
+          from __future__ import annotations
+          class A(tuple['B', 'C']): ... # String literal types needed here
+          class B: ...
+          class C: ...
+
+     Note: Some libraries may have use cases for dynamic evaluation of
+     annotations, for instance, through use of ‘typing.get_type_hints’
+     or ‘eval’.  If your annotation would raise an error when evaluated
+     (say by using PEP 604(4) syntax with Python 3.9), you may need to
+     be careful when using such libraries.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0563/
+
+   (2) https://docs.python.org/3/library/typing.html#typing.TypeVar
+
+   (3) https://docs.python.org/3/library/typing.html#typing.NamedTuple
+
+   (4) https://peps.python.org/pep-0604/
+
+
+File: Mypy.info,  Node: typing TYPE_CHECKING,  Next: Class name forward references,  Prev: Future annotations import PEP 563,  Up: Annotation issues at runtime
+
+10.3 typing.TYPE_CHECKING
+=========================
+
+The typing(1) module defines a TYPE_CHECKING(2) constant that is ‘False’
+at runtime but treated as ‘True’ while type checking.
+
+Since code inside ‘if TYPE_CHECKING:’ is not executed at runtime, it
+provides a convenient way to tell mypy something without the code being
+evaluated at runtime.  This is most useful for resolving *note import
+cycles: 8c.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+   (2) 
+https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
+
+
+File: Mypy.info,  Node: Class name forward references,  Next: Import cycles,  Prev: typing TYPE_CHECKING,  Up: Annotation issues at runtime
+
+10.4 Class name forward references
+==================================
+
+Python does not allow references to a class object before the class is
+defined (aka forward reference).  Thus this code does not work as
+expected:
+
+     def f(x: A) -> None: ...  # NameError: name "A" is not defined
+     class A: ...
+
+Starting from Python 3.7, you can add ‘from __future__ import
+annotations’ to resolve this, as discussed earlier:
+
+     from __future__ import annotations
+
+     def f(x: A) -> None: ...  # OK
+     class A: ...
+
+For Python 3.6 and below, you can enter the type as a string literal or
+type comment:
+
+     def f(x: 'A') -> None: ...  # OK
+
+     # Also OK
+     def g(x):  # type: (A) -> None
+         ...
+
+     class A: ...
+
+Of course, instead of using future annotations import or string literal
+types, you could move the function definition after the class
+definition.  This is not always desirable or even possible, though.
+
+
+File: Mypy.info,  Node: Import cycles,  Next: Using classes that are generic in stubs but not at runtime,  Prev: Class name forward references,  Up: Annotation issues at runtime
+
+10.5 Import cycles
+==================
+
+An import cycle occurs where module A imports module B and module B
+imports module A (perhaps indirectly, e.g.  ‘A -> B -> C -> A’).
+Sometimes in order to add type annotations you have to add extra imports
+to a module and those imports cause cycles that didn’t exist before.
+This can lead to errors at runtime like:
+
+     ImportError: cannot import name 'b' from partially initialized module 'A' (most likely due to a circular import)
+
+If those cycles do become a problem when running your program, there’s a
+trick: if the import is only needed for type annotations and you’re
+using a) the *note future annotations import: 8d, or b) string literals
+or type comments for the relevant annotations, you can write the imports
+inside ‘if TYPE_CHECKING:’ so that they are not executed at runtime.
+Example:
+
+File ‘foo.py’:
+
+     from typing import TYPE_CHECKING
+
+     if TYPE_CHECKING:
+         import bar
+
+     def listify(arg: 'bar.BarClass') -> 'list[bar.BarClass]':
+         return [arg]
+
+File ‘bar.py’:
+
+     from foo import listify
+
+     class BarClass:
+         def listifyme(self) -> 'list[BarClass]':
+             return listify(self)
+
+
+File: Mypy.info,  Node: Using classes that are generic in stubs but not at runtime,  Next: Using types defined in stubs but not at runtime,  Prev: Import cycles,  Up: Annotation issues at runtime
+
+10.6 Using classes that are generic in stubs but not at runtime
+===============================================================
+
+Some classes are declared as *note generic: 84. in stubs, but not at
+runtime.
+
+In Python 3.8 and earlier, there are several examples within the
+standard library, for instance, os.PathLike(1) and queue.Queue(2).
+Subscripting such a class will result in a runtime error:
+
+     from queue import Queue
+
+     class Tasks(Queue[str]):  # TypeError: 'type' object is not subscriptable
+         ...
+
+     results: Queue[int] = Queue()  # TypeError: 'type' object is not subscriptable
+
+To avoid errors from use of these generics in annotations, just use the
+*note future annotations import: 8d. (or string literals or type
+comments for Python 3.6 and below).
+
+To avoid errors when inheriting from these classes, things are a little
+more complicated and you need to use *note typing.TYPE_CHECKING: 91.:
+
+     from typing import TYPE_CHECKING
+     from queue import Queue
+
+     if TYPE_CHECKING:
+         BaseQueue = Queue[str]  # this is only processed by mypy
+     else:
+         BaseQueue = Queue  # this is not seen by mypy but will be executed at runtime
+
+     class Tasks(BaseQueue):  # OK
+         ...
+
+     task_queue: Tasks
+     reveal_type(task_queue.get())  # Reveals str
+
+If your subclass is also generic, you can use the following:
+
+     from typing import TYPE_CHECKING, TypeVar, Generic
+     from queue import Queue
+
+     _T = TypeVar("_T")
+     if TYPE_CHECKING:
+         class _MyQueueBase(Queue[_T]): pass
+     else:
+         class _MyQueueBase(Generic[_T], Queue): pass
+
+     class MyQueue(_MyQueueBase[_T]): pass
+
+     task_queue: MyQueue[str]
+     reveal_type(task_queue.get())  # Reveals str
+
+In Python 3.9, we can just inherit directly from ‘Queue[str]’ or
+‘Queue[T]’ since its queue.Queue(3) implements ‘__class_getitem__()’, so
+the class object can be subscripted at runtime without issue.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/os.html#os.PathLike
+
+   (2) https://docs.python.org/3/library/queue.html#queue.Queue
+
+   (3) https://docs.python.org/3/library/queue.html#queue.Queue
+
+
+File: Mypy.info,  Node: Using types defined in stubs but not at runtime,  Next: Using generic builtins,  Prev: Using classes that are generic in stubs but not at runtime,  Up: Annotation issues at runtime
+
+10.7 Using types defined in stubs but not at runtime
+====================================================
+
+Sometimes stubs that you’re using may define types you wish to re-use
+that do not exist at runtime.  Importing these types naively will cause
+your code to fail at runtime with ‘ImportError’ or
+‘ModuleNotFoundError’.  Similar to previous sections, these can be dealt
+with by using *note typing.TYPE_CHECKING: 91.:
+
+     from typing import TYPE_CHECKING
+     if TYPE_CHECKING:
+         from _typeshed import SupportsLessThan
+
+
+File: Mypy.info,  Node: Using generic builtins,  Next: Using X | Y syntax for Unions,  Prev: Using types defined in stubs but not at runtime,  Up: Annotation issues at runtime
+
+10.8 Using generic builtins
+===========================
+
+Starting with Python 3.9 ( PEP 585(1)), the type objects of many
+collections in the standard library support subscription at runtime.
+This means that you no longer have to import the equivalents from
+typing(2); you can simply use the built-in collections or those from
+collections.abc(3):
+
+     from collections.abc import Sequence
+     x: list[str]
+     y: dict[int, str]
+     z: Sequence[str] = x
+
+There is limited support for using this syntax in Python 3.7 and later
+as well.  If you use ‘from __future__ import annotations’, mypy will
+understand this syntax in annotations.  However, since this will not be
+supported by the Python interpreter at runtime, make sure you’re aware
+of the caveats mentioned in the notes at *note future annotations
+import: 8d.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0585/
+
+   (2) https://docs.python.org/3/library/typing.html#module-typing
+
+   (3) 
+https://docs.python.org/3/library/collections.abc.html#module-collections.abc
+
+
+File: Mypy.info,  Node: Using X | Y syntax for Unions,  Next: Using new additions to the typing module,  Prev: Using generic builtins,  Up: Annotation issues at runtime
+
+10.9 Using X | Y syntax for Unions
+==================================
+
+Starting with Python 3.10 ( PEP 604(1)), you can spell union types as
+‘x: int | str’, instead of ‘x: typing.Union[int, str]’.
+
+There is limited support for using this syntax in Python 3.7 and later
+as well.  If you use ‘from __future__ import annotations’, mypy will
+understand this syntax in annotations, string literal types, type
+comments and stub files.  However, since this will not be supported by
+the Python interpreter at runtime (if evaluated, ‘int | str’ will raise
+‘TypeError: unsupported operand type(s) for |: 'type' and 'type'’), make
+sure you’re aware of the caveats mentioned in the notes at *note future
+annotations import: 8d.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0604/
+
+
+File: Mypy.info,  Node: Using new additions to the typing module,  Prev: Using X | Y syntax for Unions,  Up: Annotation issues at runtime
+
+10.10 Using new additions to the typing module
+==============================================
+
+You may find yourself wanting to use features added to the typing(1)
+module in earlier versions of Python than the addition, for example,
+using any of ‘Literal’, ‘Protocol’, ‘TypedDict’ with Python 3.6.
+
+The easiest way to do this is to install and use the ‘typing_extensions’
+package from PyPI for the relevant imports, for example:
+
+     from typing_extensions import Literal
+     x: Literal["open", "close"]
+
+If you don’t want to rely on ‘typing_extensions’ being installed on
+newer Pythons, you could alternatively use:
+
+     import sys
+     if sys.version_info >= (3, 8):
+         from typing import Literal
+     else:
+         from typing_extensions import Literal
+
+     x: Literal["open", "close"]
+
+This plays nicely well with following PEP 508(2) dependency
+specification: ‘typing_extensions; python_version<"3.8"’
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+   (2) https://peps.python.org/pep-0508/
+
+
+File: Mypy.info,  Node: Protocols and structural subtyping,  Next: Dynamically typed code,  Prev: Annotation issues at runtime,  Up: Top
+
+11 Protocols and structural subtyping
+*************************************
+
+Mypy supports two ways of deciding whether two classes are compatible as
+types: nominal subtyping and structural subtyping.  `Nominal' subtyping
+is strictly based on the class hierarchy.  If class ‘D’ inherits class
+‘C’, it’s also a subtype of ‘C’, and instances of ‘D’ can be used when
+‘C’ instances are expected.  This form of subtyping is used by default
+in mypy, since it’s easy to understand and produces clear and concise
+error messages, and since it matches how the native isinstance(1) check
+works – based on class hierarchy.  `Structural' subtyping can also be
+useful.  Class ‘D’ is a structural subtype of class ‘C’ if the former
+has all attributes and methods of the latter, and with compatible types.
+
+Structural subtyping can be seen as a static equivalent of duck typing,
+which is well known to Python programmers.  Mypy provides support for
+structural subtyping via protocol classes described below.  See PEP
+544(2) for the detailed specification of protocols and structural
+subtyping in Python.
+
+* Menu:
+
+* Predefined protocols::
+* Simple user-defined protocols::
+* Defining subprotocols and subclassing protocols::
+* Recursive protocols::
+* Using isinstance() with protocols: Using isinstance with protocols.
+* Callback protocols::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+   (2) https://peps.python.org/pep-0544/
+
+
+File: Mypy.info,  Node: Predefined protocols,  Next: Simple user-defined protocols,  Up: Protocols and structural subtyping
+
+11.1 Predefined protocols
+=========================
+
+The typing(1) module defines various protocol classes that correspond to
+common Python protocols, such as Iterable[T](2). If a class defines a
+suitable __iter__(3) method, mypy understands that it implements the
+iterable protocol and is compatible with Iterable[T](4). For example,
+‘IntList’ below is iterable, over ‘int’ values:
+
+     from typing import Iterator, Iterable, Optional
+
+     class IntList:
+         def __init__(self, value: int, next: Optional['IntList']) -> None:
+             self.value = value
+             self.next = next
+
+         def __iter__(self) -> Iterator[int]:
+             current = self
+             while current:
+                 yield current.value
+                 current = current.next
+
+     def print_numbered(items: Iterable[int]) -> None:
+         for n, x in enumerate(items):
+             print(n + 1, x)
+
+     x = IntList(3, IntList(5, None))
+     print_numbered(x)  # OK
+     print_numbered([4, 5])  # Also OK
+
+The subsections below introduce all built-in protocols defined in
+typing(5) and the signatures of the corresponding methods you need to
+define to implement each protocol (the signatures can be left out, as
+always, but mypy won’t type check unannotated methods).
+
+* Menu:
+
+* Iteration protocols::
+* Collection protocols::
+* One-off protocols::
+* Async protocols::
+* Context manager protocols::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (3) 
+https://docs.python.org/3/reference/datamodel.html#object.__iter__
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (5) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Iteration protocols,  Next: Collection protocols,  Up: Predefined protocols
+
+11.1.1 Iteration protocols
+--------------------------
+
+The iteration protocols are useful in many contexts.  For example, they
+allow iteration of objects in for loops.
+
+* Menu:
+
+* Iterable[T]::
+* Iterator[T]::
+
+
+File: Mypy.info,  Node: Iterable[T],  Next: Iterator[T],  Up: Iteration protocols
+
+11.1.1.1 Iterable[T]
+....................
+
+The *note example above: 9d. has a simple implementation of an
+__iter__(1) method.
+
+     def __iter__(self) -> Iterator[T]
+
+See also Iterable(2).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__iter__
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+
+File: Mypy.info,  Node: Iterator[T],  Prev: Iterable[T],  Up: Iteration protocols
+
+11.1.1.2 Iterator[T]
+....................
+
+     def __next__(self) -> T
+     def __iter__(self) -> Iterator[T]
+
+See also Iterator(1).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Iterator
+
+
+File: Mypy.info,  Node: Collection protocols,  Next: One-off protocols,  Prev: Iteration protocols,  Up: Predefined protocols
+
+11.1.2 Collection protocols
+---------------------------
+
+Many of these are implemented by built-in container types such as
+list(1) and dict(2), and these are also useful for user-defined
+collection objects.
+
+* Menu:
+
+* Sized::
+* Container[T]::
+* Collection[T]::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#list
+
+   (2) https://docs.python.org/3/library/stdtypes.html#dict
+
+
+File: Mypy.info,  Node: Sized,  Next: Container[T],  Up: Collection protocols
+
+11.1.2.1 Sized
+..............
+
+This is a type for objects that support len(x)(1).
+
+     def __len__(self) -> int
+
+See also Sized(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#len
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Sized
+
+
+File: Mypy.info,  Node: Container[T],  Next: Collection[T],  Prev: Sized,  Up: Collection protocols
+
+11.1.2.2 Container[T]
+.....................
+
+This is a type for objects that support the ‘in’ operator.
+
+     def __contains__(self, x: object) -> bool
+
+See also Container(1).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Container
+
+
+File: Mypy.info,  Node: Collection[T],  Prev: Container[T],  Up: Collection protocols
+
+11.1.2.3 Collection[T]
+......................
+
+     def __len__(self) -> int
+     def __iter__(self) -> Iterator[T]
+     def __contains__(self, x: object) -> bool
+
+See also Collection(1).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Collection
+
+
+File: Mypy.info,  Node: One-off protocols,  Next: Async protocols,  Prev: Collection protocols,  Up: Predefined protocols
+
+11.1.3 One-off protocols
+------------------------
+
+These protocols are typically only useful with a single standard library
+function or class.
+
+* Menu:
+
+* Reversible[T]::
+* SupportsAbs[T]::
+* SupportsBytes::
+* SupportsComplex::
+* SupportsFloat::
+* SupportsInt::
+* SupportsRound[T]::
+
+
+File: Mypy.info,  Node: Reversible[T],  Next: SupportsAbs[T],  Up: One-off protocols
+
+11.1.3.1 Reversible[T]
+......................
+
+This is a type for objects that support reversed(x)(1).
+
+     def __reversed__(self) -> Iterator[T]
+
+See also Reversible(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#reversed
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Reversible
+
+
+File: Mypy.info,  Node: SupportsAbs[T],  Next: SupportsBytes,  Prev: Reversible[T],  Up: One-off protocols
+
+11.1.3.2 SupportsAbs[T]
+.......................
+
+This is a type for objects that support abs(x)(1).  ‘T’ is the type of
+value returned by abs(x)(2).
+
+     def __abs__(self) -> T
+
+See also SupportsAbs(3).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#abs
+
+   (2) https://docs.python.org/3/library/functions.html#abs
+
+   (3) https://docs.python.org/3/library/typing.html#typing.SupportsAbs
+
+
+File: Mypy.info,  Node: SupportsBytes,  Next: SupportsComplex,  Prev: SupportsAbs[T],  Up: One-off protocols
+
+11.1.3.3 SupportsBytes
+......................
+
+This is a type for objects that support bytes(x)(1).
+
+     def __bytes__(self) -> bytes
+
+See also SupportsBytes(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#bytes
+
+   (2) 
+https://docs.python.org/3/library/typing.html#typing.SupportsBytes
+
+
+File: Mypy.info,  Node: SupportsComplex,  Next: SupportsFloat,  Prev: SupportsBytes,  Up: One-off protocols
+
+11.1.3.4 SupportsComplex
+........................
+
+This is a type for objects that support complex(x)(1).  Note that no
+arithmetic operations are supported.
+
+     def __complex__(self) -> complex
+
+See also SupportsComplex(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#complex
+
+   (2) 
+https://docs.python.org/3/library/typing.html#typing.SupportsComplex
+
+
+File: Mypy.info,  Node: SupportsFloat,  Next: SupportsInt,  Prev: SupportsComplex,  Up: One-off protocols
+
+11.1.3.5 SupportsFloat
+......................
+
+This is a type for objects that support float(x)(1).  Note that no
+arithmetic operations are supported.
+
+     def __float__(self) -> float
+
+See also SupportsFloat(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#float
+
+   (2) 
+https://docs.python.org/3/library/typing.html#typing.SupportsFloat
+
+
+File: Mypy.info,  Node: SupportsInt,  Next: SupportsRound[T],  Prev: SupportsFloat,  Up: One-off protocols
+
+11.1.3.6 SupportsInt
+....................
+
+This is a type for objects that support int(x)(1).  Note that no
+arithmetic operations are supported.
+
+     def __int__(self) -> int
+
+See also SupportsInt(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#int
+
+   (2) https://docs.python.org/3/library/typing.html#typing.SupportsInt
+
+
+File: Mypy.info,  Node: SupportsRound[T],  Prev: SupportsInt,  Up: One-off protocols
+
+11.1.3.7 SupportsRound[T]
+.........................
+
+This is a type for objects that support round(x)(1).
+
+     def __round__(self) -> T
+
+See also SupportsRound(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#round
+
+   (2) 
+https://docs.python.org/3/library/typing.html#typing.SupportsRound
+
+
+File: Mypy.info,  Node: Async protocols,  Next: Context manager protocols,  Prev: One-off protocols,  Up: Predefined protocols
+
+11.1.4 Async protocols
+----------------------
+
+These protocols can be useful in async code.  See *note Typing
+async/await: 3a. for more information.
+
+* Menu:
+
+* Awaitable[T]::
+* AsyncIterable[T]::
+* AsyncIterator[T]::
+
+
+File: Mypy.info,  Node: Awaitable[T],  Next: AsyncIterable[T],  Up: Async protocols
+
+11.1.4.1 Awaitable[T]
+.....................
+
+     def __await__(self) -> Generator[Any, None, T]
+
+See also Awaitable(1).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Awaitable
+
+
+File: Mypy.info,  Node: AsyncIterable[T],  Next: AsyncIterator[T],  Prev: Awaitable[T],  Up: Async protocols
+
+11.1.4.2 AsyncIterable[T]
+.........................
+
+     def __aiter__(self) -> AsyncIterator[T]
+
+See also AsyncIterable(1).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/typing.html#typing.AsyncIterable
+
+
+File: Mypy.info,  Node: AsyncIterator[T],  Prev: AsyncIterable[T],  Up: Async protocols
+
+11.1.4.3 AsyncIterator[T]
+.........................
+
+     def __anext__(self) -> Awaitable[T]
+     def __aiter__(self) -> AsyncIterator[T]
+
+See also AsyncIterator(1).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/typing.html#typing.AsyncIterator
+
+
+File: Mypy.info,  Node: Context manager protocols,  Prev: Async protocols,  Up: Predefined protocols
+
+11.1.5 Context manager protocols
+--------------------------------
+
+There are two protocols for context managers – one for regular context
+managers and one for async ones.  These allow defining objects that can
+be used in ‘with’ and ‘async with’ statements.
+
+* Menu:
+
+* ContextManager[T]::
+* AsyncContextManager[T]::
+
+
+File: Mypy.info,  Node: ContextManager[T],  Next: AsyncContextManager[T],  Up: Context manager protocols
+
+11.1.5.1 ContextManager[T]
+..........................
+
+     def __enter__(self) -> T
+     def __exit__(self,
+                  exc_type: Optional[Type[BaseException]],
+                  exc_value: Optional[BaseException],
+                  traceback: Optional[TracebackType]) -> Optional[bool]
+
+See also ContextManager(1).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/typing.html#typing.ContextManager
+
+
+File: Mypy.info,  Node: AsyncContextManager[T],  Prev: ContextManager[T],  Up: Context manager protocols
+
+11.1.5.2 AsyncContextManager[T]
+...............................
+
+     def __aenter__(self) -> Awaitable[T]
+     def __aexit__(self,
+                   exc_type: Optional[Type[BaseException]],
+                   exc_value: Optional[BaseException],
+                   traceback: Optional[TracebackType]) -> Awaitable[Optional[bool]]
+
+See also AsyncContextManager(1).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/typing.html#typing.AsyncContextManager
+
+
+File: Mypy.info,  Node: Simple user-defined protocols,  Next: Defining subprotocols and subclassing protocols,  Prev: Predefined protocols,  Up: Protocols and structural subtyping
+
+11.2 Simple user-defined protocols
+==================================
+
+You can define your own protocol class by inheriting the special
+‘Protocol’ class:
+
+     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()(1)
+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.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#open
+
+
+File: Mypy.info,  Node: Defining subprotocols and subclassing protocols,  Next: Recursive protocols,  Prev: Simple user-defined protocols,  Up: Protocols and structural subtyping
+
+11.3 Defining subprotocols and subclassing protocols
+====================================================
+
+You can also define subprotocols.  Existing protocols can be extended
+and merged using multiple inheritance.  Example:
+
+     # ... 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(1)) to
+     declare protocol attributes.  On Python 2.7 and earlier Python 3
+     versions you can use type comments and properties.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0526/
+
+
+File: Mypy.info,  Node: Recursive protocols,  Next: Using isinstance with protocols,  Prev: Defining subprotocols and subclassing protocols,  Up: Protocols and structural subtyping
+
+11.4 Recursive protocols
+========================
+
+Protocols can be recursive (self-referential) and mutually recursive.
+This is useful for declaring abstract recursive collections such as
+trees and linked lists:
+
+     from typing import TypeVar, Optional
+     from typing_extensions import Protocol
+
+     class TreeLike(Protocol):
+         value: int
+
+         @property
+         def left(self) -> Optional['TreeLike']: ...
+
+         @property
+         def right(self) -> Optional['TreeLike']: ...
+
+     class SimpleTree:
+         def __init__(self, value: int) -> None:
+             self.value = value
+             self.left: Optional['SimpleTree'] = None
+             self.right: Optional['SimpleTree'] = None
+
+     root: TreeLike = SimpleTree(0)  # OK
+
+
+File: Mypy.info,  Node: Using isinstance with protocols,  Next: Callback protocols,  Prev: Recursive protocols,  Up: Protocols and structural subtyping
+
+11.5 Using isinstance() with protocols
+======================================
+
+You can use a protocol class with isinstance()(1) if you decorate it
+with the ‘@runtime_checkable’ class decorator.  The decorator adds
+support for basic runtime structural checks:
+
+     from typing_extensions import Protocol, runtime_checkable
+
+     @runtime_checkable
+     class Portable(Protocol):
+         handles: int
+
+     class Mug:
+         def __init__(self) -> None:
+             self.handles = 1
+
+     def use(handles: int) -> None: ...
+
+     mug = Mug()
+     if isinstance(mug, Portable):
+        use(mug.handles)  # Works statically and at runtime
+
+isinstance()(2) also works with the *note predefined protocols: 9d. in
+typing(3) such as Iterable(4).
+
+     Note: isinstance()(5) with protocols is not completely safe at
+     runtime.  For example, signatures of methods are not checked.  The
+     runtime implementation only checks that all protocol members are
+     defined.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+   (2) https://docs.python.org/3/library/functions.html#isinstance
+
+   (3) https://docs.python.org/3/library/typing.html#module-typing
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (5) https://docs.python.org/3/library/functions.html#isinstance
+
+
+File: Mypy.info,  Node: Callback protocols,  Prev: Using isinstance with protocols,  Up: Protocols and structural subtyping
+
+11.6 Callback protocols
+=======================
+
+Protocols can be used to define flexible callback types that are hard
+(or even impossible) to express using the Callable[...](1)  syntax, such
+as variadic, overloaded, and complex generic callbacks.  They are
+defined with a special __call__(2) member:
+
+     from typing import Optional, Iterable
+     from typing_extensions import Protocol
+
+     class Combiner(Protocol):
+         def __call__(self, *vals: bytes, maxlen: Optional[int] = None) -> list[bytes]: ...
+
+     def batch_proc(data: Iterable[bytes], cb_results: Combiner) -> bytes:
+         for item in data:
+             ...
+
+     def good_cb(*vals: bytes, maxlen: Optional[int] = None) -> list[bytes]:
+         ...
+     def bad_cb(*vals: bytes, maxitems: Optional[int]) -> list[bytes]:
+         ...
+
+     batch_proc([], good_cb)  # OK
+     batch_proc([], bad_cb)   # Error! Argument 2 has incompatible type because of
+                              # different name and kind in the callback
+
+Callback protocols and Callable(3) types can be used interchangeably.
+Keyword argument names in __call__(4) methods must be identical, unless
+a double underscore prefix is used.  For example:
+
+     from typing import Callable, TypeVar
+     from typing_extensions import Protocol
+
+     T = TypeVar('T')
+
+     class Copy(Protocol):
+         def __call__(self, __origin: T) -> T: ...
+
+     copy_a: Callable[[T], T]
+     copy_b: Copy
+
+     copy_a = copy_b  # OK
+     copy_b = copy_a  # Also OK
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (2) 
+https://docs.python.org/3/reference/datamodel.html#object.__call__
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (4) 
+https://docs.python.org/3/reference/datamodel.html#object.__call__
+
+
+File: Mypy.info,  Node: Dynamically typed code,  Next: Type checking Python 2 code,  Prev: Protocols and structural subtyping,  Up: Top
+
+12 Dynamically typed code
+*************************
+
+As mentioned earlier, bodies of functions that don’t have any explicit
+types in their function annotation are dynamically typed (operations are
+checked at runtime).  Code outside functions is statically typed by
+default, and types of variables are inferred.  This does usually the
+right thing, but you can also make any variable dynamically typed by
+defining it explicitly with the type ‘Any’:
+
+     from typing import Any
+
+     s = 1         # Statically typed (type int)
+     d: Any = 1    # Dynamically typed (type Any)
+     s = 'x'       # Type check error
+     d = 'x'       # OK
+
+* Menu:
+
+* Operations on Any values::
+* Any vs. object: Any vs object.
+
+
+File: Mypy.info,  Node: Operations on Any values,  Next: Any vs object,  Up: Dynamically typed code
+
+12.1 Operations on Any values
+=============================
+
+You can do anything using a value with type ‘Any’, and type checker does
+not complain:
+
+     def f(x: Any) -> int:
+         # All of these are valid!
+         x.foobar(1, y=2)
+         print(x[3] + 'f')
+         if x:
+             x.z = x(2)
+         open(x).read()
+         return x
+
+Values derived from an ‘Any’ value also often have the type ‘Any’
+implicitly, as mypy can’t infer a more precise result type.  For
+example, if you get the attribute of an ‘Any’ value or call a ‘Any’
+value the result is ‘Any’:
+
+     def f(x: Any) -> None:
+         y = x.foo()  # y has type Any
+         y.bar()      # Okay as well!
+
+‘Any’ types may propagate through your program, making type checking
+less effective, unless you are careful.
+
+
+File: Mypy.info,  Node: Any vs object,  Prev: Operations on Any values,  Up: Dynamically typed code
+
+12.2 Any vs. object
+===================
+
+The type object(1) is another type that can have an instance of
+arbitrary type as a value.  Unlike ‘Any’, object(2) is an ordinary
+static type (it is similar to ‘Object’ in Java), and only operations
+valid for `all' types are accepted for object(3) values.  These are all
+valid:
+
+     def f(o: object) -> None:
+         if o:
+             print(o)
+         print(isinstance(o, int))
+         o = 2
+         o = 'foo'
+
+These are, however, flagged as errors, since not all objects support
+these operations:
+
+     def f(o: object) -> None:
+         o.foo()       # Error!
+         o + 2         # Error!
+         open(o)       # Error!
+         n = 1  # type: int
+         n = o         # Error!
+
+You can use different *note type narrowing: 8f. techniques to narrow
+object(4) to a more specific type (subtype) such as ‘int’.  Type
+narrowing is not needed with dynamically typed values (values with type
+‘Any’).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#object
+
+   (2) https://docs.python.org/3/library/functions.html#object
+
+   (3) https://docs.python.org/3/library/functions.html#object
+
+   (4) https://docs.python.org/3/library/functions.html#object
+
+
+File: Mypy.info,  Node: Type checking Python 2 code,  Next: Type narrowing,  Prev: Dynamically typed code,  Up: Top
+
+13 Type checking Python 2 code
+******************************
+
+For code that needs to be Python 2.7 compatible, function type
+annotations are given in comments, since the function annotation syntax
+was introduced in Python 3.  The comment-based syntax is specified in
+PEP 484(1).
+
+Mypy requires typed-ast in order to check Python 2 code.  You can
+install it using ‘pip install 'mypy[python2]'’.
+
+Run mypy in Python 2 mode by using the *note –py2: 8. option:
+
+     $ mypy --py2 program.py
+
+To run your program, you must have the ‘typing’ module in your Python 2
+module search path.  Use ‘pip install typing’ to install the module.
+This also works for Python 3 versions prior to 3.5 that don’t include
+typing(2) in the standard library.
+
+The example below illustrates the Python 2 function type annotation
+syntax.  This syntax is also valid in Python 3 mode:
+
+     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."""
+             ...
+
+It’s worth going through these details carefully to avoid surprises:
+
+   - You don’t provide an annotation for the ‘self’ / ‘cls’ variable of
+     methods.
+
+   - Docstring always comes `after' the type comment.
+
+   - For ‘*args’ and ‘**kwargs’ the type should be prefixed with ‘*’ or
+     ‘**’, respectively (except when using the multi-line annotation
+     syntax described below).  Again, the above example illustrates
+     this.
+
+   - Things like ‘Any’ must be imported from ‘typing’, even if they are
+     only used in comments.
+
+   - In Python 2 mode ‘str’ is implicitly promoted to ‘unicode’, similar
+     to how ‘int’ is compatible with ‘float’.  This is unlike ‘bytes’
+     and ‘str’ in Python 3, which are incompatible.  ‘bytes’ in Python 2
+     is equivalent to ‘str’.  (This might change in the future.)
+
+* Menu:
+
+* Multi-line Python 2 function annotations::
+* Additional notes::
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+   (2) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Multi-line Python 2 function annotations,  Next: Additional notes,  Up: Type checking Python 2 code
+
+13.1 Multi-line Python 2 function annotations
+=============================================
+
+Mypy also supports a multi-line comment annotation syntax.  You can
+provide a separate annotation for each argument using the variable
+annotation syntax.  When using the single-line annotation syntax
+described above, functions with long argument lists tend to result in
+overly long type comments and it’s often tricky to see which argument
+type corresponds to which argument.  The alternative, multi-line
+annotation syntax makes long annotations easier to read and write.
+
+Here is an example (from PEP 484(1)):
+
+     def send_email(address,     # type: Union[str, List[str]]
+                    sender,      # type: str
+                    cc,          # type: Optional[List[str]]
+                    bcc,         # type: Optional[List[str]]
+                    subject='',
+                    body=None    # type: List[str]
+                    ):
+         # type: (...) -> bool
+         """Send an email message.  Return True if successful."""
+         <code>
+
+You write a separate annotation for each function argument on the same
+line as the argument.  Each annotation must be on a separate line.  If
+you leave out an annotation for an argument, it defaults to ‘Any’.  You
+provide a return type annotation in the body of the function using the
+form ‘# type: (...) -> rt’, where ‘rt’ is the return type.  Note that
+the return type annotation contains literal three dots.
+
+When using multi-line comments, you do not need to prefix the types of
+your ‘*arg’ and ‘**kwarg’ parameters with ‘*’ or ‘**’.  For example,
+here is how you would annotate the first example using multi-line
+comments:
+
+     from typing import List
+
+     class Example:
+         def method(self,
+                    lst,      # type: List[str]
+                    opt=0,    # type: int
+                    *args,    # type: str
+                    **kwargs  # type: bool
+                    ):
+             # type: (...) -> int
+             """Docstring comes after type comment."""
+             ...
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+
+File: Mypy.info,  Node: Additional notes,  Prev: Multi-line Python 2 function annotations,  Up: Type checking Python 2 code
+
+13.2 Additional notes
+=====================
+
+   - You should include types for arguments with default values in the
+     annotation.  The ‘opt’ argument of ‘method’ in the example at the
+     beginning of this section is an example of this.
+
+   - The annotation can be on the same line as the function header or on
+     the following line.
+
+   - Variables use a comment-based type syntax (explained in *note
+     Explicit types for variables: 52.).
+
+   - You don’t need to use string literal escapes for forward references
+     within comments (string literal escapes are explained later).
+
+   - Mypy uses a separate set of library stub files in typeshed(1) for
+     Python 2.  Library support may vary between Python 2 and Python 3.
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/typeshed
+
+
+File: Mypy.info,  Node: Type narrowing,  Next: Duck type compatibility,  Prev: Type checking Python 2 code,  Up: Top
+
+14 Type narrowing
+*****************
+
+This section is dedicated to several type narrowing techniques which are
+supported by mypy.
+
+Type narrowing is when you convince a type checker that a broader type
+is actually more specific, for instance, that an object of type ‘Shape’
+is actually of the narrower type ‘Square’.
+
+* Menu:
+
+* Type narrowing expressions::
+* Casts::
+* User-Defined Type Guards::
+
+
+File: Mypy.info,  Node: Type narrowing expressions,  Next: Casts,  Up: Type narrowing
+
+14.1 Type narrowing expressions
+===============================
+
+The simplest way to narrow a type is to use one of the supported
+expressions:
+
+   - isinstance()(1) like in ‘isinstance(obj, float)’ will narrow ‘obj’
+     to have ‘float’ type
+
+   - issubclass()(2) like in ‘issubclass(cls, MyClass)’ will narrow
+     ‘cls’ to be ‘Type[MyClass]’
+
+   - ‘type()’ like in ‘type(obj) is int’ will narrow ‘obj’ to have ‘int’
+     type
+
+   - callable()(3) like in ‘callable(obj)’ will narrow object to
+     callable type
+
+Type narrowing is contextual.  For example, based on the condition, mypy
+will narrow an expression only within an ‘if’ branch:
+
+     def function(arg: object):
+         if isinstance(arg, int):
+             # Type is narrowed within the ``if`` branch only
+             reveal_type(arg)  # Revealed type: "builtins.int"
+         elif isinstance(arg, str) or isinstance(arg, bool):
+             # Type is narrowed differently within this ``elif`` branch:
+             reveal_type(arg)  # Revealed type: "builtins.str | builtins.bool"
+
+             # Subsequent narrowing operations will narrow the type further
+             if isinstance(arg, bool):
+                 reveal_type(arg)  # Revealed type: "builtins.bool"
+
+         # Back outside of the ``if`` statement, the type isn't narrowed:
+         reveal_type(arg)  # Revealed type: "builtins.object"
+
+Mypy understands the implications ‘return’ or exception raising can have
+for what type an object could be:
+
+     def function(arg: int | str):
+         if isinstance(arg, int):
+             return
+
+         # `arg` can't be `int` at this point:
+         reveal_type(arg)  # Revealed type: "builtins.str"
+
+We can also use ‘assert’ to narrow types in the same context:
+
+     def function(arg: Any):
+         assert isinstance(arg, int)
+         reveal_type(arg)  # Revealed type: "builtins.int"
+
+     Note: With *note –warn-unreachable: c6. narrowing types to some
+     impossible state will be treated as an error.
+
+          def function(arg: int):
+              # error: Subclass of "int" and "str" cannot exist:
+              # would have incompatible method signatures
+              assert isinstance(arg, str)
+
+              # error: Statement is unreachable
+              print("so mypy concludes the assert will always trigger")
+
+     Without ‘--warn-unreachable’ mypy will simply not check code it
+     deems to be unreachable.  See *note Unreachable code: c7. for more
+     information.
+
+          x: int = 1
+          assert isinstance(x, str)
+          reveal_type(x)  # Revealed type is "builtins.int"
+          print(x + '!')  # Typechecks with `mypy`, but fails in runtime.
+
+* Menu:
+
+* issubclass::
+* callable::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+   (2) https://docs.python.org/3/library/functions.html#issubclass
+
+   (3) https://docs.python.org/3/library/functions.html#callable
+
+
+File: Mypy.info,  Node: issubclass,  Next: callable,  Up: Type narrowing expressions
+
+14.1.1 issubclass
+-----------------
+
+Mypy can also use issubclass()(1) for better type inference when working
+with types and metaclasses:
+
+     class MyCalcMeta(type):
+         @classmethod
+         def calc(cls) -> int:
+             ...
+
+     def f(o: object) -> None:
+         t = type(o)  # We must use a variable here
+         reveal_type(t)  # Revealed type is "builtins.type"
+
+         if issubtype(t, MyCalcMeta):  # `issubtype(type(o), MyCalcMeta)` won't work
+             reveal_type(t)  # Revealed type is "Type[MyCalcMeta]"
+             t.calc()  # Okay
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#issubclass
+
+
+File: Mypy.info,  Node: callable,  Prev: issubclass,  Up: Type narrowing expressions
+
+14.1.2 callable
+---------------
+
+Mypy knows what types are callable and which ones are not during type
+checking.  So, we know what ‘callable()’ will return.  For example:
+
+     from typing import Callable
+
+     x: Callable[[], int]
+
+     if callable(x):
+         reveal_type(x)  # N: Revealed type is "def () -> builtins.int"
+     else:
+         ...  # Will never be executed and will raise error with `--warn-unreachable`
+
+‘callable’ function can even split ‘Union’ type for callable and
+non-callable parts:
+
+     from typing import Callable, Union
+
+     x: Union[int, Callable[[], int]]
+
+     if callable(x):
+         reveal_type(x)  # N: Revealed type is "def () -> builtins.int"
+     else:
+         reveal_type(x)  # N: Revealed type is "builtins.int"
+
+
+File: Mypy.info,  Node: Casts,  Next: User-Defined Type Guards,  Prev: Type narrowing expressions,  Up: Type narrowing
+
+14.2 Casts
+==========
+
+Mypy supports type casts that are usually used to coerce a statically
+typed value to a subtype.  Unlike languages such as Java or C#, however,
+mypy casts are only used as hints for the type checker, and they don’t
+perform a runtime type check.  Use the function cast()(1) to perform a
+cast:
+
+     from typing import cast
+
+     o: object = [1]
+     x = cast(list[int], o)  # OK
+     y = cast(list[str], o)  # OK (cast performs no actual runtime check)
+
+To support runtime checking of casts such as the above, we’d have to
+check the types of all list items, which would be very inefficient for
+large lists.  Casts are used to silence spurious type checker warnings
+and give the type checker a little help when it can’t quite understand
+what is going on.
+
+     Note: You can use an assertion if you want to perform an actual
+     runtime check:
+
+          def foo(o: object) -> None:
+              print(o + 5)  # Error: can't add 'object' and 'int'
+              assert isinstance(o, int)
+              print(o + 5)  # OK: type of 'o' is 'int' here
+
+You don’t need a cast for expressions with type ‘Any’, or when assigning
+to a variable with type ‘Any’, as was explained earlier.  You can also
+use ‘Any’ as the cast target type – this lets you perform any operations
+on the result.  For example:
+
+     from typing import cast, Any
+
+     x = 1
+     x.whatever()  # Type check error
+     y = cast(Any, x)
+     y.whatever()  # Type check OK (runtime error)
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.cast
+
+
+File: Mypy.info,  Node: User-Defined Type Guards,  Prev: Casts,  Up: Type narrowing
+
+14.3 User-Defined Type Guards
+=============================
+
+Mypy supports User-Defined Type Guards ( PEP 647(1)).
+
+A type guard is a way for programs to influence conditional type
+narrowing employed by a type checker based on runtime checks.
+
+Basically, a ‘TypeGuard’ is a “smart” alias for a ‘bool’ type.  Let’s
+have a look at the regular ‘bool’ example:
+
+     def is_str_list(val: list[object]) -> bool:
+       """Determines whether all objects in the list are strings"""
+       return all(isinstance(x, str) for x in val)
+
+     def func1(val: list[object]) -> None:
+         if is_str_list(val):
+             reveal_type(val)  # Reveals list[object]
+             print(" ".join(val)) # Error: incompatible type
+
+The same example with ‘TypeGuard’:
+
+     from typing import TypeGuard  # use `typing_extensions` for Python 3.9 and below
+
+     def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
+         """Determines whether all objects in the list are strings"""
+         return all(isinstance(x, str) for x in val)
+
+     def func1(val: list[object]) -> None:
+         if is_str_list(val):
+             reveal_type(val)  # list[str]
+             print(" ".join(val)) # ok
+
+How does it work?  ‘TypeGuard’ narrows the first function argument
+(‘val’) to the type specified as the first type parameter (‘list[str]’).
+
+     Note: Narrowing is not strict(2).  For example, you can narrow
+     ‘str’ to ‘int’:
+
+          def f(value: str) -> TypeGuard[int]:
+              return True
+
+     Note: since strict narrowing is not enforced, it’s easy to break
+     type safety.
+
+     However, there are many ways a determined or uninformed developer
+     can subvert type safety – most commonly by using cast or Any.  If a
+     Python developer takes the time to learn about and implement
+     user-defined type guards within their code, it is safe to assume
+     that they are interested in type safety and will not write their
+     type guard functions in a way that will undermine type safety or
+     produce nonsensical results.
+
+* Menu:
+
+* Generic TypeGuards::
+* Typeguards with parameters::
+* TypeGuards as methods::
+* Assignment expressions as TypeGuards::
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0647/
+
+   (2) 
+https://www.python.org/dev/peps/pep-0647/#enforcing-strict-narrowing
+
+
+File: Mypy.info,  Node: Generic TypeGuards,  Next: Typeguards with parameters,  Up: User-Defined Type Guards
+
+14.3.1 Generic TypeGuards
+-------------------------
+
+‘TypeGuard’ can also work with generic types:
+
+     from typing import TypeVar
+     from typing import TypeGuard  # use `typing_extensions` for `python<3.10`
+
+     _T = TypeVar("_T")
+
+     def is_two_element_tuple(val: tuple[_T, ...]) -> TypeGuard[tuple[_T, _T]]:
+         return len(val) == 2
+
+     def func(names: tuple[str, ...]):
+         if is_two_element_tuple(names):
+             reveal_type(names)  # tuple[str, str]
+         else:
+             reveal_type(names)  # tuple[str, ...]
+
+
+File: Mypy.info,  Node: Typeguards with parameters,  Next: TypeGuards as methods,  Prev: Generic TypeGuards,  Up: User-Defined Type Guards
+
+14.3.2 Typeguards with parameters
+---------------------------------
+
+Type guard functions can accept extra arguments:
+
+     from typing import Type, TypeVar
+     from typing import TypeGuard  # use `typing_extensions` for `python<3.10`
+
+     _T = TypeVar("_T")
+
+     def is_set_of(val: set[Any], type: Type[_T]) -> TypeGuard[set[_T]]:
+         return all(isinstance(x, type) for x in val)
+
+     items: set[Any]
+     if is_set_of(items, str):
+         reveal_type(items)  # set[str]
+
+
+File: Mypy.info,  Node: TypeGuards as methods,  Next: Assignment expressions as TypeGuards,  Prev: Typeguards with parameters,  Up: User-Defined Type Guards
+
+14.3.3 TypeGuards as methods
+----------------------------
+
+     A method can also serve as the ‘TypeGuard’:
+
+     class StrValidator:
+         def is_valid(self, instance: object) -> TypeGuard[str]:
+             return isinstance(instance, str)
+
+     def func(to_validate: object) -> None:
+         if StrValidator().is_valid(to_validate):
+             reveal_type(to_validate)  # Revealed type is "builtins.str"
+
+     Note: Note, that ‘TypeGuard’ does not narrow(1) types of ‘self’ or
+     ‘cls’ implicit arguments.
+
+     If narrowing of ‘self’ or ‘cls’ is required, the value can be
+     passed as an explicit argument to a type guard function:
+
+          class Parent:
+              def method(self) -> None:
+                  reveal_type(self)  # Revealed type is "Parent"
+                  if is_child(self):
+                      reveal_type(self)  # Revealed type is "Child"
+
+          class Child(Parent):
+              ...
+
+          def is_child(instance: Parent) -> TypeGuard[Child]:
+              return isinstance(instance, Child)
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://www.python.org/dev/peps/pep-0647/#narrowing-of-implicit-self-and-cls-parameters
+
+
+File: Mypy.info,  Node: Assignment expressions as TypeGuards,  Prev: TypeGuards as methods,  Up: User-Defined Type Guards
+
+14.3.4 Assignment expressions as TypeGuards
+-------------------------------------------
+
+Sometimes you might need to create a new variable and narrow it to some
+specific type at the same time.  This can be achieved by using
+‘TypeGuard’ together with := operator(1).
+
+     from typing import TypeGuard  # use `typing_extensions` for `python<3.10`
+
+     def is_float(a: object) -> TypeGuard[float]:
+         return isinstance(a, float)
+
+     def main(a: object) -> None:
+         if is_float(x := a):
+             reveal_type(x)  # N: Revealed type is 'builtins.float'
+             reveal_type(a)  # N: Revealed type is 'builtins.object'
+         reveal_type(x)  # N: Revealed type is 'builtins.object'
+         reveal_type(a)  # N: Revealed type is 'builtins.object'
+
+What happens here?
+
+  1. We create a new variable ‘x’ and assign a value of ‘a’ to it
+
+  2. We run ‘is_float()’ type guard on ‘x’
+
+  3. It narrows ‘x’ to be ‘float’ in the ‘if’ context and does not touch
+     ‘a’
+
+     Note: The same will work with ‘isinstance(x := a, float)’ as well.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/whatsnew/3.8.html#assignment-expressions
+
+
+File: Mypy.info,  Node: Duck type compatibility,  Next: Stub files,  Prev: Type narrowing,  Up: Top
+
+15 Duck type compatibility
+**************************
+
+In Python, certain types are compatible even though they aren’t
+subclasses of each other.  For example, ‘int’ objects are valid whenever
+‘float’ objects are expected.  Mypy supports this idiom via `duck type
+compatibility'.  This is supported for a small set of built-in types:
+
+   * ‘int’ is duck type compatible with ‘float’ and ‘complex’.
+
+   * ‘float’ is duck type compatible with ‘complex’.
+
+   * ‘bytearray’ and ‘memoryview’ are duck type compatible with ‘bytes’.
+
+   * In Python 2, ‘str’ is duck type compatible with ‘unicode’.
+
+For example, mypy considers an ‘int’ object to be valid whenever a
+‘float’ object is expected.  Thus code like this is nice and clean and
+also behaves as expected:
+
+     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!
+
+You can also often use *note Protocols and structural subtyping: 37. to
+achieve a similar effect in a more principled and extensible fashion.
+Protocols don’t apply to cases like ‘int’ being compatible with ‘float’,
+since ‘float’ is not a protocol class but a regular, concrete class, and
+many standard library functions expect concrete instances of ‘float’ (or
+‘int’).
+
+     Note: Note that in Python 2 a ‘str’ object with non-ASCII
+     characters is often `not valid' when a unicode string is expected.
+     The mypy type system does not consider a string with non-ASCII
+     values as a separate type so some programs with this kind of error
+     will silently pass type checking.  In Python 3 ‘str’ and ‘bytes’
+     are separate, unrelated types and this kind of error is easy to
+     detect.  This a good reason for preferring Python 3 over Python 2!
+
+     See *note Text and AnyStr: 7b. for details on how to enforce that a
+     value must be a unicode string in a cross-compatible way.
+
+
+File: Mypy.info,  Node: Stub files,  Next: Generics,  Prev: Duck type compatibility,  Up: Top
+
+16 Stub files
+*************
+
+Mypy uses stub files stored in the typeshed(1) repository to determine
+the types of standard library and third-party library functions,
+classes, and other definitions.  You can also create your own stubs that
+will be used to type check your code.  The basic properties of stubs
+were introduced back in *note Library stubs and typeshed: 13.
+
+* Menu:
+
+* Creating a stub::
+* Stub file syntax::
+* Using stub file syntax at runtime::
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/typeshed
+
+
+File: Mypy.info,  Node: Creating a stub,  Next: Stub file syntax,  Up: Stub files
+
+16.1 Creating a stub
+====================
+
+Here is an overview of how to create a stub file:
+
+   * Write a stub file for the library (or an arbitrary module) and
+     store it as a ‘.pyi’ file in the same directory as the library
+     module.
+
+   * Alternatively, put your stubs (‘.pyi’ files) in a directory
+     reserved for stubs (e.g., ‘myproject/stubs’).  In this case you
+     have to set the environment variable ‘MYPYPATH’ to refer to the
+     directory.  For example:
+
+          $ export MYPYPATH=~/work/myproject/stubs
+
+Use the normal Python file name conventions for modules, e.g.  ‘csv.pyi’
+for module ‘csv’.  Use a subdirectory with ‘__init__.pyi’ for packages.
+Note that PEP 561(1) stub-only packages must be installed, and may not
+be pointed at through the ‘MYPYPATH’ (see *note PEP 561 support: 15.).
+
+If a directory contains both a ‘.py’ and a ‘.pyi’ file for the same
+module, the ‘.pyi’ file takes precedence.  This way you can easily add
+annotations for a module even if you don’t want to modify the source
+code.  This can be useful, for example, if you use 3rd party open source
+libraries in your program (and there are no stubs in typeshed yet).
+
+That’s it!
+
+Now you can access the module in mypy programs and type check code that
+uses the library.  If you write a stub for a library module, consider
+making it available for other programmers that use mypy by contributing
+it back to the typeshed repo.
+
+Mypy also ships with two tools for making it easier to create and
+maintain stubs: *note Automatic stub generation (stubgen): d7. and *note
+Automatic stub testing (stubtest): d8.
+
+The following sections explain the kinds of type annotations you can use
+in your programs and stub files.
+
+     Note: You may be tempted to point ‘MYPYPATH’ to the standard
+     library or to the ‘site-packages’ directory where your 3rd party
+     packages are installed.  This is almost always a bad idea – you
+     will likely get tons of error messages about code you didn’t write
+     and that mypy can’t analyze all that well yet, and in the worst
+     case scenario mypy may crash due to some construct in a 3rd party
+     package that it didn’t expect.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0561/
+
+
+File: Mypy.info,  Node: Stub file syntax,  Next: Using stub file syntax at runtime,  Prev: Creating a stub,  Up: Stub files
+
+16.2 Stub file syntax
+=====================
+
+Stub files are written in normal Python 3 syntax, but generally leaving
+out runtime logic like variable initializers, function bodies, and
+default arguments.
+
+If it is not possible to completely leave out some piece of runtime
+logic, the recommended convention is to replace or elide them with
+ellipsis expressions (‘...’).  Each ellipsis below is literally written
+in the stub file as three dots:
+
+     # Variables with annotations do not need to be assigned a value.
+     # So by convention, we omit them in the stub file.
+     x: int
+
+     # Function bodies cannot be completely removed. By convention,
+     # we replace them with `...` instead of the `pass` statement.
+     def func_1(code: str) -> int: ...
+
+     # We can do the same with default arguments.
+     def func_2(a: int, b: int = ...) -> int: ...
+
+     Note: The ellipsis ‘...’ is also used with a different meaning in
+     *note callable types: 63. and *note tuple types: 61.
+
+     Note: It is always legal to use Python 3 syntax in stub files, even
+     when writing Python 2 code.  The example above is a valid stub file
+     for both Python 2 and 3.
+
+
+File: Mypy.info,  Node: Using stub file syntax at runtime,  Prev: Stub file syntax,  Up: Stub files
+
+16.3 Using stub file syntax at runtime
+======================================
+
+You may also occasionally need to elide actual logic in regular Python
+code – for example, when writing methods in *note overload variants: 68.
+or *note custom protocols: 37.
+
+The recommended style is to use ellipses to do so, just like in stub
+files.  It is also considered stylistically acceptable to throw a
+NotImplementedError(1) in cases where the user of the code may
+accidentally call functions with no actual logic.
+
+You can also elide default arguments as long as the function body also
+contains no runtime logic: the function body only contains a single
+ellipsis, the pass statement, or a ‘raise NotImplementedError()’.  It is
+also acceptable for the function body to contain a docstring.  For
+example:
+
+     from typing_extensions import Protocol
+
+     class Resource(Protocol):
+         def ok_1(self, foo: list[str] = ...) -> None: ...
+
+         def ok_2(self, foo: list[str] = ...) -> None:
+             raise NotImplementedError()
+
+         def ok_3(self, foo: list[str] = ...) -> None:
+             """Some docstring"""
+             pass
+
+         # Error: Incompatible default for argument "foo" (default has
+         # type "ellipsis", argument has type "list[str]")
+         def not_ok(self, foo: list[str] = ...) -> None:
+             print(foo)
+
+     Note: Ellipsis expressions are legal syntax in Python 3 only.  This
+     means it is not possible to elide default arguments in Python 2
+     code.  You can still elide function bodies in Python 2 by using
+     either the ‘pass’ statement or by throwing a
+     NotImplementedError(2).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/exceptions.html#NotImplementedError
+
+   (2) 
+https://docs.python.org/3/library/exceptions.html#NotImplementedError
+
+
+File: Mypy.info,  Node: Generics,  Next: More types,  Prev: Stub files,  Up: Top
+
+17 Generics
+***********
+
+This section explains how you can define your own generic classes that
+take one or more type parameters, similar to built-in types such as
+‘list[X]’.  User-defined generics are a moderately advanced feature and
+you can get far without ever using them – feel free to skip this section
+and come back later.
+
+* Menu:
+
+* Defining generic classes::
+* Generic class internals::
+* Defining sub-classes of generic classes::
+* Generic functions::
+* Generic methods and generic self::
+* Variance of generic types::
+* Type variables with value restriction::
+* Type variables with upper bounds::
+* Declaring decorators::
+* Generic protocols::
+* Generic type aliases::
+
+
+File: Mypy.info,  Node: Defining generic classes,  Next: Generic class internals,  Up: Generics
+
+17.1 Defining generic classes
+=============================
+
+The built-in collection classes are generic classes.  Generic types have
+one or more type parameters, which can be arbitrary types.  For example,
+‘dict[int, str]’ has the type parameters ‘int’ and ‘str’, and
+‘list[int]’ has a type parameter ‘int’.
+
+Programs can also define new generic classes.  Here is a very simple
+generic class that represents a stack:
+
+     from typing import TypeVar, Generic
+
+     T = TypeVar('T')
+
+     class Stack(Generic[T]):
+         def __init__(self) -> None:
+             # Create an empty list with items of type T
+             self.items: list[T] = []
+
+         def push(self, item: T) -> None:
+             self.items.append(item)
+
+         def pop(self) -> T:
+             return self.items.pop()
+
+         def empty(self) -> bool:
+             return not self.items
+
+The ‘Stack’ class can be used to represent a stack of any type:
+‘Stack[int]’, ‘Stack[tuple[int, str]]’, etc.
+
+Using ‘Stack’ is similar to built-in container types:
+
+     # Construct an empty Stack[int] instance
+     stack = Stack[int]()
+     stack.push(2)
+     stack.pop()
+     stack.push('x')        # Type error
+
+Type inference works for user-defined generic types as well:
+
+     def process(stack: Stack[int]) -> None: ...
+
+     process(Stack())   # Argument has inferred type Stack[int]
+
+Construction of instances of generic types is also type checked:
+
+     class Box(Generic[T]):
+         def __init__(self, content: T) -> None:
+             self.content = content
+
+     Box(1)  # OK, inferred type is Box[int]
+     Box[int](1)  # Also OK
+     s = 'some string'
+     Box[int](s)  # Type error
+
+
+File: Mypy.info,  Node: Generic class internals,  Next: Defining sub-classes of generic classes,  Prev: Defining generic classes,  Up: Generics
+
+17.2 Generic class internals
+============================
+
+You may wonder what happens at runtime when you index ‘Stack’.  Indexing
+‘Stack’ returns a `generic alias' to ‘Stack’ that returns instances of
+the original class on instantiation:
+
+     >>> print(Stack)
+     __main__.Stack
+     >>> print(Stack[int])
+     __main__.Stack[int]
+     >>> print(Stack[int]().__class__)
+     __main__.Stack
+
+Generic aliases can be instantiated or subclassed, similar to real
+classes, but the above examples illustrate that type variables are
+erased at runtime.  Generic ‘Stack’ instances are just ordinary Python
+objects, and they have no extra runtime overhead or magic due to being
+generic, other than a metaclass that overloads the indexing operator.
+
+Note that in Python 3.8 and lower, the built-in types list(1), dict(2)
+and others do not support indexing.  This is why we have the aliases
+List(3), Dict(4) and so on in the typing(5) module.  Indexing these
+aliases gives you a generic alias that resembles generic aliases
+constructed by directly indexing the target class in more recent
+versions of Python:
+
+     >>> # Only relevant for Python 3.8 and below
+     >>> # For Python 3.9 onwards, prefer `list[int]` syntax
+     >>> from typing import List
+     >>> List[int]
+     typing.List[int]
+
+Note that the generic aliases in ‘typing’ don’t support constructing
+instances:
+
+     >>> from typing import List
+     >>> List[int]()
+     Traceback (most recent call last):
+     ...
+     TypeError: Type List cannot be instantiated; use list() instead
+
+     Note: In Python 3.6 indexing generic types or type aliases results
+     in actual type objects.  This means that generic types in type
+     annotations can have a significant runtime cost.  This was changed
+     in Python 3.7, and indexing generic types became a cheap operation.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#list
+
+   (2) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (3) https://docs.python.org/3/library/typing.html#typing.List
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Dict
+
+   (5) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Defining sub-classes of generic classes,  Next: Generic functions,  Prev: Generic class internals,  Up: Generics
+
+17.3 Defining sub-classes of generic classes
+============================================
+
+User-defined generic classes and generic classes defined in typing(1)
+can be used as base classes for another classes, both generic and
+non-generic.  For example:
+
+     from typing import Generic, TypeVar, Mapping, Iterator
+
+     KT = TypeVar('KT')
+     VT = TypeVar('VT')
+
+     class MyMap(Mapping[KT, VT]):  # This is a generic subclass of Mapping
+         def __getitem__(self, k: KT) -> VT:
+             ...  # Implementations omitted
+         def __iter__(self) -> Iterator[KT]:
+             ...
+         def __len__(self) -> int:
+             ...
+
+     items: MyMap[str, int]  # Okay
+
+     class StrDict(dict[str, str]):  # This is a non-generic subclass of dict
+         def __str__(self) -> str:
+             return 'StrDict({})'.format(super().__str__())
+
+     data: StrDict[int, int]  # Error! StrDict is not generic
+     data2: StrDict  # OK
+
+     class Receiver(Generic[T]):
+         def accept(self, value: T) -> None:
+             ...
+
+     class AdvancedReceiver(Receiver[T]):
+         ...
+
+     Note: You have to add an explicit Mapping(2) base class if you want
+     mypy to consider a user-defined class as a mapping (and Sequence(3)
+     for sequences, etc.).  This is because mypy doesn’t use `structural
+     subtyping' for these ABCs, unlike simpler protocols like
+     Iterable(4), which use *note structural subtyping: 37.
+
+Generic(5) can be omitted from bases if there are other base classes
+that include type variables, such as ‘Mapping[KT, VT]’ in the above
+example.  If you include ‘Generic[...]’ in bases, then it should list
+all type variables present in other bases (or more, if needed).  The
+order of type variables is defined by the following rules:
+
+   * If ‘Generic[...]’ is present, then the order of variables is always
+     determined by their order in ‘Generic[...]’.
+
+   * If there are no ‘Generic[...]’ in bases, then all type variables
+     are collected in the lexicographic order (i.e.  by first
+     appearance).
+
+For example:
+
+     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
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Mapping
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Sequence
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (5) https://docs.python.org/3/library/typing.html#typing.Generic
+
+
+File: Mypy.info,  Node: Generic functions,  Next: Generic methods and generic self,  Prev: Defining sub-classes of generic classes,  Up: Generics
+
+17.4 Generic functions
+======================
+
+Generic type variables can also be used to define generic functions:
+
+     from typing import TypeVar, Sequence
+
+     T = TypeVar('T')      # Declare type variable
+
+     def first(seq: Sequence[T]) -> T:   # Generic function
+         return seq[0]
+
+As with generic classes, the type variable can be replaced with any
+type.  That means ‘first’ can be used with any sequence type, and the
+return type is derived from the sequence item type.  For example:
+
+     # Assume first defined as above.
+
+     s = first('foo')      # s has type str.
+     n = first([1, 2, 3])  # n has type int.
+
+Note also that a single definition of a type variable (such as ‘T’
+above) can be used in multiple generic functions or classes.  In this
+example we use the same type variable in two generic functions:
+
+     from typing import TypeVar, Sequence
+
+     T = TypeVar('T')      # Declare type variable
+
+     def first(seq: Sequence[T]) -> T:
+         return seq[0]
+
+     def last(seq: Sequence[T]) -> T:
+         return seq[-1]
+
+A variable cannot have a type variable in its type unless the type
+variable is bound in a containing generic class or function.
+
+
+File: Mypy.info,  Node: Generic methods and generic self,  Next: Variance of generic types,  Prev: Generic functions,  Up: Generics
+
+17.5 Generic methods and generic self
+=====================================
+
+You can also define generic methods — just use a type variable in the
+method signature that is different from class type variables.  In
+particular, ‘self’ may also be generic, allowing a method to return the
+most precise type known at the point of access.
+
+     Note: This feature is experimental.  Checking code with type
+     annotations for self arguments is still not fully implemented.
+     Mypy may disallow valid code or allow unsafe code.
+
+In this way, for example, you can typecheck chaining of setter methods:
+
+     from typing import TypeVar
+
+     T = TypeVar('T', bound='Shape')
+
+     class Shape:
+         def set_scale(self: T, scale: float) -> T:
+             self.scale = scale
+             return self
+
+     class Circle(Shape):
+         def set_radius(self, r: float) -> 'Circle':
+             self.radius = r
+             return self
+
+     class Square(Shape):
+         def set_width(self, w: float) -> 'Square':
+             self.width = w
+             return self
+
+     circle = Circle().set_scale(0.5).set_radius(2.7)  # type: Circle
+     square = Square().set_scale(0.5).set_width(3.2)  # type: Square
+
+Without using generic ‘self’, the last two lines could not be
+type-checked properly.
+
+Other uses are factory methods, such as copy and deserialization.  For
+class methods, you can also define generic ‘cls’, using Type[T](1):
+
+     from typing import TypeVar, Type
+
+     T = TypeVar('T', bound='Friend')
+
+     class Friend:
+         other = None  # type: Friend
+
+         @classmethod
+         def make_pair(cls: Type[T]) -> tuple[T, T]:
+             a, b = cls(), cls()
+             a.other = b
+             b.other = a
+             return a, b
+
+     class SuperFriend(Friend):
+         pass
+
+     a, b = SuperFriend.make_pair()
+
+Note that when overriding a method with generic ‘self’, you must either
+return a generic ‘self’ too, or return an instance of the current class.
+In the latter case, you must implement this method in all future
+subclasses.
+
+Note also that mypy cannot always verify that the implementation of a
+copy or a deserialization method returns the actual type of self.
+Therefore you may need to silence mypy inside these methods (but not at
+the call site), possibly by making use of the ‘Any’ type.
+
+For some advanced uses of self-types see *note additional examples: e5.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Type
+
+
+File: Mypy.info,  Node: Variance of generic types,  Next: Type variables with value restriction,  Prev: Generic methods and generic self,  Up: Generics
+
+17.6 Variance of generic types
+==============================
+
+There are three main kinds of generic types with respect to subtype
+relations between them: invariant, covariant, and contravariant.
+Assuming that we have a pair of types ‘A’ and ‘B’, and ‘B’ is a subtype
+of ‘A’, these are defined as follows:
+
+   * A generic class ‘MyCovGen[T, ...]’ is called covariant in type
+     variable ‘T’ if ‘MyCovGen[B, ...]’ is always a subtype of
+     ‘MyCovGen[A, ...]’.
+
+   * A generic class ‘MyContraGen[T, ...]’ is called contravariant in
+     type variable ‘T’ if ‘MyContraGen[A, ...]’ is always a subtype of
+     ‘MyContraGen[B, ...]’.
+
+   * A generic class ‘MyInvGen[T, ...]’ is called invariant in ‘T’ if
+     neither of the above is true.
+
+Let us illustrate this by few simple examples:
+
+   * Union(1) is covariant in all variables: ‘Union[Cat, int]’ is a
+     subtype of ‘Union[Animal, int]’, ‘Union[Dog, int]’ is also a
+     subtype of ‘Union[Animal, int]’, etc.  Most immutable containers
+     such as Sequence(2) and FrozenSet(3) are also covariant.
+
+   * Callable(4) is an example of type that behaves contravariant in
+     types of arguments, namely ‘Callable[[Employee], int]’ is a subtype
+     of ‘Callable[[Manager], int]’.  To understand this, consider a
+     function:
+
+          def salaries(staff: list[Manager],
+                       accountant: Callable[[Manager], int]) -> list[int]: ...
+
+     This function needs a callable that can calculate a salary for
+     managers, and if we give it a callable that can calculate a salary
+     for an arbitrary employee, it’s still safe.
+
+   * List(5) is an invariant generic type.  Naively, one would think
+     that it is covariant, but let us consider this code:
+
+          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
+
+     Another example of invariant type is Dict(6).  Most mutable
+     containers are invariant.
+
+By default, mypy assumes that all user-defined generics are invariant.
+To declare a given generic class as covariant or contravariant use type
+variables defined with special keyword arguments ‘covariant’ or
+‘contravariant’.  For example:
+
+     from typing import Generic, TypeVar
+
+     T_co = TypeVar('T_co', covariant=True)
+
+     class Box(Generic[T_co]):  # this type is declared covariant
+         def __init__(self, content: T_co) -> None:
+             self._content = content
+
+         def get_content(self) -> T_co:
+             return self._content
+
+     def look_into(box: Box[Animal]): ...
+
+     my_box = Box(Cat())
+     look_into(my_box)  # OK, but mypy would complain here for an invariant type
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Union
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Sequence
+
+   (3) https://docs.python.org/3/library/typing.html#typing.FrozenSet
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (5) https://docs.python.org/3/library/typing.html#typing.List
+
+   (6) https://docs.python.org/3/library/typing.html#typing.Dict
+
+
+File: Mypy.info,  Node: Type variables with value restriction,  Next: Type variables with upper bounds,  Prev: Variance of generic types,  Up: Generics
+
+17.7 Type variables with value restriction
+==========================================
+
+By default, a type variable can be replaced with any type.  However,
+sometimes it’s useful to have a type variable that can only have some
+specific types as its value.  A typical example is a type variable that
+can only have values ‘str’ and ‘bytes’:
+
+     from typing import TypeVar
+
+     AnyStr = TypeVar('AnyStr', str, bytes)
+
+This is actually such a common type variable that AnyStr(1) is defined
+in typing(2) and we don’t need to define it ourselves.
+
+We can use AnyStr(3) to define a function that can concatenate two
+strings or bytes objects, but it can’t be called with other argument
+types:
+
+     from typing import AnyStr
+
+     def concat(x: AnyStr, y: AnyStr) -> AnyStr:
+         return x + y
+
+     concat('a', 'b')    # Okay
+     concat(b'a', b'b')  # Okay
+     concat(1, 2)        # Error!
+
+Note that this is different from a union type, since combinations of
+‘str’ and ‘bytes’ are not accepted:
+
+     concat('string', b'bytes')   # Error!
+
+In this case, this is exactly what we want, since it’s not possible to
+concatenate a string and a bytes object!  The type checker will reject
+this function:
+
+     def union_concat(x: Union[str, bytes], y: Union[str, bytes]) -> Union[str, bytes]:
+         return x + y  # Error: can't concatenate str and bytes
+
+Another interesting special case is calling ‘concat()’ with a subtype of
+‘str’:
+
+     class S(str): pass
+
+     ss = concat(S('foo'), S('bar'))
+
+You may expect that the type of ‘ss’ is ‘S’, but the type is actually
+‘str’: a subtype gets promoted to one of the valid values for the type
+variable, which in this case is ‘str’.  This is thus subtly different
+from `bounded quantification' in languages such as Java, where the
+return type would be ‘S’.  The way mypy implements this is correct for
+‘concat’, since ‘concat’ actually returns a ‘str’ instance in the above
+example:
+
+     >>> print(type(ss))
+     <class 'str'>
+
+You can also use a TypeVar(4) with a restricted set of possible values
+when defining a generic class.  For example, mypy uses the type
+Pattern[AnyStr](5) for the return value of re.compile()(6), since
+regular expressions can be based on a string or a bytes pattern.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.AnyStr
+
+   (2) https://docs.python.org/3/library/typing.html#module-typing
+
+   (3) https://docs.python.org/3/library/typing.html#typing.AnyStr
+
+   (4) https://docs.python.org/3/library/typing.html#typing.TypeVar
+
+   (5) https://docs.python.org/3/library/typing.html#typing.Pattern
+
+   (6) https://docs.python.org/3/library/re.html#re.compile
+
+
+File: Mypy.info,  Node: Type variables with upper bounds,  Next: Declaring decorators,  Prev: Type variables with value restriction,  Up: Generics
+
+17.8 Type variables with upper bounds
+=====================================
+
+A type variable can also be restricted to having values that are
+subtypes of a specific type.  This type is called the upper bound of the
+type variable, and is specified with the ‘bound=...’ keyword argument to
+TypeVar(1).
+
+     from typing import TypeVar, SupportsAbs
+
+     T = TypeVar('T', bound=SupportsAbs[float])
+
+In the definition of a generic function that uses such a type variable
+‘T’, the type represented by ‘T’ is assumed to be a subtype of its upper
+bound, so the function can use methods of the upper bound on values of
+type ‘T’.
+
+     def largest_in_absolute_value(*xs: T) -> T:
+         return max(xs, key=abs)  # Okay, because T is a subtype of SupportsAbs[float].
+
+In a call to such a function, the type ‘T’ must be replaced by a type
+that is a subtype of its upper bound.  Continuing the example above,
+
+     largest_in_absolute_value(-3.5, 2)   # Okay, has type float.
+     largest_in_absolute_value(5+6j, 7)   # Okay, has type complex.
+     largest_in_absolute_value('a', 'b')  # Error: 'str' is not a subtype of SupportsAbs[float].
+
+Type parameters of generic classes may also have upper bounds, which
+restrict the valid values for the type parameter in the same way.
+
+A type variable may not have both a value restriction (see *note Type
+variables with value restriction: 7c.) and an upper bound.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.TypeVar
+
+
+File: Mypy.info,  Node: Declaring decorators,  Next: Generic protocols,  Prev: Type variables with upper bounds,  Up: Generics
+
+17.9 Declaring decorators
+=========================
+
+One common application of type variable upper bounds is in declaring a
+decorator that preserves the signature of the function it decorates,
+regardless of that signature.
+
+Note that class decorators are handled differently than function
+decorators in mypy: decorating a class does not erase its type, even if
+the decorator has incomplete type annotations.
+
+Here’s a complete example of a function decorator:
+
+     from typing import Any, Callable, TypeVar, cast
+
+     F = TypeVar('F', bound=Callable[..., Any])
+
+     # A decorator that preserves the signature.
+     def my_decorator(func: F) -> F:
+         def wrapper(*args, **kwds):
+             print("Calling", func)
+             return func(*args, **kwds)
+         return cast(F, wrapper)
+
+     # 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"
+
+From the final block we see that the signatures of the decorated
+functions ‘foo()’ and ‘bar()’ are the same as those of the original
+functions (before the decorator is applied).
+
+The bound on ‘F’ is used so that calling the decorator on a non-function
+(e.g.  ‘my_decorator(1)’) will be rejected.
+
+Also note that the ‘wrapper()’ function is not type-checked.  Wrapper
+functions are typically small enough that this is not a big problem.
+This is also the reason for the cast()(1) call in the ‘return’ statement
+in ‘my_decorator()’.  See *note casts: ca.
+
+* Menu:
+
+* Decorator factories::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.cast
+
+
+File: Mypy.info,  Node: Decorator factories,  Up: Declaring decorators
+
+17.9.1 Decorator factories
+--------------------------
+
+Functions that take arguments and return a decorator (also called
+second-order decorators), are similarly supported via generics:
+
+     from typing import Any, Callable, TypeVar
+
+     F = TypeVar('F', bound=Callable[..., Any])
+
+     def route(url: str) -> Callable[[F], F]:
+         ...
+
+     @route(url='/')
+     def index(request: Any) -> str:
+         return 'Hello world'
+
+Sometimes the same decorator supports both bare calls and calls with
+arguments.  This can be achieved by combining with @overload(1):
+
+     from typing import Any, Callable, TypeVar, overload
+
+     F = TypeVar('F', bound=Callable[..., Any])
+
+     # Bare decorator usage
+     @overload
+     def atomic(__func: F) -> F: ...
+     # Decorator with arguments
+     @overload
+     def atomic(*, savepoint: bool = True) -> Callable[[F], F]: ...
+
+     # Implementation
+     def atomic(__func: Callable[..., Any] = None, *, savepoint: bool = True):
+         def decorator(func: Callable[..., Any]):
+             ...  # Code goes here
+         if __func is not None:
+             return decorator(__func)
+         else:
+             return decorator
+
+     # Usage
+     @atomic
+     def func1() -> None: ...
+
+     @atomic(savepoint=False)
+     def func2() -> None: ...
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.overload
+
+
+File: Mypy.info,  Node: Generic protocols,  Next: Generic type aliases,  Prev: Declaring decorators,  Up: Generics
+
+17.10 Generic protocols
+=======================
+
+Mypy supports generic protocols (see also *note Protocols and structural
+subtyping: 37.).  Several *note predefined protocols: 9d. are generic,
+such as Iterable[T](1), and you can define additional generic protocols.
+Generic protocols mostly follow the normal rules for generic classes.
+Example:
+
+     from typing import TypeVar
+     from typing_extensions import Protocol
+
+     T = TypeVar('T')
+
+     class Box(Protocol[T]):
+         content: T
+
+     def do_stuff(one: Box[str], other: Box[bytes]) -> None:
+         ...
+
+     class StringWrapper:
+         def __init__(self, content: str) -> None:
+             self.content = content
+
+     class BytesWrapper:
+         def __init__(self, content: bytes) -> None:
+             self.content = content
+
+     do_stuff(StringWrapper('one'), BytesWrapper(b'other'))  # OK
+
+     x: Box[float] = ...
+     y: Box[int] = ...
+     x = y  # Error -- Box is invariant
+
+Per PEP 544: Generic protocols(2), ‘class ClassName(Protocol[T])’ is
+allowed as a shorthand for ‘class ClassName(Protocol, Generic[T])’.
+
+The main difference between generic protocols and ordinary generic
+classes is that mypy checks that the declared variances of generic type
+variables in a protocol match how they are used in the protocol
+definition.  The protocol in this example is rejected, since the type
+variable ‘T’ is used covariantly as a return type, but the type variable
+is invariant:
+
+     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: ...
+
+This example correctly uses a covariant type variable:
+
+     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
+
+See *note Variance of generic types: e7. for more about variance.
+
+Generic protocols can also be recursive.  Example:
+
+     T = TypeVar('T')
+
+     class Linked(Protocol[T]):
+         val: T
+         def next(self) -> 'Linked[T]': ...
+
+     class L:
+         val: int
+
+         ...  # details omitted
+
+         def next(self) -> 'L':
+             ...  # details omitted
+
+     def last(seq: Linked[T]) -> T:
+         ...  # implementation omitted
+
+     result = last(L())  # Inferred type of 'result' is 'int'
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (2) https://peps.python.org/pep-0544/#generic-protocols
+
+
+File: Mypy.info,  Node: Generic type aliases,  Prev: Generic protocols,  Up: Generics
+
+17.11 Generic type aliases
+==========================
+
+Type aliases can be generic.  In this case they can be used in two ways:
+Subscripted aliases are equivalent to original types with substituted
+type variables, so the number of type arguments must match the number of
+free type variables in the generic type alias.  Unsubscripted aliases
+are treated as original types with free variables replaced with ‘Any’.
+Examples (following PEP 484: Type aliases(1)):
+
+     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!
+
+Type aliases can be imported from modules just like other names.  An
+alias can also target another alias, although building complex chains of
+aliases is not recommended – this impedes code readability, thus
+defeating the purpose of using aliases.  Example:
+
+     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]]
+
+     Note: A type alias does not define a new type.  For generic type
+     aliases this means that variance of type variables used for alias
+     definition does not apply to aliases.  A parameterized generic
+     alias is treated simply as an original type with the corresponding
+     type variables substituted.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/#type-aliases
+
+
+File: Mypy.info,  Node: More types,  Next: Literal types and Enums,  Prev: Generics,  Up: Top
+
+18 More types
+*************
+
+This section introduces a few additional kinds of types, including
+NoReturn(1), ‘NewType’, ‘TypedDict’, and types for async code.  It also
+discusses how to give functions more precise types using overloads.  All
+of these are only situationally useful, so feel free to skip this
+section and come back when you have a need for some of them.
+
+Here’s a quick summary of what’s covered here:
+
+   * NoReturn(2) lets you tell mypy that a function never returns
+     normally.
+
+   * ‘NewType’ lets you define a variant of a type that is treated as a
+     separate type by mypy but is identical to the original type at
+     runtime.  For example, you can have ‘UserId’ as a variant of ‘int’
+     that is just an ‘int’ at runtime.
+
+   * @overload(3) lets you define a function that can accept multiple
+     distinct signatures.  This is useful if you need to encode a
+     relationship between the arguments and the return type that would
+     be difficult to express normally.
+
+   * ‘TypedDict’ lets you give precise types for dictionaries that
+     represent objects with a fixed schema, such as ‘{'id': 1, 'items':
+     ['x']}’.
+
+   * Async types let you type check programs using ‘async’ and ‘await’.
+
+* Menu:
+
+* The NoReturn type::
+* NewTypes::
+* Function overloading::
+* Advanced uses of self-types::
+* Typing async/await::
+* TypedDict::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.NoReturn
+
+   (2) https://docs.python.org/3/library/typing.html#typing.NoReturn
+
+   (3) https://docs.python.org/3/library/typing.html#typing.overload
+
+
+File: Mypy.info,  Node: The NoReturn type,  Next: NewTypes,  Up: More types
+
+18.1 The NoReturn type
+======================
+
+Mypy provides support for functions that never return.  For example, a
+function that unconditionally raises an exception:
+
+     from typing import NoReturn
+
+     def stop() -> NoReturn:
+         raise Exception('no way')
+
+Mypy will ensure that functions annotated as returning NoReturn(1) truly
+never return, either implicitly or explicitly.  Mypy will also recognize
+that the code after calls to such functions is unreachable and will
+behave accordingly:
+
+     def f(x: int) -> int:
+         if x == 0:
+             return x
+         stop()
+         return 'whatever works'  # No error in an unreachable block
+
+In earlier Python versions you need to install ‘typing_extensions’ using
+pip to use NoReturn(2) in your code.  Python 3 command line:
+
+     python3 -m pip install --upgrade typing-extensions
+
+This works for Python 2:
+
+     pip install --upgrade typing-extensions
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.NoReturn
+
+   (2) https://docs.python.org/3/library/typing.html#typing.NoReturn
+
+
+File: Mypy.info,  Node: NewTypes,  Next: Function overloading,  Prev: The NoReturn type,  Up: More types
+
+18.2 NewTypes
+=============
+
+There are situations where you may want to avoid programming errors by
+creating simple derived classes that are only used to distinguish
+certain values from base class instances.  Example:
+
+     class UserId(int):
+         pass
+
+     def get_by_user_id(user_id: UserId):
+         ...
+
+However, this approach introduces some runtime overhead.  To avoid this,
+the typing module provides a helper object ‘NewType’ that creates simple
+unique types with almost zero runtime overhead.  Mypy will treat the
+statement ‘Derived = NewType('Derived', Base)’ as being roughly
+equivalent to the following definition:
+
+     class Derived(Base):
+         def __init__(self, _x: Base) -> None:
+             ...
+
+However, at runtime, ‘NewType('Derived', Base)’ will return a dummy
+callable that simply returns its argument:
+
+     def Derived(_x):
+         return _x
+
+Mypy will require explicit casts from ‘int’ where ‘UserId’ is expected,
+while implicitly casting from ‘UserId’ where ‘int’ is expected.
+Examples:
+
+     from typing import NewType
+
+     UserId = NewType('UserId', int)
+
+     def name_by_id(user_id: UserId) -> str:
+         ...
+
+     UserId('user')          # Fails type check
+
+     name_by_id(42)          # Fails type check
+     name_by_id(UserId(42))  # OK
+
+     num = UserId(5) + 1     # type: int
+
+‘NewType’ accepts exactly two arguments.  The first argument must be a
+string literal containing the name of the new type and must equal the
+name of the variable to which the new type is assigned.  The second
+argument must be a properly subclassable class, i.e., not a type
+construct like Union(1), etc.
+
+The callable returned by ‘NewType’ accepts only one argument; this is
+equivalent to supporting only one constructor accepting an instance of
+the base class (see above).  Example:
+
+     from typing import NewType
+
+     class PacketId:
+         def __init__(self, major: int, minor: int) -> None:
+             self._major = major
+             self._minor = minor
+
+     TcpPacketId = NewType('TcpPacketId', PacketId)
+
+     packet = PacketId(100, 100)
+     tcp_packet = TcpPacketId(packet)  # OK
+
+     tcp_packet = TcpPacketId(127, 0)  # Fails in type checker and at runtime
+
+You cannot use isinstance()(2) or issubclass()(3) on the object returned
+by ‘NewType()’, nor can you subclass an object returned by ‘NewType()’.
+
+     Note: Unlike type aliases, ‘NewType’ will create an entirely new
+     and unique type when used.  The intended purpose of ‘NewType’ is to
+     help you detect cases where you accidentally mixed together the old
+     base type and the new derived type.
+
+     For example, the following will successfully typecheck when using
+     type aliases:
+
+          UserId = int
+
+          def name_by_id(user_id: UserId) -> str:
+              ...
+
+          name_by_id(3)  # ints and UserId are synonymous
+
+     But a similar example using ‘NewType’ will not typecheck:
+
+          from typing import NewType
+
+          UserId = NewType('UserId', int)
+
+          def name_by_id(user_id: UserId) -> str:
+              ...
+
+          name_by_id(3)  # int is not the same as UserId
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Union
+
+   (2) https://docs.python.org/3/library/functions.html#isinstance
+
+   (3) https://docs.python.org/3/library/functions.html#issubclass
+
+
+File: Mypy.info,  Node: Function overloading,  Next: Advanced uses of self-types,  Prev: NewTypes,  Up: More types
+
+18.3 Function overloading
+=========================
+
+Sometimes the arguments and types in a function depend on each other in
+ways that can’t be captured with a Union(1).  For example, suppose we
+want to write a function that can accept x-y coordinates.  If we pass in
+just a single x-y coordinate, we return a ‘ClickEvent’ object.  However,
+if we pass in two x-y coordinates, we return a ‘DragEvent’ object.
+
+Our first attempt at writing this function might look like this:
+
+     from typing import Union, Optional
+
+     def mouse_event(x1: int,
+                     y1: int,
+                     x2: Optional[int] = None,
+                     y2: Optional[int] = None) -> Union[ClickEvent, DragEvent]:
+         if x2 is None and y2 is None:
+             return ClickEvent(x1, y1)
+         elif x2 is not None and y2 is not None:
+             return DragEvent(x1, y1, x2, y2)
+         else:
+             raise TypeError("Bad arguments")
+
+While this function signature works, it’s too loose: it implies
+‘mouse_event’ could return either object regardless of the number of
+arguments we pass in.  It also does not prohibit a caller from passing
+in the wrong number of ints: mypy would treat calls like ‘mouse_event(1,
+2, 20)’ as being valid, for example.
+
+We can do better by using overloading(2) which lets us give the same
+function multiple type annotations (signatures) to more accurately
+describe the function’s behavior:
+
+     from typing import Union, overload
+
+     # Overload *variants* for 'mouse_event'.
+     # These variants give extra information to the type checker.
+     # They are ignored at runtime.
+
+     @overload
+     def mouse_event(x1: int, y1: int) -> ClickEvent: ...
+     @overload
+     def mouse_event(x1: int, y1: int, x2: int, y2: int) -> DragEvent: ...
+
+     # The actual *implementation* of 'mouse_event'.
+     # The implementation contains the actual runtime logic.
+     #
+     # It may or may not have type hints. If it does, mypy
+     # will check the body of the implementation against the
+     # type hints.
+     #
+     # Mypy will also check and make sure the signature is
+     # consistent with the provided variants.
+
+     def mouse_event(x1: int,
+                     y1: int,
+                     x2: Optional[int] = None,
+                     y2: Optional[int] = None) -> Union[ClickEvent, DragEvent]:
+         if x2 is None and y2 is None:
+             return ClickEvent(x1, y1)
+         elif x2 is not None and y2 is not None:
+             return DragEvent(x1, y1, x2, y2)
+         else:
+             raise TypeError("Bad arguments")
+
+This allows mypy to understand calls to ‘mouse_event’ much more
+precisely.  For example, mypy will understand that ‘mouse_event(5, 25)’
+will always have a return type of ‘ClickEvent’ and will report errors
+for calls like ‘mouse_event(5, 25, 2)’.
+
+As another example, suppose we want to write a custom container class
+that implements the __getitem__(3) method (‘[]’ bracket indexing).  If
+this method receives an integer we return a single item.  If it receives
+a ‘slice’, we return a Sequence(4) of items.
+
+We can precisely encode this relationship between the argument and the
+return type by using overloads like so:
+
+     from typing import Sequence, TypeVar, Union, overload
+
+     T = TypeVar('T')
+
+     class MyList(Sequence[T]):
+         @overload
+         def __getitem__(self, index: int) -> T: ...
+
+         @overload
+         def __getitem__(self, index: slice) -> Sequence[T]: ...
+
+         def __getitem__(self, index: Union[int, slice]) -> Union[T, Sequence[T]]:
+             if isinstance(index, int):
+                 # Return a T here
+             elif isinstance(index, slice):
+                 # Return a sequence of Ts here
+             else:
+                 raise TypeError(...)
+
+     Note: If you just need to constrain a type variable to certain
+     types or subtypes, you can use a *note value restriction: 7c.
+
+The default values of a function’s arguments don’t affect its signature
+– only the absence or presence of a default value does.  So in order to
+reduce redundancy, it’s possible to replace default values in overload
+definitions with ‘...’ as a placeholder:
+
+     from typing import overload
+
+     class M: ...
+
+     @overload
+     def get_model(model_or_pk: M, flag: bool = ...) -> M: ...
+     @overload
+     def get_model(model_or_pk: int, flag: bool = ...) -> M | None: ...
+
+     def get_model(model_or_pk: int | M, flag: bool = True) -> M | None:
+         ...
+
+* Menu:
+
+* Runtime behavior::
+* Type checking calls to overloads::
+* Type checking the variants::
+* Type checking the implementation::
+* Conditional overloads::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Union
+
+   (2) https://peps.python.org/pep-0484/#function-method-overloading
+
+   (3) 
+https://docs.python.org/3/reference/datamodel.html#object.__getitem__
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Sequence
+
+
+File: Mypy.info,  Node: Runtime behavior,  Next: Type checking calls to overloads,  Up: Function overloading
+
+18.3.1 Runtime behavior
+-----------------------
+
+An overloaded function must consist of two or more overload `variants'
+followed by an `implementation'.  The variants and the implementations
+must be adjacent in the code: think of them as one indivisible unit.
+
+The variant bodies must all be empty; only the implementation is allowed
+to contain code.  This is because at runtime, the variants are
+completely ignored: they’re overridden by the final implementation
+function.
+
+This means that an overloaded function is still an ordinary Python
+function!  There is no automatic dispatch handling and you must manually
+handle the different types in the implementation (e.g.  by using ‘if’
+statements and isinstance(1) checks).
+
+If you are adding an overload within a stub file, the implementation
+function should be omitted: stubs do not contain runtime logic.
+
+     Note: While we can leave the variant body empty using the ‘pass’
+     keyword, the more common convention is to instead use the ellipsis
+     (‘...’) literal.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+
+File: Mypy.info,  Node: Type checking calls to overloads,  Next: Type checking the variants,  Prev: Runtime behavior,  Up: Function overloading
+
+18.3.2 Type checking calls to overloads
+---------------------------------------
+
+When you call an overloaded function, mypy will infer the correct return
+type by picking the best matching variant, after taking into
+consideration both the argument types and arity.  However, a call is
+never type checked against the implementation.  This is why mypy will
+report calls like ‘mouse_event(5, 25, 3)’ as being invalid even though
+it matches the implementation signature.
+
+If there are multiple equally good matching variants, mypy will select
+the variant that was defined first.  For example, consider the following
+program:
+
+     # For Python 3.8 and below you must use `typing.List` instead of `list`. e.g.
+     # from typing import List
+     from typing import overload
+
+     @overload
+     def summarize(data: list[int]) -> float: ...
+
+     @overload
+     def summarize(data: list[str]) -> str: ...
+
+     def summarize(data):
+         if not data:
+             return 0.0
+         elif isinstance(data[0], int):
+             # Do int specific code
+         else:
+             # Do str-specific code
+
+     # What is the type of 'output'? float or str?
+     output = summarize([])
+
+The ‘summarize([])’ call matches both variants: an empty list could be
+either a ‘list[int]’ or a ‘list[str]’.  In this case, mypy will break
+the tie by picking the first matching variant: ‘output’ will have an
+inferred type of ‘float’.  The implementor is responsible for making
+sure ‘summarize’ breaks ties in the same way at runtime.
+
+However, there are two exceptions to the “pick the first match” rule.
+First, if multiple variants match due to an argument being of type
+‘Any’, mypy will make the inferred type also be ‘Any’:
+
+     dynamic_var: Any = some_dynamic_function()
+
+     # output2 is of type 'Any'
+     output2 = summarize(dynamic_var)
+
+Second, if multiple variants match due to one or more of the arguments
+being a union, mypy will make the inferred type be the union of the
+matching variant returns:
+
+     some_list: Union[list[int], list[str]]
+
+     # output3 is of type 'Union[float, str]'
+     output3 = summarize(some_list)
+
+     Note: Due to the “pick the first match” rule, changing the order of
+     your overload variants can change how mypy type checks your
+     program.
+
+     To minimize potential issues, we recommend that you:
+
+       1. Make sure your overload variants are listed in the same order
+          as the runtime checks (e.g.  isinstance(1) checks) in your
+          implementation.
+
+       2. Order your variants and runtime checks from most to least
+          specific.  (See the following section for an example).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+
+File: Mypy.info,  Node: Type checking the variants,  Next: Type checking the implementation,  Prev: Type checking calls to overloads,  Up: Function overloading
+
+18.3.3 Type checking the variants
+---------------------------------
+
+Mypy will perform several checks on your overload variant definitions to
+ensure they behave as expected.  First, mypy will check and make sure
+that no overload variant is shadowing a subsequent one.  For example,
+consider the following function which adds together two ‘Expression’
+objects, and contains a special-case to handle receiving two ‘Literal’
+types:
+
+     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...
+
+While this code snippet is technically type-safe, it does contain an
+anti-pattern: the second variant will never be selected!  If we try
+calling ‘add(Literal(3), Literal(4))’, mypy will always pick the first
+variant and evaluate the function call to be of type ‘Expression’, not
+‘Literal’.  This is because ‘Literal’ is a subtype of ‘Expression’,
+which means the “pick the first match” rule will always halt after
+considering the first overload.
+
+Because having an overload variant that can never be matched is almost
+certainly a mistake, mypy will report an error.  To fix the error, we
+can either 1) delete the second overload or 2) swap the order of the
+overloads:
+
+     # Everything is ok now -- the variants are correctly ordered
+     # from most to least specific.
+
+     @overload
+     def add(left: Literal, right: Literal) -> Literal: ...
+
+     @overload
+     def add(left: Expression, right: Expression) -> Expression: ...
+
+     def add(left: Expression, right: Expression) -> Expression:
+         # ...snip...
+
+Mypy will also type check the different variants and flag any overloads
+that have inherently unsafely overlapping variants.  For example,
+consider the following unsafe overload definition:
+
+     from typing import overload, Union
+
+     @overload
+     def unsafe_func(x: int) -> int: ...
+
+     @overload
+     def unsafe_func(x: object) -> str: ...
+
+     def unsafe_func(x: object) -> Union[int, str]:
+         if isinstance(x, int):
+             return 42
+         else:
+             return "some string"
+
+On the surface, this function definition appears to be fine.  However,
+it will result in a discrepancy between the inferred type and the actual
+runtime type when we try using it like so:
+
+     some_obj: object = 42
+     unsafe_func(some_obj) + " danger danger"  # Type checks, yet crashes at runtime!
+
+Since ‘some_obj’ is of type object(1), mypy will decide that
+‘unsafe_func’ must return something of type ‘str’ and concludes the
+above will type check.  But in reality, ‘unsafe_func’ will return an
+int, causing the code to crash at runtime!
+
+To prevent these kinds of issues, mypy will detect and prohibit
+inherently unsafely overlapping overloads on a best-effort basis.  Two
+variants are considered unsafely overlapping when both of the following
+are true:
+
+  1. All of the arguments of the first variant are compatible with the
+     second.
+
+  2. The return type of the first variant is `not' compatible with (e.g.
+     is not a subtype of) the second.
+
+So in this example, the ‘int’ argument in the first variant is a subtype
+of the ‘object’ argument in the second, yet the ‘int’ return type is not
+a subtype of ‘str’.  Both conditions are true, so mypy will correctly
+flag ‘unsafe_func’ as being unsafe.
+
+However, mypy will not detect `all' unsafe uses of overloads.  For
+example, suppose we modify the above snippet so it calls ‘summarize’
+instead of ‘unsafe_func’:
+
+     some_list: list[str] = []
+     summarize(some_list) + "danger danger"  # Type safe, yet crashes at runtime!
+
+We run into a similar issue here.  This program type checks if we look
+just at the annotations on the overloads.  But since ‘summarize(...)’ is
+designed to be biased towards returning a float when it receives an
+empty list, this program will actually crash during runtime.
+
+The reason mypy does not flag definitions like ‘summarize’ as being
+potentially unsafe is because if it did, it would be extremely difficult
+to write a safe overload.  For example, suppose we define an overload
+with two variants that accept types ‘A’ and ‘B’ respectively.  Even if
+those two types were completely unrelated, the user could still
+potentially trigger a runtime error similar to the ones above by passing
+in a value of some third type ‘C’ that inherits from both ‘A’ and ‘B’.
+
+Thankfully, these types of situations are relatively rare.  What this
+does mean, however, is that you should exercise caution when designing
+or using an overloaded function that can potentially receive values that
+are an instance of two seemingly unrelated types.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#object
+
+
+File: Mypy.info,  Node: Type checking the implementation,  Next: Conditional overloads,  Prev: Type checking the variants,  Up: Function overloading
+
+18.3.4 Type checking the implementation
+---------------------------------------
+
+The body of an implementation is type-checked against the type hints
+provided on the implementation.  For example, in the ‘MyList’ example up
+above, the code in the body is checked with argument list ‘index:
+Union[int, slice]’ and a return type of ‘Union[T, Sequence[T]]’.  If
+there are no annotations on the implementation, then the body is not
+type checked.  If you want to force mypy to check the body anyways, use
+the *note –check-untyped-defs: fa. flag (*note more details here: fb.).
+
+The variants must also also be compatible with the implementation type
+hints.  In the ‘MyList’ example, mypy will check that the parameter type
+‘int’ and the return type ‘T’ are compatible with ‘Union[int, slice]’
+and ‘Union[T, Sequence]’ for the first variant.  For the second variant
+it verifies the parameter type ‘slice’ and the return type ‘Sequence[T]’
+are compatible with ‘Union[int, slice]’ and ‘Union[T, Sequence]’.
+
+     Note: The overload semantics documented above are new as of mypy
+     0.620.
+
+     Previously, mypy used to perform type erasure on all overload
+     variants.  For example, the ‘summarize’ example from the previous
+     section used to be illegal because ‘list[str]’ and ‘list[int]’ both
+     erased to just ‘list[Any]’.  This restriction was removed in mypy
+     0.620.
+
+     Mypy also previously used to select the best matching variant using
+     a different algorithm.  If this algorithm failed to find a match,
+     it would default to returning ‘Any’.  The new algorithm uses the
+     “pick the first match” rule and will fall back to returning ‘Any’
+     only if the input arguments also contain ‘Any’.
+
+
+File: Mypy.info,  Node: Conditional overloads,  Prev: Type checking the implementation,  Up: Function overloading
+
+18.3.5 Conditional overloads
+----------------------------
+
+Sometimes it is useful to define overloads conditionally.  Common use
+cases include types that are unavailable at runtime or that only exist
+in a certain Python version.  All existing overload rules still apply.
+For example, there must be at least two overloads.
+
+     Note: Mypy can only infer a limited number of conditions.
+     Supported ones currently include TYPE_CHECKING(1), ‘MYPY’, *note
+     Python version and system platform checks: fd, *note –always-true:
+     fe, and *note –always-false: ff. values.
+
+     from typing import TYPE_CHECKING, Any, overload
+
+     if TYPE_CHECKING:
+         class A: ...
+         class B: ...
+
+
+     if TYPE_CHECKING:
+         @overload
+         def func(var: A) -> A: ...
+
+         @overload
+         def func(var: B) -> B: ...
+
+     def func(var: Any) -> Any:
+         return var
+
+
+     reveal_type(func(A()))  # Revealed type is "A"
+
+     # flags: --python-version 3.10
+     import sys
+     from typing import Any, overload
+
+     class A: ...
+     class B: ...
+     class C: ...
+     class D: ...
+
+
+     if sys.version_info < (3, 7):
+         @overload
+         def func(var: A) -> A: ...
+
+     elif sys.version_info >= (3, 10):
+         @overload
+         def func(var: B) -> B: ...
+
+     else:
+         @overload
+         def func(var: C) -> C: ...
+
+     @overload
+     def func(var: D) -> D: ...
+
+     def func(var: Any) -> Any:
+         return var
+
+
+     reveal_type(func(B()))  # Revealed type is "B"
+     reveal_type(func(C()))  # No overload variant of "func" matches argument type "C"
+         # Possible overload variants:
+         #     def func(var: B) -> B
+         #     def func(var: D) -> D
+         # Revealed type is "Any"
+
+     Note: In the last example, mypy is executed with *note
+     –python-version 3.10: 100.  Therefore, the condition
+     ‘sys.version_info >= (3, 10)’ will match and the overload for ‘B’
+     will be added.  The overloads for ‘A’ and ‘C’ are ignored!  The
+     overload for ‘D’ is not defined conditionally and thus is also
+     added.
+
+When mypy cannot infer a condition to be always ‘True’ or always
+‘False’, an error is emitted.
+
+     from typing import Any, overload
+
+     class A: ...
+     class B: ...
+
+
+     def g(bool_var: bool) -> None:
+         if bool_var:  # Condition can't be inferred, unable to merge overloads
+             @overload
+             def func(var: A) -> A: ...
+
+             @overload
+             def func(var: B) -> B: ...
+
+         def func(var: Any) -> Any: ...
+
+         reveal_type(func(A()))  # Revealed type is "Any"
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
+
+
+File: Mypy.info,  Node: Advanced uses of self-types,  Next: Typing async/await,  Prev: Function overloading,  Up: More types
+
+18.4 Advanced uses of self-types
+================================
+
+Normally, mypy doesn’t require annotations for the first arguments of
+instance and class methods.  However, they may be needed to have more
+precise static typing for certain programming patterns.
+
+* Menu:
+
+* Restricted methods in generic classes::
+* Mixin classes::
+* Precise typing of alternative constructors::
+
+
+File: Mypy.info,  Node: Restricted methods in generic classes,  Next: Mixin classes,  Up: Advanced uses of self-types
+
+18.4.1 Restricted methods in generic classes
+--------------------------------------------
+
+In generic classes some methods may be allowed to be called only for
+certain values of type arguments:
+
+     T = TypeVar('T')
+
+     class Tag(Generic[T]):
+         item: T
+         def uppercase_item(self: Tag[str]) -> str:
+             return self.item.upper()
+
+     def label(ti: Tag[int], ts: Tag[str]) -> None:
+         ti.uppercase_item()  # E: Invalid self argument "Tag[int]" to attribute function
+                              # "uppercase_item" with type "Callable[[Tag[str]], str]"
+         ts.uppercase_item()  # This is OK
+
+This pattern also allows matching on nested types in situations where
+the type argument is itself generic:
+
+     T = TypeVar('T', covariant=True)
+     S = TypeVar('S')
+
+      class Storage(Generic[T]):
+          def __init__(self, content: T) -> None:
+              self.content = content
+          def first_chunk(self: Storage[Sequence[S]]) -> S:
+              return self.content[0]
+
+      page: Storage[list[str]]
+      page.first_chunk()  # OK, type is "str"
+
+      Storage(0).first_chunk()  # Error: Invalid self argument "Storage[int]" to attribute function
+                                # "first_chunk" with type "Callable[[Storage[Sequence[S]]], S]"
+
+Finally, one can use overloads on self-type to express precise types of
+some tricky methods:
+
+     T = TypeVar('T')
+
+     class Tag(Generic[T]):
+         @overload
+         def export(self: Tag[str]) -> str: ...
+         @overload
+         def export(self, converter: Callable[[T], str]) -> str: ...
+
+         def export(self, converter=None):
+             if isinstance(self.item, str):
+                 return self.item
+             return converter(self.item)
+
+In particular, an __init__()(1) method overloaded on self-type may be
+useful to annotate generic class constructors where type arguments
+depend on constructor parameters in a non-trivial way, see e.g.
+Popen(2).
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (2) 
+https://docs.python.org/3/library/subprocess.html#subprocess.Popen
+
+
+File: Mypy.info,  Node: Mixin classes,  Next: Precise typing of alternative constructors,  Prev: Restricted methods in generic classes,  Up: Advanced uses of self-types
+
+18.4.2 Mixin classes
+--------------------
+
+Using host class protocol as a self-type in mixin methods allows more
+code re-usability for static typing of mixin classes.  For example, one
+can define a protocol that defines common functionality for host classes
+instead of adding required abstract methods to every mixin:
+
+     class Lockable(Protocol):
+         @property
+         def lock(self) -> Lock: ...
+
+     class AtomicCloseMixin:
+         def atomic_close(self: Lockable) -> int:
+             with self.lock:
+                 # perform actions
+
+     class AtomicOpenMixin:
+         def atomic_open(self: Lockable) -> int:
+             with self.lock:
+                 # perform actions
+
+     class File(AtomicCloseMixin, AtomicOpenMixin):
+         def __init__(self) -> None:
+             self.lock = Lock()
+
+     class Bad(AtomicCloseMixin):
+         pass
+
+     f = File()
+     b: Bad
+     f.atomic_close()  # OK
+     b.atomic_close()  # Error: Invalid self type for "atomic_close"
+
+Note that the explicit self-type is `required' to be a protocol whenever
+it is not a supertype of the current class.  In this case mypy will
+check the validity of the self-type only at the call site.
+
+
+File: Mypy.info,  Node: Precise typing of alternative constructors,  Prev: Mixin classes,  Up: Advanced uses of self-types
+
+18.4.3 Precise typing of alternative constructors
+-------------------------------------------------
+
+Some classes may define alternative constructors.  If these classes are
+generic, self-type allows giving them precise signatures:
+
+     T = TypeVar('T')
+
+     class Base(Generic[T]):
+         Q = TypeVar('Q', bound='Base[T]')
+
+         def __init__(self, item: T) -> None:
+             self.item = item
+
+         @classmethod
+         def make_pair(cls: Type[Q], item: T) -> tuple[Q, Q]:
+             return cls(item), cls(item)
+
+     class Sub(Base[T]):
+         ...
+
+     pair = Sub.make_pair('yes')  # Type is "tuple[Sub[str], Sub[str]]"
+     bad = Sub[int].make_pair('no')  # Error: Argument 1 to "make_pair" of "Base"
+                                     # has incompatible type "str"; expected "int"
+
+
+File: Mypy.info,  Node: Typing async/await,  Next: TypedDict,  Prev: Advanced uses of self-types,  Up: More types
+
+18.5 Typing async/await
+=======================
+
+Mypy supports the ability to type coroutines that use the ‘async/await’
+syntax introduced in Python 3.5.  For more information regarding
+coroutines and this new syntax, see PEP 492(1).
+
+Functions defined using ‘async def’ are typed just like normal
+functions.  The return type annotation should be the same as the type of
+the value you expect to get back when ‘await’-ing the coroutine.
+
+     import asyncio
+
+     async def format_string(tag: str, count: int) -> str:
+         return 'T-minus {} ({})'.format(count, tag)
+
+     async def countdown_1(tag: str, count: int) -> str:
+         while count > 0:
+             my_str = await format_string(tag, count)  # has type 'str'
+             print(my_str)
+             await asyncio.sleep(0.1)
+             count -= 1
+         return "Blastoff!"
+
+     loop = asyncio.get_event_loop()
+     loop.run_until_complete(countdown_1("Millennium Falcon", 5))
+     loop.close()
+
+The result of calling an ‘async def’ function `without awaiting' will be
+a value of type Coroutine[Any, Any, T](2), which is a subtype of
+Awaitable[T](3):
+
+     my_coroutine = countdown_1("Millennium Falcon", 5)
+     reveal_type(my_coroutine)  # has type 'Coroutine[Any, Any, str]'
+
+     Note: *note reveal_type(): 106. displays the inferred static type
+     of an expression.
+
+You may also choose to create a subclass of Awaitable(4) instead:
+
+     from typing import Any, Awaitable, Generator
+     import asyncio
+
+     class MyAwaitable(Awaitable[str]):
+         def __init__(self, tag: str, count: int) -> None:
+             self.tag = tag
+             self.count = count
+
+         def __await__(self) -> Generator[Any, None, str]:
+             for i in range(n, 0, -1):
+                 print('T-minus {} ({})'.format(i, tag))
+                 yield from asyncio.sleep(0.1)
+             return "Blastoff!"
+
+     def countdown_3(tag: str, count: int) -> Awaitable[str]:
+         return MyAwaitable(tag, count)
+
+     loop = asyncio.get_event_loop()
+     loop.run_until_complete(countdown_3("Heart of Gold", 5))
+     loop.close()
+
+To create an iterable coroutine, subclass AsyncIterator(5):
+
+     from typing import Optional, AsyncIterator
+     import asyncio
+
+     class arange(AsyncIterator[int]):
+         def __init__(self, start: int, stop: int, step: int) -> None:
+             self.start = start
+             self.stop = stop
+             self.step = step
+             self.count = start - step
+
+         def __aiter__(self) -> AsyncIterator[int]:
+             return self
+
+         async def __anext__(self) -> int:
+             self.count += self.step
+             if self.count == self.stop:
+                 raise StopAsyncIteration
+             else:
+                 return self.count
+
+     async def countdown_4(tag: str, n: int) -> str:
+         async for i in arange(n, 0, -1):
+             print('T-minus {} ({})'.format(i, tag))
+             await asyncio.sleep(0.1)
+         return "Blastoff!"
+
+     loop = asyncio.get_event_loop()
+     loop.run_until_complete(countdown_4("Serenity", 5))
+     loop.close()
+
+If you use coroutines in legacy code that was originally written for
+Python 3.4, which did not support the ‘async def’ syntax, you would
+instead use the @asyncio.coroutine(6) decorator to convert a generator
+into a coroutine, and use a generator type as the return type:
+
+     from typing import Any, Generator
+     import asyncio
+
+     @asyncio.coroutine
+     def countdown_2(tag: str, count: int) -> Generator[Any, None, str]:
+         while count > 0:
+             print('T-minus {} ({})'.format(count, tag))
+             yield from asyncio.sleep(0.1)
+             count -= 1
+         return "Blastoff!"
+
+     loop = asyncio.get_event_loop()
+     loop.run_until_complete(countdown_2("USS Enterprise", 5))
+     loop.close()
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0492/
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Coroutine
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Awaitable
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Awaitable
+
+   (5) 
+https://docs.python.org/3/library/typing.html#typing.AsyncIterator
+
+   (6) 
+https://docs.python.org/3/library/asyncio-task.html#asyncio.coroutine
+
+
+File: Mypy.info,  Node: TypedDict,  Prev: Typing async/await,  Up: More types
+
+18.6 TypedDict
+==============
+
+Python programs often use dictionaries with string keys to represent
+objects.  Here is a typical example:
+
+     movie = {'name': 'Blade Runner', 'year': 1982}
+
+Only a fixed set of string keys is expected (‘'name'’ and ‘'year'’
+above), and each key has an independent value type (‘str’ for ‘'name'’
+and ‘int’ for ‘'year'’ above).  We’ve previously seen the ‘dict[K, V]’
+type, which lets you declare uniform dictionary types, where every value
+has the same type, and arbitrary keys are supported.  This is clearly
+not a good fit for ‘movie’ above.  Instead, you can use a ‘TypedDict’ to
+give a precise type for objects like ‘movie’, where the type of each
+dictionary value depends on the key:
+
+     from typing_extensions import TypedDict
+
+     Movie = TypedDict('Movie', {'name': str, 'year': int})
+
+     movie = {'name': 'Blade Runner', 'year': 1982}  # type: Movie
+
+‘Movie’ is a ‘TypedDict’ type with two items: ‘'name'’ (with type ‘str’)
+and ‘'year'’ (with type ‘int’).  Note that we used an explicit type
+annotation for the ‘movie’ variable.  This type annotation is important
+– without it, mypy will try to infer a regular, uniform dict(1) type for
+‘movie’, which is not what we want here.
+
+     Note: If you pass a ‘TypedDict’ object as an argument to a
+     function, no type annotation is usually necessary since mypy can
+     infer the desired type based on the declared argument type.  Also,
+     if an assignment target has been previously defined, and it has a
+     ‘TypedDict’ type, mypy will treat the assigned value as a
+     ‘TypedDict’, not dict(2).
+
+Now mypy will recognize these as valid:
+
+     name = movie['name']  # Okay; type of name is str
+     year = movie['year']  # Okay; type of year is int
+
+Mypy will detect an invalid key as an error:
+
+     director = movie['director']  # Error: 'director' is not a valid key
+
+Mypy will also reject a runtime-computed expression as a key, as it
+can’t verify that it’s a valid key.  You can only use string literals as
+‘TypedDict’ keys.
+
+The ‘TypedDict’ type object can also act as a constructor.  It returns a
+normal dict(3) object at runtime – a ‘TypedDict’ does not define a new
+runtime type:
+
+     toy_story = Movie(name='Toy Story', year=1995)
+
+This is equivalent to just constructing a dictionary directly using ‘{
+... }’ or ‘dict(key=value, ...)’.  The constructor form is sometimes
+convenient, since it can be used without a type annotation, and it also
+makes the type of the object explicit.
+
+Like all types, ‘TypedDict’s can be used as components to build
+arbitrarily complex types.  For example, you can define nested
+‘TypedDict’s and containers with ‘TypedDict’ items.  Unlike most other
+types, mypy uses structural compatibility checking (or structural
+subtyping) with ‘TypedDict’s.  A ‘TypedDict’ object with extra items is
+compatible with (a subtype of) a narrower ‘TypedDict’, assuming item
+types are compatible (`totality' also affects subtyping, as discussed
+below).
+
+A ‘TypedDict’ object is not a subtype of the regular ‘dict[...]’ type
+(and vice versa), since dict(4) allows arbitrary keys to be added and
+removed, unlike ‘TypedDict’.  However, any ‘TypedDict’ object is a
+subtype of (that is, compatible with) ‘Mapping[str, object]’, since
+Mapping(5) only provides read-only access to the dictionary items:
+
+     def print_typed_dict(obj: Mapping[str, object]) -> None:
+         for key, value in obj.items():
+             print('{}: {}'.format(key, value))
+
+     print_typed_dict(Movie(name='Toy Story', year=1995))  # OK
+
+     Note: Unless you are on Python 3.8 or newer (where ‘TypedDict’ is
+     available in standard library typing(6) module) you need to install
+     ‘typing_extensions’ using pip to use ‘TypedDict’:
+
+          python3 -m pip install --upgrade typing-extensions
+
+     Or, if you are using Python 2:
+
+          pip install --upgrade typing-extensions
+
+* Menu:
+
+* Totality::
+* Supported operations::
+* Class-based syntax::
+* Mixing required and non-required items::
+* Unions of TypedDicts::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (2) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (3) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (4) https://docs.python.org/3/library/stdtypes.html#dict
+
+   (5) https://docs.python.org/3/library/typing.html#typing.Mapping
+
+   (6) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Totality,  Next: Supported operations,  Up: TypedDict
+
+18.6.1 Totality
+---------------
+
+By default mypy ensures that a ‘TypedDict’ object has all the specified
+keys.  This will be flagged as an error:
+
+     # Error: 'year' missing
+     toy_story = {'name': 'Toy Story'}  # type: Movie
+
+Sometimes you want to allow keys to be left out when creating a
+‘TypedDict’ object.  You can provide the ‘total=False’ argument to
+‘TypedDict(...)’ to achieve this:
+
+     GuiOptions = TypedDict(
+         'GuiOptions', {'language': str, 'color': str}, total=False)
+     options = {}  # type: GuiOptions  # Okay
+     options['language'] = 'en'
+
+You may need to use get()(1) to access items of a partial (non-total)
+‘TypedDict’, since indexing using ‘[]’ could fail at runtime.  However,
+mypy still lets use ‘[]’ with a partial ‘TypedDict’ – you just need to
+be careful with it, as it could result in a KeyError(2).  Requiring
+get()(3) everywhere would be too cumbersome.  (Note that you are free to
+use get()(4) with total ‘TypedDict’s as well.)
+
+Keys that aren’t required are shown with a ‘?’ in error messages:
+
+     # Revealed type is "TypedDict('GuiOptions', {'language'?: builtins.str,
+     #                                            'color'?: builtins.str})"
+     reveal_type(options)
+
+Totality also affects structural compatibility.  You can’t use a partial
+‘TypedDict’ when a total one is expected.  Also, a total ‘TypedDict’ is
+not valid when a partial one is expected.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/stdtypes.html#dict.get
+
+   (2) https://docs.python.org/3/library/exceptions.html#KeyError
+
+   (3) https://docs.python.org/3/library/stdtypes.html#dict.get
+
+   (4) https://docs.python.org/3/library/stdtypes.html#dict.get
+
+
+File: Mypy.info,  Node: Supported operations,  Next: Class-based syntax,  Prev: Totality,  Up: TypedDict
+
+18.6.2 Supported operations
+---------------------------
+
+‘TypedDict’ objects support a subset of dictionary operations and
+methods.  You must use string literals as keys when calling most of the
+methods, as otherwise mypy won’t be able to check that the key is valid.
+List of supported operations:
+
+   * Anything included in Mapping(1):
+
+        * ‘d[key]’
+
+        * ‘key in d’
+
+        * ‘len(d)’
+
+        * ‘for key in d’ (iteration)
+
+        * d.get(key[, default])(2)
+
+        * d.keys()(3)
+
+        * d.values()(4)
+
+        * d.items()(5)
+
+   * d.copy()(6)
+
+   * d.setdefault(key, default)(7)
+
+   * d1.update(d2)(8)
+
+   * d.pop(key[, default])(9) (partial ‘TypedDict’s only)
+
+   * ‘del d[key]’ (partial ‘TypedDict’s only)
+
+In Python 2 code, these methods are also supported:
+
+   * ‘has_key(key)’
+
+   * ‘viewitems()’
+
+   * ‘viewkeys()’
+
+   * ‘viewvalues()’
+
+     Note: clear()(10) and popitem()(11) are not supported since they
+     are unsafe – they could delete required ‘TypedDict’ items that are
+     not visible to mypy because of structural subtyping.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Mapping
+
+   (2) https://docs.python.org/3/library/stdtypes.html#dict.get
+
+   (3) https://docs.python.org/3/library/stdtypes.html#dict.keys
+
+   (4) https://docs.python.org/3/library/stdtypes.html#dict.values
+
+   (5) https://docs.python.org/3/library/stdtypes.html#dict.items
+
+   (6) https://docs.python.org/3/library/stdtypes.html#dict.copy
+
+   (7) https://docs.python.org/3/library/stdtypes.html#dict.setdefault
+
+   (8) https://docs.python.org/3/library/stdtypes.html#dict.update
+
+   (9) https://docs.python.org/3/library/stdtypes.html#dict.pop
+
+   (10) https://docs.python.org/3/library/stdtypes.html#dict.clear
+
+   (11) https://docs.python.org/3/library/stdtypes.html#dict.popitem
+
+
+File: Mypy.info,  Node: Class-based syntax,  Next: Mixing required and non-required items,  Prev: Supported operations,  Up: TypedDict
+
+18.6.3 Class-based syntax
+-------------------------
+
+An alternative, class-based syntax to define a ‘TypedDict’ is supported
+in Python 3.6 and later:
+
+     from typing_extensions import TypedDict
+
+     class Movie(TypedDict):
+         name: str
+         year: int
+
+The above definition is equivalent to the original ‘Movie’ definition.
+It doesn’t actually define a real class.  This syntax also supports a
+form of inheritance – subclasses can define additional items.  However,
+this is primarily a notational shortcut.  Since mypy uses structural
+compatibility with ‘TypedDict’s, inheritance is not required for
+compatibility.  Here is an example of inheritance:
+
+     class Movie(TypedDict):
+         name: str
+         year: int
+
+     class BookBasedMovie(Movie):
+         based_on: str
+
+Now ‘BookBasedMovie’ has keys ‘name’, ‘year’ and ‘based_on’.
+
+
+File: Mypy.info,  Node: Mixing required and non-required items,  Next: Unions of TypedDicts,  Prev: Class-based syntax,  Up: TypedDict
+
+18.6.4 Mixing required and non-required items
+---------------------------------------------
+
+In addition to allowing reuse across ‘TypedDict’ types, inheritance also
+allows you to mix required and non-required (using ‘total=False’) items
+in a single ‘TypedDict’.  Example:
+
+     class MovieBase(TypedDict):
+         name: str
+         year: int
+
+     class Movie(MovieBase, total=False):
+         based_on: str
+
+Now ‘Movie’ has required keys ‘name’ and ‘year’, while ‘based_on’ can be
+left out when constructing an object.  A ‘TypedDict’ with a mix of
+required and non-required keys, such as ‘Movie’ above, will only be
+compatible with another ‘TypedDict’ if all required keys in the other
+‘TypedDict’ are required keys in the first ‘TypedDict’, and all
+non-required keys of the other ‘TypedDict’ are also non-required keys in
+the first ‘TypedDict’.
+
+
+File: Mypy.info,  Node: Unions of TypedDicts,  Prev: Mixing required and non-required items,  Up: TypedDict
+
+18.6.5 Unions of TypedDicts
+---------------------------
+
+Since TypedDicts are really just regular dicts at runtime, it is not
+possible to use ‘isinstance’ checks to distinguish between different
+variants of a Union of TypedDict in the same way you can with regular
+objects.
+
+Instead, you can use the *note tagged union pattern: 10e.  The
+referenced section of the docs has a full description with an example,
+but in short, you will need to give each TypedDict the same key where
+each value has a unique *note Literal type: 10f.  Then, check that key
+to distinguish between your TypedDicts.
+
+
+File: Mypy.info,  Node: Literal types and Enums,  Next: Final names methods and classes,  Prev: More types,  Up: Top
+
+19 Literal types and Enums
+**************************
+
+* Menu:
+
+* Literal types::
+* Enums::
+
+
+File: Mypy.info,  Node: Literal types,  Next: Enums,  Up: Literal types and Enums
+
+19.1 Literal types
+==================
+
+Literal types let you indicate that an expression is equal to some
+specific primitive value.  For example, if we annotate a variable with
+type ‘Literal["foo"]’, mypy will understand that variable is not only of
+type ‘str’, but is also equal to specifically the string ‘"foo"’.
+
+This feature is primarily useful when annotating functions that behave
+differently based on the exact value the caller provides.  For example,
+suppose we have a function ‘fetch_data(...)’ that returns ‘bytes’ if the
+first argument is ‘True’, and ‘str’ if it’s ‘False’.  We can construct a
+precise type signature for this function using ‘Literal[...]’ and
+overloads:
+
+     from typing import overload, Union, Literal
+
+     # The first two overloads use Literal[...] so we can
+     # have precise return types:
+
+     @overload
+     def fetch_data(raw: Literal[True]) -> bytes: ...
+     @overload
+     def fetch_data(raw: Literal[False]) -> str: ...
+
+     # The last overload is a fallback in case the caller
+     # provides a regular bool:
+
+     @overload
+     def fetch_data(raw: bool) -> Union[bytes, str]: ...
+
+     def fetch_data(raw: bool) -> Union[bytes, str]:
+         # Implementation is omitted
+         ...
+
+     reveal_type(fetch_data(True))        # Revealed type is "bytes"
+     reveal_type(fetch_data(False))       # Revealed type is "str"
+
+     # Variables declared without annotations will continue to have an
+     # inferred type of 'bool'.
+
+     variable = True
+     reveal_type(fetch_data(variable))    # Revealed type is "Union[bytes, str]"
+
+     Note: The examples in this page import ‘Literal’ as well as ‘Final’
+     and ‘TypedDict’ from the ‘typing’ module.  These types were added
+     to ‘typing’ in Python 3.8, but are also available for use in Python
+     2.7 and 3.4 - 3.7 via the ‘typing_extensions’ package.
+
+* Menu:
+
+* Parameterizing Literals::
+* Declaring literal variables::
+* Intelligent indexing::
+* Tagged unions::
+* Exhaustiveness checking::
+* Limitations::
+
+
+File: Mypy.info,  Node: Parameterizing Literals,  Next: Declaring literal variables,  Up: Literal types
+
+19.1.1 Parameterizing Literals
+------------------------------
+
+Literal types may contain one or more literal bools, ints, strs, bytes,
+and enum values.  However, literal types `cannot' contain arbitrary
+expressions: types like ‘Literal[my_string.trim()]’, ‘Literal[x > 3]’,
+or ‘Literal[3j + 4]’ are all illegal.
+
+Literals containing two or more values are equivalent to the union of
+those values.  So, ‘Literal[-3, b"foo", MyEnum.A]’ is equivalent to
+‘Union[Literal[-3], Literal[b"foo"], Literal[MyEnum.A]]’.  This makes
+writing more complex types involving literals a little more convenient.
+
+Literal types may also contain ‘None’.  Mypy will treat ‘Literal[None]’
+as being equivalent to just ‘None’.  This means that ‘Literal[4, None]’,
+‘Union[Literal[4], None]’, and ‘Optional[Literal[4]]’ are all
+equivalent.
+
+Literals may also contain aliases to other literal types.  For example,
+the following program is legal:
+
+     PrimaryColors = Literal["red", "blue", "yellow"]
+     SecondaryColors = Literal["purple", "green", "orange"]
+     AllowedColors = Literal[PrimaryColors, SecondaryColors]
+
+     def paint(color: AllowedColors) -> None: ...
+
+     paint("red")        # Type checks!
+     paint("turquoise")  # Does not type check
+
+Literals may not contain any other kind of type or expression.  This
+means doing ‘Literal[my_instance]’, ‘Literal[Any]’, ‘Literal[3.14]’, or
+‘Literal[{"foo": 2, "bar": 5}]’ are all illegal.
+
+
+File: Mypy.info,  Node: Declaring literal variables,  Next: Intelligent indexing,  Prev: Parameterizing Literals,  Up: Literal types
+
+19.1.2 Declaring literal variables
+----------------------------------
+
+You must explicitly add an annotation to a variable to declare that it
+has a literal type:
+
+     a: Literal[19] = 19
+     reveal_type(a)          # Revealed type is "Literal[19]"
+
+In order to preserve backwards-compatibility, variables without this
+annotation are `not' assumed to be literals:
+
+     b = 19
+     reveal_type(b)          # Revealed type is "int"
+
+If you find repeating the value of the variable in the type hint to be
+tedious, you can instead change the variable to be ‘Final’ (see *note
+Final names, methods and classes: 115.):
+
+     from typing import Final, Literal
+
+     def expects_literal(x: Literal[19]) -> None: pass
+
+     c: Final = 19
+
+     reveal_type(c)          # Revealed type is "Literal[19]?"
+     expects_literal(c)      # ...and this type checks!
+
+If you do not provide an explicit type in the ‘Final’, the type of ‘c’
+becomes `context-sensitive': mypy will basically try “substituting” the
+original assigned value whenever it’s used before performing type
+checking.  This is why the revealed type of ‘c’ is ‘Literal[19]?’: the
+question mark at the end reflects this context-sensitive nature.
+
+For example, mypy will type check the above program almost as if it were
+written like so:
+
+     from typing import Final, Literal
+
+     def expects_literal(x: Literal[19]) -> None: pass
+
+     reveal_type(19)
+     expects_literal(19)
+
+This means that while changing a variable to be ‘Final’ is not quite the
+same thing as adding an explicit ‘Literal[...]’ annotation, it often
+leads to the same effect in practice.
+
+The main cases where the behavior of context-sensitive vs true literal
+types differ are when you try using those types in places that are not
+explicitly expecting a ‘Literal[...]’.  For example, compare and
+contrast what happens when you try appending these types to a list:
+
+     from typing import Final, Literal
+
+     a: Final = 19
+     b: Literal[19] = 19
+
+     # Mypy will choose to infer list[int] here.
+     list_of_ints = []
+     list_of_ints.append(a)
+     reveal_type(list_of_ints)  # Revealed type is "list[int]"
+
+     # But if the variable you're appending is an explicit Literal, mypy
+     # will infer list[Literal[19]].
+     list_of_lits = []
+     list_of_lits.append(b)
+     reveal_type(list_of_lits)  # Revealed type is "list[Literal[19]]"
+
+
+File: Mypy.info,  Node: Intelligent indexing,  Next: Tagged unions,  Prev: Declaring literal variables,  Up: Literal types
+
+19.1.3 Intelligent indexing
+---------------------------
+
+We can use Literal types to more precisely index into structured
+heterogeneous types such as tuples, NamedTuples, and TypedDicts.  This
+feature is known as `intelligent indexing'.
+
+For example, when we index into a tuple using some int, the inferred
+type is normally the union of the tuple item types.  However, if we want
+just the type corresponding to some particular index, we can use Literal
+types like so:
+
+     from typing import TypedDict
+
+     tup = ("foo", 3.4)
+
+     # Indexing with an int literal gives us the exact type for that index
+     reveal_type(tup[0])  # Revealed type is "str"
+
+     # But what if we want the index to be a variable? Normally mypy won't
+     # know exactly what the index is and so will return a less precise type:
+     int_index = 0
+     reveal_type(tup[int_index])  # Revealed type is "Union[str, float]"
+
+     # But if we use either Literal types or a Final int, we can gain back
+     # the precision we originally had:
+     lit_index: Literal[0] = 0
+     fin_index: Final = 0
+     reveal_type(tup[lit_index])  # Revealed type is "str"
+     reveal_type(tup[fin_index])  # Revealed type is "str"
+
+     # We can do the same thing with with TypedDict and str keys:
+     class MyDict(TypedDict):
+         name: str
+         main_id: int
+         backup_id: int
+
+     d: MyDict = {"name": "Saanvi", "main_id": 111, "backup_id": 222}
+     name_key: Final = "name"
+     reveal_type(d[name_key])  # Revealed type is "str"
+
+     # You can also index using unions of literals
+     id_key: Literal["main_id", "backup_id"]
+     reveal_type(d[id_key])    # Revealed type is "int"
+
+
+File: Mypy.info,  Node: Tagged unions,  Next: Exhaustiveness checking,  Prev: Intelligent indexing,  Up: Literal types
+
+19.1.4 Tagged unions
+--------------------
+
+When you have a union of types, you can normally discriminate between
+each type in the union by using ‘isinstance’ checks.  For example, if
+you had a variable ‘x’ of type ‘Union[int, str]’, you could write some
+code that runs only if ‘x’ is an int by doing ‘if isinstance(x, int):
+...’.
+
+However, it is not always possible or convenient to do this.  For
+example, it is not possible to use ‘isinstance’ to distinguish between
+two different TypedDicts since at runtime, your variable will simply be
+just a dict.
+
+Instead, what you can do is `label' or `tag' your TypedDicts with a
+distinct Literal type.  Then, you can discriminate between each kind of
+TypedDict by checking the label:
+
+     from typing import Literal, TypedDict, Union
+
+     class NewJobEvent(TypedDict):
+         tag: Literal["new-job"]
+         job_name: str
+         config_file_path: str
+
+     class CancelJobEvent(TypedDict):
+         tag: Literal["cancel-job"]
+         job_id: int
+
+     Event = Union[NewJobEvent, CancelJobEvent]
+
+     def process_event(event: Event) -> None:
+         # Since we made sure both TypedDicts have a key named 'tag', it's
+         # safe to do 'event["tag"]'. This expression normally has the type
+         # Literal["new-job", "cancel-job"], but the check below will narrow
+         # the type to either Literal["new-job"] or Literal["cancel-job"].
+         #
+         # This in turns narrows the type of 'event' to either NewJobEvent
+         # or CancelJobEvent.
+         if event["tag"] == "new-job":
+             print(event["job_name"])
+         else:
+             print(event["job_id"])
+
+While this feature is mostly useful when working with TypedDicts, you
+can also use the same technique with regular objects, tuples, or
+namedtuples.
+
+Similarly, tags do not need to be specifically str Literals: they can be
+any type you can normally narrow within ‘if’ statements and the like.
+For example, you could have your tags be int or Enum Literals or even
+regular classes you narrow using ‘isinstance()’:
+
+     from typing import Generic, TypeVar, Union
+
+     T = TypeVar('T')
+
+     class Wrapper(Generic[T]):
+         def __init__(self, inner: T) -> None:
+             self.inner = inner
+
+     def process(w: Union[Wrapper[int], Wrapper[str]]) -> None:
+         # Doing `if isinstance(w, Wrapper[int])` does not work: isinstance requires
+         # that the second argument always be an *erased* type, with no generics.
+         # This is because generics are a typing-only concept and do not exist at
+         # runtime in a way `isinstance` can always check.
+         #
+         # However, we can side-step this by checking the type of `w.inner` to
+         # narrow `w` itself:
+         if isinstance(w.inner, int):
+             reveal_type(w)  # Revealed type is "Wrapper[int]"
+         else:
+             reveal_type(w)  # Revealed type is "Wrapper[str]"
+
+This feature is sometimes called “sum types” or “discriminated union
+types” in other programming languages.
+
+
+File: Mypy.info,  Node: Exhaustiveness checking,  Next: Limitations,  Prev: Tagged unions,  Up: Literal types
+
+19.1.5 Exhaustiveness checking
+------------------------------
+
+You may want to check that some code covers all possible ‘Literal’ or
+‘Enum’ cases.  Example:
+
+     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
+
+In the code above, it’s easy to make a mistake.  You can add a new
+literal value to ‘PossibleValues’ but forget to handle it in the
+‘validate’ function:
+
+     PossibleValues = Literal['one', 'two', 'three']
+
+Mypy won’t catch that ‘'three'’ is not covered.  If you want mypy to
+perform an exhaustiveness check, you need to update your code to use an
+‘assert_never()’ check:
+
+     from typing import Literal, NoReturn
+
+     PossibleValues = Literal['one', 'two']
+
+     def assert_never(value: NoReturn) -> NoReturn:
+         # This also works at runtime as well
+         assert False, f'This code should never be reached, got: {value}'
+
+     def validate(x: PossibleValues) -> bool:
+         if x == 'one':
+             return True
+         elif x == 'two':
+             return False
+         assert_never(x)
+
+Now if you add a new value to ‘PossibleValues’ but don’t update
+‘validate’, mypy will spot the error:
+
+     PossibleValues = Literal['one', 'two', 'three']
+
+     def validate(x: PossibleValues) -> bool:
+         if x == 'one':
+             return True
+         elif x == 'two':
+             return False
+         # Error: Argument 1 to "assert_never" has incompatible type "Literal['three']";
+         # expected "NoReturn"
+         assert_never(x)
+
+If runtime checking against unexpected values is not needed, you can
+leave out the ‘assert_never’ call in the above example, and mypy will
+still generate an error about function ‘validate’ returning without a
+value:
+
+     PossibleValues = Literal['one', 'two', 'three']
+
+     # Error: Missing return statement
+     def validate(x: PossibleValues) -> bool:
+         if x == 'one':
+             return True
+         elif x == 'two':
+             return False
+
+Exhaustiveness checking is also supported for match statements (Python
+3.10 and later):
+
+     def validate(x: PossibleValues) -> bool:
+         match x:
+             case 'one':
+                 return True
+             case 'two':
+                 return False
+         assert_never(x)
+
+
+File: Mypy.info,  Node: Limitations,  Prev: Exhaustiveness checking,  Up: Literal types
+
+19.1.6 Limitations
+------------------
+
+Mypy will not understand expressions that use variables of type
+‘Literal[..]’ on a deep level.  For example, if you have a variable ‘a’
+of type ‘Literal[3]’ and another variable ‘b’ of type ‘Literal[5]’, mypy
+will infer that ‘a + b’ has type ‘int’, `not' type ‘Literal[8]’.
+
+The basic rule is that literal types are treated as just regular
+subtypes of whatever type the parameter has.  For example, ‘Literal[3]’
+is treated as a subtype of ‘int’ and so will inherit all of ‘int’’s
+methods directly.  This means that ‘Literal[3].__add__’ accepts the same
+arguments and has the same return type as ‘int.__add__’.
+
+
+File: Mypy.info,  Node: Enums,  Prev: Literal types,  Up: Literal types and Enums
+
+19.2 Enums
+==========
+
+Mypy has special support for enum.Enum(1) and its subclasses:
+enum.IntEnum(2), enum.Flag(3), enum.IntFlag(4), and ‘enum.StrEnum’.
+
+     from enum import Enum
+
+     class Direction(Enum):
+         up = 'up'
+         down = 'down'
+
+     reveal_type(Direction.up)  # Revealed type is "Literal[Direction.up]?"
+     reveal_type(Direction.down)  # Revealed type is "Literal[Direction.down]?"
+
+You can use enums to annotate types as you would expect:
+
+     class Movement:
+         def __init__(self, direction: Direction, speed: float) -> None:
+             self.direction = direction
+             self.speed = speed
+
+     Movement(Direction.up, 5.0)  # ok
+     Movement('up', 5.0)  # E: Argument 1 to "Movemement" has incompatible type "str"; expected "Direction"
+
+* Menu:
+
+* Exhaustiveness checking: Exhaustiveness checking<2>.
+* Extra Enum checks::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/enum.html#enum.Enum
+
+   (2) https://docs.python.org/3/library/enum.html#enum.IntEnum
+
+   (3) https://docs.python.org/3/library/enum.html#enum.Flag
+
+   (4) https://docs.python.org/3/library/enum.html#enum.IntFlag
+
+
+File: Mypy.info,  Node: Exhaustiveness checking<2>,  Next: Extra Enum checks,  Up: Enums
+
+19.2.1 Exhaustiveness checking
+------------------------------
+
+Similar to ‘Literal’ types, ‘Enum’ supports exhaustiveness checking.
+Let’s start with a definition:
+
+     from enum import Enum
+     from typing import NoReturn
+
+     def assert_never(value: NoReturn) -> NoReturn:
+         # This also works in runtime as well:
+         assert False, 'This code should never be reached, got: {0}'.format(value)
+
+     class Direction(Enum):
+         up = 'up'
+         down = 'down'
+
+Now, let’s use an exhaustiveness check:
+
+     def choose_direction(direction: Direction) -> None:
+         if direction is Direction.up:
+             reveal_type(direction)  # N: Revealed type is "Literal[Direction.up]"
+             print('Going up!')
+             return
+         elif direction is Direction.down:
+             print('Down')
+             return
+         # This line is never reached
+         assert_never(direction)
+
+If we forget to handle one of the cases, mypy will generate an error:
+
+     def choose_direction(direction: Direction) -> None:
+         if direction == Direction.up:
+             print('Going up!')
+             return
+         assert_never(direction)  # E: Argument 1 to "assert_never" has incompatible type "Direction"; expected "NoReturn"
+
+Exhaustiveness checking is also supported for match statements (Python
+3.10 and later).
+
+
+File: Mypy.info,  Node: Extra Enum checks,  Prev: Exhaustiveness checking<2>,  Up: Enums
+
+19.2.2 Extra Enum checks
+------------------------
+
+Mypy also tries to support special features of ‘Enum’ the same way
+Python’s runtime does:
+
+   - Any ‘Enum’ class with values is implicitly *note final: 115.  This
+     is what happens in CPython:
+
+          >>> class AllDirection(Direction):
+          ...     left = 'left'
+          ...     right = 'right'
+          Traceback (most recent call last):
+            ...
+          TypeError: Other: cannot extend enumeration 'Some'
+
+     Mypy also catches this error:
+
+          class AllDirection(Direction):  # E: Cannot inherit from final class "Some"
+              left = 'left'
+              right = 'right'
+
+   - All ‘Enum’ fields are implictly ‘final’ as well.
+
+          Direction.up = '^'  # E: Cannot assign to final attribute "up"
+
+   - All field names are checked to be unique.
+
+          class Some(Enum):
+             x = 1
+             x = 2  # E: Attempted to reuse member name "x" in Enum definition "Some"
+
+   - Base classes have no conflicts and mixin types are correct.
+
+          class WrongEnum(str, int, enum.Enum):
+              # E: Only a single data type mixin is allowed for Enum subtypes, found extra "int"
+              ...
+
+          class MixinAfterEnum(enum.Enum, Mixin): # E: No base classes are allowed after "enum.Enum"
+              ...
+
+
+File: Mypy.info,  Node: Final names methods and classes,  Next: Metaclasses,  Prev: Literal types and Enums,  Up: Top
+
+20 Final names, methods and classes
+***********************************
+
+This section introduces these related features:
+
+  1. `Final names' are variables or attributes that should not be
+     reassigned after initialization.  They are useful for declaring
+     constants.
+
+  2. `Final methods' should not be overridden in a subclass.
+
+  3. `Final classes' should not be subclassed.
+
+All of these are only enforced by mypy, and only in annotated code.
+There is no runtime enforcement by the Python runtime.
+
+     Note: The examples in this page import ‘Final’ and ‘final’ from the
+     ‘typing’ module.  These types were added to ‘typing’ in Python 3.8,
+     but are also available for use in Python 2.7 and 3.4 - 3.7 via the
+     ‘typing_extensions’ package.
+
+* Menu:
+
+* Final names::
+* Final methods::
+* Final classes::
+
+
+File: Mypy.info,  Node: Final names,  Next: Final methods,  Up: Final names methods and classes
+
+20.1 Final names
+================
+
+You can use the ‘typing.Final’ qualifier to indicate that a name or
+attribute should not be reassigned, redefined, or overridden.  This is
+often useful for module and class level constants as a way to prevent
+unintended modification.  Mypy will prevent further assignments to final
+names in type-checked code:
+
+     from typing import Final
+
+     RATE: Final = 3000
+
+     class Base:
+         DEFAULT_ID: Final = 0
+
+     RATE = 300  # Error: can't assign to final attribute
+     Base.DEFAULT_ID = 1  # Error: can't override a final attribute
+
+Another use case for final attributes is to protect certain attributes
+from being overridden in a subclass:
+
+     from typing import Final
+
+     class Window:
+         BORDER_WIDTH: Final = 2.5
+         ...
+
+     class ListView(Window):
+         BORDER_WIDTH = 3  # Error: can't override a final attribute
+
+You can use @property(1) to make an attribute read-only, but unlike
+‘Final’, it doesn’t work with module attributes, and it doesn’t prevent
+overriding in subclasses.
+
+* Menu:
+
+* Syntax variants::
+* Details of using Final::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#property
+
+
+File: Mypy.info,  Node: Syntax variants,  Next: Details of using Final,  Up: Final names
+
+20.1.1 Syntax variants
+----------------------
+
+You can use ‘Final’ in one of these forms:
+
+   * You can provide an explicit type using the syntax ‘Final[<type>]’.
+     Example:
+
+          ID: Final[int] = 1
+
+     Here mypy will infer type ‘int’ for ‘ID’.
+
+   * You can omit the type:
+
+          ID: Final = 1
+
+     Here mypy will infer type ‘Literal[1]’ for ‘ID’.  Note that unlike
+     for generic classes this is `not' the same as ‘Final[Any]’.
+
+   * In class bodies and stub files you can omit the right hand side and
+     just write ‘ID: Final[int]’.
+
+   * Finally, you can write ‘self.id: Final = 1’ (also optionally with a
+     type in square brackets).  This is allowed `only' in __init__(1)
+     methods, so that the final instance attribute is assigned only once
+     when an instance is created.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+
+File: Mypy.info,  Node: Details of using Final,  Prev: Syntax variants,  Up: Final names
+
+20.1.2 Details of using ‘Final’
+-------------------------------
+
+These are the two main rules for defining a final name:
+
+   * There can be `at most one' final declaration per module or class
+     for a given attribute.  There can’t be separate class-level and
+     instance-level constants with the same name.
+
+   * There must be `exactly one' assignment to a final name.
+
+A final attribute declared in a class body without an initializer must
+be initialized in the __init__(1) method (you can skip the initializer
+in stub files):
+
+     class ImmutablePoint:
+         x: Final[int]
+         y: Final[int]  # Error: final attribute without an initializer
+
+         def __init__(self) -> None:
+             self.x = 1  # Good
+
+‘Final’ can only be used as the outermost type in assignments or
+variable annotations.  Using it in any other position is an error.  In
+particular, ‘Final’ can’t be used in annotations for function arguments:
+
+     x: list[Final[int]] = []  # Error!
+
+     def fun(x: Final[list[int]]) ->  None:  # Error!
+         ...
+
+‘Final’ and ClassVar(2) should not be used together.  Mypy will infer
+the scope of a final declaration automatically depending on whether it
+was initialized in the class body or in __init__(3).
+
+A final attribute can’t be overridden by a subclass (even with another
+explicit final declaration).  Note however that a final attribute can
+override a read-only property:
+
+     class Base:
+         @property
+         def ID(self) -> int: ...
+
+     class Derived(Base):
+         ID: Final = 1  # OK
+
+Declaring a name as final only guarantees that the name will not be
+re-bound to another value.  It doesn’t make the value immutable.  You
+can use immutable ABCs and containers to prevent mutating such values:
+
+     x: Final = ['a', 'b']
+     x.append('c')  # OK
+
+     y: Final[Sequence[str]] = ['a', 'b']
+     y.append('x')  # Error: Sequence is immutable
+     z: Final = ('a', 'b')  # Also an option
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (2) https://docs.python.org/3/library/typing.html#typing.ClassVar
+
+   (3) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+
+File: Mypy.info,  Node: Final methods,  Next: Final classes,  Prev: Final names,  Up: Final names methods and classes
+
+20.2 Final methods
+==================
+
+Like with attributes, sometimes it is useful to protect a method from
+overriding.  You can use the ‘typing.final’ decorator for this purpose:
+
+     from typing import final
+
+     class Base:
+         @final
+         def common_name(self) -> None:
+             ...
+
+     class Derived(Base):
+         def common_name(self) -> None:  # Error: cannot override a final method
+             ...
+
+This ‘@final’ decorator can be used with instance methods, class
+methods, static methods, and properties.
+
+For overloaded methods you should add ‘@final’ on the implementation to
+make it final (or on the first overload in stubs):
+
+     from typing import Any, overload
+
+     class Base:
+         @overload
+         def method(self) -> None: ...
+         @overload
+         def method(self, arg: int) -> int: ...
+         @final
+         def method(self, x=None):
+             ...
+
+
+File: Mypy.info,  Node: Final classes,  Prev: Final methods,  Up: Final names methods and classes
+
+20.3 Final classes
+==================
+
+You can apply the ‘typing.final’ decorator to a class to indicate to
+mypy that it should not be subclassed:
+
+     from typing import final
+
+     @final
+     class Leaf:
+         ...
+
+     class MyLeaf(Leaf):  # Error: Leaf can't be subclassed
+         ...
+
+The decorator acts as a declaration for mypy (and as documentation for
+humans), but it doesn’t actually prevent subclassing at runtime.
+
+Here are some situations where using a final class may be useful:
+
+   * A class wasn’t designed to be subclassed.  Perhaps subclassing
+     would not work as expected, or subclassing would be error-prone.
+
+   * Subclassing would make code harder to understand or maintain.  For
+     example, you may want to prevent unnecessarily tight coupling
+     between base classes and subclasses.
+
+   * You want to retain the freedom to arbitrarily change the class
+     implementation in the future, and these changes might break
+     subclasses.
+
+An abstract class that defines at least one abstract method or property
+and has ‘@final’ decorator will generate an error from mypy, since those
+attributes could never be implemented.
+
+     from abc import ABCMeta, abstractmethod
+     from typing import final
+
+     @final
+     class A(metaclass=ABCMeta):  # error: Final class A has abstract attributes "f"
+         @abstractmethod
+         def f(self, x: int) -> None: pass
+
+
+File: Mypy.info,  Node: Metaclasses,  Next: Running mypy and managing imports,  Prev: Final names methods and classes,  Up: Top
+
+21 Metaclasses
+**************
+
+A metaclass(1) is a class that describes the construction and behavior
+of other classes, similarly to how classes describe the construction and
+behavior of objects.  The default metaclass is type(2), but it’s
+possible to use other metaclasses.  Metaclasses allows one to create “a
+different kind of class”, such as Enum(3)s, NamedTuple(4)s and
+singletons.
+
+Mypy has some special understanding of ABCMeta(5) and ‘EnumMeta’.
+
+* Menu:
+
+* Defining a metaclass::
+* Metaclass usage example::
+* Gotchas and limitations of metaclass support::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/reference/datamodel.html#metaclasses
+
+   (2) https://docs.python.org/3/library/functions.html#type
+
+   (3) https://docs.python.org/3/library/enum.html#enum.Enum
+
+   (4) https://docs.python.org/3/library/typing.html#typing.NamedTuple
+
+   (5) https://docs.python.org/3/library/abc.html#abc.ABCMeta
+
+
+File: Mypy.info,  Node: Defining a metaclass,  Next: Metaclass usage example,  Up: Metaclasses
+
+21.1 Defining a metaclass
+=========================
+
+     class M(type):
+         pass
+
+     class A(metaclass=M):
+         pass
+
+In Python 2, the syntax for defining a metaclass is different:
+
+     class A(object):
+         __metaclass__ = M
+
+Mypy also supports using six.with_metaclass()(1) and
+@six.add_metaclass(2) to define metaclass in a portable way:
+
+     import six
+
+     class A(six.with_metaclass(M)):
+         pass
+
+     @six.add_metaclass(M)
+     class C(object):
+         pass
+
+   ---------- Footnotes ----------
+
+   (1) https://six.readthedocs.io/index.html#six.with_metaclass
+
+   (2) https://six.readthedocs.io/index.html#six.add_metaclass
+
+
+File: Mypy.info,  Node: Metaclass usage example,  Next: Gotchas and limitations of metaclass support,  Prev: Defining a metaclass,  Up: Metaclasses
+
+21.2 Metaclass usage example
+============================
+
+Mypy supports the lookup of attributes in the metaclass:
+
+     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")
+
+
+File: Mypy.info,  Node: Gotchas and limitations of metaclass support,  Prev: Metaclass usage example,  Up: Metaclasses
+
+21.3 Gotchas and limitations of metaclass support
+=================================================
+
+Note that metaclasses pose some requirements on the inheritance
+structure, so it’s better not to combine metaclasses and class
+hierarchies:
+
+     class M1(type): pass
+     class M2(type): pass
+
+     class A1(metaclass=M1): pass
+     class A2(metaclass=M2): pass
+
+     class B1(A1, metaclass=M2): pass  # Mypy Error: Inconsistent metaclass structure for "B1"
+     # At runtime the above definition raises an exception
+     # TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases
+
+     # Same runtime error as in B1, but mypy does not catch it yet
+     class B12(A1, A2): pass
+
+   * Mypy does not understand dynamically-computed metaclasses, such as
+     ‘class A(metaclass=f()): ...’
+
+   * Mypy does not and cannot understand arbitrary metaclass code.
+
+   * Mypy only recognizes subclasses of type(1) as potential
+     metaclasses.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#type
+
+
+File: Mypy.info,  Node: Running mypy and managing imports,  Next: The mypy command line,  Prev: Metaclasses,  Up: Top
+
+22 Running mypy and managing imports
+************************************
+
+The *note Getting started: 5. page should have already introduced you to
+the basics of how to run mypy – pass in the files and directories you
+want to type check via the command line:
+
+     $ mypy foo.py bar.py some_directory
+
+This page discusses in more detail how exactly to specify what files you
+want mypy to type check, how mypy discovers imported modules, and
+recommendations on how to handle any issues you may encounter along the
+way.
+
+If you are interested in learning about how to configure the actual way
+mypy type checks your code, see our *note The mypy command line: c.
+guide.
+
+* Menu:
+
+* Specifying code to be checked::
+* Reading a list of files from a file::
+* How mypy handles imports::
+* Missing imports::
+* Following imports::
+* Mapping file paths to modules::
+* How imports are found::
+* Other advice and best practices::
+* Directories specific to Python 2 (@python2): Directories specific to Python 2 @python2.
+
+
+File: Mypy.info,  Node: Specifying code to be checked,  Next: Reading a list of files from a file,  Up: Running mypy and managing imports
+
+22.1 Specifying code to be checked
+==================================
+
+Mypy lets you specify what files it should type check in several
+different ways.
+
+Note that if you use namespace packages (in particular, packages without
+‘__init__.py’), you’ll need to specify *note –namespace-packages: 132.
+
+  1. First, you can pass in paths to Python files and directories you
+     want to type check.  For example:
+
+          $ mypy file_1.py foo/file_2.py file_3.pyi some/directory
+
+     The above command tells mypy it should type check all of the
+     provided files together.  In addition, mypy will recursively type
+     check the entire contents of any provided directories.
+
+     For more details about how exactly this is done, see *note Mapping
+     file paths to modules: 133.
+
+  2. Second, you can use the *note -m: 134. flag (long form: *note
+     –module: 134.) to specify a module name to be type checked.  The
+     name of a module is identical to the name you would use to import
+     that module within a Python program.  For example, running:
+
+          $ mypy -m html.parser
+
+     …will type check the module ‘html.parser’ (this happens to be a
+     library stub).
+
+     Mypy will use an algorithm very similar to the one Python uses to
+     find where modules and imports are located on the file system.  For
+     more details, see *note How imports are found: 135.
+
+  3. Third, you can use the *note -p: 136. (long form: *note –package:
+     136.) flag to specify a package to be (recursively) type checked.
+     This flag is almost identical to the *note -m: 134. flag except
+     that if you give it a package name, mypy will recursively type
+     check all submodules and subpackages of that package.  For example,
+     running:
+
+          $ mypy -p html
+
+     …will type check the entire ‘html’ package (of library stubs).  In
+     contrast, if we had used the *note -m: 134. flag, mypy would have
+     type checked just ‘html’’s ‘__init__.py’ file and anything imported
+     from there.
+
+     Note that we can specify multiple packages and modules on the
+     command line.  For example:
+
+          $ mypy --package p.a --package p.b --module c
+
+  4. Fourth, you can also instruct mypy to directly type check small
+     strings as programs by using the *note -c: 137. (long form: *note
+     –command: 137.) flag.  For example:
+
+          $ mypy -c 'x = [1, 2]; print(x())'
+
+     …will type check the above string as a mini-program (and in this
+     case, will report that ‘list[int]’ is not callable).
+
+
+File: Mypy.info,  Node: Reading a list of files from a file,  Next: How mypy handles imports,  Prev: Specifying code to be checked,  Up: Running mypy and managing imports
+
+22.2 Reading a list of files from a file
+========================================
+
+Finally, any command-line argument starting with ‘@’ reads additional
+command-line arguments from the file following the ‘@’ character.  This
+is primarily useful if you have a file containing a list of files that
+you want to be type-checked: instead of using shell syntax like:
+
+     $ mypy $(cat file_of_files.txt)
+
+you can use this instead:
+
+     $ mypy @file_of_files.txt
+
+This file can technically also contain any command line flag, not just
+file paths.  However, if you want to configure many different flags, the
+recommended approach is to use a *note configuration file: 2e. instead.
+
+
+File: Mypy.info,  Node: How mypy handles imports,  Next: Missing imports,  Prev: Reading a list of files from a file,  Up: Running mypy and managing imports
+
+22.3 How mypy handles imports
+=============================
+
+When mypy encounters an ‘import’ statement, it will first *note attempt
+to locate: 135. that module or type stubs for that module in the file
+system.  Mypy will then type check the imported module.  There are three
+different outcomes of this process:
+
+  1. Mypy is unable to follow the import: the module either does not
+     exist, or is a third party library that does not use type hints.
+
+  2. Mypy is able to follow and type check the import, but you did not
+     want mypy to type check that module at all.
+
+  3. Mypy is able to successfully both follow and type check the module,
+     and you want mypy to type check that module.
+
+The third outcome is what mypy will do in the ideal case.  The following
+sections will discuss what to do in the other two cases.
+
+
+File: Mypy.info,  Node: Missing imports,  Next: Following imports,  Prev: How mypy handles imports,  Up: Running mypy and managing imports
+
+22.4 Missing imports
+====================
+
+When you import a module, mypy may report that it is unable to follow
+the import.  This can cause errors that look like the following:
+
+     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"
+
+If you get any of these errors on an import, mypy will assume the type
+of that module is ‘Any’, the dynamic type.  This means attempting to
+access any attribute of the module will automatically succeed:
+
+     # Error: Cannot find implementation or library stub for module named 'does_not_exist'
+     import does_not_exist
+
+     # But this type checks, and x will have type 'Any'
+     x = does_not_exist.foobar()
+
+The next sections describe what each of these errors means and
+recommended next steps; scroll to the section that matches your error.
+
+* Menu:
+
+* Missing library stubs or py.typed marker: Missing library stubs or py typed marker.
+* Library stubs not installed::
+* Cannot find implementation or library stub::
+
+
+File: Mypy.info,  Node: Missing library stubs or py typed marker,  Next: Library stubs not installed,  Up: Missing imports
+
+22.4.1 Missing library stubs or py.typed marker
+-----------------------------------------------
+
+If you are getting a ‘Skipping analyzing X: module is installed, but
+missing library stubs or py.typed marker’, error, this means mypy was
+able to find the module you were importing, but no corresponding type
+hints.
+
+Mypy will not try inferring the types of any 3rd party libraries you
+have installed unless they either have declared themselves to be *note
+PEP 561 compliant stub package: 15. (e.g.  with a ‘py.typed’ file) or
+have registered themselves on typeshed(1), the repository of types for
+the standard library and some 3rd party libraries.
+
+If you are getting this error, try:
+
+  1. Upgrading the version of the library you’re using, in case a newer
+     version has started to include type hints.
+
+  2. Searching to see if there is a *note PEP 561 compliant stub
+     package: 15.  corresponding to your third party library.  Stub
+     packages let you install type hints independently from the library
+     itself.
+
+     For example, if you want type hints for the ‘django’ library, you
+     can install the django-stubs(2) package.
+
+  3. *note Writing your own stub files: 16. containing type hints for
+     the library.  You can point mypy at your type hints either by
+     passing them in via the command line, by using the *note files:
+     13c. or *note mypy_path: 13d. config file options, or by adding the
+     location to the ‘MYPYPATH’ environment variable.
+
+     These stub files do not need to be complete!  A good strategy is to
+     use stubgen, a program that comes bundled with mypy, to generate a
+     first rough draft of the stubs.  You can then iterate on just the
+     parts of the library you need.
+
+     If you want to share your work, you can try contributing your stubs
+     back to the library – see our documentation on creating *note PEP
+     561 compliant packages: 15.
+
+If you are unable to find any existing type hints nor have time to write
+your own, you can instead `suppress' the errors.  All this will do is
+make mypy stop reporting an error on the line containing the import: the
+imported module will continue to be of type ‘Any’.
+
+  1. To suppress a `single' missing import error, add a ‘# type: ignore’
+     at the end of the line containing the import.
+
+  2. To suppress `all' missing import imports errors from a single
+     library, add a section to your *note mypy config file: 2e. for that
+     library setting *note ignore_missing_imports: 13e. to True.  For
+     example, suppose your codebase makes heavy use of an (untyped)
+     library named ‘foobar’.  You can silence all import errors
+     associated with that library and that library alone by adding the
+     following section to your config file:
+
+          [mypy-foobar.*]
+          ignore_missing_imports = True
+
+     Note: this option is equivalent to adding a ‘# type: ignore’ to
+     every import of ‘foobar’ in your codebase.  For more information,
+     see the documentation about configuring *note import discovery:
+     13f. in config files.  The ‘.*’ after ‘foobar’ will ignore imports
+     of ‘foobar’ modules and subpackages in addition to the ‘foobar’
+     top-level package namespace.
+
+  3. To suppress `all' missing import errors for `all' libraries in your
+     codebase, invoke mypy with the *note –ignore-missing-imports: 140.
+     command line flag or set the *note ignore_missing_imports: 13e.
+     config file option to True in the `global' section of your mypy
+     config file:
+
+          [mypy]
+          ignore_missing_imports = True
+
+     We recommend using this approach only as a last resort: it’s
+     equivalent to adding a ‘# type: ignore’ to all unresolved imports
+     in your codebase.
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/typeshed
+
+   (2) https://pypi.org/project/django-stubs/
+
+
+File: Mypy.info,  Node: Library stubs not installed,  Next: Cannot find implementation or library stub,  Prev: Missing library stubs or py typed marker,  Up: Missing imports
+
+22.4.2 Library stubs not installed
+----------------------------------
+
+If mypy can’t find stubs for a third-party library, and it knows that
+stubs exist for the library, you will get a message like this:
+
+     main.py:1: error: Library stubs not installed for "yaml" (or incompatible with Python 3.8)
+     main.py:1: note: Hint: "python3 -m pip install types-PyYAML"
+     main.py:1: note: (or run "mypy --install-types" to install all missing stub packages)
+
+You can resolve the issue by running the suggested pip command or
+commands.  Alternatively, you can use *note –install-types: 142. to
+install all known missing stubs:
+
+     mypy --install-types
+
+This installs any stub packages that were suggested in the previous mypy
+run.  You can also use your normal mypy command line with the extra
+*note –install-types: 142. option to install missing stubs at the end of
+the run (if any were found).
+
+Use *note –install-types: 142. with *note –non-interactive: 143. to
+install all suggested stub packages without asking for confirmation,
+`and' type check your code, in a single command:
+
+     mypy --install-types --non-interactive src/
+
+This can be useful in Continuous Integration jobs if you’d prefer not to
+manage stub packages manually.  This is somewhat slower than explicitly
+installing stubs before running mypy, since it may type check your code
+twice – the first time to find the missing stubs, and the second time to
+type check your code properly after mypy has installed the stubs.
+
+
+File: Mypy.info,  Node: Cannot find implementation or library stub,  Prev: Library stubs not installed,  Up: Missing imports
+
+22.4.3 Cannot find implementation or library stub
+-------------------------------------------------
+
+If you are getting a ‘Cannot find implementation or library stub for
+module’ error, this means mypy was not able to find the module you are
+trying to import, whether it comes bundled with type hints or not.  If
+you are getting this error, try:
+
+  1. Making sure your import does not contain a typo.
+
+  2. If the module is a third party library, making sure that mypy is
+     able to find the interpreter containing the installed library.
+
+     For example, if you are running your code in a virtualenv, make
+     sure to install and use mypy within the virtualenv.  Alternatively,
+     if you want to use a globally installed mypy, set the *note
+     –python-executable: 146. command line flag to point the Python
+     interpreter containing your installed third party packages.
+
+  2. Reading the *note How imports are found: 135. section below to make
+     sure you understand how exactly mypy searches for and finds modules
+     and modify how you’re invoking mypy accordingly.
+
+  3. Directly specifying the directory containing the module you want to
+     type check from the command line, by using the *note mypy_path:
+     13d. or *note files: 13c. config file options, or by using the
+     ‘MYPYPATH’ environment variable.
+
+     Note: if the module you are trying to import is actually a
+     `submodule' of some package, you should specify the directory
+     containing the `entire' package.  For example, suppose you are
+     trying to add the module ‘foo.bar.baz’ which is located at
+     ‘~/foo-project/src/foo/bar/baz.py’.  In this case, you must run
+     ‘mypy ~/foo-project/src’ (or set the ‘MYPYPATH’ to
+     ‘~/foo-project/src’.
+
+  4. If you are using namespace packages – packages which do not contain
+     ‘__init__.py’ files within each subfolder – using the *note
+     –namespace-packages: 132. command line flag.
+
+In some rare cases, you may get the “Cannot find implementation or
+library stub for module” error even when the module is installed in your
+system.  This can happen when the module is both missing type hints and
+is installed on your system in a unconventional way.
+
+In this case, follow the steps above on how to handle *note missing type
+hints in third party libraries: 145.
+
+
+File: Mypy.info,  Node: Following imports,  Next: Mapping file paths to modules,  Prev: Missing imports,  Up: Running mypy and managing imports
+
+22.5 Following imports
+======================
+
+Mypy is designed to *note doggedly follow all imports: 135, even if the
+imported module is not a file you explicitly wanted mypy to check.
+
+For example, suppose we have two modules ‘mycode.foo’ and ‘mycode.bar’:
+the former has type hints and the latter does not.  We run *note mypy -m
+mycode.foo: 134. and mypy discovers that ‘mycode.foo’ imports
+‘mycode.bar’.
+
+How do we want mypy to type check ‘mycode.bar’?  Mypy’s behaviour here
+is configurable – although we `strongly recommend' using the default –
+by using the *note –follow-imports: 148. flag.  This flag accepts one of
+four string values:
+
+   - ‘normal’ (the default, recommended) follows all imports normally
+     and type checks all top level code (as well as the bodies of all
+     functions and methods with at least one type annotation in the
+     signature).
+
+   - ‘silent’ behaves in the same way as ‘normal’ but will additionally
+     `suppress' any error messages.
+
+   - ‘skip’ will `not' follow imports and instead will silently replace
+     the module (and `anything imported from it') with an object of type
+     ‘Any’.
+
+   - ‘error’ behaves in the same way as ‘skip’ but is not quite as
+     silent – it will flag the import as an error, like this:
+
+          main.py:1: note: Import of "mycode.bar" ignored
+          main.py:1: note: (Using --follow-imports=error, module not passed on command line)
+
+If you are starting a new codebase and plan on using type hints from the
+start, we recommend you use either *note –follow-imports=normal: 148.
+(the default) or *note –follow-imports=error: 148.  Either option will
+help make sure you are not skipping checking any part of your codebase
+by accident.
+
+If you are planning on adding type hints to a large, existing code base,
+we recommend you start by trying to make your entire codebase (including
+files that do not use type hints) pass under *note
+–follow-imports=normal: 148.  This is usually not too difficult to do:
+mypy is designed to report as few error messages as possible when it is
+looking at unannotated code.
+
+Only if doing this is intractable, we recommend passing mypy just the
+files you want to type check and use *note –follow-imports=silent: 148.
+Even if mypy is unable to perfectly type check a file, it can still
+glean some useful information by parsing it (for example, understanding
+what methods a given object has).  See *note Using mypy with an existing
+codebase: 1a. for more recommendations.
+
+We do not recommend using ‘skip’ unless you know what you are doing:
+while this option can be quite powerful, it can also cause many
+hard-to-debug errors.
+
+Adjusting import following behaviour is often most useful when
+restricted to specific modules.  This can be accomplished by setting a
+per-module *note follow_imports: 149. config option.
+
+
+File: Mypy.info,  Node: Mapping file paths to modules,  Next: How imports are found,  Prev: Following imports,  Up: Running mypy and managing imports
+
+22.6 Mapping file paths to modules
+==================================
+
+One of the main ways you can tell mypy what to type check is by
+providing mypy a list of paths.  For example:
+
+     $ mypy file_1.py foo/file_2.py file_3.pyi some/directory
+
+This section describes how exactly mypy maps the provided paths to
+modules to type check.
+
+   - Mypy will check all paths provided that correspond to files.
+
+   - Mypy will recursively discover and check all files ending in ‘.py’
+     or ‘.pyi’ in directory paths provided, after accounting for *note
+     –exclude: 14b.
+
+   - For each file to be checked, mypy will attempt to associate the
+     file (e.g.  ‘project/foo/bar/baz.py’) with a fully qualified module
+     name (e.g.  ‘foo.bar.baz’).  The directory the package is in
+     (‘project’) is then added to mypy’s module search paths.
+
+How mypy determines fully qualified module names depends on if the
+options *note –namespace-packages: 132. and *note
+–explicit-package-bases: 14c. are set.
+
+  1. If *note –namespace-packages: 132. is off, mypy will rely solely
+     upon the presence of ‘__init__.py[i]’ files to determine the fully
+     qualified module name.  That is, mypy will crawl up the directory
+     tree for as long as it continues to find ‘__init__.py’ (or
+     ‘__init__.pyi’) files.
+
+     For example, if your directory tree consists of
+     ‘pkg/subpkg/mod.py’, mypy would require ‘pkg/__init__.py’ and
+     ‘pkg/subpkg/__init__.py’ to exist in order correctly associate
+     ‘mod.py’ with ‘pkg.subpkg.mod’
+
+  2. If *note –namespace-packages: 132. is on, but *note
+     –explicit-package-bases: 14c. is off, mypy will allow for the
+     possibility that directories without ‘__init__.py[i]’ are packages.
+     Specifically, mypy will look at all parent directories of the file
+     and use the location of the highest ‘__init__.py[i]’ in the
+     directory tree to determine the top-level package.
+
+     For example, say your directory tree consists solely of
+     ‘pkg/__init__.py’ and ‘pkg/a/b/c/d/mod.py’.  When determining
+     ‘mod.py’’s fully qualified module name, mypy will look at
+     ‘pkg/__init__.py’ and conclude that the associated module name is
+     ‘pkg.a.b.c.d.mod’.
+
+  3. You’ll notice that the above case still relies on ‘__init__.py’.
+     If you can’t put an ‘__init__.py’ in your top-level package, but
+     still wish to pass paths (as opposed to packages or modules using
+     the ‘-p’ or ‘-m’ flags), *note –explicit-package-bases: 14c.
+     provides a solution.
+
+     With *note –explicit-package-bases: 14c, mypy will locate the
+     nearest parent directory that is a member of the ‘MYPYPATH’
+     environment variable, the *note mypy_path: 13d. config or is the
+     current working directory.  Mypy will then use the relative path to
+     determine the fully qualified module name.
+
+     For example, say your directory tree consists solely of
+     ‘src/namespace_pkg/mod.py’.  If you run the following command, mypy
+     will correctly associate ‘mod.py’ with ‘namespace_pkg.mod’:
+
+          $ MYPYPATH=src mypy --namespace-packages --explicit-package-bases .
+
+If you pass a file not ending in ‘.py[i]’, the module name assumed is
+‘__main__’ (matching the behavior of the Python interpreter), unless
+*note –scripts-are-modules: 14d. is passed.
+
+Passing *note -v: 14e. will show you the files and associated module
+names that mypy will check.
+
+
+File: Mypy.info,  Node: How imports are found,  Next: Other advice and best practices,  Prev: Mapping file paths to modules,  Up: Running mypy and managing imports
+
+22.7 How imports are found
+==========================
+
+When mypy encounters an ‘import’ statement or receives module names from
+the command line via the *note –module: 134. or *note –package: 136.
+flags, mypy tries to find the module on the file system similar to the
+way Python finds it.  However, there are some differences.
+
+First, mypy has its own search path.  This is computed from the
+following items:
+
+   - The ‘MYPYPATH’ environment variable (a colon-separated list of
+     directories).
+
+   - The *note mypy_path: 13d. config file option.
+
+   - The directories containing the sources given on the command line
+     (see *note Mapping file paths to modules: 133.).
+
+   - The installed packages marked as safe for type checking (see *note
+     PEP 561 support: 15.)
+
+   - The relevant directories of the typeshed(1) repo.
+
+     Note: You cannot point to a stub-only package ( PEP 561(2)) via the
+     ‘MYPYPATH’, it must be installed (see *note PEP 561 support: 15.)
+
+Second, mypy searches for stub files in addition to regular Python files
+and packages.  The rules for searching for a module ‘foo’ are as
+follows:
+
+   - The search looks in each of the directories in the search path (see
+     above) until a match is found.
+
+   - If a package named ‘foo’ is found (i.e.  a directory ‘foo’
+     containing an ‘__init__.py’ or ‘__init__.pyi’ file) that’s a match.
+
+   - If a stub file named ‘foo.pyi’ is found, that’s a match.
+
+   - If a Python module named ‘foo.py’ is found, that’s a match.
+
+These matches are tried in order, so that if multiple matches are found
+in the same directory on the search path (e.g.  a package and a Python
+file, or a stub file and a Python file) the first one in the above list
+wins.
+
+In particular, if a Python file and a stub file are both present in the
+same directory on the search path, only the stub file is used.
+(However, if the files are in different directories, the one found in
+the earlier directory is used.)
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/typeshed
+
+   (2) https://peps.python.org/pep-0561/
+
+
+File: Mypy.info,  Node: Other advice and best practices,  Next: Directories specific to Python 2 @python2,  Prev: How imports are found,  Up: Running mypy and managing imports
+
+22.8 Other advice and best practices
+====================================
+
+There are multiple ways of telling mypy what files to type check,
+ranging from passing in command line arguments to using the *note files:
+13c. or *note mypy_path: 13d. config file options to setting the
+‘MYPYPATH’ environment variable.
+
+However, in practice, it is usually sufficient to just use either
+command line arguments or the *note files: 13c. config file option (the
+two are largely interchangeable).
+
+Setting *note mypy_path: 13d./‘MYPYPATH’ is mostly useful in the case
+where you want to try running mypy against multiple distinct sets of
+files that happen to share some common dependencies.
+
+For example, if you have multiple projects that happen to be using the
+same set of work-in-progress stubs, it could be convenient to just have
+your ‘MYPYPATH’ point to a single directory containing the stubs.
+
+
+File: Mypy.info,  Node: Directories specific to Python 2 @python2,  Prev: Other advice and best practices,  Up: Running mypy and managing imports
+
+22.9 Directories specific to Python 2 (@python2)
+================================================
+
+When type checking in Python 2 mode, mypy also looks for files under the
+‘@python2’ subdirectory of each ‘MYPYPATH’ and ‘mypy_path’ entry, if the
+subdirectory exists.  Files under the subdirectory take precedence over
+the parent directory.  This can be used to provide separate Python 2
+versions of stubs.
+
+     Note: This does not need to be used (and cannot be used) with *note
+     PEP 561 compliant stub packages: 15.
+
+
+File: Mypy.info,  Node: The mypy command line,  Next: The mypy configuration file,  Prev: Running mypy and managing imports,  Up: Top
+
+23 The mypy command line
+************************
+
+This section documents mypy’s command line interface.  You can view a
+quick summary of the available flags by running *note mypy –help: 154.
+
+     Note: Command line flags are liable to change between releases.
+
+* Menu:
+
+* Specifying what to type check::
+* Optional arguments::
+* Config file::
+* Import discovery::
+* Platform configuration::
+* Disallow dynamic typing::
+* Untyped definitions and calls::
+* None and Optional handling::
+* Configuring warnings::
+* Miscellaneous strictness flags::
+* Configuring error messages::
+* Incremental mode::
+* Advanced options::
+* Report generation::
+* Miscellaneous: Miscellaneous<3>.
+
+
+File: Mypy.info,  Node: Specifying what to type check,  Next: Optional arguments,  Up: The mypy command line
+
+23.1 Specifying what to type check
+==================================
+
+By default, you can specify what code you want mypy to type check by
+passing in the paths to what you want to have type checked:
+
+     $ mypy foo.py bar.py some_directory
+
+Note that directories are checked recursively.
+
+Mypy also lets you specify what code to type check in several other
+ways.  A short summary of the relevant flags is included below: for full
+details, see *note Running mypy and managing imports: 12e.
+
+ -- Option: -m MODULE, --module MODULE
+
+     Asks mypy to type check the provided module.  This flag may be
+     repeated multiple times.
+
+     Mypy `will not' recursively type check any submodules of the
+     provided module.
+
+ -- Option: -p PACKAGE, --package PACKAGE
+
+     Asks mypy to type check the provided package.  This flag may be
+     repeated multiple times.
+
+     Mypy `will' recursively type check any submodules of the provided
+     package.  This flag is identical to *note –module: 134. apart from
+     this behavior.
+
+ -- Option: -c PROGRAM_TEXT, --command PROGRAM_TEXT
+
+     Asks mypy to type check the provided string as a program.
+
+ -- Option: --exclude
+
+     A regular expression that matches file names, directory names and
+     paths which mypy should ignore while recursively discovering files
+     to check.  Use forward slashes on all platforms.
+
+     For instance, to avoid discovering any files named ‘setup.py’ you
+     could pass ‘--exclude '/setup\.py$'’.  Similarly, you can ignore
+     discovering directories with a given name by e.g.  ‘--exclude
+     /build/’ or those matching a subpath with ‘--exclude
+     /project/vendor/’.  To ignore multiple files / directories / paths,
+     you can provide the –exclude flag more than once, e.g ‘--exclude
+     '/setup\.py$' --exclude '/build/'’.
+
+     Note that this flag only affects recursive directory tree
+     discovery, that is, when mypy is discovering files within a
+     directory tree or submodules of a package to check.  If you pass a
+     file or module explicitly it will still be checked.  For instance,
+     ‘mypy --exclude '/setup.py$' but_still_check/setup.py’.
+
+     In particular, ‘--exclude’ does not affect mypy’s *note import
+     following: 22.  You can use a per-module *note follow_imports: 149.
+     config option to additionally avoid mypy from following imports and
+     checking code you do not wish to be checked.
+
+     Note that mypy will never recursively discover files and
+     directories named “site-packages”, “node_modules” or “__pycache__”,
+     or those whose name starts with a period, exactly as ‘--exclude
+     '/(site-packages|node_modules|__pycache__|\..*)/$'’ would.  Mypy
+     will also never recursively discover files with extensions other
+     than ‘.py’ or ‘.pyi’.
+
+
+File: Mypy.info,  Node: Optional arguments,  Next: Config file,  Prev: Specifying what to type check,  Up: The mypy command line
+
+23.2 Optional arguments
+=======================
+
+ -- Option: -h, --help
+
+     Show help message and exit.
+
+ -- Option: -v, --verbose
+
+     More verbose messages.
+
+ -- Option: -V, --version
+
+     Show program’s version number and exit.
+
+
+File: Mypy.info,  Node: Config file,  Next: Import discovery,  Prev: Optional arguments,  Up: The mypy command line
+
+23.3 Config file
+================
+
+ -- Option: --config-file CONFIG_FILE
+
+     This flag makes mypy read configuration settings from the given
+     file.
+
+     By default settings are read from ‘mypy.ini’, ‘.mypy.ini’,
+     ‘pyproject.toml’, or ‘setup.cfg’ in the current directory.
+     Settings override mypy’s built-in defaults and command line flags
+     can override settings.
+
+     Specifying *note –config-file=: 160. (with no filename) will ignore
+     `all' config files.
+
+     See *note The mypy configuration file: 2e. for the syntax of
+     configuration files.
+
+ -- Option: --warn-unused-configs
+
+     This flag makes mypy warn about unused ‘[mypy-<pattern>]’ config
+     file sections.  (This requires turning off incremental mode using
+     *note –no-incremental: 162.)
+
+
+File: Mypy.info,  Node: Import discovery,  Next: Platform configuration,  Prev: Config file,  Up: The mypy command line
+
+23.4 Import discovery
+=====================
+
+The following flags customize how exactly mypy discovers and follows
+imports.
+
+ -- Option: --namespace-packages
+
+     This flag enables import discovery to use namespace packages (see
+     PEP 420(1)).  In particular, this allows discovery of imported
+     packages that don’t have an ‘__init__.py’ (or ‘__init__.pyi’) file.
+
+     Namespace packages are found (using the PEP 420 rules, which
+     prefers “classic” packages over namespace packages) along the
+     module search path – this is primarily set from the source files
+     passed on the command line, the ‘MYPYPATH’ environment variable,
+     and the *note mypy_path: 13d. config option.
+
+     This flag affects how mypy finds modules and packages explicitly
+     passed on the command line.  It also affects how mypy determines
+     fully qualified module names for files passed on the command line.
+     See *note Mapping file paths to modules: 133. for details.
+
+ -- Option: --explicit-package-bases
+
+     This flag tells mypy that top-level packages will be based in
+     either the current directory, or a member of the ‘MYPYPATH’
+     environment variable or *note mypy_path: 13d. config option.  This
+     option is only useful in conjunction with *note
+     –namespace-packages: 132.  See *note Mapping file paths to modules:
+     133. for details.
+
+ -- Option: --ignore-missing-imports
+
+     This flag makes mypy ignore all missing imports.  It is equivalent
+     to adding ‘# type: ignore’ comments to all unresolved imports
+     within your codebase.
+
+     Note that this flag does `not' suppress errors about missing names
+     in successfully resolved modules.  For example, if one has the
+     following files:
+
+          package/__init__.py
+          package/mod.py
+
+     Then mypy will generate the following errors with *note
+     –ignore-missing-imports: 140.:
+
+          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'
+
+     For more details, see *note Missing imports: 17.
+
+ -- Option: --follow-imports {normal,silent,skip,error}
+
+     This flag adjusts how mypy follows imported modules that were not
+     explicitly passed in via the command line.
+
+     The default option is ‘normal’: mypy will follow and type check all
+     modules.  For more information on what the other options do, see
+     *note Following imports: 22.
+
+ -- Option: --python-executable EXECUTABLE
+
+     This flag will have mypy collect type information from PEP 561(2)
+     compliant packages installed for the Python executable
+     ‘EXECUTABLE’.  If not provided, mypy will use PEP 561 compliant
+     packages installed for the Python executable running mypy.
+
+     See *note Using installed packages: 15. for more on making PEP 561
+     compliant packages.
+
+ -- Option: --no-site-packages
+
+     This flag will disable searching for PEP 561(3) compliant packages.
+     This will also disable searching for a usable Python executable.
+
+     Use this flag if mypy cannot find a Python executable for the
+     version of Python being checked, and you don’t need to use PEP 561
+     typed packages.  Otherwise, use *note –python-executable: 146.
+
+ -- Option: --no-silence-site-packages
+
+     By default, mypy will suppress any error messages generated within
+     PEP 561(4) compliant packages.  Adding this flag will disable this
+     behavior.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0420/
+
+   (2) https://peps.python.org/pep-0561/
+
+   (3) https://peps.python.org/pep-0561/
+
+   (4) https://peps.python.org/pep-0561/
+
+
+File: Mypy.info,  Node: Platform configuration,  Next: Disallow dynamic typing,  Prev: Import discovery,  Up: The mypy command line
+
+23.5 Platform configuration
+===========================
+
+By default, mypy will assume that you intend to run your code using the
+same operating system and Python version you are using to run mypy
+itself.  The following flags let you modify this behavior.
+
+For more information on how to use these flags, see *note Python version
+and system platform checks: fd.
+
+ -- Option: --python-version X.Y
+
+     This flag will make mypy type check your code as if it were run
+     under Python version X.Y. Without this option, mypy will default to
+     using whatever version of Python is running mypy.  Note that the
+     *note -2: 8. and *note –py2: 8. flags are aliases for *note
+     –python-version 2.7: 100.
+
+     This flag will attempt to find a Python executable of the
+     corresponding version to search for PEP 561(1) compliant packages.
+     If you’d like to disable this, use the *note –no-site-packages:
+     165. flag (see *note Import discovery: 164. for more details).
+
+ -- Option: -2, --py2
+
+     Equivalent to running *note –python-version 2.7: 100.
+
+          Note: To check Python 2 code with mypy, you’ll need to install
+          mypy with ‘pip install 'mypy[python2]'’.
+
+ -- Option: --platform PLATFORM
+
+     This flag will make mypy type check your code as if it were run
+     under the given operating system.  Without this option, mypy will
+     default to using whatever operating system you are currently using.
+
+     The ‘PLATFORM’ parameter may be any string supported by
+     sys.platform(2).
+ -- Option: --always-true NAME
+
+     This flag will treat all variables named ‘NAME’ as compile-time
+     constants that are always true.  This flag may be repeated.
+
+ -- Option: --always-false NAME
+
+     This flag will treat all variables named ‘NAME’ as compile-time
+     constants that are always false.  This flag may be repeated.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0561/
+
+   (2) https://docs.python.org/3/library/sys.html#sys.platform
+
+
+File: Mypy.info,  Node: Disallow dynamic typing,  Next: Untyped definitions and calls,  Prev: Platform configuration,  Up: The mypy command line
+
+23.6 Disallow dynamic typing
+============================
+
+The ‘Any’ type is used to represent a value that has a *note dynamic
+type: 4b.  The ‘--disallow-any’ family of flags will disallow various
+uses of the ‘Any’ type in a module – this lets us strategically disallow
+the use of dynamic typing in a controlled way.
+
+The following options are available:
+
+ -- Option: --disallow-any-unimported
+
+     This flag disallows usage of types that come from unfollowed
+     imports (such types become aliases for ‘Any’).  Unfollowed imports
+     occur either when the imported module does not exist or when *note
+     –follow-imports=skip: 148. is set.
+
+ -- Option: --disallow-any-expr
+
+     This flag disallows all expressions in the module that have type
+     ‘Any’.  If an expression of type ‘Any’ appears anywhere in the
+     module mypy will output an error unless the expression is
+     immediately used as an argument to cast()(1) or assigned to a
+     variable with an explicit type annotation.
+
+     In addition, declaring a variable of type ‘Any’ or casting to type
+     ‘Any’ is not allowed.  Note that calling functions that take
+     parameters of type ‘Any’ is still allowed.
+
+ -- Option: --disallow-any-decorated
+
+     This flag disallows functions that have ‘Any’ in their signature
+     after decorator transformation.
+
+ -- Option: --disallow-any-explicit
+
+     This flag disallows explicit ‘Any’ in type positions such as type
+     annotations and generic type parameters.
+
+ -- Option: --disallow-any-generics
+
+     This flag disallows usage of generic types that do not specify
+     explicit type parameters.  For example, you can’t use a bare ‘x:
+     list’.  Instead, you must always write something like ‘x:
+     list[int]’.
+
+ -- Option: --disallow-subclassing-any
+
+     This flag reports an error whenever a class subclasses a value of
+     type ‘Any’.  This may occur when the base class is imported from a
+     module that doesn’t exist (when using *note
+     –ignore-missing-imports: 140.) or is ignored due to *note
+     –follow-imports=skip: 148. or a ‘# type: ignore’ comment on the
+     ‘import’ statement.
+
+     Since the module is silenced, the imported class is given a type of
+     ‘Any’.  By default mypy will assume that the subclass correctly
+     inherited the base class even though that may not actually be the
+     case.  This flag makes mypy raise an error instead.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.cast
+
+
+File: Mypy.info,  Node: Untyped definitions and calls,  Next: None and Optional handling,  Prev: Disallow dynamic typing,  Up: The mypy command line
+
+23.7 Untyped definitions and calls
+==================================
+
+The following flags configure how mypy handles untyped function
+definitions or calls.
+
+ -- Option: --disallow-untyped-calls
+
+     This flag reports an error whenever a function with type
+     annotations calls a function defined without annotations.
+
+ -- Option: --disallow-untyped-defs
+
+     This flag reports an error whenever it encounters a function
+     definition without type annotations.
+
+ -- Option: --disallow-incomplete-defs
+
+     This flag reports an error whenever it encounters a partly
+     annotated function definition.
+
+ -- Option: --check-untyped-defs
+
+     This flag is less severe than the previous two options – it type
+     checks the body of every function, regardless of whether it has
+     type annotations.  (By default the bodies of functions without
+     annotations are not type checked.)
+
+     It will assume all arguments have type ‘Any’ and always infer ‘Any’
+     as the return type.
+
+ -- Option: --disallow-untyped-decorators
+
+     This flag reports an error whenever a function with type
+     annotations is decorated with a decorator without annotations.
+
+
+File: Mypy.info,  Node: None and Optional handling,  Next: Configuring warnings,  Prev: Untyped definitions and calls,  Up: The mypy command line
+
+23.8 None and Optional handling
+===============================
+
+The following flags adjust how mypy handles values of type ‘None’.  For
+more details, see *note Disabling strict optional checking: 70.
+ -- Option: --no-implicit-optional
+
+     This flag causes mypy to stop treating arguments with a ‘None’
+     default value as having an implicit Optional(1) type.
+
+     For example, by default mypy will assume that the ‘x’ parameter is
+     of type ‘Optional[int]’ in the code snippet below since the default
+     parameter is ‘None’:
+
+          def foo(x: int = None) -> None:
+              print(x)
+
+     If this flag is set, the above snippet will no longer type check:
+     we must now explicitly indicate that the type is ‘Optional[int]’:
+
+          def foo(x: Optional[int] = None) -> None:
+              print(x)
+
+ -- Option: --no-strict-optional
+
+     This flag disables strict checking of Optional(2) types and ‘None’
+     values.  With this option, mypy doesn’t generally check the use of
+     ‘None’ values – they are valid everywhere.  See *note Disabling
+     strict optional checking: 70. for more about this feature.
+
+     `Note:' Strict optional checking was enabled by default starting in
+     mypy 0.600, and in previous versions it had to be explicitly
+     enabled using ‘--strict-optional’ (which is still accepted).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Optional
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Optional
+
+
+File: Mypy.info,  Node: Configuring warnings,  Next: Miscellaneous strictness flags,  Prev: None and Optional handling,  Up: The mypy command line
+
+23.9 Configuring warnings
+=========================
+
+The following flags enable warnings for code that is sound but is
+potentially problematic or redundant in some way.
+
+ -- Option: --warn-redundant-casts
+
+     This flag will make mypy report an error whenever your code uses an
+     unnecessary cast that can safely be removed.
+
+ -- Option: --warn-unused-ignores
+
+     This flag will make mypy report an error whenever your code uses a
+     ‘# type: ignore’ comment on a line that is not actually generating
+     an error message.
+
+     This flag, along with the *note –warn-redundant-casts: 17d. flag,
+     are both particularly useful when you are upgrading mypy.
+     Previously, you may have needed to add casts or ‘# type: ignore’
+     annotations to work around bugs in mypy or missing stubs for 3rd
+     party libraries.
+
+     These two flags let you discover cases where either workarounds are
+     no longer necessary.
+
+ -- Option: --no-warn-no-return
+
+     By default, mypy will generate errors when a function is missing
+     return statements in some execution paths.  The only exceptions are
+     when:
+
+        - The function has a ‘None’ or ‘Any’ return type
+
+        - The function has an empty body or a body that is just ellipsis
+          (‘...’).  Empty functions are often used for abstract methods.
+
+     Passing in *note –no-warn-no-return: 17f. will disable these error
+     messages in all cases.
+
+ -- Option: --warn-return-any
+
+     This flag causes mypy to generate a warning when returning a value
+     with type ‘Any’ from a function declared with a non-‘Any’ return
+     type.
+
+ -- Option: --warn-unreachable
+
+     This flag will make mypy report an error whenever it encounters
+     code determined to be unreachable or redundant after performing
+     type analysis.  This can be a helpful way of detecting certain
+     kinds of bugs in your code.
+
+     For example, enabling this flag will make mypy report that the ‘x >
+     7’ check is redundant and that the ‘else’ block below is
+     unreachable.
+
+          def process(x: int) -> None:
+              # Error: Right operand of "or" is never evaluated
+              if isinstance(x, int) or x > 7:
+                  # Error: Unsupported operand types for + ("int" and "str")
+                  print(x + "bad")
+              else:
+                  # Error: 'Statement is unreachable' error
+                  print(x + "bad")
+
+     To help prevent mypy from generating spurious warnings, the
+     “Statement is unreachable” warning will be silenced in exactly two
+     cases:
+
+       1. When the unreachable statement is a ‘raise’ statement, is an
+          ‘assert False’ statement, or calls a function that has the
+          NoReturn(1) return type hint.  In other words, when the
+          unreachable statement throws an error or terminates the
+          program in some way.
+
+       2. When the unreachable statement was `intentionally' marked as
+          unreachable using *note Python version and system platform
+          checks: fd.
+
+          Note: Mypy currently cannot detect and report unreachable or
+          redundant code inside any functions using *note Type variables
+          with value restriction: 7c.
+
+          This limitation will be removed in future releases of mypy.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.NoReturn
+
+
+File: Mypy.info,  Node: Miscellaneous strictness flags,  Next: Configuring error messages,  Prev: Configuring warnings,  Up: The mypy command line
+
+23.10 Miscellaneous strictness flags
+====================================
+
+This section documents any other flags that do not neatly fall under any
+of the above sections.
+
+ -- Option: --allow-untyped-globals
+
+     This flag causes mypy to suppress errors caused by not being able
+     to fully infer the types of global and class variables.
+
+ -- Option: --allow-redefinition
+
+     By default, mypy won’t allow a variable to be redefined with an
+     unrelated type.  This flag enables redefinition of a variable with
+     an arbitrary type `in some contexts': only redefinitions within the
+     same block and nesting depth as the original definition are
+     allowed.  Example where this can be useful:
+
+          def process(items: list[str]) -> None:
+              # 'items' has type list[str]
+              items = [item.split() for item in items]
+              # 'items' now has type list[list[str]]
+
+     The variable must be used before it can be redefined:
+
+          def process(items: list[str]) -> None:
+             items = "mypy"  # invalid redefinition to str because the variable hasn't been used yet
+             print(items)
+             items = "100"  # valid, items now has type str
+             items = int(items)  # valid, items now has type int
+
+ -- Option: --local-partial-types
+
+     In mypy, the most common cases for partial types are variables
+     initialized using ‘None’, but without explicit ‘Optional’
+     annotations.  By default, mypy won’t check partial types spanning
+     module top level or class top level.  This flag changes the
+     behavior to only allow partial types at local level, therefore it
+     disallows inferring variable type for ‘None’ from two assignments
+     in different scopes.  For example:
+
+          from typing import Optional
+
+          a = None  # Need type annotation here if using --local-partial-types
+          b = None  # type: Optional[int]
+
+          class Foo:
+              bar = None  # Need type annotation here if using --local-partial-types
+              baz = None  # type: Optional[int]
+
+              def __init__(self) -> None:
+                  self.bar = 1
+
+          reveal_type(Foo().bar)  # Union[int, None] without --local-partial-types
+
+     Note: this option is always implicitly enabled in mypy daemon and
+     will become enabled by default for mypy in a future release.
+
+ -- Option: --no-implicit-reexport
+
+     By default, imported values to a module are treated as exported and
+     mypy allows other modules to import them.  This flag changes the
+     behavior to not re-export unless the item is imported using from-as
+     or is included in ‘__all__’.  Note this is always treated as
+     enabled for stub files.  For example:
+
+          # This won't re-export the value
+          from foo import bar
+
+          # Neither will this
+          from foo import bar as bang
+
+          # This will re-export it as bar and allow other modules to import it
+          from foo import bar as bar
+
+          # This will also re-export bar
+          from foo import bar
+          __all__ = ['bar']
+
+ -- Option: --strict-equality
+
+     By default, mypy allows always-false comparisons like ‘42 == 'no'’.
+     Use this flag to prohibit such comparisons of non-overlapping
+     types, and similar identity and container checks:
+
+          from typing import Text
+
+          items: list[int]
+          if 'some string' in items:  # Error: non-overlapping container check!
+              ...
+
+          text: Text
+          if text != b'other bytes':  # Error: non-overlapping equality check!
+              ...
+
+          assert text is not None  # OK, check against None is allowed as a special case.
+
+ -- Option: --strict
+
+     This flag mode enables all optional error checking flags.  You can
+     see the list of flags enabled by strict mode in the full *note mypy
+     –help: 154. output.
+
+     Note: the exact list of flags enabled by running *note –strict: 19.
+     may change over time.
+
+ -- Option: --disable-error-code
+
+     This flag allows disabling one or multiple error codes globally.
+
+          # no flag
+          x = 'a string'
+          x.trim()  # error: "str" has no attribute "trim"  [attr-defined]
+
+          # --disable-error-code attr-defined
+          x = 'a string'
+          x.trim()
+
+ -- Option: --enable-error-code
+
+     This flag allows enabling one or multiple error codes globally.
+
+     Note: This flag will override disabled error codes from the
+     –disable-error-code flag
+
+          # --disable-error-code attr-defined
+          x = 'a string'
+          x.trim()
+
+          # --disable-error-code attr-defined --enable-error-code attr-defined
+          x = 'a string'
+          x.trim()  # error: "str" has no attribute "trim"  [attr-defined]
+
+
+File: Mypy.info,  Node: Configuring error messages,  Next: Incremental mode,  Prev: Miscellaneous strictness flags,  Up: The mypy command line
+
+23.11 Configuring error messages
+================================
+
+The following flags let you adjust how much detail mypy displays in
+error messages.
+
+ -- Option: --show-error-context
+
+     This flag will precede all errors with “note” messages explaining
+     the context of the error.  For example, consider the following
+     program:
+
+          class Test:
+              def foo(self, x: int) -> int:
+                  return x + "bar"
+
+     Mypy normally displays an error message that looks like this:
+
+          main.py:3: error: Unsupported operand types for + ("int" and "str")
+
+     If we enable this flag, the error message now looks like this:
+
+          main.py: note: In member "foo" of class "Test":
+          main.py:3: error: Unsupported operand types for + ("int" and "str")
+
+ -- Option: --show-column-numbers
+
+     This flag will add column offsets to error messages.  For example,
+     the following indicates an error in line 12, column 9 (note that
+     column offsets are 0-based):
+
+          main.py:12:9: error: Unsupported operand types for / ("int" and "str")
+
+ -- Option: --show-error-codes
+
+     This flag will add an error code ‘[<code>]’ to error messages.  The
+     error code is shown after each error message:
+
+          prog.py:1: error: "str" has no attribute "trim"  [attr-defined]
+
+     See *note Error codes: 18e. for more information.
+
+ -- Option: --pretty
+
+     Use visually nicer output in error messages: use soft word wrap,
+     show source code snippets, and show error location markers.
+
+ -- Option: --no-color-output
+
+     This flag will disable color output in error messages, enabled by
+     default.
+
+ -- Option: --no-error-summary
+
+     This flag will disable error summary.  By default mypy shows a
+     summary line including total number of errors, number of files with
+     errors, and number of files checked.
+
+ -- Option: --show-absolute-path
+
+     Show absolute paths to files.
+
+ -- Option: --soft-error-limit N
+
+     This flag will adjust the limit after which mypy will (sometimes)
+     disable reporting most additional errors.  The limit only applies
+     if it seems likely that most of the remaining errors will not be
+     useful or they may be overly noisy.  If ‘N’ is negative, there is
+     no limit.  The default limit is 200.
+
+
+File: Mypy.info,  Node: Incremental mode,  Next: Advanced options,  Prev: Configuring error messages,  Up: The mypy command line
+
+23.12 Incremental mode
+======================
+
+By default, mypy will store type information into a cache.  Mypy will
+use this information to avoid unnecessary recomputation when it type
+checks your code again.  This can help speed up the type checking
+process, especially when most parts of your program have not changed
+since the previous mypy run.
+
+If you want to speed up how long it takes to recheck your code beyond
+what incremental mode can offer, try running mypy in *note daemon mode:
+29.
+
+ -- Option: --no-incremental
+
+     This flag disables incremental mode: mypy will no longer reference
+     the cache when re-run.
+
+     Note that mypy will still write out to the cache even when
+     incremental mode is disabled: see the *note –cache-dir: 196. flag
+     below for more details.
+
+ -- Option: --cache-dir DIR
+
+     By default, mypy stores all cache data inside of a folder named
+     ‘.mypy_cache’ in the current directory.  This flag lets you change
+     this folder.  This flag can also be useful for controlling cache
+     use when using *note remote caching: 2a.
+
+     This setting will override the ‘MYPY_CACHE_DIR’ environment
+     variable if it is set.
+
+     Mypy will also always write to the cache even when incremental mode
+     is disabled so it can “warm up” the cache.  To disable writing to
+     the cache, use ‘--cache-dir=/dev/null’ (UNIX) or ‘--cache-dir=nul’
+     (Windows).
+
+ -- Option: --sqlite-cache
+
+     Use an SQLite(1) database to store the cache.
+
+ -- Option: --cache-fine-grained
+
+     Include fine-grained dependency information in the cache for the
+     mypy daemon.
+
+ -- Option: --skip-version-check
+
+     By default, mypy will ignore cache data generated by a different
+     version of mypy.  This flag disables that behavior.
+
+ -- Option: --skip-cache-mtime-checks
+
+     Skip cache internal consistency checks based on mtime.
+
+   ---------- Footnotes ----------
+
+   (1) https://www.sqlite.org/
+
+
+File: Mypy.info,  Node: Advanced options,  Next: Report generation,  Prev: Incremental mode,  Up: The mypy command line
+
+23.13 Advanced options
+======================
+
+The following flags are useful mostly for people who are interested in
+developing or debugging mypy internals.
+
+ -- Option: --pdb
+
+     This flag will invoke the Python debugger when mypy encounters a
+     fatal error.
+
+ -- Option: --show-traceback, --tb
+
+     If set, this flag will display a full traceback when mypy
+     encounters a fatal error.
+
+ -- Option: --raise-exceptions
+
+     Raise exception on fatal error.
+
+ -- Option: --custom-typing-module MODULE
+
+     This flag lets you use a custom module as a substitute for the
+     typing(1) module.
+
+ -- Option: --custom-typeshed-dir DIR
+
+     This flag specifies the directory where mypy looks for standard
+     library typeshed stubs, instead of the typeshed that ships with
+     mypy.  This is primarily intended to make it easier to test
+     typeshed changes before submitting them upstream, but also allows
+     you to use a forked version of typeshed.
+
+     Note that this doesn’t affect third-party library stubs.
+ -- Option: --warn-incomplete-stub
+
+     This flag modifies both the *note –disallow-untyped-defs: b. and
+     *note –disallow-incomplete-defs: 176. flags so they also report
+     errors if stubs in typeshed are missing type annotations or has
+     incomplete annotations.  If both flags are missing, *note
+     –warn-incomplete-stub: 1a3. also does nothing.
+
+     This flag is mainly intended to be used by people who want
+     contribute to typeshed and would like a convenient way to find gaps
+     and omissions.
+
+     If you want mypy to report an error when your codebase `uses' an
+     untyped function, whether that function is defined in typeshed or
+     not, use the *note –disallow-untyped-calls: 175. flag.  See *note
+     Untyped definitions and calls: fb. for more details.
+ -- Option: --shadow-file SOURCE_FILE SHADOW_FILE
+
+     When mypy is asked to type check ‘SOURCE_FILE’, this flag makes
+     mypy read from and type check the contents of ‘SHADOW_FILE’
+     instead.  However, diagnostics will continue to refer to
+     ‘SOURCE_FILE’.
+
+     Specifying this argument multiple times (‘--shadow-file X1 Y1
+     --shadow-file X2 Y2’) will allow mypy to perform multiple
+     substitutions.
+
+     This allows tooling to create temporary files with helpful
+     modifications without having to change the source file in place.
+     For example, suppose we have a pipeline that adds ‘reveal_type’ for
+     certain variables.  This pipeline is run on ‘original.py’ to
+     produce ‘temp.py’.  Running ‘mypy --shadow-file original.py temp.py
+     original.py’ will then cause mypy to type check the contents of
+     ‘temp.py’ instead of ‘original.py’, but error messages will still
+     reference ‘original.py’.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Report generation,  Next: Miscellaneous<3>,  Prev: Advanced options,  Up: The mypy command line
+
+23.14 Report generation
+=======================
+
+If these flags are set, mypy will generate a report in the specified
+format into the specified directory.
+
+ -- Option: --any-exprs-report DIR
+
+     Causes mypy to generate a text file report documenting how many
+     expressions of type ‘Any’ are present within your codebase.
+
+ -- Option: --cobertura-xml-report DIR
+
+     Causes mypy to generate a Cobertura XML type checking coverage
+     report.
+
+     To generate this report, you must either manually install the
+     lxml(1) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+ -- Option: --html-report / --xslt-html-report DIR
+
+     Causes mypy to generate an HTML type checking coverage report.
+
+     To generate this report, you must either manually install the
+     lxml(2) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+ -- Option: --linecount-report DIR
+
+     Causes mypy to generate a text file report documenting the
+     functions and lines that are typed and untyped within your
+     codebase.
+
+ -- Option: --linecoverage-report DIR
+
+     Causes mypy to generate a JSON file that maps each source file’s
+     absolute filename to a list of line numbers that belong to typed
+     functions in that file.
+
+ -- Option: --lineprecision-report DIR
+
+     Causes mypy to generate a flat text file report with per-module
+     statistics of how many lines are typechecked etc.
+
+ -- Option: --txt-report / --xslt-txt-report DIR
+
+     Causes mypy to generate a text file type checking coverage report.
+
+     To generate this report, you must either manually install the
+     lxml(3) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+ -- Option: --xml-report DIR
+
+     Causes mypy to generate an XML type checking coverage report.
+
+     To generate this report, you must either manually install the
+     lxml(4) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+   ---------- Footnotes ----------
+
+   (1) https://pypi.org/project/lxml/
+
+   (2) https://pypi.org/project/lxml/
+
+   (3) https://pypi.org/project/lxml/
+
+   (4) https://pypi.org/project/lxml/
+
+
+File: Mypy.info,  Node: Miscellaneous<3>,  Prev: Report generation,  Up: The mypy command line
+
+23.15 Miscellaneous
+===================
+
+ -- Option: --install-types
+
+     This flag causes mypy to install known missing stub packages for
+     third-party libraries using pip.  It will display the pip command
+     that will be run, and expects a confirmation before installing
+     anything.  For security reasons, these stubs are limited to only a
+     small subset of manually selected packages that have been verified
+     by the typeshed team.  These packages include only stub files and
+     no executable code.
+
+     If you use this option without providing any files or modules to
+     type check, mypy will install stub packages suggested during the
+     previous mypy run.  If there are files or modules to type check,
+     mypy first type checks those, and proposes to install missing stubs
+     at the end of the run, but only if any missing modules were
+     detected.
+
+          Note: This is new in mypy 0.900.  Previous mypy versions
+          included a selection of third-party package stubs, instead of
+          having them installed separately.
+
+ -- Option: --non-interactive
+
+     When used together with *note –install-types: 142, this causes mypy
+     to install all suggested stub packages using pip without asking for
+     confirmation, and then continues to perform type checking using the
+     installed stubs, if some files or modules are provided to type
+     check.
+
+     This is implemented as up to two mypy runs internally.  The first
+     run is used to find missing stub packages, and output is shown from
+     this run only if no missing stub packages were found.  If missing
+     stub packages were found, they are installed and then another run
+     is performed.
+
+ -- Option: --junit-xml JUNIT_XML
+
+     Causes mypy to generate a JUnit XML test result document with type
+     checking results.  This can make it easier to integrate mypy with
+     continuous integration (CI) tools.
+
+ -- Option: --find-occurrences CLASS.MEMBER
+
+     This flag will make mypy print out all usages of a class member
+     based on static type information.  This feature is experimental.
+
+ -- Option: --scripts-are-modules
+
+     This flag will give command line arguments that appear to be
+     scripts (i.e.  files whose name does not end in ‘.py’) a module
+     name derived from the script name rather than the fixed name
+     __main__(1).
+
+     This lets you check more than one script in a single mypy
+     invocation.  (The default __main__(2) is technically more correct,
+     but if you have many scripts that import a large package, the
+     behavior enabled by this flag is often more convenient.)
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/__main__.html#module-__main__
+
+   (2) https://docs.python.org/3/library/__main__.html#module-__main__
+
+
+File: Mypy.info,  Node: The mypy configuration file,  Next: Inline configuration,  Prev: The mypy command line,  Up: Top
+
+24 The mypy configuration file
+******************************
+
+Mypy supports reading configuration settings from a file.  By default it
+uses the file ‘mypy.ini’ with a fallback to ‘.mypy.ini’, then
+‘pyproject.toml’, then ‘setup.cfg’ in the current directory, then
+‘$XDG_CONFIG_HOME/mypy/config’, then ‘~/.config/mypy/config’, and
+finally ‘.mypy.ini’ in the user home directory if none of them are
+found; the *note –config-file: 160. command-line flag can be used to
+read a different file instead (see *note Config file: 15f.).
+
+It is important to understand that there is no merging of configuration
+files, as it would lead to ambiguity.  The *note –config-file: 160. flag
+has the highest precedence and must be correct; otherwise mypy will
+report an error and exit.  Without command line option, mypy will look
+for configuration files in the above mentioned order.
+
+Most flags correspond closely to *note command-line flags: c. but there
+are some differences in flag names and some flags may take a different
+value based on the module being processed.
+
+Some flags support user home directory and environment variable
+expansion.  To refer to the user home directory, use ‘~’ at the
+beginning of the path.  To expand environment variables use ‘$VARNAME’
+or ‘${VARNAME}’.
+
+* Menu:
+
+* Config file format::
+* Per-module and global options::
+* Inverting option values::
+* Examples::
+* Import discovery: Import discovery<2>.
+* Platform configuration: Platform configuration<2>.
+* Disallow dynamic typing: Disallow dynamic typing<2>.
+* Untyped definitions and calls: Untyped definitions and calls<2>.
+* None and Optional handling: None and Optional handling<2>.
+* Configuring warnings: Configuring warnings<2>.
+* Suppressing errors::
+* Miscellaneous strictness flags: Miscellaneous strictness flags<2>.
+* Configuring error messages: Configuring error messages<2>.
+* Incremental mode: Incremental mode<2>.
+* Advanced options: Advanced options<2>.
+* Report generation: Report generation<2>.
+* Miscellaneous: Miscellaneous<4>.
+* Using a pyproject.toml file: Using a pyproject toml file.
+* Example pyproject.toml: Example pyproject toml.
+
+
+File: Mypy.info,  Node: Config file format,  Next: Per-module and global options,  Up: The mypy configuration file
+
+24.1 Config file format
+=======================
+
+The configuration file format is the usual ini file(1) format.  It
+should contain section names in square brackets and flag settings of the
+form ‘NAME = VALUE’. Comments start with ‘#’ characters.
+
+   - A section named ‘[mypy]’ must be present.  This specifies the
+     global flags.
+
+   - Additional sections named ‘[mypy-PATTERN1,PATTERN2,...]’ may be
+     present, where ‘PATTERN1’, ‘PATTERN2’, etc., are comma-separated
+     patterns of fully-qualified module names, with some components
+     optionally replaced by the ‘*’ character (e.g.  ‘foo.bar’,
+     ‘foo.bar.*’, ‘foo.*.baz’).  These sections specify additional flags
+     that only apply to `modules' whose name matches at least one of the
+     patterns.
+
+     A pattern of the form ‘qualified_module_name’ matches only the
+     named module, while ‘dotted_module_name.*’ matches
+     ‘dotted_module_name’ and any submodules (so ‘foo.bar.*’ would match
+     all of ‘foo.bar’, ‘foo.bar.baz’, and ‘foo.bar.baz.quux’).
+
+     Patterns may also be “unstructured” wildcards, in which stars may
+     appear in the middle of a name (e.g ‘site.*.migrations.*’).  Stars
+     match zero or more module components (so ‘site.*.migrations.*’ can
+     match ‘site.migrations’).  When options conflict, the precedence
+     order for configuration is:
+
+            1. *note Inline configuration: 1b7. in the source file
+
+            2. Sections with concrete module names (‘foo.bar’)
+
+            3. Sections with “unstructured” wildcard patterns
+               (‘foo.*.baz’), with sections later in the configuration
+               file overriding sections earlier.
+
+            4. Sections with “well-structured” wildcard patterns
+               (‘foo.bar.*’), with more specific overriding more
+               general.
+
+            5. Command line options.
+
+            6. Top-level configuration file options.
+
+The difference in precedence order between “structured” patterns (by
+specificity) and “unstructured” patterns (by order in the file) is
+unfortunate, and is subject to change in future versions.
+
+     Note: The *note warn_unused_configs: 1b8. flag may be useful to
+     debug misspelled section names.
+
+     Note: Configuration flags are liable to change between releases.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/configparser.html
+
+
+File: Mypy.info,  Node: Per-module and global options,  Next: Inverting option values,  Prev: Config file format,  Up: The mypy configuration file
+
+24.2 Per-module and global options
+==================================
+
+Some of the config options may be set either globally (in the ‘[mypy]’
+section) or on a per-module basis (in sections like ‘[mypy-foo.bar]’).
+
+If you set an option both globally and for a specific module, the module
+configuration options take precedence.  This lets you set global
+defaults and override them on a module-by-module basis.  If multiple
+pattern sections match a module, *note the options from the most
+specific section are used where they disagree: 1b6.
+
+Some other options, as specified in their description, may only be set
+in the global section (‘[mypy]’).
+
+
+File: Mypy.info,  Node: Inverting option values,  Next: Examples,  Prev: Per-module and global options,  Up: The mypy configuration file
+
+24.3 Inverting option values
+============================
+
+Options that take a boolean value may be inverted by adding ‘no_’ to
+their name or by (when applicable) swapping their prefix from ‘disallow’
+to ‘allow’ (and vice versa).
+
+
+File: Mypy.info,  Node: Examples,  Next: Import discovery<2>,  Prev: Inverting option values,  Up: The mypy configuration file
+
+24.4 Examples
+=============
+
+Here is an example of a ‘mypy.ini’ file.  To use this config file, place
+it at the root of your repo and run mypy.
+
+     # Global options:
+
+     [mypy]
+     python_version = 2.7
+     warn_return_any = True
+     warn_unused_configs = True
+
+     # Per-module options:
+
+     [mypy-mycode.foo.*]
+     disallow_untyped_defs = True
+
+     [mypy-mycode.bar]
+     warn_return_any = False
+
+     [mypy-somelibrary]
+     ignore_missing_imports = True
+
+This config file specifies three global options in the ‘[mypy]’ section.
+These three options will:
+
+  1. Type-check your entire project assuming it will be run using Python
+     2.7.  (This is equivalent to using the *note –python-version 2.7:
+     100. or *note -2: 8. flag).
+
+  2. Report an error whenever a function returns a value that is
+     inferred to have type ‘Any’.
+
+  3. Report any config options that are unused by mypy.  (This will help
+     us catch typos when making changes to our config file).
+
+Next, this module specifies three per-module options.  The first two
+options change how mypy type checks code in ‘mycode.foo.*’ and
+‘mycode.bar’, which we assume here are two modules that you wrote.  The
+final config option changes how mypy type checks ‘somelibrary’, which we
+assume here is some 3rd party library you’ve installed and are
+importing.  These options will:
+
+  1. Selectively disallow untyped function definitions only within the
+     ‘mycode.foo’ package – that is, only for function definitions
+     defined in the ‘mycode/foo’ directory.
+
+  2. Selectively `disable' the “function is returning any” warnings
+     within ‘mycode.bar’ only.  This overrides the global default we set
+     earlier.
+
+  3. Suppress any error messages generated when your codebase tries
+     importing the module ‘somelibrary’.  This is useful if
+     ‘somelibrary’ is some 3rd party library missing type hints.
+
+
+File: Mypy.info,  Node: Import discovery<2>,  Next: Platform configuration<2>,  Prev: Examples,  Up: The mypy configuration file
+
+24.5 Import discovery
+=====================
+
+For more information, see the *note Import discovery: 164. section of
+the command line docs.
+
+ -- Configuration Value: mypy_path
+
+
+     Type: string
+
+     Specifies the paths to use, after trying the paths from ‘MYPYPATH’
+     environment variable.  Useful if you’d like to keep stubs in your
+     repo, along with the config file.  Multiple paths are always
+     separated with a ‘:’ or ‘,’ regardless of the platform.  User home
+     directory and environment variables will be expanded.
+
+     Relative paths are treated relative to the working directory of the
+     mypy command, not the config file.  Use the ‘MYPY_CONFIG_FILE_DIR’
+     environment variable to refer to paths relative to the config file
+     (e.g.  ‘mypy_path = $MYPY_CONFIG_FILE_DIR/src’).
+
+     This option may only be set in the global section (‘[mypy]’).
+
+     `Note:' On Windows, use UNC paths to avoid using ‘:’ (e.g.
+     ‘\\127.0.0.1\X$\MyDir’ where ‘X’ is the drive letter).
+
+ -- Configuration Value: files
+
+
+     Type: comma-separated list of strings
+
+     A comma-separated list of paths which should be checked by mypy if
+     none are given on the command line.  Supports recursive file
+     globbing using glob(1), where ‘*’ (e.g.  ‘*.py’) matches files in
+     the current directory and ‘**/’ (e.g.  ‘**/*.py’) matches files in
+     any directories below the current one.  User home directory and
+     environment variables will be expanded.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: exclude
+
+
+     Type: regular expression
+
+     A regular expression that matches file names, directory names and
+     paths which mypy should ignore while recursively discovering files
+     to check.  Use forward slashes (‘/’) as directory separators on all
+     platforms.
+
+          [mypy]
+          exclude = (?x)(
+              ^one\.py$    # files named "one.py"
+              | two\.pyi$  # or files ending with "two.pyi"
+              | ^three\.   # or files starting with "three."
+            )
+
+     Crafting a single regular expression that excludes multiple files
+     while remaining human-readable can be a challenge.  The above
+     example demonstrates one approach.  ‘(?x)’ enables the ‘VERBOSE’
+     flag for the subsequent regular expression, which ignores most
+     whitespace and supports comments(2).  The above is equivalent to:
+     ‘(^one\.py$|two\.pyi$|^three\.)’.
+
+     For more details, see *note –exclude: 14b.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+          Note: Note that the TOML equivalent differs slightly.  It can
+          be either a single string (including a multi-line string) –
+          which is treated as a single regular expression – or an array
+          of such strings.  The following TOML examples are equivalent
+          to the above INI example.
+
+          Array of strings:
+
+               [tool.mypy]
+               exclude = [
+                   "^one\\.py$",  # TOML's double-quoted strings require escaping backslashes
+                   'two\.pyi$',  # but TOML's single-quoted strings do not
+                   '^three\.',
+               ]
+
+          A single, multi-line string:
+
+               [tool.mypy]
+               exclude = '''(?x)(
+                   ^one\.py$    # files named "one.py"
+                   | two\.pyi$  # or files ending with "two.pyi"
+                   | ^three\.   # or files starting with "three."
+               )'''  # TOML's single-quoted strings do not require escaping backslashes
+
+          See *note Using a pyproject.toml file: 1be.
+
+ -- Configuration Value: namespace_packages
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Enables PEP 420(3) style namespace packages.  See the corresponding
+     flag *note –namespace-packages: 132. for more information.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: explicit_package_bases
+
+
+     Type: boolean
+
+
+     Default: False
+
+     This flag tells mypy that top-level packages will be based in
+     either the current directory, or a member of the ‘MYPYPATH’
+     environment variable or *note mypy_path: 13d. config option.  This
+     option is only useful in conjunction with *note namespace_packages:
+     1bf.  See *note Mapping file paths to modules: 133. for details.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: ignore_missing_imports
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Suppresses error messages about imports that cannot be resolved.
+
+     If this option is used in a per-module section, the module name
+     should match the name of the `imported' module, not the module
+     containing the import statement.
+
+ -- Configuration Value: follow_imports
+
+
+     Type: string
+
+
+     Default: ‘normal’
+
+     Directs what to do with imports when the imported module is found
+     as a ‘.py’ file and not part of the files, modules and packages
+     provided on the command line.
+
+     The four possible values are ‘normal’, ‘silent’, ‘skip’ and
+     ‘error’.  For explanations see the discussion for the *note
+     –follow-imports: 148. command line flag.
+
+     Using this option in a per-module section (potentially with a
+     wildcard, as described at the top of this page) is a good way to
+     prevent mypy from checking portions of your code.
+
+     If this option is used in a per-module section, the module name
+     should match the name of the `imported' module, not the module
+     containing the import statement.
+
+ -- Configuration Value: follow_imports_for_stubs
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Determines whether to respect the *note follow_imports: 149.
+     setting even for stub (‘.pyi’) files.
+
+     Used in conjunction with *note follow_imports=skip: 149, this can
+     be used to suppress the import of a module from ‘typeshed’,
+     replacing it with ‘Any’.
+
+     Used in conjunction with *note follow_imports=error: 149, this can
+     be used to make any use of a particular ‘typeshed’ module an error.
+
+          Note: This is not supported by the mypy daemon.
+
+ -- Configuration Value: python_executable
+
+
+     Type: string
+
+     Specifies the path to the Python executable to inspect to collect a
+     list of available *note PEP 561 packages: 15.  User home directory
+     and environment variables will be expanded.  Defaults to the
+     executable used to run mypy.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: no_site_packages
+
+
+     Type: bool
+
+
+     Default: False
+
+     Disables using type information in installed packages (see PEP
+     561(4)).  This will also disable searching for a usable Python
+     executable.  This acts the same as *note –no-site-packages: 165.
+     command line flag.
+
+ -- Configuration Value: no_silence_site_packages
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Enables reporting error messages generated within installed
+     packages (see PEP 561(5) for more details on distributing type
+     information).  Those error messages are suppressed by default,
+     since you are usually not able to control errors in 3rd party code.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/glob.html#module-glob
+
+   (2) https://docs.python.org/3/library/re.html#re.X
+
+   (3) https://peps.python.org/pep-0420/
+
+   (4) https://peps.python.org/pep-0561/
+
+   (5) https://peps.python.org/pep-0561/
+
+
+File: Mypy.info,  Node: Platform configuration<2>,  Next: Disallow dynamic typing<2>,  Prev: Import discovery<2>,  Up: The mypy configuration file
+
+24.6 Platform configuration
+===========================
+
+ -- Configuration Value: python_version
+
+
+     Type: string
+
+     Specifies the Python version used to parse and check the target
+     program.  The string should be in the format ‘MAJOR.MINOR’ – for
+     example ‘2.7’.  The default is the version of the Python
+     interpreter used to run mypy.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: platform
+
+
+     Type: string
+
+     Specifies the OS platform for the target program, for example
+     ‘darwin’ or ‘win32’ (meaning OS X or Windows, respectively).  The
+     default is the current platform as revealed by Python’s
+     sys.platform(1) variable.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: always_true
+
+
+     Type: comma-separated list of strings
+
+     Specifies a list of variables that mypy will treat as compile-time
+     constants that are always true.
+
+ -- Configuration Value: always_false
+
+
+     Type: comma-separated list of strings
+
+     Specifies a list of variables that mypy will treat as compile-time
+     constants that are always false.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/sys.html#sys.platform
+
+
+File: Mypy.info,  Node: Disallow dynamic typing<2>,  Next: Untyped definitions and calls<2>,  Prev: Platform configuration<2>,  Up: The mypy configuration file
+
+24.7 Disallow dynamic typing
+============================
+
+For more information, see the *note Disallow dynamic typing: 16c.
+section of the command line docs.
+
+ -- Configuration Value: disallow_any_unimported
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows usage of types that come from unfollowed imports
+     (anything imported from an unfollowed import is automatically given
+     a type of ‘Any’).
+
+ -- Configuration Value: disallow_any_expr
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows all expressions in the module that have type ‘Any’.
+
+ -- Configuration Value: disallow_any_decorated
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows functions that have ‘Any’ in their signature after
+     decorator transformation.
+
+ -- Configuration Value: disallow_any_explicit
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows explicit ‘Any’ in type positions such as type annotations
+     and generic type parameters.
+
+ -- Configuration Value: disallow_any_generics
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows usage of generic types that do not specify explicit type
+     parameters.
+
+ -- Configuration Value: disallow_subclassing_any
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows subclassing a value of type ‘Any’.
+
+
+File: Mypy.info,  Node: Untyped definitions and calls<2>,  Next: None and Optional handling<2>,  Prev: Disallow dynamic typing<2>,  Up: The mypy configuration file
+
+24.8 Untyped definitions and calls
+==================================
+
+For more information, see the *note Untyped definitions and calls: fb.
+section of the command line docs.
+
+ -- Configuration Value: disallow_untyped_calls
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows calling functions without type annotations from functions
+     with type annotations.
+
+ -- Configuration Value: disallow_untyped_defs
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows defining functions without type annotations or with
+     incomplete type annotations.
+
+ -- Configuration Value: disallow_incomplete_defs
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows defining functions with incomplete type annotations.
+
+ -- Configuration Value: check_untyped_defs
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Type-checks the interior of functions without type annotations.
+
+ -- Configuration Value: disallow_untyped_decorators
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Reports an error whenever a function with type annotations is
+     decorated with a decorator without annotations.
+
+
+File: Mypy.info,  Node: None and Optional handling<2>,  Next: Configuring warnings<2>,  Prev: Untyped definitions and calls<2>,  Up: The mypy configuration file
+
+24.9 None and Optional handling
+===============================
+
+For more information, see the *note None and Optional handling: 179.
+section of the command line docs.
+
+ -- Configuration Value: no_implicit_optional
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Changes the treatment of arguments with a default value of ‘None’
+     by not implicitly making their type Optional(1).
+
+ -- Configuration Value: strict_optional
+
+
+     Type: boolean
+
+
+     Default: True
+
+     Enables or disables strict Optional checks.  If False, mypy treats
+     ‘None’ as compatible with every type.
+
+     `Note:' This was False by default in mypy versions earlier than
+     0.600.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Optional
+
+
+File: Mypy.info,  Node: Configuring warnings<2>,  Next: Suppressing errors,  Prev: None and Optional handling<2>,  Up: The mypy configuration file
+
+24.10 Configuring warnings
+==========================
+
+For more information, see the *note Configuring warnings: 17b. section
+of the command line docs.
+
+ -- Configuration Value: warn_redundant_casts
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Warns about casting an expression to its inferred type.
+
+     This option may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: warn_unused_ignores
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Warns about unneeded ‘# type: ignore’ comments.
+
+ -- Configuration Value: warn_no_return
+
+
+     Type: boolean
+
+
+     Default: True
+
+     Shows errors for missing return statements on some execution paths.
+
+ -- Configuration Value: warn_return_any
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Shows a warning when returning a value with type ‘Any’ from a
+     function declared with a non- ‘Any’ return type.
+
+ -- Configuration Value: warn_unreachable
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Shows a warning when encountering any code inferred to be
+     unreachable or redundant after performing type analysis.
+
+
+File: Mypy.info,  Node: Suppressing errors,  Next: Miscellaneous strictness flags<2>,  Prev: Configuring warnings<2>,  Up: The mypy configuration file
+
+24.11 Suppressing errors
+========================
+
+Note: these configuration options are available in the config file only.
+There is no analog available via the command line options.
+
+ -- Configuration Value: show_none_errors
+
+
+     Type: boolean
+
+
+     Default: True
+
+     Shows errors related to strict ‘None’ checking, if the global *note
+     strict_optional: 72. flag is enabled.
+
+ -- Configuration Value: ignore_errors
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Ignores all non-fatal errors.
+
+
+File: Mypy.info,  Node: Miscellaneous strictness flags<2>,  Next: Configuring error messages<2>,  Prev: Suppressing errors,  Up: The mypy configuration file
+
+24.12 Miscellaneous strictness flags
+====================================
+
+For more information, see the *note Miscellaneous strictness flags: 182.
+section of the command line docs.
+
+ -- Configuration Value: allow_untyped_globals
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Causes mypy to suppress errors caused by not being able to fully
+     infer the types of global and class variables.
+
+ -- Configuration Value: allow_redefinition
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Allows variables to be redefined with an arbitrary type, as long as
+     the redefinition is in the same block and nesting level as the
+     original definition.  Example where this can be useful:
+
+          def process(items: list[str]) -> None:
+              # 'items' has type list[str]
+              items = [item.split() for item in items]
+              # 'items' now has type list[list[str]]
+
+     The variable must be used before it can be redefined:
+
+          def process(items: list[str]) -> None:
+             items = "mypy"  # invalid redefinition to str because the variable hasn't been used yet
+             print(items)
+             items = "100"  # valid, items now has type str
+             items = int(items)  # valid, items now has type int
+
+ -- Configuration Value: local_partial_types
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Disallows inferring variable type for ‘None’ from two assignments
+     in different scopes.  This is always implicitly enabled when using
+     the *note mypy daemon: 29.
+
+ -- Configuration Value: disable_error_code
+
+
+     Type: comma-separated list of strings
+
+     Allows disabling one or multiple error codes globally.
+
+ -- Configuration Value: implicit_reexport
+
+
+     Type: boolean
+
+
+     Default: True
+
+     By default, imported values to a module are treated as exported and
+     mypy allows other modules to import them.  When false, mypy will
+     not re-export unless the item is imported using from-as or is
+     included in ‘__all__’.  Note that mypy treats stub files as if this
+     is always disabled.  For example:
+
+          # This won't re-export the value
+          from foo import bar
+          # This will re-export it as bar and allow other modules to import it
+          from foo import bar as bar
+          # This will also re-export bar
+          from foo import bar
+          __all__ = ['bar']
+
+ -- Configuration Value: strict_equality
+
+
+          type: boolean
+
+
+          default: False
+
+     Prohibit equality checks, identity checks, and container checks
+     between non-overlapping types.
+
+ -- Configuration Value: strict
+
+
+          type: boolean
+
+
+          default: False
+
+     Enable all optional error checking flags.  You can see the list of
+     flags enabled by strict mode in the full *note mypy –help: 154.
+     output.
+
+     Note: the exact list of flags enabled by *note strict: 1e8. may
+     change over time.
+
+
+File: Mypy.info,  Node: Configuring error messages<2>,  Next: Incremental mode<2>,  Prev: Miscellaneous strictness flags<2>,  Up: The mypy configuration file
+
+24.13 Configuring error messages
+================================
+
+For more information, see the *note Configuring error messages: 18a.
+section of the command line docs.
+
+These options may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: show_error_context
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Prefixes each error with the relevant context.
+
+ -- Configuration Value: show_column_numbers
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Shows column numbers in error messages.
+
+ -- Configuration Value: show_error_codes
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Shows error codes in error messages.  See *note Error codes: 18e.
+     for more information.
+
+ -- Configuration Value: pretty
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Use visually nicer output in error messages: use soft word wrap,
+     show source code snippets, and show error location markers.
+
+ -- Configuration Value: color_output
+
+
+     Type: boolean
+
+
+     Default: True
+
+     Shows error messages with color enabled.
+
+ -- Configuration Value: error_summary
+
+
+     Type: boolean
+
+
+     Default: True
+
+     Shows a short summary line after error messages.
+
+ -- Configuration Value: show_absolute_path
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Show absolute paths to files.
+
+
+File: Mypy.info,  Node: Incremental mode<2>,  Next: Advanced options<2>,  Prev: Configuring error messages<2>,  Up: The mypy configuration file
+
+24.14 Incremental mode
+======================
+
+These options may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: incremental
+
+
+     Type: boolean
+
+
+     Default: True
+
+     Enables *note incremental mode: 194.
+
+ -- Configuration Value: cache_dir
+
+
+     Type: string
+
+
+     Default: ‘.mypy_cache’
+
+     Specifies the location where mypy stores incremental cache info.
+     User home directory and environment variables will be expanded.
+     This setting will be overridden by the ‘MYPY_CACHE_DIR’ environment
+     variable.
+
+     Note that the cache is only read when incremental mode is enabled
+     but is always written to, unless the value is set to ‘/dev/null’
+     (UNIX) or ‘nul’ (Windows).
+
+ -- Configuration Value: sqlite_cache
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Use an SQLite(1) database to store the cache.
+
+ -- Configuration Value: cache_fine_grained
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Include fine-grained dependency information in the cache for the
+     mypy daemon.
+
+ -- Configuration Value: skip_version_check
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Makes mypy use incremental cache data even if it was generated by a
+     different version of mypy.  (By default, mypy will perform a
+     version check and regenerate the cache if it was written by older
+     versions of mypy.)
+
+ -- Configuration Value: skip_cache_mtime_checks
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Skip cache internal consistency checks based on mtime.
+
+   ---------- Footnotes ----------
+
+   (1) https://www.sqlite.org/
+
+
+File: Mypy.info,  Node: Advanced options<2>,  Next: Report generation<2>,  Prev: Incremental mode<2>,  Up: The mypy configuration file
+
+24.15 Advanced options
+======================
+
+These options may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: plugins
+
+
+     Type: comma-separated list of strings
+
+     A comma-separated list of mypy plugins.  See *note Extending mypy
+     using plugins: 1fa.
+
+ -- Configuration Value: pdb
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Invokes pdb(1) on fatal error.
+
+ -- Configuration Value: show_traceback
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Shows traceback on fatal error.
+
+ -- Configuration Value: raise_exceptions
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Raise exception on fatal error.
+
+ -- Configuration Value: custom_typing_module
+
+
+     Type: string
+
+     Specifies a custom module to use as a substitute for the typing(2)
+     module.
+
+ -- Configuration Value: custom_typeshed_dir
+
+
+     Type: string
+
+     Specifies an alternative directory to look for stubs instead of the
+     default ‘typeshed’ directory.  User home directory and environment
+     variables will be expanded.
+
+ -- Configuration Value: warn_incomplete_stub
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Warns about missing type annotations in typeshed.  This is only
+     relevant in combination with *note disallow_untyped_defs: 2c. or
+     *note disallow_incomplete_defs: 1d3.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/pdb.html#module-pdb
+
+   (2) https://docs.python.org/3/library/typing.html#module-typing
+
+
+File: Mypy.info,  Node: Report generation<2>,  Next: Miscellaneous<4>,  Prev: Advanced options<2>,  Up: The mypy configuration file
+
+24.16 Report generation
+=======================
+
+If these options are set, mypy will generate a report in the specified
+format into the specified directory.
+
+ -- Configuration Value: any_exprs_report
+
+
+     Type: string
+
+     Causes mypy to generate a text file report documenting how many
+     expressions of type ‘Any’ are present within your codebase.
+
+ -- Configuration Value: cobertura_xml_report
+
+
+     Type: string
+
+     Causes mypy to generate a Cobertura XML type checking coverage
+     report.
+
+     To generate this report, you must either manually install the
+     lxml(1) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+ -- Configuration Value: html_report / xslt_html_report
+
+
+     Type: string
+
+     Causes mypy to generate an HTML type checking coverage report.
+
+     To generate this report, you must either manually install the
+     lxml(2) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+ -- Configuration Value: linecount_report
+
+
+     Type: string
+
+     Causes mypy to generate a text file report documenting the
+     functions and lines that are typed and untyped within your
+     codebase.
+
+ -- Configuration Value: linecoverage_report
+
+
+     Type: string
+
+     Causes mypy to generate a JSON file that maps each source file’s
+     absolute filename to a list of line numbers that belong to typed
+     functions in that file.
+
+ -- Configuration Value: lineprecision_report
+
+
+     Type: string
+
+     Causes mypy to generate a flat text file report with per-module
+     statistics of how many lines are typechecked etc.
+
+ -- Configuration Value: txt_report / xslt_txt_report
+
+
+     Type: string
+
+     Causes mypy to generate a text file type checking coverage report.
+
+     To generate this report, you must either manually install the
+     lxml(3) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+ -- Configuration Value: xml_report
+
+
+     Type: string
+
+     Causes mypy to generate an XML type checking coverage report.
+
+     To generate this report, you must either manually install the
+     lxml(4) library or specify mypy installation with the setuptools
+     extra ‘mypy[reports]’.
+
+   ---------- Footnotes ----------
+
+   (1) https://pypi.org/project/lxml/
+
+   (2) https://pypi.org/project/lxml/
+
+   (3) https://pypi.org/project/lxml/
+
+   (4) https://pypi.org/project/lxml/
+
+
+File: Mypy.info,  Node: Miscellaneous<4>,  Next: Using a pyproject toml file,  Prev: Report generation<2>,  Up: The mypy configuration file
+
+24.17 Miscellaneous
+===================
+
+These options may only be set in the global section (‘[mypy]’).
+
+ -- Configuration Value: junit_xml
+
+
+     Type: string
+
+     Causes mypy to generate a JUnit XML test result document with type
+     checking results.  This can make it easier to integrate mypy with
+     continuous integration (CI) tools.
+
+ -- Configuration Value: scripts_are_modules
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Makes script ‘x’ become module ‘x’ instead of ‘__main__’.  This is
+     useful when checking multiple scripts in a single run.
+
+ -- Configuration Value: warn_unused_configs
+
+
+     Type: boolean
+
+
+     Default: False
+
+     Warns about per-module sections in the config file that do not
+     match any files processed when invoking mypy.  (This requires
+     turning off incremental mode using *note incremental = False: 1f2.)
+
+ -- Configuration Value: verbosity
+
+
+     Type: integer
+
+
+     Default: 0
+
+     Controls how much debug output will be generated.  Higher numbers
+     are more verbose.
+
+
+File: Mypy.info,  Node: Using a pyproject toml file,  Next: Example pyproject toml,  Prev: Miscellaneous<4>,  Up: The mypy configuration file
+
+24.18 Using a pyproject.toml file
+=================================
+
+Instead of using a ‘mypy.ini’ file, a ‘pyproject.toml’ file (as
+specified by PEP 518(1)) may be used instead.  A few notes on doing so:
+
+   * The ‘[mypy]’ section should have ‘tool.’ prepended to its name:
+
+        * I.e., ‘[mypy]’ would become ‘[tool.mypy]’
+
+   * The module specific sections should be moved into
+     ‘[[tool.mypy.overrides]]’ sections:
+
+        * For example, ‘[mypy-packagename]’ would become:
+
+     [[tool.mypy.overrides]]
+     module = 'packagename'
+     ...
+
+   * Multi-module specific sections can be moved into a single
+     ‘[[tool.mypy.overrides]]’ section with a module property set to an
+     array of modules:
+
+        * For example, ‘[mypy-packagename,packagename2]’ would become:
+
+     [[tool.mypy.overrides]]
+     module = [
+         'packagename',
+         'packagename2'
+     ]
+     ...
+
+   * The following care should be given to values in the
+     ‘pyproject.toml’ files as compared to ‘ini’ files:
+
+        * Strings must be wrapped in double quotes, or single quotes if
+          the string contains special characters
+
+        * Boolean values should be all lower case
+
+Please see the TOML Documentation(2) for more details and information on
+what is allowed in a ‘toml’ file.  See PEP 518(3) for more information
+on the layout and structure of the ‘pyproject.toml’ file.
+
+   ---------- Footnotes ----------
+
+   (1) https://www.python.org/dev/peps/pep-0518/
+
+   (2) https://toml.io/
+
+   (3) https://www.python.org/dev/peps/pep-0518/
+
+
+File: Mypy.info,  Node: Example pyproject toml,  Prev: Using a pyproject toml file,  Up: The mypy configuration file
+
+24.19 Example ‘pyproject.toml’
+==============================
+
+Here is an example of a ‘pyproject.toml’ file.  To use this config file,
+place it at the root of your repo (or append it to the end of an
+existing ‘pyproject.toml’ file) and run mypy.
+
+     # 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)
+     ]
+
+     # mypy per-module options:
+
+     [[tool.mypy.overrides]]
+     module = "mycode.foo.*"
+     disallow_untyped_defs = true
+
+     [[tool.mypy.overrides]]
+     module = "mycode.bar"
+     warn_return_any = false
+
+     [[tool.mypy.overrides]]
+     module = [
+         "somelibrary",
+         "some_other_library"
+     ]
+     ignore_missing_imports = true
+
+
+File: Mypy.info,  Node: Inline configuration,  Next: Mypy daemon mypy server,  Prev: The mypy configuration file,  Up: Top
+
+25 Inline configuration
+***********************
+
+Mypy supports setting per-file configuration options inside files
+themselves using ‘# mypy:’ comments.  For example:
+
+     # mypy: disallow-any-generics
+
+Inline configuration comments take precedence over all other
+configuration mechanisms.
+
+* Menu:
+
+* Configuration comment format::
+
+
+File: Mypy.info,  Node: Configuration comment format,  Up: Inline configuration
+
+25.1 Configuration comment format
+=================================
+
+Flags correspond to *note config file flags: 2e. but allow hyphens to be
+substituted for underscores.
+
+Values are specified using ‘=’, but ‘= True’ may be omitted:
+
+     # mypy: disallow-any-generics
+     # mypy: always-true=FOO
+
+Multiple flags can be separated by commas or placed on separate lines.
+To include a comma as part of an option’s value, place the value inside
+quotes:
+
+     # mypy: disallow-untyped-defs, always-false="FOO,BAR"
+
+Like in the configuration file, options that take a boolean value may be
+inverted by adding ‘no-’ to their name or by (when applicable) swapping
+their prefix from ‘disallow’ to ‘allow’ (and vice versa):
+
+     # mypy: allow-untyped-defs, no-strict-optional
+
+
+File: Mypy.info,  Node: Mypy daemon mypy server,  Next: Using installed packages,  Prev: Inline configuration,  Up: Top
+
+26 Mypy daemon (mypy server)
+****************************
+
+Instead of running mypy as a command-line tool, you can also run it as a
+long-running daemon (server) process and use a command-line client to
+send type-checking requests to the server.  This way mypy can perform
+type checking much faster, since program state cached from previous runs
+is kept in memory and doesn’t have to be read from the file system on
+each run.  The server also uses finer-grained dependency tracking to
+reduce the amount of work that needs to be done.
+
+If you have a large codebase to check, running mypy using the mypy
+daemon can be `10 or more times faster' than the regular command-line
+‘mypy’ tool, especially if your workflow involves running mypy
+repeatedly after small edits – which is often a good idea, as this way
+you’ll find errors sooner.
+
+     Note: The command-line interface of mypy daemon may change in
+     future mypy releases.
+
+     Note: Each mypy daemon process supports one user and one set of
+     source files, and it can only process one type checking request at
+     a time.  You can run multiple mypy daemon processes to type check
+     multiple repositories.
+
+* Menu:
+
+* Basic usage::
+* Daemon client commands::
+* Additional daemon flags::
+* Static inference of annotations::
+
+
+File: Mypy.info,  Node: Basic usage,  Next: Daemon client commands,  Up: Mypy daemon mypy server
+
+26.1 Basic usage
+================
+
+The client utility ‘dmypy’ is used to control the mypy daemon.  Use
+‘dmypy run -- <flags> <files>’ to type check a set of files (or
+directories).  This will launch the daemon if it is not running.  You
+can use almost arbitrary mypy flags after ‘--’.  The daemon will always
+run on the current host.  Example:
+
+     dmypy run -- prog.py pkg/*.py
+
+‘dmypy run’ will automatically restart the daemon if the configuration
+or mypy version changes.
+
+The initial run will process all the code and may take a while to
+finish, but subsequent runs will be quick, especially if you’ve only
+changed a few files.  (You can use *note remote caching: 2a. to speed up
+the initial run.  The speedup can be significant if you have a large
+codebase.)
+
+     Note: Mypy 0.780 added support for following imports in dmypy
+     (enabled by default).  This functionality is still experimental.
+     You can use ‘--follow-imports=skip’ or ‘--follow-imports=error’ to
+     fall back to the stable functionality.  See *note Following
+     imports: 22. for details on how these work.
+
+
+File: Mypy.info,  Node: Daemon client commands,  Next: Additional daemon flags,  Prev: Basic usage,  Up: Mypy daemon mypy server
+
+26.2 Daemon client commands
+===========================
+
+While ‘dmypy run’ is sufficient for most uses, some workflows (ones
+using *note remote caching: 2a, perhaps), require more precise control
+over the lifetime of the daemon process:
+
+   * ‘dmypy stop’ stops the daemon.
+
+   * ‘dmypy start -- <flags>’ starts the daemon but does not check any
+     files.  You can use almost arbitrary mypy flags after ‘--’.
+
+   * ‘dmypy restart -- <flags>’ restarts the daemon.  The flags are the
+     same as with ‘dmypy start’.  This is equivalent to a stop command
+     followed by a start.
+
+   * Use ‘dmypy run --timeout SECONDS -- <flags>’ (or ‘start’ or
+     ‘restart’) to automatically shut down the daemon after inactivity.
+     By default, the daemon runs until it’s explicitly stopped.
+
+   * ‘dmypy check <files>’ checks a set of files using an already
+     running daemon.
+
+   * ‘dmypy recheck’ checks the same set of files as the most recent
+     ‘check’ or ‘recheck’ command.  (You can also use the *note –update:
+     21a. and *note –remove: 21b. options to alter the set of files, and
+     to define which files should be processed.)
+
+   * ‘dmypy status’ checks whether a daemon is running.  It prints a
+     diagnostic and exits with ‘0’ if there is a running daemon.
+
+Use ‘dmypy --help’ for help on additional commands and command-line
+options not discussed here, and ‘dmypy <command> --help’ for help on
+command-specific options.
+
+
+File: Mypy.info,  Node: Additional daemon flags,  Next: Static inference of annotations,  Prev: Daemon client commands,  Up: Mypy daemon mypy server
+
+26.3 Additional daemon flags
+============================
+
+ -- Option: --status-file FILE
+
+     Use ‘FILE’ as the status file for storing daemon runtime state.
+     This is normally a JSON file that contains information about daemon
+     process and connection.  The default path is ‘.dmypy.json’ in the
+     current working directory.
+
+ -- Option: --log-file FILE
+
+     Direct daemon stdout/stderr to ‘FILE’.  This is useful for
+     debugging daemon crashes, since the server traceback is not always
+     printed by the client.  This is available for the ‘start’,
+     ‘restart’, and ‘run’ commands.
+
+ -- Option: --timeout TIMEOUT
+
+     Automatically shut down server after ‘TIMEOUT’ seconds of
+     inactivity.  This is available for the ‘start’, ‘restart’, and
+     ‘run’ commands.
+
+ -- Option: --update FILE
+
+     Re-check ‘FILE’, or add it to the set of files being checked (and
+     check it).  This option may be repeated, and it’s only available
+     for the ‘recheck’ command.  By default, mypy finds and checks all
+     files changed since the previous run and files that depend on them.
+     However, if you use this option (and/or *note –remove: 21b.), mypy
+     assumes that only the explicitly specified files have changed.
+     This is only useful to speed up mypy if you type check a very large
+     number of files, and use an external, fast file system watcher,
+     such as watchman(1) or watchdog(2), to determine which files got
+     edited or deleted.  `Note:' This option is never required and is
+     only available for performance tuning.
+
+ -- Option: --remove FILE
+
+     Remove ‘FILE’ from the set of files being checked.  This option may
+     be repeated.  This is only available for the ‘recheck’ command.
+     See *note –update: 21a. above for when this may be useful.  `Note:'
+     This option is never required and is only available for performance
+     tuning.
+
+ -- Option: --fswatcher-dump-file FILE
+
+     Collect information about the current internal file state.  This is
+     only available for the ‘status’ command.  This will dump JSON to
+     ‘FILE’ in the format ‘{path: [modification_time, size,
+     content_hash]}’.  This is useful for debugging the built-in file
+     system watcher.  `Note:' This is an internal flag and the format
+     may change.
+
+ -- Option: --perf-stats-file FILE
+
+     Write performance profiling information to ‘FILE’.  This is only
+     available for the ‘check’, ‘recheck’, and ‘run’ commands.
+
+   ---------- Footnotes ----------
+
+   (1) https://facebook.github.io/watchman/
+
+   (2) https://pypi.org/project/watchdog/
+
+
+File: Mypy.info,  Node: Static inference of annotations,  Prev: Additional daemon flags,  Up: Mypy daemon mypy server
+
+26.4 Static inference of annotations
+====================================
+
+The mypy daemon supports (as an experimental feature) statically
+inferring draft function and method type annotations.  Use ‘dmypy
+suggest FUNCTION’ to generate a draft signature in the format
+‘(param_type_1, param_type_2, ...) -> ret_type’ (types are included for
+all arguments, including keyword-only arguments, ‘*args’ and
+‘**kwargs’).
+
+This is a low-level feature intended to be used by editor integrations,
+IDEs, and other tools (for example, the mypy plugin for PyCharm(1)), to
+automatically add annotations to source files, or to propose function
+signatures.
+
+In this example, the function ‘format_id()’ has no annotation:
+
+     def format_id(user):
+         return "User: {}".format(user)
+
+     root = format_id(0)
+
+‘dmypy suggest’ uses call sites, return statements, and other heuristics
+(such as looking for signatures in base classes) to infer that
+‘format_id()’ accepts an ‘int’ argument and returns a ‘str’.  Use ‘dmypy
+suggest module.format_id’ to print the suggested signature for the
+function.
+
+More generally, the target function may be specified in two ways:
+
+   * By its fully qualified name, i.e.
+     ‘[package.]module.[class.]function’.
+
+   * By its location in a source file, i.e.  ‘/path/to/file.py:line’.
+     The path can be absolute or relative, and ‘line’ can refer to any
+     line number within the function body.
+
+This command can also be used to find a more precise alternative for an
+existing, imprecise annotation with some ‘Any’ types.
+
+The following flags customize various aspects of the ‘dmypy suggest’
+command.
+
+ -- Option: --json
+
+     Output the signature as JSON, so that PyAnnotate(2) can read it and
+     add the signature to the source file.  Here is what the JSON looks
+     like:
+
+          [{"func_name": "example.format_id",
+            "line": 1,
+            "path": "/absolute/path/to/example.py",
+            "samples": 0,
+            "signature": {"arg_types": ["int"], "return_type": "str"}}]
+
+ -- Option: --no-errors
+
+     Only produce suggestions that cause no errors in the checked code.
+     By default, mypy will try to find the most precise type, even if it
+     causes some type errors.
+
+ -- Option: --no-any
+
+     Only produce suggestions that don’t contain ‘Any’ types.  By
+     default mypy proposes the most precise signature found, even if it
+     contains ‘Any’ types.
+
+ -- Option: --flex-any FRACTION
+
+     Only allow some fraction of types in the suggested signature to be
+     ‘Any’ types.  The fraction ranges from ‘0’ (same as ‘--no-any’) to
+     ‘1’.
+
+ -- Option: --try-text
+
+     Try also using ‘unicode’ wherever ‘str’ is inferred.  This flag may
+     be useful for annotating Python 2/3 straddling code.
+
+ -- Option: --callsites
+
+     Only find call sites for a given function instead of suggesting a
+     type.  This will produce a list with line numbers and types of
+     actual arguments for each call: ‘/path/to/file.py:line:
+     (arg_type_1, arg_type_2, ...)’.
+
+ -- Option: --use-fixme NAME
+
+     Use a dummy name instead of plain ‘Any’ for types that cannot be
+     inferred.  This may be useful to emphasize to a user that a given
+     type couldn’t be inferred and needs to be entered manually.
+
+ -- Option: --max-guesses NUMBER
+
+     Set the maximum number of types to try for a function (default:
+     ‘64’).
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/dropbox/mypy-PyCharm-plugin
+
+   (2) https://github.com/dropbox/pyannotate
+
+
+File: Mypy.info,  Node: Using installed packages,  Next: Extending and integrating mypy,  Prev: Mypy daemon mypy server,  Up: Top
+
+27 Using installed packages
+***************************
+
+Packages installed with pip can declare that they support type checking.
+For example, the aiohttp(1) package has built-in support for type
+checking.
+
+Packages can also provide stubs for a library.  For example,
+‘types-requests’ is a stub-only package that provides stubs for the
+requests(2) package.  Stub packages are usually published from
+typeshed(3), a shared repository for Python library stubs, and have a
+name of form ‘types-<library>’.  Note that many stub packages are not
+maintained by the original maintainers of the package.
+
+The sections below explain how mypy can use these packages, and how you
+can create such packages.
+
+     Note: PEP 561(4) specifies how a package can declare that it
+     supports type checking.
+
+* Menu:
+
+* Using installed packages with mypy (PEP 561): Using installed packages with mypy PEP 561.
+* Creating PEP 561 compatible packages::
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.aiohttp.org/en/stable/
+
+   (2) https://requests.readthedocs.io/en/master/
+
+   (3) https://github.com/python/typeshed
+
+   (4) https://peps.python.org/pep-0561/
+
+
+File: Mypy.info,  Node: Using installed packages with mypy PEP 561,  Next: Creating PEP 561 compatible packages,  Up: Using installed packages
+
+27.1 Using installed packages with mypy (PEP 561)
+=================================================
+
+Typically mypy will automatically find and use installed packages that
+support type checking or provide stubs.  This requires that you install
+the packages in the Python environment that you use to run mypy.  As
+many packages don’t support type checking yet, you may also have to
+install a separate stub package, usually named ‘types-<library>’.  (See
+*note Missing imports: 14. for how to deal with libraries that don’t
+support type checking and are also missing stubs.)
+
+If you have installed typed packages in another Python installation or
+environment, mypy won’t automatically find them.  One option is to
+install another copy of those packages in the environment in which you
+use to run mypy.  Alternatively, you can use the *note
+–python-executable: 146. flag to point to the target Python executable,
+and mypy will find packages installed for that Python executable.
+
+Note that mypy does not support some more advanced import features, such
+as zip imports and custom import hooks.
+
+If you don’t want to use installed packages that provide type
+information at all, use the *note –no-site-packages: 165. flag to
+disable searching for installed packages.
+
+Note that stub-only packages cannot be used with ‘MYPYPATH’.  If you
+want mypy to find the package, it must be installed.  For a package
+‘foo’, the name of the stub-only package (‘foo-stubs’) is not a legal
+package name, so mypy will not find it, unless it is installed (see PEP
+561: Stub-only Packages(1) for more information).
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0561/#stub-only-packages
+
+
+File: Mypy.info,  Node: Creating PEP 561 compatible packages,  Prev: Using installed packages with mypy PEP 561,  Up: Using installed packages
+
+27.2 Creating PEP 561 compatible packages
+=========================================
+
+     Note: You can generally ignore this section unless you maintain a
+     package on PyPI, or want to publish type information for an
+     existing PyPI package.
+
+PEP 561(1) describes three main ways to distribute type information:
+
+  1. A package has inline type annotations in the Python implementation.
+
+  2. A package ships *note stub files: 16. with type information
+     alongside the Python implementation.
+
+  3. A package ships type information for another package separately as
+     stub files (also known as a “stub-only package”).
+
+If you want to create a stub-only package for an existing library, the
+simplest way is to contribute stubs to the typeshed(2) repository, and a
+stub package will automatically be uploaded to PyPI.
+
+If you would like to publish a library package to a package repository
+yourself (e.g.  on PyPI) for either internal or external use in type
+checking, packages that supply type information via type comments or
+annotations in the code should put a ‘py.typed’ file in their package
+directory.  For example, here is a typical directory structure:
+
+     setup.py
+     package_a/
+         __init__.py
+         lib.py
+         py.typed
+
+The ‘setup.py’ file could look like this:
+
+     from distutils.core import setup
+
+     setup(
+         name="SuperPackageA",
+         author="Me",
+         version="0.1",
+         package_data={"package_a": ["py.typed"]},
+         packages=["package_a"]
+     )
+
+     Note: If you use setuptools(3), you must pass the option
+     ‘zip_safe=False’ to ‘setup()’, or mypy will not be able to find the
+     installed package.
+
+Some packages have a mix of stub files and runtime files.  These
+packages also require a ‘py.typed’ file.  An example can be seen below:
+
+     setup.py
+     package_b/
+         __init__.py
+         lib.py
+         lib.pyi
+         py.typed
+
+The ‘setup.py’ file might look like this:
+
+     from distutils.core import setup
+
+     setup(
+         name="SuperPackageB",
+         author="Me",
+         version="0.1",
+         package_data={"package_b": ["py.typed", "lib.pyi"]},
+         packages=["package_b"]
+     )
+
+In this example, both ‘lib.py’ and the ‘lib.pyi’ stub file exist.  At
+runtime, the Python interpreter will use ‘lib.py’, but mypy will use
+‘lib.pyi’ instead.
+
+If the package is stub-only (not imported at runtime), the package
+should have a prefix of the runtime package name and a suffix of
+‘-stubs’.  A ‘py.typed’ file is not needed for stub-only packages.  For
+example, if we had stubs for ‘package_c’, we might do the following:
+
+     setup.py
+     package_c-stubs/
+         __init__.pyi
+         lib.pyi
+
+The ‘setup.py’ might look like this:
+
+     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"]
+     )
+
+If you have separate stubs for Python 2 and Python 3, you can place the
+Python 2 stubs in a directory with the suffix ‘-python2-stubs’.  We
+recommend that Python 2 and Python 3 stubs are bundled together for
+simplicity, instead of distributing them separately.
+
+The instructions above are enough to ensure that the built wheels
+contain the appropriate files.  However, to ensure inclusion inside the
+‘sdist’ (‘.tar.gz’ archive), you may also need to modify the inclusion
+rules in your ‘MANIFEST.in’:
+
+     global-include *.pyi
+     global-include *.typed
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0561/
+
+   (2) https://github.com/python/typeshed
+
+   (3) https://setuptools.pypa.io/en/latest/index.html
+
+
+File: Mypy.info,  Node: Extending and integrating mypy,  Next: Automatic stub generation stubgen,  Prev: Using installed packages,  Up: Top
+
+28 Extending and integrating mypy
+*********************************
+
+* Menu:
+
+* Integrating mypy into another Python application::
+* Extending mypy using plugins::
+* Configuring mypy to use plugins::
+* High-level overview::
+* Current list of plugin hooks::
+* Notes about the semantic analyzer::
+
+
+File: Mypy.info,  Node: Integrating mypy into another Python application,  Next: Extending mypy using plugins,  Up: Extending and integrating mypy
+
+28.1 Integrating mypy into another Python application
+=====================================================
+
+It is possible to integrate mypy into another Python 3 application by
+importing ‘mypy.api’ and calling the ‘run’ function with a parameter of
+type ‘list[str]’, containing what normally would have been the command
+line arguments to mypy.
+
+Function ‘run’ returns a ‘tuple[str, str, int]’, namely
+‘(<normal_report>, <error_report>, <exit_status>)’, in which
+‘<normal_report>’ is what mypy normally writes to sys.stdout(1),
+‘<error_report>’ is what mypy normally writes to sys.stderr(2) and
+‘exit_status’ is the exit status mypy normally returns to the operating
+system.
+
+A trivial example of using the api is the following
+
+     import sys
+     from mypy import api
+
+     result = api.run(sys.argv[1:])
+
+     if result[0]:
+         print('\nType checking report:\n')
+         print(result[0])  # stdout
+
+     if result[1]:
+         print('\nError report:\n')
+         print(result[1])  # stderr
+
+     print('\nExit status:', result[2])
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/sys.html#sys.stdout
+
+   (2) https://docs.python.org/3/library/sys.html#sys.stderr
+
+
+File: Mypy.info,  Node: Extending mypy using plugins,  Next: Configuring mypy to use plugins,  Prev: Integrating mypy into another Python application,  Up: Extending and integrating mypy
+
+28.2 Extending mypy using plugins
+=================================
+
+Python is a highly dynamic language and has extensive metaprogramming
+capabilities.  Many popular libraries use these to create APIs that may
+be more flexible and/or natural for humans, but are hard to express
+using static types.  Extending the PEP 484(1) type system to accommodate
+all existing dynamic patterns is impractical and often just impossible.
+
+Mypy supports a plugin system that lets you customize the way mypy type
+checks code.  This can be useful if you want to extend mypy so it can
+type check code that uses a library that is difficult to express using
+just PEP 484(2) types.
+
+The plugin system is focused on improving mypy’s understanding of
+`semantics' of third party frameworks.  There is currently no way to
+define new first class kinds of types.
+
+     Note: The plugin system is experimental and prone to change.  If
+     you want to write a mypy plugin, we recommend you start by
+     contacting the mypy core developers on gitter(3).  In particular,
+     there are no guarantees about backwards compatibility.
+
+     Backwards incompatible changes may be made without a deprecation
+     period, but we will announce them in the plugin API changes
+     announcement issue(4).
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+   (2) https://peps.python.org/pep-0484/
+
+   (3) https://gitter.im/python/typing
+
+   (4) https://github.com/python/mypy/issues/6617
+
+
+File: Mypy.info,  Node: Configuring mypy to use plugins,  Next: High-level overview,  Prev: Extending mypy using plugins,  Up: Extending and integrating mypy
+
+28.3 Configuring mypy to use plugins
+====================================
+
+Plugins are Python files that can be specified in a mypy *note config
+file: 2e. using the *note plugins: 1f9. option and one of the two
+formats: relative or absolute path to the plugin file, or a module name
+(if the plugin is installed using ‘pip install’ in the same virtual
+environment where mypy is running).  The two formats can be mixed, for
+example:
+
+     [mypy]
+     plugins = /one/plugin.py, other.plugin
+
+Mypy will try to import the plugins and will look for an entry point
+function named ‘plugin’.  If the plugin entry point function has a
+different name, it can be specified after colon:
+
+     [mypy]
+     plugins = custom_plugin:custom_entry_point
+
+In the following sections we describe the basics of the plugin system
+with some examples.  For more technical details, please read the
+docstrings in mypy/plugin.py(1) in mypy source code.  Also you can find
+good examples in the bundled plugins located in mypy/plugins(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/mypy/blob/master/mypy/plugin.py
+
+   (2) https://github.com/python/mypy/tree/master/mypy/plugins
+
+
+File: Mypy.info,  Node: High-level overview,  Next: Current list of plugin hooks,  Prev: Configuring mypy to use plugins,  Up: Extending and integrating mypy
+
+28.4 High-level overview
+========================
+
+Every entry point function should accept a single string argument that
+is a full mypy version and return a subclass of ‘mypy.plugin.Plugin’:
+
+     from mypy.plugin import Plugin
+
+     class CustomPlugin(Plugin):
+         def get_type_analyze_hook(self, fullname: str):
+             # see explanation below
+             ...
+
+     def plugin(version: str):
+         # ignore version argument if the plugin works with all mypy versions.
+         return CustomPlugin
+
+During different phases of analyzing the code (first in semantic
+analysis, and then in type checking) mypy calls plugin methods such as
+‘get_type_analyze_hook()’ on user plugins.  This particular method, for
+example, can return a callback that mypy will use to analyze unbound
+types with the given full name.  See the full plugin hook method list
+*note below: 238.
+
+Mypy maintains a list of plugins it gets from the config file plus the
+default (built-in) plugin that is always enabled.  Mypy calls a method
+once for each plugin in the list until one of the methods returns a
+non-‘None’ value.  This callback will be then used to customize the
+corresponding aspect of analyzing/checking the current abstract syntax
+tree node.
+
+The callback returned by the ‘get_xxx’ method will be given a detailed
+current context and an API to create new nodes, new types, emit error
+messages, etc., and the result will be used for further processing.
+
+Plugin developers should ensure that their plugins work well in
+incremental and daemon modes.  In particular, plugins should not hold
+global state due to caching of plugin hook results.
+
+
+File: Mypy.info,  Node: Current list of plugin hooks,  Next: Notes about the semantic analyzer,  Prev: High-level overview,  Up: Extending and integrating mypy
+
+28.5 Current list of plugin hooks
+=================================
+
+`get_type_analyze_hook()' customizes behaviour of the type analyzer.
+For example, PEP 484(1) doesn’t support defining variadic generic types:
+
+     from lib import Vector
+
+     a: Vector[int, int]
+     b: Vector[int, int, int]
+
+When analyzing this code, mypy will call
+‘get_type_analyze_hook("lib.Vector")’, so the plugin can return some
+valid type for each variable.
+
+`get_function_hook()' is used to adjust the return type of a function
+call.  This is a good choice if the return type of some function depends
+on `values' of some arguments that can’t be expressed using literal
+types (for example a function may return an ‘int’ for positive arguments
+and a ‘float’ for negative arguments).  This hook will be also called
+for instantiation of classes.  For example:
+
+     from contextlib import contextmanager
+     from typing import TypeVar, Callable
+
+     T = TypeVar('T')
+
+     @contextmanager  # built-in plugin can infer a precise type here
+     def stopwatch(timer: Callable[[], T]) -> Iterator[T]:
+         ...
+         yield timer()
+
+`get_function_signature_hook' is used to adjust the signature of a
+function.
+
+`get_method_hook()' is the same as ‘get_function_hook()’ but for methods
+instead of module level functions.
+
+`get_method_signature_hook()' is used to adjust the signature of a
+method.  This includes special Python methods except __init__()(2) and
+__new__()(3).  For example in this code:
+
+     from ctypes import Array, c_int
+
+     x: Array[c_int]
+     x[0] = 42
+
+mypy will call ‘get_method_signature_hook("ctypes.Array.__setitem__")’
+so that the plugin can mimic the ctypes(4) auto-convert behavior.
+
+`get_attribute_hook()' overrides instance member field lookups and
+property access (not assignments, and not method calls).  This hook is
+only called for fields which already exist on the class.  `Exception:'
+if __getattr__(5) or __getattribute__(6) is a method on the class, the
+hook is called for all fields which do not refer to methods.
+
+`get_class_decorator_hook()' can be used to update class definition for
+given class decorators.  For example, you can add some attributes to the
+class to match runtime behaviour:
+
+     from dataclasses import dataclass
+
+     @dataclass  # built-in plugin adds `__init__` method here
+     class User:
+         name: str
+
+     user = User(name='example')  # mypy can understand this using a plugin
+
+`get_metaclass_hook()' is similar to above, but for metaclasses.
+
+`get_base_class_hook()' is similar to above, but for base classes.
+
+`get_dynamic_class_hook()' can be used to allow dynamic class
+definitions in mypy.  This plugin hook is called for every assignment to
+a simple name where right hand side is a function call:
+
+     from lib import dynamic_class
+
+     X = dynamic_class('X', [])
+
+For such definition, mypy will call
+‘get_dynamic_class_hook("lib.dynamic_class")’.  The plugin should create
+the corresponding ‘mypy.nodes.TypeInfo’ object, and place it into a
+relevant symbol table.  (Instances of this class represent classes in
+mypy and hold essential information such as qualified name, method
+resolution order, etc.)
+
+`get_customize_class_mro_hook()' can be used to modify class MRO (for
+example insert some entries there) before the class body is analyzed.
+
+`get_additional_deps()' can be used to add new dependencies for a
+module.  It is called before semantic analysis.  For example, this can
+be used if a library has dependencies that are dynamically loaded based
+on configuration information.
+
+`report_config_data()' can be used if the plugin has some sort of
+per-module configuration that can affect typechecking.  In that case,
+when the configuration for a module changes, we want to invalidate
+mypy’s cache for that module so that it can be rechecked.  This hook
+should be used to report to mypy any relevant configuration data, so
+that mypy knows to recheck the module if the configuration changes.  The
+hooks should return data encodable as JSON.
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+   (2) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (3) https://docs.python.org/3/reference/datamodel.html#object.__new__
+
+   (4) https://docs.python.org/3/library/ctypes.html#module-ctypes
+
+   (5) 
+https://docs.python.org/3/reference/datamodel.html#object.__getattr__
+
+   (6) 
+https://docs.python.org/3/reference/datamodel.html#object.__getattribute__
+
+
+File: Mypy.info,  Node: Notes about the semantic analyzer,  Prev: Current list of plugin hooks,  Up: Extending and integrating mypy
+
+28.6 Notes about the semantic analyzer
+======================================
+
+Mypy 0.710 introduced a new semantic analyzer, and the old semantic
+analyzer was removed in mypy 0.730.  Support for the new semantic
+analyzer required some changes to existing plugins.  Here is a short
+summary of the most important changes:
+
+   * The order of processing AST nodes is different.  Code outside
+     functions is processed first, and functions and methods are
+     processed afterwards.
+
+   * Each AST node can be processed multiple times to resolve forward
+     references.  The same plugin hook may be called multiple times, so
+     they need to be idempotent.
+
+   * The ‘anal_type()’ API method returns ‘None’ if some part of the
+     type is not available yet due to forward references, for example.
+
+   * When looking up symbols, you may encounter `placeholder nodes' that
+     are used for names that haven’t been fully processed yet.  You’ll
+     generally want to request another semantic analysis iteration by
+     `deferring' in that case.
+
+See the docstring at the top of mypy/plugin.py(1) for more details.
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/mypy/blob/master/mypy/plugin.py
+
+
+File: Mypy.info,  Node: Automatic stub generation stubgen,  Next: Automatic stub testing stubtest,  Prev: Extending and integrating mypy,  Up: Top
+
+29 Automatic stub generation (stubgen)
+**************************************
+
+A stub file (see PEP 484(1)) contains only type hints for the public
+interface of a module, with empty function bodies.  Mypy can use a stub
+file instead of the real implementation to provide type information for
+the module.  They are useful for third-party modules whose authors have
+not yet added type hints (and when no stubs are available in typeshed)
+and C extension modules (which mypy can’t directly process).
+
+Mypy includes the ‘stubgen’ tool that can automatically generate stub
+files (‘.pyi’ files) for Python modules and C extension modules.  For
+example, consider this source file:
+
+     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)
+
+Stubgen can generate this stub file based on the above file:
+
+     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: ...
+
+Stubgen generates `draft' stubs.  The auto-generated stub files often
+require some manual updates, and most types will default to ‘Any’.  The
+stubs will be much more useful if you add more precise type annotations,
+at least for the most commonly used functionality.
+
+The rest of this section documents the command line interface of
+stubgen.  Run *note stubgen –help: 23d. for a quick summary of options.
+
+     Note: The command-line flags may change between releases.
+
+* Menu:
+
+* Specifying what to stub::
+* Specifying how to generate stubs::
+* Additional flags::
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0484/
+
+
+File: Mypy.info,  Node: Specifying what to stub,  Next: Specifying how to generate stubs,  Up: Automatic stub generation stubgen
+
+29.1 Specifying what to stub
+============================
+
+You can give stubgen paths of the source files for which you want to
+generate stubs:
+
+     $ stubgen foo.py bar.py
+
+This generates stubs ‘out/foo.pyi’ and ‘out/bar.pyi’.  The default
+output directory ‘out’ can be overridden with *note -o DIR: 23f.
+
+You can also pass directories, and stubgen will recursively search them
+for any ‘.py’ files and generate stubs for all of them:
+
+     $ stubgen my_pkg_dir
+
+Alternatively, you can give module or package names using the *note -m:
+240. or *note -p: 241. options:
+
+     $ stubgen -m foo -m bar -p my_pkg_dir
+
+Details of the options:
+
+ -- Option: -m MODULE, --module MODULE
+
+     Generate a stub file for the given module.  This flag may be
+     repeated multiple times.
+
+     Stubgen `will not' recursively generate stubs for any submodules of
+     the provided module.
+
+ -- Option: -p PACKAGE, --package PACKAGE
+
+     Generate stubs for the given package.  This flag maybe repeated
+     multiple times.
+
+     Stubgen `will' recursively generate stubs for all submodules of the
+     provided package.  This flag is identical to *note –module: 240.
+     apart from this behavior.
+
+     Note: You can’t mix paths and *note -m: 240./*note -p: 241. options
+     in the same stubgen invocation.
+
+Stubgen applies heuristics to avoid generating stubs for submodules that
+include tests or vendored third-party packages.
+
+
+File: Mypy.info,  Node: Specifying how to generate stubs,  Next: Additional flags,  Prev: Specifying what to stub,  Up: Automatic stub generation stubgen
+
+29.2 Specifying how to generate stubs
+=====================================
+
+By default stubgen will try to import the target modules and packages.
+This allows stubgen to use runtime introspection to generate stubs for C
+extension modules and to improve the quality of the generated stubs.  By
+default, stubgen will also use mypy to perform light-weight semantic
+analysis of any Python modules.  Use the following flags to alter the
+default behavior:
+
+ -- Option: --no-import
+
+     Don’t try to import modules.  Instead only use mypy’s normal search
+     mechanism to find sources.  This does not support C extension
+     modules.  This flag also disables runtime introspection
+     functionality, which mypy uses to find the value of ‘__all__’.  As
+     result the set of exported imported names in stubs may be
+     incomplete.  This flag is generally only useful when importing a
+     module causes unwanted side effects, such as the running of tests.
+     Stubgen tries to skip test modules even without this option, but
+     this does not always work.
+
+ -- Option: --parse-only
+
+     Don’t perform semantic analysis of source files.  This may generate
+     worse stubs – in particular, some module, class, and function
+     aliases may be represented as variables with the ‘Any’ type.  This
+     is generally only useful if semantic analysis causes a critical
+     mypy error.
+
+ -- Option: --doc-dir PATH
+
+     Try to infer better signatures by parsing .rst documentation in
+     ‘PATH’.  This may result in better stubs, but currently it only
+     works for C extension modules.
+
+
+File: Mypy.info,  Node: Additional flags,  Prev: Specifying how to generate stubs,  Up: Automatic stub generation stubgen
+
+29.3 Additional flags
+=====================
+
+ -- Option: -h, --help
+
+     Show help message and exit.
+
+ -- Option: --py2
+
+     Run stubgen in Python 2 mode (the default is Python 3 mode).
+
+ -- Option: --ignore-errors
+
+     If an exception was raised during stub generation, continue to
+     process any remaining modules instead of immediately failing with
+     an error.
+
+ -- Option: --include-private
+
+     Include definitions that are considered private in stubs (with
+     names such as ‘_foo’ with single leading underscore and no trailing
+     underscores).
+
+ -- Option: --export-less
+
+     Don’t export all names imported from other modules within the same
+     package.  Instead, only export imported names that are not
+     referenced in the module that contains the import.
+
+ -- Option: --search-path PATH
+
+     Specify module search directories, separated by colons (only used
+     if *note –no-import: 245. is given).
+
+ -- Option: --python-executable PATH
+
+     Use Python interpreter at ‘PATH’ for importing modules and runtime
+     introspection.  This has no effect with *note –no-import: 245, and
+     this only works in Python 2 mode.  In Python 3 mode the Python
+     interpreter used to run stubgen will always be used.
+
+ -- Option: -o PATH, --output PATH
+
+     Change the output directory.  By default the stubs are written in
+     the ‘./out’ directory.  The output directory will be created if it
+     doesn’t exist.  Existing stubs in the output directory will be
+     overwritten without warning.
+
+ -- Option: -v, --verbose
+
+     Produce more verbose output.
+
+ -- Option: -q, --quiet
+
+     Produce less verbose output.
+
+
+File: Mypy.info,  Node: Automatic stub testing stubtest,  Next: Common issues and solutions,  Prev: Automatic stub generation stubgen,  Up: Top
+
+30 Automatic stub testing (stubtest)
+************************************
+
+Stub files are files containing type annotations.  See PEP 484(1) for
+more motivation and details.
+
+A common problem with stub files is that they tend to diverge from the
+actual implementation.  Mypy includes the ‘stubtest’ tool that can
+automatically check for discrepancies between the stubs and the
+implementation at runtime.
+
+* Menu:
+
+* What stubtest does and does not do::
+* Example::
+* Usage::
+
+   ---------- Footnotes ----------
+
+   (1) https://www.python.org/dev/peps/pep-0484/#stub-files
+
+
+File: Mypy.info,  Node: What stubtest does and does not do,  Next: Example,  Up: Automatic stub testing stubtest
+
+30.1 What stubtest does and does not do
+=======================================
+
+Stubtest will import your code and introspect your code objects at
+runtime, for example, by using the capabilities of the inspect(1)
+module.  Stubtest will then analyse the stub files, and compare the two,
+pointing out things that differ between stubs and the implementation at
+runtime.
+
+It’s important to be aware of the limitations of this comparison.
+Stubtest will not make any attempt to statically analyse your actual
+code and relies only on dynamic runtime introspection (in particular,
+this approach means stubtest works well with extension modules).
+However, this means that stubtest has limited visibility; for instance,
+it cannot tell if a return type of a function is accurately typed in the
+stubs.
+
+For clarity, here are some additional things stubtest can’t do:
+
+   * Type check your code – use ‘mypy’ instead
+
+   * Generate stubs – use ‘stubgen’ or ‘pyright --createstub’ instead
+
+   * Generate stubs based on running your application or test suite –
+     use ‘monkeytype’ instead
+
+   * Apply stubs to code to produce inline types – use ‘retype’ or
+     ‘libcst’ instead
+
+In summary, stubtest works very well for ensuring basic consistency
+between stubs and implementation or to check for stub completeness.
+It’s used to test Python’s official collection of library stubs,
+typeshed(2).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/inspect.html#module-inspect
+
+   (2) https://github.com/python/typeshed
+
+
+File: Mypy.info,  Node: Example,  Next: Usage,  Prev: What stubtest does and does not do,  Up: Automatic stub testing stubtest
+
+30.2 Example
+============
+
+Here’s a quick example of what stubtest can do:
+
+     $ python3 -m pip install mypy
+
+     $ cat library.py
+     x = "hello, stubtest"
+
+     def foo(x=None):
+         print(x)
+
+     $ cat library.pyi
+     x: int
+
+     def foo(x: int) -> None: ...
+
+     $ python3 -m mypy.stubtest library
+     error: library.foo is inconsistent, runtime argument "x" has a default value but stub argument does not
+     Stub: at line 3
+     def (x: builtins.int)
+     Runtime: at line 3 in file ~/library.py
+     def (x=None)
+
+     error: library.x variable differs from runtime type Literal['hello, stubtest']
+     Stub: at line 1
+     builtins.int
+     Runtime:
+     hello, stubtest
+
+
+File: Mypy.info,  Node: Usage,  Prev: Example,  Up: Automatic stub testing stubtest
+
+30.3 Usage
+==========
+
+Running stubtest can be as simple as ‘stubtest module_to_check’.  Run
+*note stubtest –help: 25a. for a quick summary of options.
+
+Subtest must be able to import the code to be checked, so make sure that
+mypy is installed in the same environment as the library to be tested.
+In some cases, setting ‘PYTHONPATH’ can help stubtest find the code to
+import.
+
+Similarly, stubtest must be able to find the stubs to be checked.
+Stubtest respects the ‘MYPYPATH’ environment variable.
+
+If you wish to ignore some of stubtest’s complaints, stubtest supports a
+pretty handy allowlist system.
+
+The rest of this section documents the command line interface of
+stubtest.
+
+ -- Option: --concise
+
+     Makes stubtest’s output more concise, one line per error
+
+ -- Option: --ignore-missing-stub
+
+     Ignore errors for stub missing things that are present at runtime
+
+ -- Option: --ignore-positional-only
+
+     Ignore errors for whether an argument should or shouldn’t be
+     positional-only
+
+ -- Option: --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.
+
+ -- Option: --generate-allowlist
+
+     Print an allowlist (to stdout) to be used with –allowlist
+
+ -- Option: --ignore-unused-allowlist
+
+     Ignore unused allowlist entries
+
+ -- Option: --mypy-config-file FILE
+
+     Use specified mypy config file to determine mypy plugins and mypy
+     path
+
+ -- Option: --custom-typeshed-dir DIR
+
+     Use the custom typeshed in DIR
+
+ -- Option: --check-typeshed
+
+     Check all stdlib modules in typeshed
+
+ -- Option: --help
+
+     Show a help message :-)
+
+
+File: Mypy.info,  Node: Common issues and solutions,  Next: Supported Python features,  Prev: Automatic stub testing stubtest,  Up: Top
+
+31 Common issues and solutions
+******************************
+
+This section has examples of cases when you need to update your code to
+use static typing, and ideas for working around issues if mypy doesn’t
+work as expected.  Statically typed code is often identical to normal
+Python code (except for type annotations), but sometimes you need to do
+things slightly differently.
+
+* Menu:
+
+* Can’t install mypy using pip::
+* No errors reported for obviously wrong code::
+* Spurious errors and locally silencing the checker::
+* Ignoring a whole file::
+* Unexpected errors about ‘None’ and/or ‘Optional’ types::
+* Issues with code at runtime::
+* Mypy runs are slow::
+* Types of empty collections::
+* Redefinitions with incompatible types::
+* Invariance vs covariance::
+* Declaring a supertype as variable type::
+* Complex type tests::
+* Python version and system platform checks::
+* Displaying the type of an expression::
+* Silencing linters::
+* Covariant subtyping of mutable protocol members is rejected::
+* Dealing with conflicting names::
+* Using a development mypy build::
+* Variables vs type aliases::
+* Incompatible overrides::
+* Unreachable code::
+* Narrowing and inner functions::
+
+
+File: Mypy.info,  Node: Can’t install mypy using pip,  Next: No errors reported for obviously wrong code,  Up: Common issues and solutions
+
+31.1 Can’t install mypy using pip
+=================================
+
+If installation fails, you’ve probably hit one of these issues:
+
+   * Mypy needs Python 3.6 or later to run.
+
+   * You may have to run pip like this: ‘python3 -m pip install mypy’.
+
+
+File: Mypy.info,  Node: No errors reported for obviously wrong code,  Next: Spurious errors and locally silencing the checker,  Prev: Can’t install mypy using pip,  Up: Common issues and solutions
+
+31.2 No errors reported for obviously wrong code
+================================================
+
+There are several common reasons why obviously wrong code is not flagged
+as an error.
+
+`The function containing the error is not annotated.'  Functions that do
+not have any annotations (neither for any argument nor for the return
+type) are not type-checked, and even the most blatant type errors (e.g.
+‘2 + 'a'’) pass silently.  The solution is to add annotations.  Where
+that isn’t possible, functions without annotations can be checked using
+*note –check-untyped-defs: fa.
+
+Example:
+
+     def foo(a):
+         return '(' + a.split() + ')'  # No error!
+
+This gives no error even though ‘a.split()’ is “obviously” a list (the
+author probably meant ‘a.strip()’).  The error is reported once you add
+annotations:
+
+     def foo(a: str) -> str:
+         return '(' + a.split() + ')'
+     # error: Unsupported operand types for + ("str" and List[str])
+
+If you don’t know what types to add, you can use ‘Any’, but beware:
+
+`One of the values involved has type ‘Any’.'  Extending the above
+example, if we were to leave out the annotation for ‘a’, we’d get no
+error:
+
+     def foo(a) -> str:
+         return '(' + a.split() + ')'  # No error!
+
+The reason is that if the type of ‘a’ is unknown, the type of
+‘a.split()’ is also unknown, so it is inferred as having type ‘Any’, and
+it is no error to add a string to an ‘Any’.
+
+If you’re having trouble debugging such situations, *note reveal_type():
+106. might come in handy.
+
+Note that sometimes library stubs have imprecise type information, e.g.
+the pow()(1) builtin returns ‘Any’ (see typeshed issue 285(2) for the
+reason).
+
+__init__(3) `method has no annotated arguments or return type
+annotation.'  __init__(4) is considered fully-annotated `if at least one
+argument is annotated', while mypy will infer the return type as ‘None’.
+The implication is that, for a __init__(5) method that has no argument,
+you’ll have to explicitly annotate the return type as ‘None’ to
+type-check this __init__(6) method:
+
+     def foo(s: str) -> str:
+         return s
+
+     class A():
+         def __init__(self, value: str): # Return type inferred as None, considered as typed method
+             self.value = value
+             foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str"
+
+     class B():
+         def __init__(self):  # No argument is annotated, considered as untyped method
+             foo(1)  # No error!
+
+     class C():
+         def __init__(self) -> None:  # Must specify return type to type-check
+             foo(1) # error: Argument 1 to "foo" has incompatible type "int"; expected "str"
+
+`Some imports may be silently ignored'.  Another source of unexpected
+‘Any’ values are the *note –ignore-missing-imports: 140. and *note
+–follow-imports=skip: 148. flags.  When you use *note
+–ignore-missing-imports: 140, any imported module that cannot be found
+is silently replaced with ‘Any’.  When using *note –follow-imports=skip:
+148. the same is true for modules for which a ‘.py’ file is found but
+that are not specified on the command line.  (If a ‘.pyi’ stub is found
+it is always processed normally, regardless of the value of *note
+–follow-imports: 148.)  To help debug the former situation (no module
+found at all) leave out *note –ignore-missing-imports: 140.; to get
+clarity about the latter use *note –follow-imports=error: 148.  You can
+read up about these and other useful flags in *note The mypy command
+line: c.
+
+`A function annotated as returning a non-optional type returns ‘None’
+and mypy doesn’t complain'.
+
+     def foo() -> str:
+         return None  # No error!
+
+You may have disabled strict optional checking (see *note Disabling
+strict optional checking: 70. for more).
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#pow
+
+   (2) https://github.com/python/typeshed/issues/285
+
+   (3) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (4) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (5) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (6) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+
+File: Mypy.info,  Node: Spurious errors and locally silencing the checker,  Next: Ignoring a whole file,  Prev: No errors reported for obviously wrong code,  Up: Common issues and solutions
+
+31.3 Spurious errors and locally silencing the checker
+======================================================
+
+You can use a ‘# type: ignore’ comment to silence the type checker on a
+particular line.  For example, let’s say our code is using the C
+extension module ‘frobnicate’, and there’s no stub available.  Mypy will
+complain about this, as it has no information about the module:
+
+     import frobnicate  # Error: No module "frobnicate"
+     frobnicate.start()
+
+You can add a ‘# type: ignore’ comment to tell mypy to ignore this
+error:
+
+     import frobnicate  # type: ignore
+     frobnicate.start()  # Okay!
+
+The second line is now fine, since the ignore comment causes the name
+‘frobnicate’ to get an implicit ‘Any’ type.
+
+     Note: You can use the form ‘# type: ignore[<code>]’ to only ignore
+     specific errors on the line.  This way you are less likely to
+     silence unexpected errors that are not safe to ignore, and this
+     will also document what the purpose of the comment is.  See *note
+     Error codes: 18e. for more information.
+
+     Note: The ‘# type: ignore’ comment will only assign the implicit
+     ‘Any’ type if mypy cannot find information about that particular
+     module.  So, if we did have a stub available for ‘frobnicate’ then
+     mypy would ignore the ‘# type: ignore’ comment and typecheck the
+     stub as usual.
+
+Another option is to explicitly annotate values with type ‘Any’ – mypy
+will let you perform arbitrary operations on ‘Any’ values.  Sometimes
+there is no more precise type you can use for a particular value,
+especially if you use dynamic Python features such as __getattr__(1):
+
+     class Wrapper:
+         ...
+         def __getattr__(self, a: str) -> Any:
+             return getattr(self._wrapped, a)
+
+Finally, you can create a stub file (‘.pyi’) for a file that generates
+spurious errors.  Mypy will only look at the stub file and ignore the
+implementation, since stub files take precedence over ‘.py’ files.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__getattr__
+
+
+File: Mypy.info,  Node: Ignoring a whole file,  Next: Unexpected errors about ‘None’ and/or ‘Optional’ types,  Prev: Spurious errors and locally silencing the checker,  Up: Common issues and solutions
+
+31.4 Ignoring a whole file
+==========================
+
+A ‘# type: ignore’ comment at the top of a module (before any
+statements, including imports or docstrings) has the effect of ignoring
+the `entire' module.
+
+     # type: ignore
+
+     import foo
+
+     foo.bar()
+
+
+File: Mypy.info,  Node: Unexpected errors about ‘None’ and/or ‘Optional’ types,  Next: Issues with code at runtime,  Prev: Ignoring a whole file,  Up: Common issues and solutions
+
+31.5 Unexpected errors about ‘None’ and/or ‘Optional’ types
+===========================================================
+
+Starting from mypy 0.600, mypy uses *note strict optional checking: 6a.
+by default, and the ‘None’ value is not compatible with non-optional
+types.  It’s easy to switch back to the older behavior where ‘None’ was
+compatible with arbitrary types (see *note Disabling strict optional
+checking: 70.).  You can also fall back to this behavior if strict
+optional checking would require a large number of ‘assert foo is not
+None’ checks to be inserted, and you want to minimize the number of code
+changes required to get a clean mypy run.
+
+
+File: Mypy.info,  Node: Issues with code at runtime,  Next: Mypy runs are slow,  Prev: Unexpected errors about ‘None’ and/or ‘Optional’ types,  Up: Common issues and solutions
+
+31.6 Issues with code at runtime
+================================
+
+Idiomatic use of type annotations can sometimes run up against what a
+given version of Python considers legal code.  These can result in some
+of the following errors when trying to run your code:
+
+   * ‘ImportError’ from circular imports
+
+   * ‘NameError: name "X" is not defined’ from forward references
+
+   * ‘TypeError: 'type' object is not subscriptable’ from types that are
+     not generic at runtime
+
+   * ‘ImportError’ or ‘ModuleNotFoundError’ from use of stub definitions
+     not available at runtime
+
+   * ‘TypeError: unsupported operand type(s) for |: 'type' and 'type'’
+     from use of new syntax
+
+For dealing with these, see *note Annotation issues at runtime: 6e.
+
+
+File: Mypy.info,  Node: Mypy runs are slow,  Next: Types of empty collections,  Prev: Issues with code at runtime,  Up: Common issues and solutions
+
+31.7 Mypy runs are slow
+=======================
+
+If your mypy runs feel slow, you should probably use the *note mypy
+daemon: 29, which can speed up incremental mypy runtimes by a factor of
+10 or more.  *note Remote caching: 2a. can make cold mypy runs several
+times faster.
+
+
+File: Mypy.info,  Node: Types of empty collections,  Next: Redefinitions with incompatible types,  Prev: Mypy runs are slow,  Up: Common issues and solutions
+
+31.8 Types of empty collections
+===============================
+
+You often need to specify the type when you assign an empty list or dict
+to a new variable, as mentioned earlier:
+
+     a: List[int] = []
+
+Without the annotation mypy can’t always figure out the precise type of
+‘a’.
+
+You can use a simple empty list literal in a dynamically typed function
+(as the type of ‘a’ would be implicitly ‘Any’ and need not be inferred),
+if type of the variable has been declared or inferred before, or if you
+perform a simple modification operation in the same scope (such as
+‘append’ for a list):
+
+     a = []  # Okay because followed by append, inferred type List[int]
+     for i in range(n):
+         a.append(i * i)
+
+However, in more complex cases an explicit type annotation can be
+required (mypy will tell you this).  Often the annotation can make your
+code easier to understand, so it doesn’t only help mypy but everybody
+who is reading the code!
+
+
+File: Mypy.info,  Node: Redefinitions with incompatible types,  Next: Invariance vs covariance,  Prev: Types of empty collections,  Up: Common issues and solutions
+
+31.9 Redefinitions with incompatible types
+==========================================
+
+Each name within a function only has a single ‘declared’ type.  You can
+reuse for loop indices etc., but if you want to use a variable with
+multiple types within a single function, you may need to declare it with
+the ‘Any’ type.
+
+     def f() -> None:
+         n = 1
+         ...
+         n = 'x'        # Type error: n has type int
+
+     Note: This limitation could be lifted in a future mypy release.
+
+Note that you can redefine a variable with a more `precise' or a more
+concrete type.  For example, you can redefine a sequence (which does not
+support ‘sort()’) as a list and sort it in-place:
+
+     def f(x: Sequence[int]) -> None:
+         # Type of x is Sequence[int] here; we don't know the concrete type.
+         x = list(x)
+         # Type of x is List[int] here.
+         x.sort()  # Okay!
+
+
+File: Mypy.info,  Node: Invariance vs covariance,  Next: Declaring a supertype as variable type,  Prev: Redefinitions with incompatible types,  Up: Common issues and solutions
+
+31.10 Invariance vs covariance
+==============================
+
+Most mutable generic collections are invariant, and mypy considers all
+user-defined generic classes invariant by default (see *note Variance of
+generic types: e7. for motivation).  This could lead to some unexpected
+errors when combined with type inference.  For example:
+
+     class A: ...
+     class B(A): ...
+
+     lst = [A(), A()]  # Inferred type is List[A]
+     new_lst = [B(), B()]  # inferred type is List[B]
+     lst = new_lst  # mypy will complain about this, because List is invariant
+
+Possible strategies in such situations are:
+
+   * Use an explicit type annotation:
+
+          new_lst: List[A] = [B(), B()]
+          lst = new_lst  # OK
+
+   * Make a copy of the right hand side:
+
+          lst = list(new_lst) # Also OK
+
+   * Use immutable collections as annotations whenever possible:
+
+          def f_bad(x: List[A]) -> A:
+              return x[0]
+          f_bad(new_lst) # Fails
+
+          def f_good(x: Sequence[A]) -> A:
+              return x[0]
+          f_good(new_lst) # OK
+
+
+File: Mypy.info,  Node: Declaring a supertype as variable type,  Next: Complex type tests,  Prev: Invariance vs covariance,  Up: Common issues and solutions
+
+31.11 Declaring a supertype as variable type
+============================================
+
+Sometimes the inferred type is a subtype (subclass) of the desired type.
+The type inference uses the first assignment to infer the type of a name
+(assume here that ‘Shape’ is the base class of both ‘Circle’ and
+‘Triangle’):
+
+     shape = Circle()    # Infer shape to be Circle
+     ...
+     shape = Triangle()  # Type error: Triangle is not a Circle
+
+You can just give an explicit type for the variable in cases such the
+above example:
+
+     shape = Circle() # type: Shape   # The variable s can be any Shape,
+                                      # not just Circle
+     ...
+     shape = Triangle()               # OK
+
+
+File: Mypy.info,  Node: Complex type tests,  Next: Python version and system platform checks,  Prev: Declaring a supertype as variable type,  Up: Common issues and solutions
+
+31.12 Complex type tests
+========================
+
+Mypy can usually infer the types correctly when using isinstance(1),
+issubclass(2), or ‘type(obj) is some_class’ type tests, and even *note
+user-defined type guards: cc, but for other kinds of checks you may need
+to add an explicit type cast:
+
+     from typing import Sequence, cast
+
+     def find_first_str(a: Sequence[object]) -> str:
+         index = next((i for i, s in enumerate(a) if isinstance(s, str)), -1)
+         if index < 0:
+             raise ValueError('No str found')
+
+         found = a[index]  # Has type "object", despite the fact that we know it is "str"
+         return cast(str, found)  # We need an explicit cast to make mypy happy
+
+Alternatively, you can use an ‘assert’ statement together with some of
+the supported type inference techniques:
+
+     def find_first_str(a: Sequence[object]) -> str:
+         index = next((i for i, s in enumerate(a) if isinstance(s, str)), -1)
+         if index < 0:
+             raise ValueError('No str found')
+
+         found = a[index]  # Has type "object", despite the fact that we know it is "str"
+         assert isinstance(found, str)  # Now, "found" will be narrowed to "str"
+         return found  # No need for the explicit "cast()" anymore
+
+     Note: Note that the object(3) type used in the above example is
+     similar to ‘Object’ in Java: it only supports operations defined
+     for `all' objects, such as equality and isinstance()(4).  The type
+     ‘Any’, in contrast, supports all operations, even if they may fail
+     at runtime.  The cast above would have been unnecessary if the type
+     of ‘o’ was ‘Any’.
+
+     Note: You can read more about type narrowing techniques *note here:
+     8f.
+
+Type inference in Mypy is designed to work well in common cases, to be
+predictable and to let the type checker give useful error messages.
+More powerful type inference strategies often have complex and
+difficult-to-predict failure modes and could result in very confusing
+error messages.  The tradeoff is that you as a programmer sometimes have
+to give the type checker a little help.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#isinstance
+
+   (2) https://docs.python.org/3/library/functions.html#issubclass
+
+   (3) https://docs.python.org/3/library/functions.html#object
+
+   (4) https://docs.python.org/3/library/functions.html#isinstance
+
+
+File: Mypy.info,  Node: Python version and system platform checks,  Next: Displaying the type of an expression,  Prev: Complex type tests,  Up: Common issues and solutions
+
+31.13 Python version and system platform checks
+===============================================
+
+Mypy supports the ability to perform Python version checks and platform
+checks (e.g.  Windows vs Posix), ignoring code paths that won’t be run
+on the targeted Python version or platform.  This allows you to more
+effectively typecheck code that supports multiple versions of Python or
+multiple operating systems.
+
+More specifically, mypy will understand the use of sys.version_info(1)
+and sys.platform(2) checks within ‘if/elif/else’ statements.  For
+example:
+
+     import sys
+
+     # Distinguishing between different versions of Python:
+     if sys.version_info >= (3, 8):
+         # Python 3.8+ specific definitions and imports
+     elif sys.version_info[0] >= 3:
+         # Python 3 specific definitions and imports
+     else:
+         # Python 2 specific definitions and imports
+
+     # Distinguishing between different operating systems:
+     if sys.platform.startswith("linux"):
+         # Linux-specific code
+     elif sys.platform == "darwin":
+         # Mac-specific code
+     elif sys.platform == "win32":
+         # Windows-specific code
+     else:
+         # Other systems
+
+As a special case, you can also use one of these checks in a top-level
+(unindented) ‘assert’; this makes mypy skip the rest of the file.
+Example:
+
+     import sys
+
+     assert sys.platform != 'win32'
+
+     # The rest of this file doesn't apply to Windows.
+
+Some other expressions exhibit similar behavior; in particular,
+TYPE_CHECKING(3), variables named ‘MYPY’, and any variable whose name is
+passed to *note –always-true: fe. or *note –always-false: ff.  (However,
+‘True’ and ‘False’ are not treated specially!)
+
+     Note: Mypy currently does not support more complex checks, and does
+     not assign any special meaning when assigning a sys.version_info(4)
+     or sys.platform(5) check to a variable.  This may change in future
+     versions of mypy.
+
+By default, mypy will use your current version of Python and your
+current operating system as default values for sys.version_info(6) and
+sys.platform(7).
+
+To target a different Python version, use the *note –python-version X.Y:
+100. flag.  For example, to verify your code typechecks if were run
+using Python 2, pass in *note –python-version 2.7: 100. from the command
+line.  Note that you do not need to have Python 2.7 installed to perform
+this check.
+
+To target a different operating system, use the *note –platform
+PLATFORM: 16a. flag.  For example, to verify your code typechecks if it
+were run in Windows, pass in *note –platform win32: 16a.  See the
+documentation for sys.platform(8) for examples of valid platform
+parameters.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/sys.html#sys.version_info
+
+   (2) https://docs.python.org/3/library/sys.html#sys.platform
+
+   (3) 
+https://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING
+
+   (4) https://docs.python.org/3/library/sys.html#sys.version_info
+
+   (5) https://docs.python.org/3/library/sys.html#sys.platform
+
+   (6) https://docs.python.org/3/library/sys.html#sys.version_info
+
+   (7) https://docs.python.org/3/library/sys.html#sys.platform
+
+   (8) https://docs.python.org/3/library/sys.html#sys.platform
+
+
+File: Mypy.info,  Node: Displaying the type of an expression,  Next: Silencing linters,  Prev: Python version and system platform checks,  Up: Common issues and solutions
+
+31.14 Displaying the type of an expression
+==========================================
+
+You can use ‘reveal_type(expr)’ to ask mypy to display the inferred
+static type of an expression.  This can be useful when you don’t quite
+understand how mypy handles a particular piece of code.  Example:
+
+     reveal_type((1, 'hello'))  # Revealed type is "Tuple[builtins.int, builtins.str]"
+
+You can also use ‘reveal_locals()’ at any line in a file to see the
+types of all local variables at once.  Example:
+
+     a = 1
+     b = 'one'
+     reveal_locals()
+     # Revealed local types are:
+     #     a: builtins.int
+     #     b: builtins.str
+
+     Note: ‘reveal_type’ and ‘reveal_locals’ are only understood by mypy
+     and don’t exist in Python.  If you try to run your program, you’ll
+     have to remove any ‘reveal_type’ and ‘reveal_locals’ calls before
+     you can run your code.  Both are always available and you don’t
+     need to import them.
+
+
+File: Mypy.info,  Node: Silencing linters,  Next: Covariant subtyping of mutable protocol members is rejected,  Prev: Displaying the type of an expression,  Up: Common issues and solutions
+
+31.15 Silencing linters
+=======================
+
+In some cases, linters will complain about unused imports or code.  In
+these cases, you can silence them with a comment after type comments, or
+on the same line as the import:
+
+     # to silence complaints about unused imports
+     from typing import List  # noqa
+     a = None  # type: List[int]
+
+To silence the linter on the same line as a type comment put the linter
+comment `after' the type comment:
+
+     a = some_complex_thing()  # type: ignore  # noqa
+
+
+File: Mypy.info,  Node: Covariant subtyping of mutable protocol members is rejected,  Next: Dealing with conflicting names,  Prev: Silencing linters,  Up: Common issues and solutions
+
+31.16 Covariant subtyping of mutable protocol members is rejected
+=================================================================
+
+Mypy rejects this because this is potentially unsafe.  Consider this
+example:
+
+     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!
+
+To work around this problem consider whether “mutating” is actually part
+of a protocol.  If not, then one can use a @property(1) in the protocol
+definition:
+
+     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
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#property
+
+
+File: Mypy.info,  Node: Dealing with conflicting names,  Next: Using a development mypy build,  Prev: Covariant subtyping of mutable protocol members is rejected,  Up: Common issues and solutions
+
+31.17 Dealing with conflicting names
+====================================
+
+Suppose you have a class with a method whose name is the same as an
+imported (or built-in) type, and you want to use the type in another
+method signature.  E.g.:
+
+     class Message:
+         def bytes(self):
+             ...
+         def register(self, path: bytes):  # error: Invalid type "mod.Message.bytes"
+             ...
+
+The third line elicits an error because mypy sees the argument type
+‘bytes’ as a reference to the method by that name.  Other than renaming
+the method, a work-around is to use an alias:
+
+     bytes_ = bytes
+     class Message:
+         def bytes(self):
+             ...
+         def register(self, path: bytes_):
+             ...
+
+
+File: Mypy.info,  Node: Using a development mypy build,  Next: Variables vs type aliases,  Prev: Dealing with conflicting names,  Up: Common issues and solutions
+
+31.18 Using a development mypy build
+====================================
+
+You can install the latest development version of mypy from source.
+Clone the mypy repository on GitHub(1), and then run ‘pip install’
+locally:
+
+     git clone https://github.com/python/mypy.git
+     cd mypy
+     sudo python3 -m pip install --upgrade .
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/mypy
+
+
+File: Mypy.info,  Node: Variables vs type aliases,  Next: Incompatible overrides,  Prev: Using a development mypy build,  Up: Common issues and solutions
+
+31.19 Variables vs type aliases
+===============================
+
+Mypy has both `type aliases' and variables with types like ‘Type[...]’.
+These are subtly different, and it’s important to understand how they
+differ to avoid pitfalls.
+
+  1. A variable with type ‘Type[...]’ is defined using an assignment
+     with an explicit type annotation:
+
+          class A: ...
+          tp: Type[A] = A
+
+  2. You can define a type alias using an assignment without an explicit
+     type annotation at the top level of a module:
+
+          class A: ...
+          Alias = A
+
+     You can also use ‘TypeAlias’ ( PEP 613(1)) to define an `explicit
+     type alias':
+
+          from typing import TypeAlias  # "from typing_extensions" in Python 3.9 and earlier
+
+          class A: ...
+          Alias: TypeAlias = A
+
+     You should always use ‘TypeAlias’ to define a type alias in a class
+     body or inside a function.
+
+The main difference is that the target of an alias is precisely known
+statically, and this means that they can be used in type annotations and
+other `type contexts'.  Type aliases can’t be defined conditionally
+(unless using *note supported Python version and platform checks: fd.):
+
+          class A: ...
+          class B: ...
+
+          if random() > 0.5:
+              Alias = A
+          else:
+              # error: Cannot assign multiple types to name "Alias" without an
+              # explicit "Type[...]" annotation
+              Alias = B
+
+          tp: Type[object]  # "tp" is a variable with a type object value
+          if random() > 0.5:
+              tp = A
+          else:
+              tp = B  # This is OK
+
+          def fun1(x: Alias) -> None: ...  # OK
+          def fun2(x: tp) -> None: ...  # Error: "tp" is not valid as a type
+
+   ---------- Footnotes ----------
+
+   (1) https://peps.python.org/pep-0613/
+
+
+File: Mypy.info,  Node: Incompatible overrides,  Next: Unreachable code,  Prev: Variables vs type aliases,  Up: Common issues and solutions
+
+31.20 Incompatible overrides
+============================
+
+It’s unsafe to override a method with a more specific argument type, as
+it violates the Liskov substitution principle(1).  For return types,
+it’s unsafe to override a method with a more general return type.
+
+Other incompatible signature changes in method overrides, such as adding
+an extra required parameter, or removing an optional parameter, will
+also generate errors.  The signature of a method in a subclass should
+accept all valid calls to the base class method.  Mypy treats a subclass
+as a subtype of the base class.  An instance of a subclass is valid
+everywhere where an instance of the base class is valid.
+
+This example demonstrates both safe and unsafe overrides:
+
+     from typing import Sequence, List, Iterable
+
+     class A:
+         def test(self, t: Sequence[int]) -> Sequence[str]:
+             ...
+
+     class GeneralizedArgument(A):
+         # A more general argument type is okay
+         def test(self, t: Iterable[int]) -> Sequence[str]:  # OK
+             ...
+
+     class NarrowerArgument(A):
+         # A more specific argument type isn't accepted
+         def test(self, t: List[int]) -> Sequence[str]:  # Error
+             ...
+
+     class NarrowerReturn(A):
+         # A more specific return type is fine
+         def test(self, t: Sequence[int]) -> List[str]:  # OK
+             ...
+
+     class GeneralizedReturn(A):
+         # A more general return type is an error
+         def test(self, t: Sequence[int]) -> Iterable[str]:  # Error
+             ...
+
+You can use ‘# type: ignore[override]’ to silence the error.  Add it to
+the line that generates the error, if you decide that type safety is not
+necessary:
+
+     class NarrowerArgument(A):
+         def test(self, t: List[int]) -> Sequence[str]:  # type: ignore[override]
+             ...
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle
+
+
+File: Mypy.info,  Node: Unreachable code,  Next: Narrowing and inner functions,  Prev: Incompatible overrides,  Up: Common issues and solutions
+
+31.21 Unreachable code
+======================
+
+Mypy may consider some code as `unreachable', even if it might not be
+immediately obvious why.  It’s important to note that mypy will `not'
+type check such code.  Consider this example:
+
+     class Foo:
+         bar: str = ''
+
+     def bar() -> None:
+         foo: Foo = Foo()
+         return
+         x: int = 'abc'  # Unreachable -- no error
+
+It’s easy to see that any statement after ‘return’ is unreachable, and
+hence mypy will not complain about the mis-typed code below it.  For a
+more subtle example, consider this code:
+
+     class Foo:
+         bar: str = ''
+
+     def bar() -> None:
+         foo: Foo = Foo()
+         assert foo.bar is None
+         x: int = 'abc'  # Unreachable -- no error
+
+Again, mypy will not report any errors.  The type of ‘foo.bar’ is ‘str’,
+and mypy reasons that it can never be ‘None’.  Hence the ‘assert’
+statement will always fail and the statement below will never be
+executed.  (Note that in Python, ‘None’ is not an empty reference but an
+object of type ‘None’.)
+
+In this example mypy will go on to check the last line and report an
+error, since mypy thinks that the condition could be either True or
+False:
+
+     class Foo:
+         bar: str = ''
+
+     def bar() -> None:
+         foo: Foo = Foo()
+         if not foo.bar:
+             return
+         x: int = 'abc'  # Reachable -- error
+
+If you use the *note –warn-unreachable: c6. flag, mypy will generate an
+error about each unreachable code block.
+
+
+File: Mypy.info,  Node: Narrowing and inner functions,  Prev: Unreachable code,  Up: Common issues and solutions
+
+31.22 Narrowing and inner functions
+===================================
+
+Because closures in Python are late-binding
+(‘https://docs.python-guide.org/writing/gotchas/#late-binding-closures’),
+mypy will not narrow the type of a captured variable in an inner
+function.  This is best understood via an example:
+
+     def foo(x: Optional[int]) -> Callable[[], int]:
+         if x is None:
+             x = 5
+         print(x + 1)  # mypy correctly deduces x must be an int here
+         def inner() -> int:
+             return x + 1  # but (correctly) complains about this line
+
+         x = None  # because x could later be assigned None
+         return inner
+
+     inner = foo(5)
+     inner()  # this will raise an error when called
+
+To get this code to type check, you could assign ‘y = x’ after ‘x’ has
+been narrowed, and use ‘y’ in the inner function, or add an assert in
+the inner function.
+
+
+File: Mypy.info,  Node: Supported Python features,  Next: Error codes,  Prev: Common issues and solutions,  Up: Top
+
+32 Supported Python features
+****************************
+
+A list of unsupported Python features is maintained in the mypy wiki:
+
+   - Unsupported Python features(1)
+
+* Menu:
+
+* Runtime definition of methods and functions::
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/mypy/wiki/Unsupported-Python-Features
+
+
+File: Mypy.info,  Node: Runtime definition of methods and functions,  Up: Supported Python features
+
+32.1 Runtime definition of methods and functions
+================================================
+
+By default, mypy will complain if you add a function to a class or
+module outside its definition – but only if this is visible to the type
+checker.  This only affects static checking, as mypy performs no
+additional type checking at runtime.  You can easily work around this.
+For example, you can use dynamically typed code or values with ‘Any’
+types, or you can use setattr()(1) or other introspection features.
+However, you need to be careful if you decide to do this.  If used
+indiscriminately, you may have difficulty using static typing
+effectively, since the type checker cannot see functions defined at
+runtime.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#setattr
+
+
+File: Mypy.info,  Node: Error codes,  Next: Error codes enabled by default,  Prev: Supported Python features,  Up: Top
+
+33 Error codes
+**************
+
+Mypy can optionally display an error code such as ‘[attr-defined]’ after
+each error message.  Error codes serve two purposes:
+
+  1. It’s possible to silence specific error codes on a line using ‘#
+     type: ignore[code]’.  This way you won’t accidentally ignore other,
+     potentially more serious errors.
+
+  2. The error code can be used to find documentation about the error.
+     The next two topics (*note Error codes enabled by default: 284. and
+     *note Error codes for optional checks: 285.) document the various
+     error codes mypy can report.
+
+Most error codes are shared between multiple related error messages.
+Error codes may change in future mypy releases.
+
+* Menu:
+
+* Displaying error codes::
+* Silencing errors based on error codes::
+
+
+File: Mypy.info,  Node: Displaying error codes,  Next: Silencing errors based on error codes,  Up: Error codes
+
+33.1 Displaying error codes
+===========================
+
+Error codes are not displayed by default.  Use *note –show-error-codes:
+5a. or config ‘show_error_codes = True’ to display error codes.  Error
+codes are shown inside square brackets:
+
+     $ mypy --show-error-codes prog.py
+     prog.py:1: error: "str" has no attribute "trim"  [attr-defined]
+
+It’s also possible to require error codes for ‘type: ignore’ comments.
+See *note ignore-without-code: 287. for more information.
+
+
+File: Mypy.info,  Node: Silencing errors based on error codes,  Prev: Displaying error codes,  Up: Error codes
+
+33.2 Silencing errors based on error codes
+==========================================
+
+You can use a special comment ‘# type: ignore[code, ...]’ to only ignore
+errors with a specific error code (or codes) on a particular line.  This
+can be used even if you have not configured mypy to show error codes.
+Currently it’s only possible to disable arbitrary error codes on
+individual lines using this comment.
+
+     Note: There are command-line flags and config file settings for
+     enabling certain optional error codes, such as *note
+     –disallow-untyped-defs: b, which enables the ‘no-untyped-def’ error
+     code.
+
+This example shows how to ignore an error about an imported name mypy
+thinks is undefined:
+
+     # 'foo' is defined in 'foolib', even though mypy can't see the
+     # definition.
+     from foolib import foo  # type: ignore[attr-defined]
+
+
+File: Mypy.info,  Node: Error codes enabled by default,  Next: Error codes for optional checks,  Prev: Error codes,  Up: Top
+
+34 Error codes enabled by default
+*********************************
+
+This section documents various errors codes that mypy can generate with
+default options.  See *note Error codes: 18e. for general documentation
+about error codes.  *note Error codes for optional checks: 285.
+documents additional error codes that you can enable.
+
+* Menu:
+
+* Check that attribute exists [attr-defined]::
+* Check that attribute exists in each union item [union-attr]::
+* Check that name is defined [name-defined]::
+* Check arguments in calls [call-arg]::
+* Check argument types [arg-type]::
+* Check calls to overloaded functions [call-overload]::
+* Check validity of types [valid-type]::
+* Require annotation if variable type is unclear [var-annotated]::
+* Check validity of overrides [override]::
+* Check that function returns a value [return]::
+* Check that return value is compatible [return-value]::
+* Check types in assignment statement [assignment]::
+* Check type variable values [type-var]::
+* Check uses of various operators [operator]::
+* Check indexing operations [index]::
+* Check list items [list-item]::
+* Check dict items [dict-item]::
+* Check TypedDict items [typeddict-item]::
+* Check that type of target is known [has-type]::
+* Check that import target can be found [import]::
+* Check that each name is defined once [no-redef]::
+* Check that called function returns a value [func-returns-value]::
+* Check instantiation of abstract classes [abstract]::
+* Check the target of NewType [valid-newtype]::
+* Check the return type of __exit__ [exit-return]::
+* Check that naming is consistent [name-match]::
+* Check that overloaded functions have an implementation [no-overload-impl]::
+* Report syntax errors [syntax]::
+* Miscellaneous checks [misc]::
+
+
+File: Mypy.info,  Node: Check that attribute exists [attr-defined],  Next: Check that attribute exists in each union item [union-attr],  Up: Error codes enabled by default
+
+34.1 Check that attribute exists [attr-defined]
+===============================================
+
+Mypy checks that an attribute is defined in the target class or module
+when using the dot operator.  This applies to both getting and setting
+an attribute.  New attributes are defined by assignments in the class
+body, or assignments to ‘self.x’ in methods.  These assignments don’t
+generate ‘attr-defined’ errors.
+
+Example:
+
+     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]
+
+This error code is also generated if an imported name is not defined in
+the module in a ‘from ... import’ statement (as long as the target
+module can be found):
+
+     # Error: Module "os" has no attribute "non_existent"  [attr-defined]
+     from os import non_existent
+
+A reference to a missing attribute is given the ‘Any’ type.  In the
+above example, the type of ‘non_existent’ will be ‘Any’, which can be
+important if you silence the error.
+
+
+File: Mypy.info,  Node: Check that attribute exists in each union item [union-attr],  Next: Check that name is defined [name-defined],  Prev: Check that attribute exists [attr-defined],  Up: Error codes enabled by default
+
+34.2 Check that attribute exists in each union item [union-attr]
+================================================================
+
+If you access the attribute of a value with a union type, mypy checks
+that the attribute is defined for `every' type in that union.  Otherwise
+the operation can fail at runtime.  This also applies to optional types.
+
+Example:
+
+     from typing import Union
+
+     class Cat:
+         def sleep(self) -> None: ...
+         def miaow(self) -> None: ...
+
+     class Dog:
+         def sleep(self) -> None: ...
+         def follow_me(self) -> None: ...
+
+     def func(animal: Union[Cat, Dog]) -> None:
+         # OK: 'sleep' is defined for both Cat and Dog
+         animal.sleep()
+         # Error: Item "Cat" of "Union[Cat, Dog]" has no attribute "follow_me"  [union-attr]
+         animal.follow_me()
+
+You can often work around these errors by using ‘assert isinstance(obj,
+ClassName)’ or ‘assert obj is not None’ to tell mypy that you know that
+the type is more specific than what mypy thinks.
+
+
+File: Mypy.info,  Node: Check that name is defined [name-defined],  Next: Check arguments in calls [call-arg],  Prev: Check that attribute exists in each union item [union-attr],  Up: Error codes enabled by default
+
+34.3 Check that name is defined [name-defined]
+==============================================
+
+Mypy expects that all references to names have a corresponding
+definition in an active scope, such as an assignment, function
+definition or an import.  This can catch missing definitions, missing
+imports, and typos.
+
+This example accidentally calls ‘sort()’ instead of sorted()(1):
+
+     x = sort([3, 2, 4])  # Error: Name "sort" is not defined  [name-defined]
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/functions.html#sorted
+
+
+File: Mypy.info,  Node: Check arguments in calls [call-arg],  Next: Check argument types [arg-type],  Prev: Check that name is defined [name-defined],  Up: Error codes enabled by default
+
+34.4 Check arguments in calls [call-arg]
+========================================
+
+Mypy expects that the number and names of arguments match the called
+function.  Note that argument type checks have a separate error code
+‘arg-type’.
+
+Example:
+
+     from typing import Sequence
+
+     def greet(name: str) -> None:
+          print('hello', name)
+
+     greet('jack')  # OK
+     greet('jill', 'jack')  # Error: Too many arguments for "greet"  [call-arg]
+
+
+File: Mypy.info,  Node: Check argument types [arg-type],  Next: Check calls to overloaded functions [call-overload],  Prev: Check arguments in calls [call-arg],  Up: Error codes enabled by default
+
+34.5 Check argument types [arg-type]
+====================================
+
+Mypy checks that argument types in a call match the declared argument
+types in the signature of the called function (if one exists).
+
+Example:
+
+     from typing import Optional
+
+     def first(x: list[int]) -> Optional[int]:
+         return x[0] if x else 0
+
+     t = (5, 4)
+     # Error: Argument 1 to "first" has incompatible type "tuple[int, int]";
+     #        expected "list[int]"  [arg-type]
+     print(first(t))
+
+
+File: Mypy.info,  Node: Check calls to overloaded functions [call-overload],  Next: Check validity of types [valid-type],  Prev: Check argument types [arg-type],  Up: Error codes enabled by default
+
+34.6 Check calls to overloaded functions [call-overload]
+========================================================
+
+When you call an overloaded function, mypy checks that at least one of
+the signatures of the overload items match the argument types in the
+call.
+
+Example:
+
+     from typing import overload, Optional
+
+     @overload
+     def inc_maybe(x: None) -> None: ...
+
+     @overload
+     def inc_maybe(x: int) -> int: ...
+
+     def inc_maybe(x: Optional[int]) -> Optional[int]:
+          if x is None:
+              return None
+          else:
+              return x + 1
+
+     inc_maybe(None)  # OK
+     inc_maybe(5)  # OK
+
+     # Error: No overload variant of "inc_maybe" matches argument type "float"  [call-overload]
+     inc_maybe(1.2)
+
+
+File: Mypy.info,  Node: Check validity of types [valid-type],  Next: Require annotation if variable type is unclear [var-annotated],  Prev: Check calls to overloaded functions [call-overload],  Up: Error codes enabled by default
+
+34.7 Check validity of types [valid-type]
+=========================================
+
+Mypy checks that each type annotation and any expression that represents
+a type is a valid type.  Examples of valid types include classes, union
+types, callable types, type aliases, and literal types.  Examples of
+invalid types include bare integer literals, functions, variables, and
+modules.
+
+This example incorrectly uses the function ‘log’ as a type:
+
+     def log(x: object) -> None:
+         print('log:', repr(x))
+
+     # Error: Function "t.log" is not valid as a type  [valid-type]
+     def log_all(objs: list[object], f: log) -> None:
+         for x in objs:
+             f(x)
+
+You can use Callable(1) as the type for callable objects:
+
+     from typing import Callable
+
+     # OK
+     def log_all(objs: list[object], f: Callable[[object], None]) -> None:
+         for x in objs:
+             f(x)
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Callable
+
+
+File: Mypy.info,  Node: Require annotation if variable type is unclear [var-annotated],  Next: Check validity of overrides [override],  Prev: Check validity of types [valid-type],  Up: Error codes enabled by default
+
+34.8 Require annotation if variable type is unclear [var-annotated]
+===================================================================
+
+In some cases mypy can’t infer the type of a variable without an
+explicit annotation.  Mypy treats this as an error.  This typically
+happens when you initialize a variable with an empty collection or
+‘None’.  If mypy can’t infer the collection item type, mypy replaces any
+parts of the type it couldn’t infer with ‘Any’ and generates an error.
+
+Example with an error:
+
+     class Bundle:
+         def __init__(self) -> None:
+             # Error: Need type annotation for "items"
+             #        (hint: "items: list[<type>] = ...")  [var-annotated]
+             self.items = []
+
+     reveal_type(Bundle().items)  # list[Any]
+
+To address this, we add an explicit annotation:
+
+      class Bundle:
+          def __init__(self) -> None:
+              self.items: list[str] = []  # OK
+
+     reveal_type(Bundle().items)  # list[str]
+
+
+File: Mypy.info,  Node: Check validity of overrides [override],  Next: Check that function returns a value [return],  Prev: Require annotation if variable type is unclear [var-annotated],  Up: Error codes enabled by default
+
+34.9 Check validity of overrides [override]
+===========================================
+
+Mypy checks that an overridden method or attribute is compatible with
+the base class.  A method in a subclass must accept all arguments that
+the base class method accepts, and the return type must conform to the
+return type in the base class (Liskov substitution principle).
+
+Argument types can be more general is a subclass (i.e., they can vary
+contravariantly).  The return type can be narrowed in a subclass (i.e.,
+it can vary covariantly).  It’s okay to define additional arguments in a
+subclass method, as long all extra arguments have default values or can
+be left out (‘*args’, for example).
+
+Example:
+
+     from typing import Optional, Union
+
+     class Base:
+         def method(self,
+                    arg: int) -> Optional[int]:
+             ...
+
+     class Derived(Base):
+         def method(self,
+                    arg: Union[int, str]) -> int:  # OK
+             ...
+
+     class DerivedBad(Base):
+         # Error: Argument 1 of "method" is incompatible with "Base"  [override]
+         def method(self,
+                    arg: bool) -> int:
+             ...
+
+
+File: Mypy.info,  Node: Check that function returns a value [return],  Next: Check that return value is compatible [return-value],  Prev: Check validity of overrides [override],  Up: Error codes enabled by default
+
+34.10 Check that function returns a value [return]
+==================================================
+
+If a function has a non-‘None’ return type, mypy expects that the
+function always explicitly returns a value (or raises an exception).
+The function should not fall off the end of the function, since this is
+often a bug.
+
+Example:
+
+     # Error: Missing return statement  [return]
+     def show(x: int) -> int:
+         print(x)
+
+     # Error: Missing return statement  [return]
+     def pred1(x: int) -> int:
+         if x > 0:
+             return x - 1
+
+     # OK
+     def pred2(x: int) -> int:
+         if x > 0:
+             return x - 1
+         else:
+             raise ValueError('not defined for zero')
+
+
+File: Mypy.info,  Node: Check that return value is compatible [return-value],  Next: Check types in assignment statement [assignment],  Prev: Check that function returns a value [return],  Up: Error codes enabled by default
+
+34.11 Check that return value is compatible [return-value]
+==========================================================
+
+Mypy checks that the returned value is compatible with the type
+signature of the function.
+
+Example:
+
+     def func(x: int) -> str:
+         # Error: Incompatible return value type (got "int", expected "str")  [return-value]
+         return x + 1
+
+
+File: Mypy.info,  Node: Check types in assignment statement [assignment],  Next: Check type variable values [type-var],  Prev: Check that return value is compatible [return-value],  Up: Error codes enabled by default
+
+34.12 Check types in assignment statement [assignment]
+======================================================
+
+Mypy checks that the assigned expression is compatible with the
+assignment target (or targets).
+
+Example:
+
+     class Resource:
+         def __init__(self, name: str) -> None:
+             self.name = name
+
+     r = Resource('A')
+
+     r.name = 'B'  # OK
+
+     # Error: Incompatible types in assignment (expression has type "int",
+     #        variable has type "str")  [assignment]
+     r.name = 5
+
+
+File: Mypy.info,  Node: Check type variable values [type-var],  Next: Check uses of various operators [operator],  Prev: Check types in assignment statement [assignment],  Up: Error codes enabled by default
+
+34.13 Check type variable values [type-var]
+===========================================
+
+Mypy checks that value of a type variable is compatible with a value
+restriction or the upper bound type.
+
+Example:
+
+     from typing import TypeVar
+
+     T1 = TypeVar('T1', int, float)
+
+     def add(x: T1, y: T1) -> T1:
+         return x + y
+
+     add(4, 5.5)  # OK
+
+     # Error: Value of type variable "T1" of "add" cannot be "str"  [type-var]
+     add('x', 'y')
+
+
+File: Mypy.info,  Node: Check uses of various operators [operator],  Next: Check indexing operations [index],  Prev: Check type variable values [type-var],  Up: Error codes enabled by default
+
+34.14 Check uses of various operators [operator]
+================================================
+
+Mypy checks that operands support a binary or unary operation, such as
+‘+’ or ‘~’.  Indexing operations are so common that they have their own
+error code ‘index’ (see below).
+
+Example:
+
+     # Error: Unsupported operand types for + ("int" and "str")  [operator]
+     1 + 'x'
+
+
+File: Mypy.info,  Node: Check indexing operations [index],  Next: Check list items [list-item],  Prev: Check uses of various operators [operator],  Up: Error codes enabled by default
+
+34.15 Check indexing operations [index]
+=======================================
+
+Mypy checks that the indexed value in indexing operation such as ‘x[y]’
+supports indexing, and that the index expression has a valid type.
+
+Example:
+
+     a = {'x': 1, 'y': 2}
+
+     a['x']  # OK
+
+     # Error: Invalid index type "int" for "dict[str, int]"; expected type "str"  [index]
+     print(a[1])
+
+     # Error: Invalid index type "bytes" for "dict[str, int]"; expected type "str"  [index]
+     a[b'x'] = 4
+
+
+File: Mypy.info,  Node: Check list items [list-item],  Next: Check dict items [dict-item],  Prev: Check indexing operations [index],  Up: Error codes enabled by default
+
+34.16 Check list items [list-item]
+==================================
+
+When constructing a list using ‘[item, ...]’, mypy checks that each item
+is compatible with the list type that is inferred from the surrounding
+context.
+
+Example:
+
+     # Error: List item 0 has incompatible type "int"; expected "str"  [list-item]
+     a: list[str] = [0]
+
+
+File: Mypy.info,  Node: Check dict items [dict-item],  Next: Check TypedDict items [typeddict-item],  Prev: Check list items [list-item],  Up: Error codes enabled by default
+
+34.17 Check dict items [dict-item]
+==================================
+
+When constructing a dictionary using ‘{key: value, ...}’ or
+‘dict(key=value, ...)’, mypy checks that each key and value is
+compatible with the dictionary type that is inferred from the
+surrounding context.
+
+Example:
+
+     # Error: Dict entry 0 has incompatible type "str": "str"; expected "str": "int"  [dict-item]
+     d: dict[str, int] = {'key': 'value'}
+
+
+File: Mypy.info,  Node: Check TypedDict items [typeddict-item],  Next: Check that type of target is known [has-type],  Prev: Check dict items [dict-item],  Up: Error codes enabled by default
+
+34.18 Check TypedDict items [typeddict-item]
+============================================
+
+When constructing a ‘TypedDict’ object, mypy checks that each key and
+value is compatible with the ‘TypedDict’ type that is inferred from the
+surrounding context.
+
+When getting a ‘TypedDict’ item, mypy checks that the key exists.  When
+assigning to a ‘TypedDict’, mypy checks that both the key and the value
+are valid.
+
+Example:
+
+     from typing_extensions import TypedDict
+
+     class Point(TypedDict):
+         x: int
+         y: int
+
+     # Error: Incompatible types (expression has type "float",
+     #        TypedDict item "x" has type "int")  [typeddict-item]
+     p: Point = {'x': 1.2, 'y': 4}
+
+
+File: Mypy.info,  Node: Check that type of target is known [has-type],  Next: Check that import target can be found [import],  Prev: Check TypedDict items [typeddict-item],  Up: Error codes enabled by default
+
+34.19 Check that type of target is known [has-type]
+===================================================
+
+Mypy sometimes generates an error when it hasn’t inferred any type for a
+variable being referenced.  This can happen for references to variables
+that are initialized later in the source file, and for references across
+modules that form an import cycle.  When this happens, the reference
+gets an implicit ‘Any’ type.
+
+In this example the definitions of ‘x’ and ‘y’ are circular:
+
+     class Problem:
+         def set_x(self) -> None:
+             # Error: Cannot determine type of "y"  [has-type]
+             self.x = self.y
+
+         def set_y(self) -> None:
+             self.y = self.x
+
+To work around this error, you can add an explicit type annotation to
+the target variable or attribute.  Sometimes you can also reorganize the
+code so that the definition of the variable is placed earlier than the
+reference to the variable in a source file.  Untangling cyclic imports
+may also help.
+
+We add an explicit annotation to the ‘y’ attribute to work around the
+issue:
+
+     class Problem:
+         def set_x(self) -> None:
+             self.x = self.y  # OK
+
+         def set_y(self) -> None:
+             self.y: int = self.x  # Added annotation here
+
+
+File: Mypy.info,  Node: Check that import target can be found [import],  Next: Check that each name is defined once [no-redef],  Prev: Check that type of target is known [has-type],  Up: Error codes enabled by default
+
+34.20 Check that import target can be found [import]
+====================================================
+
+Mypy generates an error if it can’t find the source code or a stub file
+for an imported module.
+
+Example:
+
+     # Error: Cannot find implementation or library stub for module named 'acme'  [import]
+     import acme
+
+See *note Missing imports: 17. for how to work around these errors.
+
+
+File: Mypy.info,  Node: Check that each name is defined once [no-redef],  Next: Check that called function returns a value [func-returns-value],  Prev: Check that import target can be found [import],  Up: Error codes enabled by default
+
+34.21 Check that each name is defined once [no-redef]
+=====================================================
+
+Mypy may generate an error if you have multiple definitions for a name
+in the same namespace.  The reason is that this is often an error, as
+the second definition may overwrite the first one.  Also, mypy often
+can’t be able to determine whether references point to the first or the
+second definition, which would compromise type checking.
+
+If you silence this error, all references to the defined name refer to
+the `first' definition.
+
+Example:
+
+     class A:
+         def __init__(self, x: int) -> None: ...
+
+     class A:  # Error: Name "A" already defined on line 1  [no-redef]
+         def __init__(self, x: str) -> None: ...
+
+     # Error: Argument 1 to "A" has incompatible type "str"; expected "int"
+     #        (the first definition wins!)
+     A('x')
+
+
+File: Mypy.info,  Node: Check that called function returns a value [func-returns-value],  Next: Check instantiation of abstract classes [abstract],  Prev: Check that each name is defined once [no-redef],  Up: Error codes enabled by default
+
+34.22 Check that called function returns a value [func-returns-value]
+=====================================================================
+
+Mypy reports an error if you call a function with a ‘None’ return type
+and don’t ignore the return value, as this is usually (but not always) a
+programming error.
+
+In this example, the ‘if f()’ check is always false since ‘f’ returns
+‘None’:
+
+     def f() -> None:
+         ...
+
+     # OK: we don't do anything with the return value
+     f()
+
+     # Error: "f" does not return a value  [func-returns-value]
+     if f():
+          print("not false")
+
+
+File: Mypy.info,  Node: Check instantiation of abstract classes [abstract],  Next: Check the target of NewType [valid-newtype],  Prev: Check that called function returns a value [func-returns-value],  Up: Error codes enabled by default
+
+34.23 Check instantiation of abstract classes [abstract]
+========================================================
+
+Mypy generates an error if you try to instantiate an abstract base class
+(ABC). An abstract base class is a class with at least one abstract
+method or attribute.  (See also abc(1) module documentation)
+
+Sometimes a class is made accidentally abstract, often due to an
+unimplemented abstract method.  In a case like this you need to provide
+an implementation for the method to make the class concrete
+(non-abstract).
+
+Example:
+
+     from abc import ABCMeta, abstractmethod
+
+     class Persistent(metaclass=ABCMeta):
+         @abstractmethod
+         def save(self) -> None: ...
+
+     class Thing(Persistent):
+         def __init__(self) -> None:
+             ...
+
+         ...  # No "save" method
+
+     # Error: Cannot instantiate abstract class "Thing" with abstract attribute "save"  [abstract]
+     t = Thing()
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/abc.html#module-abc
+
+
+File: Mypy.info,  Node: Check the target of NewType [valid-newtype],  Next: Check the return type of __exit__ [exit-return],  Prev: Check instantiation of abstract classes [abstract],  Up: Error codes enabled by default
+
+34.24 Check the target of NewType [valid-newtype]
+=================================================
+
+The target of a ‘NewType’ definition must be a class type.  It can’t be
+a union type, ‘Any’, or various other special types.
+
+You can also get this error if the target has been imported from a
+module whose source mypy cannot find, since any such definitions are
+treated by mypy as values with ‘Any’ types.  Example:
+
+     from typing import NewType
+
+     # The source for "acme" is not available for mypy
+     from acme import Entity  # type: ignore
+
+     # Error: Argument 2 to NewType(...) must be subclassable (got "Any")  [valid-newtype]
+     UserEntity = NewType('UserEntity', Entity)
+
+To work around the issue, you can either give mypy access to the sources
+for ‘acme’ or create a stub file for the module.  See *note Missing
+imports: 17. for more information.
+
+
+File: Mypy.info,  Node: Check the return type of __exit__ [exit-return],  Next: Check that naming is consistent [name-match],  Prev: Check the target of NewType [valid-newtype],  Up: Error codes enabled by default
+
+34.25 Check the return type of __exit__ [exit-return]
+=====================================================
+
+If mypy can determine that __exit__(1) always returns ‘False’, mypy
+checks that the return type is `not' ‘bool’.  The boolean value of the
+return type affects which lines mypy thinks are reachable after a ‘with’
+statement, since any __exit__(2) method that can return ‘True’ may
+swallow exceptions.  An imprecise return type can result in mysterious
+errors reported near ‘with’ statements.
+
+To fix this, use either ‘typing_extensions.Literal[False]’ or ‘None’ as
+the return type.  Returning ‘None’ is equivalent to returning ‘False’ in
+this context, since both are treated as false values.
+
+Example:
+
+     class MyContext:
+         ...
+         def __exit__(self, exc, value, tb) -> bool:  # Error
+             print('exit')
+             return False
+
+This produces the following output from mypy:
+
+     example.py:3: error: "bool" is invalid as return type for "__exit__" that always returns False
+     example.py:3: note: Use "typing_extensions.Literal[False]" as the return type or change it to
+         "None"
+     example.py:3: note: If return type of "__exit__" implies that it may return True, the context
+         manager may swallow exceptions
+
+You can use ‘Literal[False]’ to fix the error:
+
+     from typing_extensions import Literal
+
+     class MyContext:
+         ...
+         def __exit__(self, exc, value, tb) -> Literal[False]:  # OK
+             print('exit')
+             return False
+
+You can also use ‘None’:
+
+     class MyContext:
+         ...
+         def __exit__(self, exc, value, tb) -> None:  # Also OK
+             print('exit')
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__exit__
+
+   (2) 
+https://docs.python.org/3/reference/datamodel.html#object.__exit__
+
+
+File: Mypy.info,  Node: Check that naming is consistent [name-match],  Next: Check that overloaded functions have an implementation [no-overload-impl],  Prev: Check the return type of __exit__ [exit-return],  Up: Error codes enabled by default
+
+34.26 Check that naming is consistent [name-match]
+==================================================
+
+The definition of a named tuple or a TypedDict must be named
+consistently when using the call-based syntax.  Example:
+
+     from typing import NamedTuple
+
+     # Error: First argument to namedtuple() should be "Point2D", not "Point"
+     Point2D = NamedTuple("Point", [("x", int), ("y", int)])
+
+
+File: Mypy.info,  Node: Check that overloaded functions have an implementation [no-overload-impl],  Next: Report syntax errors [syntax],  Prev: Check that naming is consistent [name-match],  Up: Error codes enabled by default
+
+34.27 Check that overloaded functions have an implementation [no-overload-impl]
+===============================================================================
+
+Overloaded functions outside of stub files must be followed by a non
+overloaded implementation.
+
+     from typing import overload
+
+     @overload
+     def func(value: int) -> int:
+         ...
+
+     @overload
+     def func(value: str) -> str:
+         ...
+
+     # presence of required function below is checked
+     def func(value):
+         pass  # actual implementation
+
+
+File: Mypy.info,  Node: Report syntax errors [syntax],  Next: Miscellaneous checks [misc],  Prev: Check that overloaded functions have an implementation [no-overload-impl],  Up: Error codes enabled by default
+
+34.28 Report syntax errors [syntax]
+===================================
+
+If the code being checked is not syntactically valid, mypy issues a
+syntax error.  Most, but not all, syntax errors are `blocking errors':
+they can’t be ignored with a ‘# type: ignore’ comment.
+
+
+File: Mypy.info,  Node: Miscellaneous checks [misc],  Prev: Report syntax errors [syntax],  Up: Error codes enabled by default
+
+34.29 Miscellaneous checks [misc]
+=================================
+
+Mypy performs numerous other, less commonly failing checks that don’t
+have specific error codes.  These use the ‘misc’ error code.  Other than
+being used for multiple unrelated errors, the ‘misc’ error code is not
+special.  For example, you can ignore all errors in this category by
+using ‘# type: ignore[misc]’ comment.  Since these errors are not
+expected to be common, it’s unlikely that you’ll see two `different'
+errors with the ‘misc’ code on a single line – though this can certainly
+happen once in a while.
+
+     Note: Future mypy versions will likely add new error codes for some
+     errors that currently use the ‘misc’ error code.
+
+
+File: Mypy.info,  Node: Error codes for optional checks,  Next: Additional features,  Prev: Error codes enabled by default,  Up: Top
+
+35 Error codes for optional checks
+**********************************
+
+This section documents various errors codes that mypy generates only if
+you enable certain options.  See *note Error codes: 18e. for general
+documentation about error codes.  *note Error codes enabled by default:
+284. documents error codes that are enabled by default.
+
+     Note: The examples in this section use *note inline configuration:
+     1b7. to specify mypy options.  You can also set the same options by
+     using a *note configuration file: 2e. or *note command-line
+     options: c.
+
+* Menu:
+
+* Check that type arguments exist [type-arg]::
+* Check that every function has an annotation [no-untyped-def]::
+* Check that cast is not redundant [redundant-cast]::
+* Check that comparisons are overlapping [comparison-overlap]::
+* Check that no untyped functions are called [no-untyped-call]::
+* Check that function does not return Any value [no-any-return]::
+* Check that types have no Any components due to missing imports [no-any-unimported]::
+* Check that statement or expression is unreachable [unreachable]::
+* Check that expression is redundant [redundant-expr]::
+* Check that expression is not implicitly true in boolean context [truthy-bool]::
+* Check that # type; ignore include an error code [ignore-without-code]: Check that # type ignore include an error code [ignore-without-code].
+
+
+File: Mypy.info,  Node: Check that type arguments exist [type-arg],  Next: Check that every function has an annotation [no-untyped-def],  Up: Error codes for optional checks
+
+35.1 Check that type arguments exist [type-arg]
+===============================================
+
+If you use *note –disallow-any-generics: 172, mypy requires that each
+generic type has values for each type argument.  For example, the types
+‘list’ or ‘dict’ would be rejected.  You should instead use types like
+‘list[int]’ or ‘dict[str, int]’.  Any omitted generic type arguments get
+implicit ‘Any’ values.  The type ‘list’ is equivalent to ‘list[Any]’,
+and so on.
+
+Example:
+
+     # mypy: disallow-any-generics
+
+     # Error: Missing type parameters for generic type "list"  [type-arg]
+     def remove_dups(items: list) -> list:
+         ...
+
+
+File: Mypy.info,  Node: Check that every function has an annotation [no-untyped-def],  Next: Check that cast is not redundant [redundant-cast],  Prev: Check that type arguments exist [type-arg],  Up: Error codes for optional checks
+
+35.2 Check that every function has an annotation [no-untyped-def]
+=================================================================
+
+If you use *note –disallow-untyped-defs: b, mypy requires that all
+functions have annotations (either a Python 3 annotation or a type
+comment).
+
+Example:
+
+     # mypy: disallow-untyped-defs
+
+     def inc(x):  # Error: Function is missing a type annotation  [no-untyped-def]
+         return x + 1
+
+     def inc_ok(x: int) -> int:  # OK
+         return x + 1
+
+     class Counter:
+          # Error: Function is missing a type annotation  [no-untyped-def]
+          def __init__(self):
+              self.value = 0
+
+     class CounterOk:
+          # OK: An explicit "-> None" is needed if "__init__" takes no arguments
+          def __init__(self) -> None:
+              self.value = 0
+
+
+File: Mypy.info,  Node: Check that cast is not redundant [redundant-cast],  Next: Check that comparisons are overlapping [comparison-overlap],  Prev: Check that every function has an annotation [no-untyped-def],  Up: Error codes for optional checks
+
+35.3 Check that cast is not redundant [redundant-cast]
+======================================================
+
+If you use *note –warn-redundant-casts: 17d, mypy will generate an error
+if the source type of a cast is the same as the target type.
+
+Example:
+
+     # mypy: warn-redundant-casts
+
+     from typing import cast
+
+     Count = int
+
+     def example(x: Count) -> int:
+         # Error: Redundant cast to "int"  [redundant-cast]
+         return cast(int, x)
+
+
+File: Mypy.info,  Node: Check that comparisons are overlapping [comparison-overlap],  Next: Check that no untyped functions are called [no-untyped-call],  Prev: Check that cast is not redundant [redundant-cast],  Up: Error codes for optional checks
+
+35.4 Check that comparisons are overlapping [comparison-overlap]
+================================================================
+
+If you use *note –strict-equality: 187, mypy will generate an error if
+it thinks that a comparison operation is always true or false.  These
+are often bugs.  Sometimes mypy is too picky and the comparison can
+actually be useful.  Instead of disabling strict equality checking
+everywhere, you can use ‘# type: ignore[comparison-overlap]’ to ignore
+the issue on a particular line only.
+
+Example:
+
+     # mypy: strict-equality
+
+     def is_magic(x: bytes) -> bool:
+         # Error: Non-overlapping equality check (left operand type: "bytes",
+         #        right operand type: "str")  [comparison-overlap]
+         return x == 'magic'
+
+We can fix the error by changing the string literal to a bytes literal:
+
+     # mypy: strict-equality
+
+     def is_magic(x: bytes) -> bool:
+         return x == b'magic'  # OK
+
+
+File: Mypy.info,  Node: Check that no untyped functions are called [no-untyped-call],  Next: Check that function does not return Any value [no-any-return],  Prev: Check that comparisons are overlapping [comparison-overlap],  Up: Error codes for optional checks
+
+35.5 Check that no untyped functions are called [no-untyped-call]
+=================================================================
+
+If you use *note –disallow-untyped-calls: 175, mypy generates an error
+when you call an unannotated function in an annotated function.
+
+Example:
+
+     # mypy: disallow-untyped-calls
+
+     def do_it() -> None:
+         # Error: Call to untyped function "bad" in typed context  [no-untyped-call]
+         bad()
+
+     def bad():
+         ...
+
+
+File: Mypy.info,  Node: Check that function does not return Any value [no-any-return],  Next: Check that types have no Any components due to missing imports [no-any-unimported],  Prev: Check that no untyped functions are called [no-untyped-call],  Up: Error codes for optional checks
+
+35.6 Check that function does not return Any value [no-any-return]
+==================================================================
+
+If you use *note –warn-return-any: 180, mypy generates an error if you
+return a value with an ‘Any’ type in a function that is annotated to
+return a non-‘Any’ value.
+
+Example:
+
+     # mypy: warn-return-any
+
+     def fields(s):
+          return s.split(',')
+
+     def first_field(x: str) -> str:
+         # Error: Returning Any from function declared to return "str"  [no-any-return]
+         return fields(x)[0]
+
+
+File: Mypy.info,  Node: Check that types have no Any components due to missing imports [no-any-unimported],  Next: Check that statement or expression is unreachable [unreachable],  Prev: Check that function does not return Any value [no-any-return],  Up: Error codes for optional checks
+
+35.7 Check that types have no Any components due to missing imports [no-any-unimported]
+=======================================================================================
+
+If you use *note –disallow-any-unimported: 16e, mypy generates an error
+if a component of a type becomes ‘Any’ because mypy couldn’t resolve an
+import.  These “stealth” ‘Any’ types can be surprising and accidentally
+cause imprecise type checking.
+
+In this example, we assume that mypy can’t find the module ‘animals’,
+which means that ‘Cat’ falls back to ‘Any’ in a type annotation:
+
+     # mypy: disallow-any-unimported
+
+     from animals import Cat  # type: ignore
+
+     # Error: Argument 1 to "feed" becomes "Any" due to an unfollowed import  [no-any-unimported]
+     def feed(cat: Cat) -> None:
+         ...
+
+
+File: Mypy.info,  Node: Check that statement or expression is unreachable [unreachable],  Next: Check that expression is redundant [redundant-expr],  Prev: Check that types have no Any components due to missing imports [no-any-unimported],  Up: Error codes for optional checks
+
+35.8 Check that statement or expression is unreachable [unreachable]
+====================================================================
+
+If you use *note –warn-unreachable: c6, mypy generates an error if it
+thinks that a statement or expression will never be executed.  In most
+cases, this is due to incorrect control flow or conditional checks that
+are accidentally always true or false.
+
+     # mypy: warn-unreachable
+
+     def example(x: int) -> None:
+         # Error: Right operand of "or" is never evaluated  [unreachable]
+         assert isinstance(x, int) or x == 'unused'
+
+         return
+         # Error: Statement is unreachable  [unreachable]
+         print('unreachable')
+
+
+File: Mypy.info,  Node: Check that expression is redundant [redundant-expr],  Next: Check that expression is not implicitly true in boolean context [truthy-bool],  Prev: Check that statement or expression is unreachable [unreachable],  Up: Error codes for optional checks
+
+35.9 Check that expression is redundant [redundant-expr]
+========================================================
+
+If you use *note –enable-error-code redundant-expr: 189, mypy generates
+an error if it thinks that an expression is redundant.
+
+     # mypy: enable-error-code redundant-expr
+
+     def example(x: int) -> None:
+         # Error: Left operand of "and" is always true  [redundant-expr]
+         if isinstance(x, int) and x > 0:
+             pass
+
+         # Error: If condition is always true  [redundant-expr]
+         1 if isinstance(x, int) else 0
+
+         # Error: If condition in comprehension is always true  [redundant-expr]
+         [i for i in range(x) if isinstance(i, int)]
+
+
+File: Mypy.info,  Node: Check that expression is not implicitly true in boolean context [truthy-bool],  Next: Check that # type ignore include an error code [ignore-without-code],  Prev: Check that expression is redundant [redundant-expr],  Up: Error codes for optional checks
+
+35.10 Check that expression is not implicitly true in boolean context [truthy-bool]
+===================================================================================
+
+Warn when an expression whose type does not implement ‘__bool__’ or
+‘__len__’ is used in boolean context, since unless implemented by a
+sub-type, the expression will always evaluate to true.
+
+     # mypy: enable-error-code truthy-bool
+
+     class Foo:
+       pass
+     foo = Foo()
+     # Error: "foo" has type "Foo" which does not implement __bool__ or __len__ so it could always be true in boolean context
+     if foo:
+        ...
+
+This check might falsely imply an error.  For example, ‘Iterable’ does
+not implement ‘__len__’ and so this code will be flagged:
+
+     # mypy: enable-error-code truthy-bool
+     from typing import Iterable
+
+     def transform(items: Iterable[int]) -> Iterable[int]:
+         # Error: "items" has type "Iterable[int]" which does not implement __bool__ or __len__ so it could always be true in boolean context  [truthy-bool]
+         if not items:
+             return [42]
+         return [x + 1 for x in items]
+
+If called as ‘transform((int(s) for s in []))’, this function would not
+return ‘[42]’ unlike what the author might have intended.  Of course
+it’s possible that ‘transform’ is only passed ‘list’ objects, and so
+there is no error in practice.  In such case, it might be prudent to
+annotate ‘items: Sequence[int]’.
+
+This is similar in concept to ensuring that an expression’s type
+implements an expected interface (e.g.  ‘Sized’), except that attempting
+to invoke an undefined method (e.g.  ‘__len__’) results in an error,
+while attempting to evaluate an object in boolean context without a
+concrete implementation results in a truthy value.
+
+
+File: Mypy.info,  Node: Check that # type ignore include an error code [ignore-without-code],  Prev: Check that expression is not implicitly true in boolean context [truthy-bool],  Up: Error codes for optional checks
+
+35.11 Check that ‘# type: ignore’ include an error code [ignore-without-code]
+=============================================================================
+
+Warn when a ‘# type: ignore’ comment does not specify any error codes.
+This clarifies the intent of the ignore and ensures that only the
+expected errors are silenced.
+
+Example:
+
+     # mypy: enable-error-code ignore-without-code
+
+     class Foo:
+         def __init__(self, name: str) -> None:
+             self.name = name
+
+     f = Foo('foo')
+
+     # This line has a typo that mypy can't help with as both:
+     # - the expected error 'assignment', and
+     # - the unexpected error 'attr-defined'
+     # are silenced.
+     # Error: "type: ignore" comment without error code (consider "type: ignore[attr-defined]" instead)
+     f.nme = 42  # type: ignore
+
+     # This line warns correctly about the typo in the attribute name
+     # Error: "Foo" has no attribute "nme"; maybe "name"?
+     f.nme = 42  # type: ignore[assignment]
+
+
+File: Mypy.info,  Node: Additional features,  Next: Frequently Asked Questions,  Prev: Error codes for optional checks,  Up: Top
+
+36 Additional features
+**********************
+
+This section discusses various features that did not fit in naturally in
+one of the previous sections.
+
+* Menu:
+
+* Dataclasses::
+* The attrs package::
+* Using a remote cache to speed up mypy runs::
+* Extended Callable types::
+
+
+File: Mypy.info,  Node: Dataclasses,  Next: The attrs package,  Up: Additional features
+
+36.1 Dataclasses
+================
+
+In Python 3.7, a new dataclasses(1) module has been added to the
+standard library.  This module allows defining and customizing simple
+boilerplate-free classes.  They can be defined using the
+@dataclasses.dataclass(2) decorator:
+
+     from dataclasses import dataclass, field
+
+     @dataclass
+     class Application:
+         name: str
+         plugins: list[str] = field(default_factory=list)
+
+     test = Application("Testing...")  # OK
+     bad = Application("Testing...", "with plugin")  # Error: list[str] expected
+
+Mypy will detect special methods (such as __lt__(3)) depending on the
+flags used to define dataclasses.  For example:
+
+     from dataclasses import dataclass
+
+     @dataclass(order=True)
+     class OrderedPoint:
+         x: int
+         y: int
+
+     @dataclass(order=False)
+     class UnorderedPoint:
+         x: int
+         y: int
+
+     OrderedPoint(1, 2) < OrderedPoint(3, 4)  # OK
+     UnorderedPoint(1, 2) < UnorderedPoint(3, 4)  # Error: Unsupported operand types
+
+Dataclasses can be generic and can be used in any other way a normal
+class can be used:
+
+     from dataclasses import dataclass
+     from typing import Generic, TypeVar
+
+     T = TypeVar('T')
+
+     @dataclass
+     class BoxedData(Generic[T]):
+         data: T
+         label: str
+
+     def unbox(bd: BoxedData[T]) -> T:
+         ...
+
+     val = unbox(BoxedData(42, "<important>"))  # OK, inferred type is int
+
+For more information see official docs(4) and PEP 557(5).
+
+* Menu:
+
+* Caveats/Known Issues::
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/dataclasses.html#module-dataclasses
+
+   (2) 
+https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass
+
+   (3) https://docs.python.org/3/reference/datamodel.html#object.__lt__
+
+   (4) https://docs.python.org/3/library/dataclasses.html
+
+   (5) https://peps.python.org/pep-0557/
+
+
+File: Mypy.info,  Node: Caveats/Known Issues,  Up: Dataclasses
+
+36.1.1 Caveats/Known Issues
+---------------------------
+
+Some functions in the dataclasses(1) module, such as replace()(2) and
+asdict()(3), have imprecise (too permissive) types.  This will be fixed
+in future releases.
+
+Mypy does not yet recognize aliases of dataclasses.dataclass(4), and
+will probably never recognize dynamically computed decorators.  The
+following examples do `not' work:
+
+     from dataclasses import dataclass
+
+     dataclass_alias = dataclass
+     def dataclass_wrapper(cls):
+       return dataclass(cls)
+
+     @dataclass_alias
+     class AliasDecorated:
+       """
+       Mypy doesn't recognize this as a dataclass because it is decorated by an
+       alias of `dataclass` rather than by `dataclass` itself.
+       """
+       attribute: int
+
+     @dataclass_wrapper
+     class DynamicallyDecorated:
+       """
+       Mypy doesn't recognize this as a dataclass because it is decorated by a
+       function returning `dataclass` rather than by `dataclass` itself.
+       """
+       attribute: int
+
+     AliasDecorated(attribute=1) # error: Unexpected keyword argument
+     DynamicallyDecorated(attribute=1) # error: Unexpected keyword argument
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/library/dataclasses.html#module-dataclasses
+
+   (2) 
+https://docs.python.org/3/library/dataclasses.html#dataclasses.replace
+
+   (3) 
+https://docs.python.org/3/library/dataclasses.html#dataclasses.asdict
+
+   (4) 
+https://docs.python.org/3/library/dataclasses.html#dataclasses.dataclass
+
+
+File: Mypy.info,  Node: The attrs package,  Next: Using a remote cache to speed up mypy runs,  Prev: Dataclasses,  Up: Additional features
+
+36.2 The attrs package
+======================
+
+attrs(1) is a package that lets you define classes without writing
+boilerplate code.  Mypy can detect uses of the package and will generate
+the necessary method definitions for decorated classes using the type
+annotations it finds.  Type annotations can be added as follows:
+
+     import attr
+
+     @attr.s
+     class A:
+         one: int = attr.ib()          # Variable annotation (Python 3.6+)
+         two = attr.ib()  # type: int  # Type comment
+         three = attr.ib(type=int)     # type= argument
+
+If you’re using ‘auto_attribs=True’ you must use variable annotations.
+
+     import attr
+
+     @attr.s(auto_attribs=True)
+     class A:
+         one: int
+         two: int = 7
+         three: int = attr.ib(8)
+
+Typeshed has a couple of “white lie” annotations to make type checking
+easier.  attr.ib()(2) and ‘attr.Factory’ actually return objects, but
+the annotation says these return the types that they expect to be
+assigned to.  That enables this to work:
+
+     import attr
+     from typing import Dict
+
+     @attr.s(auto_attribs=True)
+     class A:
+         one: int = attr.ib(8)
+         two: Dict[str, str] = attr.Factory(dict)
+         bad: str = attr.ib(16)   # Error: can't assign int to str
+
+* Menu:
+
+* Caveats/Known Issues: Caveats/Known Issues<2>.
+
+   ---------- Footnotes ----------
+
+   (1) https://www.attrs.org/en/stable/index.html
+
+   (2) https://www.attrs.org/en/stable/api.html#attr.ib
+
+
+File: Mypy.info,  Node: Caveats/Known Issues<2>,  Up: The attrs package
+
+36.2.1 Caveats/Known Issues
+---------------------------
+
+   * The detection of attr classes and attributes works by function name
+     only.  This means that if you have your own helper functions that,
+     for example, ‘return attr.ib()’ mypy will not see them.
+
+   * All boolean arguments that mypy cares about must be literal ‘True’
+     or ‘False’.  e.g the following will not work:
+
+          import attr
+          YES = True
+          @attr.s(init=YES)
+          class A:
+              ...
+
+   * Currently, ‘converter’ only supports named functions.  If mypy
+     finds something else it will complain about not understanding the
+     argument and the type annotation in __init__(1) will be replaced by
+     ‘Any’.
+
+   * Validator decorators(2) and default decorators(3) are not
+     type-checked against the attribute they are setting/validating.
+
+   * Method definitions added by mypy currently overwrite any existing
+     method definitions.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://docs.python.org/3/reference/datamodel.html#object.__init__
+
+   (2) https://www.attrs.org/en/stable/examples.html#examples-validators
+
+   (3) http://www.attrs.org/en/stable/examples.html#defaults
+
+
+File: Mypy.info,  Node: Using a remote cache to speed up mypy runs,  Next: Extended Callable types,  Prev: The attrs package,  Up: Additional features
+
+36.3 Using a remote cache to speed up mypy runs
+===============================================
+
+Mypy performs type checking `incrementally', reusing results from
+previous runs to speed up successive runs.  If you are type checking a
+large codebase, mypy can still be sometimes slower than desirable.  For
+example, if you create a new branch based on a much more recent commit
+than the target of the previous mypy run, mypy may have to process
+almost every file, as a large fraction of source files may have changed.
+This can also happen after you’ve rebased a local branch.
+
+Mypy supports using a `remote cache' to improve performance in cases
+such as the above.  In a large codebase, remote caching can sometimes
+speed up mypy runs by a factor of 10, or more.
+
+Mypy doesn’t include all components needed to set this up – generally
+you will have to perform some simple integration with your Continuous
+Integration (CI) or build system to configure mypy to use a remote
+cache.  This discussion assumes you have a CI system set up for the mypy
+build you want to speed up, and that you are using a central git
+repository.  Generalizing to different environments should not be
+difficult.
+
+Here are the main components needed:
+
+   * A shared repository for storing mypy cache files for all landed
+     commits.
+
+   * CI build that uploads mypy incremental cache files to the shared
+     repository for each commit for which the CI build runs.
+
+   * A wrapper script around mypy that developers use to run mypy with
+     remote caching enabled.
+
+Below we discuss each of these components in some detail.
+
+* Menu:
+
+* Shared repository for cache files::
+* Continuous Integration build::
+* Mypy wrapper script::
+* Caching with mypy daemon::
+* Refinements::
+
+
+File: Mypy.info,  Node: Shared repository for cache files,  Next: Continuous Integration build,  Up: Using a remote cache to speed up mypy runs
+
+36.3.1 Shared repository for cache files
+----------------------------------------
+
+You need a repository that allows you to upload mypy cache files from
+your CI build and make the cache files available for download based on a
+commit id.  A simple approach would be to produce an archive of the
+‘.mypy_cache’ directory (which contains the mypy cache data) as a
+downloadable `build artifact' from your CI build (depending on the
+capabilities of your CI system).  Alternatively, you could upload the
+data to a web server or to S3, for example.
+
+
+File: Mypy.info,  Node: Continuous Integration build,  Next: Mypy wrapper script,  Prev: Shared repository for cache files,  Up: Using a remote cache to speed up mypy runs
+
+36.3.2 Continuous Integration build
+-----------------------------------
+
+The CI build would run a regular mypy build and create an archive
+containing the ‘.mypy_cache’ directory produced by the build.  Finally,
+it will produce the cache as a build artifact or upload it to a
+repository where it is accessible by the mypy wrapper script.
+
+Your CI script might work like this:
+
+   * Run mypy normally.  This will generate cache data under the
+     ‘.mypy_cache’ directory.
+
+   * Create a tarball from the ‘.mypy_cache’ directory.
+
+   * Determine the current git master branch commit id (say, using ‘git
+     rev-parse HEAD’).
+
+   * Upload the tarball to the shared repository with a name derived
+     from the commit id.
+
+
+File: Mypy.info,  Node: Mypy wrapper script,  Next: Caching with mypy daemon,  Prev: Continuous Integration build,  Up: Using a remote cache to speed up mypy runs
+
+36.3.3 Mypy wrapper script
+--------------------------
+
+The wrapper script is used by developers to run mypy locally during
+development instead of invoking mypy directly.  The wrapper first
+populates the local ‘.mypy_cache’ directory from the shared repository
+and then runs a normal incremental build.
+
+The wrapper script needs some logic to determine the most recent central
+repository commit (by convention, the ‘origin/master’ branch for git)
+the local development branch is based on.  In a typical git setup you
+can do it like this:
+
+     git merge-base HEAD origin/master
+
+The next step is to download the cache data (contents of the
+‘.mypy_cache’ directory) from the shared repository based on the commit
+id of the merge base produced by the git command above.  The script will
+decompress the data so that mypy will start with a fresh ‘.mypy_cache’.
+Finally, the script runs mypy normally.  And that’s all!
+
+
+File: Mypy.info,  Node: Caching with mypy daemon,  Next: Refinements,  Prev: Mypy wrapper script,  Up: Using a remote cache to speed up mypy runs
+
+36.3.4 Caching with mypy daemon
+-------------------------------
+
+You can also use remote caching with the *note mypy daemon: 29.  The
+remote cache will significantly speed up the first ‘dmypy check’ run
+after starting or restarting the daemon.
+
+The mypy daemon requires extra fine-grained dependency data in the cache
+files which aren’t included by default.  To use caching with the mypy
+daemon, use the *note –cache-fine-grained: 198. option in your CI build:
+
+     $ mypy --cache-fine-grained <args...>
+
+This flag adds extra information for the daemon to the cache.  In order
+to use this extra information, you will also need to use the
+‘--use-fine-grained-cache’ option with ‘dmypy start’ or ‘dmypy restart’.
+Example:
+
+     $ dmypy start -- --use-fine-grained-cache <options...>
+
+Now your first ‘dmypy check’ run should be much faster, as it can use
+cache information to avoid processing the whole program.
+
+
+File: Mypy.info,  Node: Refinements,  Prev: Caching with mypy daemon,  Up: Using a remote cache to speed up mypy runs
+
+36.3.5 Refinements
+------------------
+
+There are several optional refinements that may improve things further,
+at least if your codebase is hundreds of thousands of lines or more:
+
+   * If the wrapper script determines that the merge base hasn’t changed
+     from a previous run, there’s no need to download the cache data and
+     it’s better to instead reuse the existing local cache data.
+
+   * If you use the mypy daemon, you may want to restart the daemon each
+     time after the merge base or local branch has changed to avoid
+     processing a potentially large number of changes in an incremental
+     build, as this can be much slower than downloading cache data and
+     restarting the daemon.
+
+   * If the current local branch is based on a very recent master
+     commit, the remote cache data may not yet be available for that
+     commit, as there will necessarily be some latency to build the
+     cache files.  It may be a good idea to look for cache data for,
+     say, the 5 latest master commits and use the most recent data that
+     is available.
+
+   * If the remote cache is not accessible for some reason (say, from a
+     public network), the script can still fall back to a normal
+     incremental build.
+
+   * You can have multiple local cache directories for different local
+     branches using the *note –cache-dir: 196. option.  If the user
+     switches to an existing branch where downloaded cache data is
+     already available, you can continue to use the existing cache data
+     instead of redownloading the data.
+
+   * You can set up your CI build to use a remote cache to speed up the
+     CI build.  This would be particularly useful if each CI build
+     starts from a fresh state without access to cache files from
+     previous builds.  It’s still recommended to run a full,
+     non-incremental mypy build to create the cache data, as repeatedly
+     updating cache data incrementally could result in drift over a long
+     time period (due to a mypy caching issue, perhaps).
+
+
+File: Mypy.info,  Node: Extended Callable types,  Prev: Using a remote cache to speed up mypy runs,  Up: Additional features
+
+36.4 Extended Callable types
+============================
+
+     Note: This feature is deprecated.  You can use *note callback
+     protocols: 65. as a replacement.
+
+As an experimental mypy extension, you can specify Callable(1) types
+that support keyword arguments, optional arguments, and more.  When you
+specify the arguments of a Callable(2), you can choose to supply just
+the type of a nameless positional argument, or an “argument specifier”
+representing a more complicated form of argument.  This allows one to
+more closely emulate the full range of possibilities given by the ‘def’
+statement in Python.
+
+As an example, here’s a complicated function definition and the
+corresponding Callable(3):
+
+     from typing import Callable
+     from mypy_extensions import (Arg, DefaultArg, NamedArg,
+                                  DefaultNamedArg, VarArg, KwArg)
+
+     def func(__a: int,  # This convention is for nameless arguments
+              b: int,
+              c: int = 0,
+              *args: int,
+              d: int,
+              e: int = 0,
+              **kwargs: int) -> int:
+         ...
+
+     F = Callable[[int,  # Or Arg(int)
+                   Arg(int, 'b'),
+                   DefaultArg(int, 'c'),
+                   VarArg(int),
+                   NamedArg(int, 'd'),
+                   DefaultNamedArg(int, 'e'),
+                   KwArg(int)],
+                  int]
+
+     f: F = func
+
+Argument specifiers are special function calls that can specify the
+following aspects of an argument:
+
+   - its type (the only thing that the basic format supports)
+
+   - its name (if it has one)
+
+   - whether it may be omitted
+
+   - whether it may or must be passed using a keyword
+
+   - whether it is a ‘*args’ argument (representing the remaining
+     positional arguments)
+
+   - whether it is a ‘**kwargs’ argument (representing the remaining
+     keyword arguments)
+
+The following functions are available in ‘mypy_extensions’ for this
+purpose:
+
+     def Arg(type=Any, name=None):
+         # A normal, mandatory, positional argument.
+         # If the name is specified it may be passed as a keyword.
+
+     def DefaultArg(type=Any, name=None):
+         # An optional positional argument (i.e. with a default value).
+         # If the name is specified it may be passed as a keyword.
+
+     def NamedArg(type=Any, name=None):
+         # A mandatory keyword-only argument.
+
+     def DefaultNamedArg(type=Any, name=None):
+         # An optional keyword-only argument (i.e. with a default value).
+
+     def VarArg(type=Any):
+         # A *args-style variadic positional argument.
+         # A single VarArg() specifier represents all remaining
+         # positional arguments.
+
+     def KwArg(type=Any):
+         # A **kwargs-style variadic keyword argument.
+         # A single KwArg() specifier represents all remaining
+         # keyword arguments.
+
+In all cases, the ‘type’ argument defaults to ‘Any’, and if the ‘name’
+argument is omitted the argument has no name (the name is required for
+‘NamedArg’ and ‘DefaultNamedArg’).  A basic Callable(4) such as
+
+     MyFunc = Callable[[int, str, int], float]
+
+is equivalent to the following:
+
+     MyFunc = Callable[[Arg(int), Arg(str), Arg(int)], float]
+
+A Callable(5) with unspecified argument types, such as
+
+     MyOtherFunc = Callable[..., int]
+
+is (roughly) equivalent to
+
+     MyOtherFunc = Callable[[VarArg(), KwArg()], int]
+
+     Note: Each of the functions above currently just returns its ‘type’
+     argument at runtime, so the information contained in the argument
+     specifiers is not available at runtime.  This limitation is
+     necessary for backwards compatibility with the existing ‘typing.py’
+     module as present in the Python 3.5+ standard library and
+     distributed via PyPI.
+
+   ---------- Footnotes ----------
+
+   (1) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (2) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (4) https://docs.python.org/3/library/typing.html#typing.Callable
+
+   (5) https://docs.python.org/3/library/typing.html#typing.Callable
+
+
+File: Mypy.info,  Node: Frequently Asked Questions,  Next: Indices and tables,  Prev: Additional features,  Up: Top
+
+37 Frequently Asked Questions
+*****************************
+
+* Menu:
+
+* Why have both dynamic and static typing?::
+* Would my project benefit from static typing?::
+* Can I use mypy to type check my existing Python code?::
+* Will static typing make my programs run faster?::
+* How do I type check my Python 2 code?::
+* Is mypy free?::
+* Can I use duck typing with mypy?::
+* I like Python and I have no need for static typing::
+* How are mypy programs different from normal Python?::
+* How is mypy different from Cython?::
+* Does it run on PyPy?::
+* Mypy is a cool project. Can I help?: Mypy is a cool project Can I help?.
+
+
+File: Mypy.info,  Node: Why have both dynamic and static typing?,  Next: Would my project benefit from static typing?,  Up: Frequently Asked Questions
+
+37.1 Why have both dynamic and static typing?
+=============================================
+
+Dynamic typing can be flexible, powerful, convenient and easy.  But it’s
+not always the best approach; there are good reasons why many developers
+choose to use statically typed languages or static typing for Python.
+
+Here are some potential benefits of mypy-style static typing:
+
+   - Static typing can make programs easier to understand and maintain.
+     Type declarations can serve as machine-checked documentation.  This
+     is important as code is typically read much more often than
+     modified, and this is especially important for large and complex
+     programs.
+
+   - Static typing can help you find bugs earlier and with less testing
+     and debugging.  Especially in large and complex projects this can
+     be a major time-saver.
+
+   - Static typing can help you find difficult-to-find bugs before your
+     code goes into production.  This can improve reliability and reduce
+     the number of security issues.
+
+   - Static typing makes it practical to build very useful development
+     tools that can improve programming productivity or software
+     quality, including IDEs with precise and reliable code completion,
+     static analysis tools, etc.
+
+   - You can get the benefits of both dynamic and static typing in a
+     single language.  Dynamic typing can be perfect for a small project
+     or for writing the UI of your program, for example.  As your
+     program grows, you can adapt tricky application logic to static
+     typing to help maintenance.
+
+See also the front page(1) of the mypy web site.
+
+   ---------- Footnotes ----------
+
+   (1) http://www.mypy-lang.org
+
+
+File: Mypy.info,  Node: Would my project benefit from static typing?,  Next: Can I use mypy to type check my existing Python code?,  Prev: Why have both dynamic and static typing?,  Up: Frequently Asked Questions
+
+37.2 Would my project benefit from static typing?
+=================================================
+
+For many projects dynamic typing is perfectly fine (we think that Python
+is a great language).  But sometimes your projects demand bigger guns,
+and that’s when mypy may come in handy.
+
+If some of these ring true for your projects, mypy (and static typing)
+may be useful:
+
+   - Your project is large or complex.
+
+   - Your codebase must be maintained for a long time.
+
+   - Multiple developers are working on the same code.
+
+   - Running tests takes a lot of time or work (type checking helps you
+     find errors quickly early in development, reducing the number of
+     testing iterations).
+
+   - Some project members (devs or management) don’t like dynamic
+     typing, but others prefer dynamic typing and Python syntax.  Mypy
+     could be a solution that everybody finds easy to accept.
+
+   - You want to future-proof your project even if currently none of the
+     above really apply.  The earlier you start, the easier it will be
+     to adopt static typing.
+
+
+File: Mypy.info,  Node: Can I use mypy to type check my existing Python code?,  Next: Will static typing make my programs run faster?,  Prev: Would my project benefit from static typing?,  Up: Frequently Asked Questions
+
+37.3 Can I use mypy to type check my existing Python code?
+==========================================================
+
+Mypy supports most Python features and idioms, and many large Python
+projects are using mypy successfully.  Code that uses complex
+introspection or metaprogramming may be impractical to type check, but
+it should still be possible to use static typing in other parts of a
+codebase that are less dynamic.
+
+
+File: Mypy.info,  Node: Will static typing make my programs run faster?,  Next: How do I type check my Python 2 code?,  Prev: Can I use mypy to type check my existing Python code?,  Up: Frequently Asked Questions
+
+37.4 Will static typing make my programs run faster?
+====================================================
+
+Mypy only does static type checking and it does not improve performance.
+It has a minimal performance impact.  In the future, there could be
+other tools that can compile statically typed mypy code to C modules or
+to efficient JVM bytecode, for example, but this is outside the scope of
+the mypy project.
+
+
+File: Mypy.info,  Node: How do I type check my Python 2 code?,  Next: Is mypy free?,  Prev: Will static typing make my programs run faster?,  Up: Frequently Asked Questions
+
+37.5 How do I type check my Python 2 code?
+==========================================
+
+You can use a comment-based function annotation syntax(1) and use the
+*note –py2: 8. command-line option to type check your Python 2 code.
+You’ll also need to install ‘typing’ for Python 2 via ‘pip install
+typing’.
+
+   ---------- Footnotes ----------
+
+   (1) 
+https://peps.python.org/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
+
+
+File: Mypy.info,  Node: Is mypy free?,  Next: Can I use duck typing with mypy?,  Prev: How do I type check my Python 2 code?,  Up: Frequently Asked Questions
+
+37.6 Is mypy free?
+==================
+
+Yes.  Mypy is free software, and it can also be used for commercial and
+proprietary projects.  Mypy is available under the MIT license.
+
+
+File: Mypy.info,  Node: Can I use duck typing with mypy?,  Next: I like Python and I have no need for static typing,  Prev: Is mypy free?,  Up: Frequently Asked Questions
+
+37.7 Can I use duck typing with mypy?
+=====================================
+
+Mypy provides support for both nominal subtyping(1) and structural
+subtyping(2).  Structural subtyping can be thought of as “static duck
+typing”.  Some argue that structural subtyping is better suited for
+languages with duck typing such as Python.  Mypy however primarily uses
+nominal subtyping, leaving structural subtyping mostly opt-in (except
+for built-in protocols such as Iterable(3) that always support
+structural subtyping).  Here are some reasons why:
+
+  1. It is easy to generate short and informative error messages when
+     using a nominal type system.  This is especially important when
+     using type inference.
+
+  2. Python provides built-in support for nominal isinstance()(4) tests
+     and they are widely used in programs.  Only limited support for
+     structural isinstance()(5) is available, and it’s less type safe
+     than nominal type tests.
+
+  3. Many programmers are already familiar with static, nominal
+     subtyping and it has been successfully used in languages such as
+     Java, C++ and C#.  Fewer languages use structural subtyping.
+
+However, structural subtyping can also be useful.  For example, a
+“public API” may be more flexible if it is typed with protocols.  Also,
+using protocol types removes the necessity to explicitly declare
+implementations of ABCs.  As a rule of thumb, we recommend using nominal
+classes where possible, and protocols where necessary.  For more details
+about protocol types and structural subtyping see *note Protocols and
+structural subtyping: 37. and PEP 544(6).
+
+   ---------- Footnotes ----------
+
+   (1) https://en.wikipedia.org/wiki/Nominative_type_system
+
+   (2) https://en.wikipedia.org/wiki/Structural_type_system
+
+   (3) https://docs.python.org/3/library/typing.html#typing.Iterable
+
+   (4) https://docs.python.org/3/library/functions.html#isinstance
+
+   (5) https://docs.python.org/3/library/functions.html#isinstance
+
+   (6) https://peps.python.org/pep-0544/
+
+
+File: Mypy.info,  Node: I like Python and I have no need for static typing,  Next: How are mypy programs different from normal Python?,  Prev: Can I use duck typing with mypy?,  Up: Frequently Asked Questions
+
+37.8 I like Python and I have no need for static typing
+=======================================================
+
+The aim of mypy is not to convince everybody to write statically typed
+Python – static typing is entirely optional, now and in the future.  The
+goal is to give more options for Python programmers, to make Python a
+more competitive alternative to other statically typed languages in
+large projects, to improve programmer productivity, and to improve
+software quality.
+
+
+File: Mypy.info,  Node: How are mypy programs different from normal Python?,  Next: How is mypy different from Cython?,  Prev: I like Python and I have no need for static typing,  Up: Frequently Asked Questions
+
+37.9 How are mypy programs different from normal Python?
+========================================================
+
+Since you use a vanilla Python implementation to run mypy programs, mypy
+programs are also Python programs.  The type checker may give warnings
+for some valid Python code, but the code is still always runnable.
+Also, some Python features and syntax are still not supported by mypy,
+but this is gradually improving.
+
+The obvious difference is the availability of static type checking.  The
+section *note Common issues and solutions: 1e. mentions some
+modifications to Python code that may be required to make code type
+check without errors.  Also, your code must make attributes explicit.
+
+Mypy supports modular, efficient type checking, and this seems to rule
+out type checking some language features, such as arbitrary monkey
+patching of methods.
+
+
+File: Mypy.info,  Node: How is mypy different from Cython?,  Next: Does it run on PyPy?,  Prev: How are mypy programs different from normal Python?,  Up: Frequently Asked Questions
+
+37.10 How is mypy different from Cython?
+========================================
+
+Cython(1) is a variant of Python that supports compilation to CPython C
+modules.  It can give major speedups to certain classes of programs
+compared to CPython, and it provides static typing (though this is
+different from mypy).  Mypy differs in the following aspects, among
+others:
+
+   - Cython is much more focused on performance than mypy.  Mypy is only
+     about static type checking, and increasing performance is not a
+     direct goal.
+
+   - The mypy syntax is arguably simpler and more “Pythonic” (no
+     cdef/cpdef, etc.)  for statically typed code.
+
+   - The mypy syntax is compatible with Python.  Mypy programs are
+     normal Python programs that can be run using any Python
+     implementation.  Cython has many incompatible extensions to Python
+     syntax, and Cython programs generally cannot be run without first
+     compiling them to CPython extension modules via C. Cython also has
+     a pure Python mode, but it seems to support only a subset of Cython
+     functionality, and the syntax is quite verbose.
+
+   - Mypy has a different set of type system features.  For example,
+     mypy has genericity (parametric polymorphism), function types and
+     bidirectional type inference, which are not supported by Cython.
+     (Cython has fused types that are different but related to mypy
+     generics.  Mypy also has a similar feature as an extension of
+     generics.)
+
+   - The mypy type checker knows about the static types of many Python
+     stdlib modules and can effectively type check code that uses them.
+
+   - Cython supports accessing C functions directly and many features
+     are defined in terms of translating them to C or C++.  Mypy just
+     uses Python semantics, and mypy does not deal with accessing C
+     library functionality.
+
+   ---------- Footnotes ----------
+
+   (1) http://docs.cython.org/en/latest/index.html
+
+
+File: Mypy.info,  Node: Does it run on PyPy?,  Next: Mypy is a cool project Can I help?,  Prev: How is mypy different from Cython?,  Up: Frequently Asked Questions
+
+37.11 Does it run on PyPy?
+==========================
+
+Somewhat.  With PyPy 3.8, mypy is at least able to type check itself.
+With older versions of PyPy, mypy relies on typed-ast(1), which uses
+several APIs that PyPy does not support (including some internal CPython
+APIs).
+
+   ---------- Footnotes ----------
+
+   (1) https://github.com/python/typed_ast
+
+
+File: Mypy.info,  Node: Mypy is a cool project Can I help?,  Prev: Does it run on PyPy?,  Up: Frequently Asked Questions
+
+37.12 Mypy is a cool project. Can I help?
+=========================================
+
+Any help is much appreciated!  Contact(1) the developers if you would
+like to contribute.  Any help related to development, design, publicity,
+documentation, testing, web site maintenance, financing, etc.  can be
+helpful.  You can learn a lot by contributing, and anybody can help,
+even beginners!  However, some knowledge of compilers and/or type
+systems is essential if you want to work on mypy internals.
+
+   ---------- Footnotes ----------
+
+   (1) http://www.mypy-lang.org/contact.html
+
+
+File: Mypy.info,  Node: Indices and tables,  Next: Index,  Prev: Frequently Asked Questions,  Up: Top
+
+Indices and tables
+******************
+
+   * genindex
+
+   * search
+
+
+File: Mypy.info,  Node: Index,  Prev: Indices and tables,  Up: Top
+
+Index
+*****
+
+[index]
+* Menu:
+
+* allow_redefinition; configuration value: Miscellaneous strictness flags<2>.
+                                                              (line  20)
+* allow_untyped_globals; configuration value: Miscellaneous strictness flags<2>.
+                                                              (line   9)
+* always_false; configuration value:     Platform configuration<2>.
+                                                              (line  38)
+* always_true; configuration value:      Platform configuration<2>.
+                                                              (line  30)
+* any_exprs_report; configuration value: Report generation<2>.
+                                                              (line   9)
+* cache_dir; configuration value:        Incremental mode<2>. (line  18)
+* cache_fine_grained; configuration value: Incremental mode<2>.
+                                                              (line  45)
+* check_untyped_defs; configuration value: Untyped definitions and calls<2>.
+                                                              (line  41)
+* cobertura_xml_report; configuration value: Report generation<2>.
+                                                              (line  17)
+* color_output; configuration value:     Configuring error messages<2>.
+                                                              (line  53)
+* custom_typeshed_dir; configuration value: Advanced options<2>.
+                                                              (line  54)
+* custom_typing_module; configuration value: Advanced options<2>.
+                                                              (line  46)
+* disable_error_code; configuration value: Miscellaneous strictness flags<2>.
+                                                              (line  57)
+* disallow_any_decorated; configuration value: Disallow dynamic typing<2>.
+                                                              (line  31)
+* disallow_any_explicit; configuration value: Disallow dynamic typing<2>.
+                                                              (line  42)
+* disallow_any_expr; configuration value: Disallow dynamic typing<2>.
+                                                              (line  21)
+* disallow_any_generics; configuration value: Disallow dynamic typing<2>.
+                                                              (line  53)
+* disallow_any_unimported; configuration value: Disallow dynamic typing<2>.
+                                                              (line   9)
+* disallow_incomplete_defs; configuration value: Untyped definitions and calls<2>.
+                                                              (line  31)
+* disallow_subclassing_any; configuration value: Disallow dynamic typing<2>.
+                                                              (line  64)
+* disallow_untyped_calls; configuration value: Untyped definitions and calls<2>.
+                                                              (line   9)
+* disallow_untyped_decorators; configuration value: Untyped definitions and calls<2>.
+                                                              (line  51)
+* disallow_untyped_defs; configuration value: Untyped definitions and calls<2>.
+                                                              (line  20)
+* dmypy command line option; –callsites: Static inference of annotations.
+                                                              (line  81)
+* dmypy command line option; –flex-any:  Static inference of annotations.
+                                                              (line  70)
+* dmypy command line option; –fswatcher-dump-file: Additional daemon flags.
+                                                              (line  48)
+* dmypy command line option; –json:      Static inference of annotations.
+                                                              (line  46)
+* dmypy command line option; –log-file:  Additional daemon flags.
+                                                              (line  13)
+* dmypy command line option; –max-guesses: Static inference of annotations.
+                                                              (line  94)
+* dmypy command line option; –no-any:    Static inference of annotations.
+                                                              (line  64)
+* dmypy command line option; –no-errors: Static inference of annotations.
+                                                              (line  58)
+* dmypy command line option; –perf-stats-file: Additional daemon flags.
+                                                              (line  57)
+* dmypy command line option; –remove:    Additional daemon flags.
+                                                              (line  40)
+* dmypy command line option; –status-file: Additional daemon flags.
+                                                              (line   6)
+* dmypy command line option; –timeout:   Additional daemon flags.
+                                                              (line  20)
+* dmypy command line option; –try-text:  Static inference of annotations.
+                                                              (line  76)
+* dmypy command line option; –update:    Additional daemon flags.
+                                                              (line  26)
+* dmypy command line option; –use-fixme: Static inference of annotations.
+                                                              (line  88)
+* error_summary; configuration value:    Configuring error messages<2>.
+                                                              (line  63)
+* exclude; configuration value:          Import discovery<2>. (line  44)
+* explicit_package_bases; configuration value: Import discovery<2>.
+                                                              (line 111)
+* files; configuration value:            Import discovery<2>. (line  30)
+* follow_imports; configuration value:   Import discovery<2>. (line 141)
+* follow_imports_for_stubs; configuration value: Import discovery<2>.
+                                                              (line 165)
+* html_report / xslt_html_report; configuration value: Report generation<2>.
+                                                              (line  29)
+* ignore_errors; configuration value:    Suppressing errors.  (line  20)
+* ignore_missing_imports; configuration value: Import discovery<2>.
+                                                              (line 127)
+* implicit_reexport; configuration value: Miscellaneous strictness flags<2>.
+                                                              (line  64)
+* incremental; configuration value:      Incremental mode<2>. (line   8)
+* junit_xml; configuration value:        Miscellaneous<4>.    (line   8)
+* linecount_report; configuration value: Report generation<2>.
+                                                              (line  40)
+* linecoverage_report; configuration value: Report generation<2>.
+                                                              (line  49)
+* lineprecision_report; configuration value: Report generation<2>.
+                                                              (line  58)
+* local_partial_types; configuration value: Miscellaneous strictness flags<2>.
+                                                              (line  45)
+* mypy command line option; -2:          Platform configuration.
+                                                              (line  26)
+* mypy command line option; –allow-redefinition: Miscellaneous strictness flags.
+                                                              (line  14)
+* mypy command line option; –allow-untyped-globals: Miscellaneous strictness flags.
+                                                              (line   9)
+* mypy command line option; –always-false: Platform configuration.
+                                                              (line  46)
+* mypy command line option; –always-true: Platform configuration.
+                                                              (line  41)
+* mypy command line option; –any-exprs-report: Report generation.
+                                                              (line   9)
+* mypy command line option; -c:          Specifying what to type check.
+                                                              (line  34)
+* mypy command line option; –cache-dir:  Incremental mode.    (line  25)
+* mypy command line option; –cache-fine-grained: Incremental mode.
+                                                              (line  44)
+* mypy command line option; –check-untyped-defs: Untyped definitions and calls.
+                                                              (line  24)
+* mypy command line option; –cobertura-xml-report: Report generation.
+                                                              (line  14)
+* mypy command line option; –command:    Specifying what to type check.
+                                                              (line  34)
+* mypy command line option; –config-file: Config file.        (line   6)
+* mypy command line option; –custom-typeshed-dir: Advanced options.
+                                                              (line  28)
+* mypy command line option; –custom-typing-module: Advanced options.
+                                                              (line  23)
+* mypy command line option; –disable-error-code: Miscellaneous strictness flags.
+                                                              (line 110)
+* mypy command line option; –disallow-any-decorated: Disallow dynamic typing.
+                                                              (line  32)
+* mypy command line option; –disallow-any-explicit: Disallow dynamic typing.
+                                                              (line  37)
+* mypy command line option; –disallow-any-expr: Disallow dynamic typing.
+                                                              (line  20)
+* mypy command line option; –disallow-any-generics: Disallow dynamic typing.
+                                                              (line  42)
+* mypy command line option; –disallow-any-unimported: Disallow dynamic typing.
+                                                              (line  13)
+* mypy command line option; –disallow-incomplete-defs: Untyped definitions and calls.
+                                                              (line  19)
+* mypy command line option; –disallow-subclassing-any: Disallow dynamic typing.
+                                                              (line  49)
+* mypy command line option; –disallow-untyped-calls: Untyped definitions and calls.
+                                                              (line   9)
+* mypy command line option; –disallow-untyped-decorators: Untyped definitions and calls.
+                                                              (line  34)
+* mypy command line option; –disallow-untyped-defs: Untyped definitions and calls.
+                                                              (line  14)
+* mypy command line option; –enable-error-code: Miscellaneous strictness flags.
+                                                              (line 122)
+* mypy command line option; –exclude:    Specifying what to type check.
+                                                              (line  38)
+* mypy command line option; –explicit-package-bases: Import discovery.
+                                                              (line  26)
+* mypy command line option; –find-occurrences: Miscellaneous<3>.
+                                                              (line  47)
+* mypy command line option; –follow-imports: Import discovery.
+                                                              (line  59)
+* mypy command line option; -h:          Optional arguments.  (line   6)
+* mypy command line option; –help:       Optional arguments.  (line   6)
+* mypy command line option; –html-report: Report generation.  (line  23)
+* mypy command line option; –ignore-missing-imports: Import discovery.
+                                                              (line  35)
+* mypy command line option; –install-types: Miscellaneous<3>. (line   6)
+* mypy command line option; –junit-xml:  Miscellaneous<3>.    (line  41)
+* mypy command line option; –linecount-report: Report generation.
+                                                              (line  31)
+* mypy command line option; –linecoverage-report: Report generation.
+                                                              (line  37)
+* mypy command line option; –lineprecision-report: Report generation.
+                                                              (line  43)
+* mypy command line option; –local-partial-types: Miscellaneous strictness flags.
+                                                              (line  35)
+* mypy command line option; -m:          Specifying what to type check.
+                                                              (line  17)
+* mypy command line option; –module:     Specifying what to type check.
+                                                              (line  17)
+* mypy command line option; –namespace-packages: Import discovery.
+                                                              (line   9)
+* mypy command line option; –no-color-output: Configuring error messages.
+                                                              (line  50)
+* mypy command line option; –no-error-summary: Configuring error messages.
+                                                              (line  55)
+* mypy command line option; –no-implicit-optional: None and Optional handling.
+                                                              (line   7)
+* mypy command line option; –no-implicit-reexport: Miscellaneous strictness flags.
+                                                              (line  62)
+* mypy command line option; –no-incremental: Incremental mode.
+                                                              (line  16)
+* mypy command line option; –no-silence-site-packages: Import discovery.
+                                                              (line  87)
+* mypy command line option; –no-site-packages: Import discovery.
+                                                              (line  78)
+* mypy command line option; –no-strict-optional: None and Optional handling.
+                                                              (line  26)
+* mypy command line option; –no-warn-no-return: Configuring warnings.
+                                                              (line  29)
+* mypy command line option; –non-interactive: Miscellaneous<3>.
+                                                              (line  27)
+* mypy command line option; -p:          Specifying what to type check.
+                                                              (line  25)
+* mypy command line option; –package:    Specifying what to type check.
+                                                              (line  25)
+* mypy command line option; –pdb:        Advanced options.    (line   9)
+* mypy command line option; –platform:   Platform configuration.
+                                                              (line  33)
+* mypy command line option; –pretty:     Configuring error messages.
+                                                              (line  45)
+* mypy command line option; –py2:        Platform configuration.
+                                                              (line  26)
+* mypy command line option; –python-executable: Import discovery.
+                                                              (line  68)
+* mypy command line option; –python-version: Platform configuration.
+                                                              (line  13)
+* mypy command line option; –raise-exceptions: Advanced options.
+                                                              (line  19)
+* mypy command line option; –scripts-are-modules: Miscellaneous<3>.
+                                                              (line  52)
+* mypy command line option; –shadow-file: Advanced options.   (line  53)
+* mypy command line option; –show-absolute-path: Configuring error messages.
+                                                              (line  61)
+* mypy command line option; –show-column-numbers: Configuring error messages.
+                                                              (line  28)
+* mypy command line option; –show-error-codes: Configuring error messages.
+                                                              (line  36)
+* mypy command line option; –show-error-context: Configuring error messages.
+                                                              (line   9)
+* mypy command line option; –show-traceback: Advanced options.
+                                                              (line  14)
+* mypy command line option; –skip-cache-mtime-checks: Incremental mode.
+                                                              (line  54)
+* mypy command line option; –skip-version-check: Incremental mode.
+                                                              (line  49)
+* mypy command line option; –soft-error-limit: Configuring error messages.
+                                                              (line  65)
+* mypy command line option; –sqlite-cache: Incremental mode.  (line  40)
+* mypy command line option; –strict:     Miscellaneous strictness flags.
+                                                              (line 101)
+* mypy command line option; –strict-equality: Miscellaneous strictness flags.
+                                                              (line  83)
+* mypy command line option; –tb:         Advanced options.    (line  14)
+* mypy command line option; –txt-report: Report generation.   (line  48)
+* mypy command line option; -v:          Optional arguments.  (line  10)
+* mypy command line option; -V:          Optional arguments.  (line  14)
+* mypy command line option; –verbose:    Optional arguments.  (line  10)
+* mypy command line option; –version:    Optional arguments.  (line  14)
+* mypy command line option; –warn-incomplete-stub: Advanced options.
+                                                              (line  37)
+* mypy command line option; –warn-redundant-casts: Configuring warnings.
+                                                              (line   9)
+* mypy command line option; –warn-return-any: Configuring warnings.
+                                                              (line  43)
+* mypy command line option; –warn-unreachable: Configuring warnings.
+                                                              (line  49)
+* mypy command line option; –warn-unused-configs: Config file.
+                                                              (line  22)
+* mypy command line option; –warn-unused-ignores: Configuring warnings.
+                                                              (line  14)
+* mypy command line option; –xml-report: Report generation.   (line  56)
+* mypy_path; configuration value:        Import discovery<2>. (line   9)
+* namespace_packages; configuration value: Import discovery<2>.
+                                                              (line  98)
+* no_implicit_optional; configuration value: None and Optional handling<2>.
+                                                              (line   9)
+* no_silence_site_packages; configuration value: Import discovery<2>.
+                                                              (line 210)
+* no_site_packages; configuration value: Import discovery<2>. (line 197)
+* pdb; configuration value:              Advanced options<2>. (line  16)
+* platform; configuration value:         Platform configuration<2>.
+                                                              (line  18)
+* plugins; configuration value:          Advanced options<2>. (line   8)
+* pretty; configuration value:           Configuring error messages<2>.
+                                                              (line  42)
+* Python Enhancement Proposals; PEP 3107: Function signatures and dynamic vs static typing.
+                                                              (line  40)
+* Python Enhancement Proposals; PEP 420: Import discovery.    (line  11)
+* Python Enhancement Proposals; PEP 420 <1>: Import discovery<2>.
+                                                              (line 106)
+* Python Enhancement Proposals; PEP 484: Introduction.        (line  13)
+* Python Enhancement Proposals; PEP 484 <1>: Type hints cheat sheet Python 3.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 484 <2>: Type hints cheat sheet Python 2.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 484 <3>: Type checking Python 2 code.
+                                                              (line   8)
+* Python Enhancement Proposals; PEP 484 <4>: Multi-line Python 2 function annotations.
+                                                              (line  14)
+* Python Enhancement Proposals; PEP 484 <5>: Extending mypy using plugins.
+                                                              (line   9)
+* Python Enhancement Proposals; PEP 484 <6>: Extending mypy using plugins.
+                                                              (line  15)
+* Python Enhancement Proposals; PEP 484 <7>: Current list of plugin hooks.
+                                                              (line   7)
+* Python Enhancement Proposals; PEP 484 <8>: Automatic stub generation stubgen.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 484#function-method-overloading: Function overloading.
+                                                              (line  33)
+* Python Enhancement Proposals; PEP 484#suggested-syntax-for-python-2-7-and-straddling-code: How do I type check my Python 2 code?.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 484#the-type-of-class-objects: The type of class objects.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 484#the-type-of-class-objects <1>: The type of class objects.
+                                                              (line  70)
+* Python Enhancement Proposals; PEP 484#type-aliases: Generic type aliases.
+                                                              (line  11)
+* Python Enhancement Proposals; PEP 492: Typing async/await.  (line   8)
+* Python Enhancement Proposals; PEP 508: Using new additions to the typing module.
+                                                              (line  27)
+* Python Enhancement Proposals; PEP 526: Introduction.        (line  13)
+* Python Enhancement Proposals; PEP 526 <1>: Local type inference.
+                                                              (line  39)
+* Python Enhancement Proposals; PEP 526 <2>: Variables.       (line   6)
+* Python Enhancement Proposals; PEP 526 <3>: Defining subprotocols and subclassing protocols.
+                                                              (line  53)
+* Python Enhancement Proposals; PEP 544: Protocols and structural subtyping.
+                                                              (line  19)
+* Python Enhancement Proposals; PEP 544 <1>: Can I use duck typing with mypy?.
+                                                              (line  33)
+* Python Enhancement Proposals; PEP 544#generic-protocols: Generic protocols.
+                                                              (line  37)
+* Python Enhancement Proposals; PEP 557: Dataclasses.         (line  57)
+* Python Enhancement Proposals; PEP 561: Creating a stub.     (line  21)
+* Python Enhancement Proposals; PEP 561 <1>: How imports are found.
+                                                              (line  27)
+* Python Enhancement Proposals; PEP 561 <2>: Import discovery.
+                                                              (line  70)
+* Python Enhancement Proposals; PEP 561 <3>: Import discovery.
+                                                              (line  80)
+* Python Enhancement Proposals; PEP 561 <4>: Import discovery.
+                                                              (line  89)
+* Python Enhancement Proposals; PEP 561 <5>: Platform configuration.
+                                                              (line  22)
+* Python Enhancement Proposals; PEP 561 <6>: Import discovery<2>.
+                                                              (line 205)
+* Python Enhancement Proposals; PEP 561 <7>: Import discovery<2>.
+                                                              (line 219)
+* Python Enhancement Proposals; PEP 561 <8>: Using installed packages.
+                                                              (line  20)
+* Python Enhancement Proposals; PEP 561 <9>: Creating PEP 561 compatible packages.
+                                                              (line  10)
+* Python Enhancement Proposals; PEP 561#stub-only-packages: Using installed packages with mypy PEP 561.
+                                                              (line  31)
+* Python Enhancement Proposals; PEP 563: Annotation issues at runtime.
+                                                              (line  12)
+* Python Enhancement Proposals; PEP 563 <1>: Future annotations import PEP 563.
+                                                              (line  15)
+* Python Enhancement Proposals; PEP 585: Using generic builtins.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 604: X | Y syntax for Unions.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 604 <1>: Future annotations import PEP 563.
+                                                              (line  38)
+* Python Enhancement Proposals; PEP 604 <2>: Using X | Y syntax for Unions.
+                                                              (line   6)
+* Python Enhancement Proposals; PEP 613: Type aliases.        (line  27)
+* Python Enhancement Proposals; PEP 613 <1>: Variables vs type aliases.
+                                                              (line  22)
+* Python Enhancement Proposals; PEP 647: User-Defined Type Guards.
+                                                              (line   6)
+* python_executable; configuration value: Import discovery<2>.
+                                                              (line 185)
+* python_version; configuration value:   Platform configuration<2>.
+                                                              (line   6)
+* raise_exceptions; configuration value: Advanced options<2>. (line  36)
+* scripts_are_modules; configuration value: Miscellaneous<4>. (line  17)
+* show_absolute_path; configuration value: Configuring error messages<2>.
+                                                              (line  73)
+* show_column_numbers; configuration value: Configuring error messages<2>.
+                                                              (line  21)
+* show_error_codes; configuration value: Configuring error messages<2>.
+                                                              (line  31)
+* show_error_context; configuration value: Configuring error messages<2>.
+                                                              (line  11)
+* show_none_errors; configuration value: Suppressing errors.  (line   9)
+* show_traceback; configuration value:   Advanced options<2>. (line  26)
+* skip_cache_mtime_checks; configuration value: Incremental mode<2>.
+                                                              (line  69)
+* skip_version_check; configuration value: Incremental mode<2>.
+                                                              (line  56)
+* sqlite_cache; configuration value:     Incremental mode<2>. (line  35)
+* strict; configuration value:           Miscellaneous strictness flags<2>.
+                                                              (line  97)
+* strict_equality; configuration value:  Miscellaneous strictness flags<2>.
+                                                              (line  86)
+* strict_optional; configuration value:  None and Optional handling<2>.
+                                                              (line  20)
+* stubgen command line option; –doc-dir: Specifying how to generate stubs.
+                                                              (line  33)
+* stubgen command line option; –export-less: Additional flags.
+                                                              (line  26)
+* stubgen command line option; -h:       Additional flags.    (line   6)
+* stubgen command line option; –help:    Additional flags.    (line   6)
+* stubgen command line option; –ignore-errors: Additional flags.
+                                                              (line  14)
+* stubgen command line option; –include-private: Additional flags.
+                                                              (line  20)
+* stubgen command line option; -m:       Specifying what to stub.
+                                                              (line  26)
+* stubgen command line option; –module:  Specifying what to stub.
+                                                              (line  26)
+* stubgen command line option; –no-import: Specifying how to generate stubs.
+                                                              (line  13)
+* stubgen command line option; -o:       Additional flags.    (line  44)
+* stubgen command line option; –output:  Additional flags.    (line  44)
+* stubgen command line option; -p:       Specifying what to stub.
+                                                              (line  34)
+* stubgen command line option; –package: Specifying what to stub.
+                                                              (line  34)
+* stubgen command line option; –parse-only: Specifying how to generate stubs.
+                                                              (line  25)
+* stubgen command line option; –py2:     Additional flags.    (line  10)
+* stubgen command line option; –python-executable: Additional flags.
+                                                              (line  37)
+* stubgen command line option; -q:       Additional flags.    (line  55)
+* stubgen command line option; –quiet:   Additional flags.    (line  55)
+* stubgen command line option; –search-path: Additional flags.
+                                                              (line  32)
+* stubgen command line option; -v:       Additional flags.    (line  51)
+* stubgen command line option; –verbose: Additional flags.    (line  51)
+* stubtest command line option; –allowlist: Usage.            (line  36)
+* stubtest command line option; –check-typeshed: Usage.       (line  59)
+* stubtest command line option; –concise: Usage.              (line  23)
+* stubtest command line option; –custom-typeshed-dir: Usage.  (line  55)
+* stubtest command line option; –generate-allowlist: Usage.   (line  42)
+* stubtest command line option; –help:   Usage.               (line  63)
+* stubtest command line option; –ignore-missing-stub: Usage.  (line  27)
+* stubtest command line option; –ignore-positional-only: Usage.
+                                                              (line  31)
+* stubtest command line option; –ignore-unused-allowlist: Usage.
+                                                              (line  46)
+* stubtest command line option; –mypy-config-file: Usage.     (line  50)
+* txt_report / xslt_txt_report; configuration value: Report generation<2>.
+                                                              (line  66)
+* verbosity; configuration value:        Miscellaneous<4>.    (line  40)
+* warn_incomplete_stub; configuration value: Advanced options<2>.
+                                                              (line  63)
+* warn_no_return; configuration value:   Configuring warnings<2>.
+                                                              (line  31)
+* warn_redundant_casts; configuration value: Configuring warnings<2>.
+                                                              (line   9)
+* warn_return_any; configuration value:  Configuring warnings<2>.
+                                                              (line  41)
+* warn_unreachable; configuration value: Configuring warnings<2>.
+                                                              (line  52)
+* warn_unused_configs; configuration value: Miscellaneous<4>. (line  28)
+* warn_unused_ignores; configuration value: Configuring warnings<2>.
+                                                              (line  21)
+* xml_report; configuration value:       Report generation<2>.
+                                                              (line  77)
+
+
+
+Tag Table:
+Node: Top311
+Ref: index doc498
+Ref: 0498
+Node: Introduction1853
+Ref: introduction doc1939
+Ref: 11939
+Ref: introduction introduction1939
+Ref: 21939
+Ref: introduction welcome-to-mypy-documentation1939
+Ref: 31939
+Ref: Introduction-Footnote-13603
+Ref: Introduction-Footnote-23645
+Node: Getting started3687
+Ref: getting_started doc3806
+Ref: 43806
+Ref: getting_started getting-started3806
+Ref: 53806
+Ref: getting_started id13806
+Ref: 63806
+Ref: Getting started-Footnote-14419
+Node: Installing and running mypy4487
+Ref: getting_started installing-and-running-mypy4621
+Ref: 74621
+Ref: Installing and running mypy-Footnote-15859
+Node: Function signatures and dynamic vs static typing5901
+Ref: getting_started function-signatures-and-dynamic-vs-static-typing6068
+Ref: a6068
+Ref: Function signatures and dynamic vs static typing-Footnote-18845
+Node: More function signatures8887
+Ref: getting_started more-function-signatures9065
+Ref: d9065
+Node: Additional types and the typing module10358
+Ref: getting_started additional-types-and-the-typing-module10508
+Ref: e10508
+Ref: Additional types and the typing module-Footnote-114531
+Ref: Additional types and the typing module-Footnote-214592
+Ref: Additional types and the typing module-Footnote-314653
+Ref: Additional types and the typing module-Footnote-414719
+Ref: Additional types and the typing module-Footnote-514787
+Ref: Additional types and the typing module-Footnote-614855
+Ref: Additional types and the typing module-Footnote-714944
+Ref: Additional types and the typing module-Footnote-815014
+Ref: Additional types and the typing module-Footnote-915075
+Ref: Additional types and the typing module-Footnote-1015142
+Ref: Additional types and the typing module-Footnote-1115210
+Ref: Additional types and the typing module-Footnote-1215279
+Ref: Additional types and the typing module-Footnote-1315348
+Ref: Additional types and the typing module-Footnote-1415436
+Node: Local type inference15507
+Ref: getting_started local-type-inference15659
+Ref: 1115659
+Ref: Local type inference-Footnote-117712
+Ref: Local type inference-Footnote-217780
+Node: Library stubs and typeshed17822
+Ref: getting_started library-stubs-and-typeshed17952
+Ref: 1217952
+Ref: getting_started stubs-intro17952
+Ref: 1317952
+Ref: Library stubs and typeshed-Footnote-120126
+Ref: Library stubs and typeshed-Footnote-220169
+Node: Configuring mypy20230
+Ref: getting_started configuring-mypy20350
+Ref: 1820350
+Node: Next steps21417
+Ref: getting_started next-steps21502
+Ref: 1b21502
+Ref: Next steps-Footnote-122629
+Ref: Next steps-Footnote-222703
+Ref: Next steps-Footnote-322755
+Ref: Next steps-Footnote-422807
+Ref: Next steps-Footnote-522853
+Node: Using mypy with an existing codebase22893
+Ref: existing_code doc23031
+Ref: 1f23031
+Ref: existing_code existing-code23031
+Ref: 1a23031
+Ref: existing_code using-mypy-with-an-existing-codebase23031
+Ref: 2023031
+Ref: Using mypy with an existing codebase-Footnote-124145
+Ref: Using mypy with an existing codebase-Footnote-224208
+Node: Start small24254
+Ref: existing_code start-small24363
+Ref: 2124363
+Node: Mypy runner script26604
+Ref: existing_code mypy-runner-script26744
+Ref: 2326744
+Node: Continuous Integration27204
+Ref: existing_code continuous-integration27365
+Ref: 2427365
+Node: Annotate widely imported modules27808
+Ref: existing_code annotate-widely-imported-modules27978
+Ref: 2527978
+Node: Write annotations as you go28470
+Ref: existing_code write-annotations-as-you-go28652
+Ref: 2628652
+Node: Automate annotation of legacy code29105
+Ref: existing_code automate-annotation-of-legacy-code29273
+Ref: 2729273
+Ref: Automate annotation of legacy code-Footnote-129923
+Ref: Automate annotation of legacy code-Footnote-229986
+Node: Speed up mypy runs30032
+Ref: existing_code speed-up-mypy-runs30199
+Ref: 2830199
+Node: Introduce stricter options30518
+Ref: existing_code introduce-stricter-options30642
+Ref: 2b30642
+Ref: index overview-cheat-sheets31208
+Ref: f31208
+Node: Type hints cheat sheet Python 331210
+Ref: cheat_sheet_py3 doc31364
+Ref: 2f31364
+Ref: cheat_sheet_py3 cheat-sheet-py331364
+Ref: 1c31364
+Ref: cheat_sheet_py3 pyannotate31364
+Ref: 3031364
+Ref: cheat_sheet_py3 type-hints-cheat-sheet-python-331364
+Ref: 3131364
+Ref: Type hints cheat sheet Python 3-Footnote-132090
+Node: Variables32132
+Ref: cheat_sheet_py3 variables32230
+Ref: 3232230
+Ref: Variables-Footnote-132894
+Node: Built-in types32936
+Ref: cheat_sheet_py3 built-in-types33052
+Ref: 3333052
+Node: Functions34590
+Ref: cheat_sheet_py3 functions34749
+Ref: 3434749
+Node: When you’re puzzled or when things are complicated36250
+Ref: cheat_sheet_py3 when-you-re-puzzled-or-when-things-are-complicated36420
+Ref: 3536420
+Node: Standard “duck types”38989
+Ref: cheat_sheet_py3 standard-duck-types39157
+Ref: 3639157
+Node: Classes40550
+Ref: cheat_sheet_py3 classes40688
+Ref: 3840688
+Node: Coroutines and asyncio41693
+Ref: cheat_sheet_py3 coroutines-and-asyncio41819
+Ref: 3941819
+Node: Miscellaneous42276
+Ref: cheat_sheet_py3 miscellaneous42405
+Ref: 3b42405
+Node: Decorators43379
+Ref: cheat_sheet_py3 decorators43477
+Ref: 3c43477
+Node: Type hints cheat sheet Python 243834
+Ref: cheat_sheet doc43969
+Ref: 3e43969
+Ref: cheat_sheet cheat-sheet-py243969
+Ref: 1d43969
+Ref: cheat_sheet type-hints-cheat-sheet-python-243969
+Ref: 3f43969
+Ref: Type hints cheat sheet Python 2-Footnote-144922
+Node: Built-in types<2>44964
+Ref: cheat_sheet built-in-types45068
+Ref: 4045068
+Node: Functions<2>46291
+Ref: cheat_sheet functions46459
+Ref: 4146459
+Node: When you’re puzzled or when things are complicated<2>48398
+Ref: cheat_sheet when-you-re-puzzled-or-when-things-are-complicated48577
+Ref: 4248577
+Node: Standard “duck types”<2>51095
+Ref: cheat_sheet standard-duck-types51272
+Ref: 4351272
+Node: Classes<2>52534
+Ref: cheat_sheet classes52672
+Ref: 4452672
+Node: Miscellaneous<2>53225
+Ref: cheat_sheet miscellaneous53348
+Ref: 4553348
+Node: Decorators<2>53988
+Ref: cheat_sheet decorators54092
+Ref: 4654092
+Ref: index overview-type-system-reference54472
+Ref: 1054472
+Node: Built-in types<3>54473
+Ref: builtin_types doc54612
+Ref: 4754612
+Ref: builtin_types built-in-types54612
+Ref: 4854612
+Node: Simple types54813
+Ref: builtin_types simple-types54894
+Ref: 4954894
+Node: Any type55873
+Ref: builtin_types any-type55976
+Ref: 4a55976
+Ref: Any type-Footnote-156521
+Node: Generic types56589
+Ref: builtin_types generic-types56671
+Ref: 4c56671
+Ref: Generic types-Footnote-160274
+Ref: Generic types-Footnote-260361
+Ref: Generic types-Footnote-360429
+Ref: Generic types-Footnote-460497
+Node: Type inference and type annotations60584
+Ref: type_inference_and_annotations doc60706
+Ref: 4e60706
+Ref: type_inference_and_annotations type-inference-and-type-annotations60706
+Ref: 4f60706
+Node: Type inference61045
+Ref: type_inference_and_annotations type-inference61166
+Ref: 5061166
+Node: Explicit types for variables61725
+Ref: type_inference_and_annotations explicit-types-for-variables61885
+Ref: 5161885
+Ref: type_inference_and_annotations explicit-var-types61885
+Ref: 5261885
+Ref: Explicit types for variables-Footnote-163383
+Node: Explicit types for collections63449
+Ref: type_inference_and_annotations explicit-types-for-collections63627
+Ref: 5363627
+Ref: Explicit types for collections-Footnote-164658
+Ref: Explicit types for collections-Footnote-264719
+Ref: Explicit types for collections-Footnote-364780
+Ref: Explicit types for collections-Footnote-464842
+Ref: Explicit types for collections-Footnote-564902
+Ref: Explicit types for collections-Footnote-664968
+Node: Compatibility of container types65034
+Ref: type_inference_and_annotations compatibility-of-container-types65209
+Ref: 5465209
+Ref: Compatibility of container types-Footnote-166411
+Ref: Compatibility of container types-Footnote-266472
+Node: Context in type inference66532
+Ref: type_inference_and_annotations context-in-type-inference66720
+Ref: 5666720
+Node: Declaring multiple variable types at a time68101
+Ref: type_inference_and_annotations declaring-multiple-variable-types-at-a-time68276
+Ref: 5768276
+Node: Starred expressions68925
+Ref: type_inference_and_annotations starred-expressions69096
+Ref: 5869096
+Node: Silencing type errors69776
+Ref: type_inference_and_annotations silencing-type-errors69895
+Ref: 5969895
+Node: Kinds of types71889
+Ref: kinds_of_types doc72006
+Ref: 5c72006
+Ref: kinds_of_types kinds-of-types72006
+Ref: 5d72006
+Node: Class types72563
+Ref: kinds_of_types class-types72644
+Ref: 5e72644
+Ref: Class types-Footnote-173460
+Node: The Any type73524
+Ref: kinds_of_types the-any-type73625
+Ref: 5f73625
+Node: Tuple types75985
+Ref: kinds_of_types id176101
+Ref: 6076101
+Ref: kinds_of_types tuple-types76101
+Ref: 6176101
+Ref: Tuple types-Footnote-177421
+Node: Callable types and lambdas77491
+Ref: kinds_of_types callable-types77606
+Ref: 6377606
+Ref: kinds_of_types callable-types-and-lambdas77606
+Ref: 6477606
+Node: Union types79598
+Ref: kinds_of_types id279734
+Ref: 6679734
+Ref: kinds_of_types union-types79734
+Ref: 6779734
+Ref: Union types-Footnote-181050
+Ref: Union types-Footnote-281118
+Ref: Union types-Footnote-381186
+Node: Optional types and the None type81254
+Ref: kinds_of_types optional-types-and-the-none-type81398
+Ref: 6981398
+Ref: kinds_of_types strict-optional81398
+Ref: 6a81398
+Ref: Optional types and the None type-Footnote-186608
+Ref: Optional types and the None type-Footnote-286678
+Node: X | Y syntax for Unions86748
+Ref: kinds_of_types alternative-union-syntax86838
+Ref: 6c86838
+Ref: kinds_of_types x-y-syntax-for-unions86838
+Ref: 6d86838
+Ref: X | Y syntax for Unions-Footnote-187422
+Node: Disabling strict optional checking87464
+Ref: kinds_of_types disabling-strict-optional-checking87609
+Ref: 6f87609
+Ref: kinds_of_types no-strict-optional87609
+Ref: 7087609
+Ref: Disabling strict optional checking-Footnote-189955
+Ref: Disabling strict optional checking-Footnote-290025
+Node: Type aliases90095
+Ref: kinds_of_types id390220
+Ref: 7390220
+Ref: kinds_of_types type-aliases90220
+Ref: 7490220
+Ref: Type aliases-Footnote-191757
+Node: Named tuples91799
+Ref: kinds_of_types id491915
+Ref: 7691915
+Ref: kinds_of_types named-tuples91915
+Ref: 6291915
+Ref: Named tuples-Footnote-193825
+Ref: Named tuples-Footnote-293908
+Node: The type of class objects93980
+Ref: kinds_of_types the-type-of-class-objects94099
+Ref: 7794099
+Ref: kinds_of_types type-of-class94099
+Ref: 7894099
+Ref: The type of class objects-Footnote-196514
+Ref: The type of class objects-Footnote-296582
+Ref: The type of class objects-Footnote-396648
+Ref: The type of class objects-Footnote-496714
+Ref: The type of class objects-Footnote-596780
+Ref: The type of class objects-Footnote-696846
+Ref: The type of class objects-Footnote-796912
+Node: Text and AnyStr96980
+Ref: kinds_of_types id597097
+Ref: 7a97097
+Ref: kinds_of_types text-and-anystr97097
+Ref: 7b97097
+Ref: Text and AnyStr-Footnote-198411
+Ref: Text and AnyStr-Footnote-298477
+Node: Generators98545
+Ref: kinds_of_types generators98628
+Ref: 7d98628
+Ref: kinds_of_types id698628
+Ref: 7e98628
+Ref: Generators-Footnote-1100829
+Ref: Generators-Footnote-2100899
+Ref: Generators-Footnote-3100969
+Ref: Generators-Footnote-4101039
+Ref: Generators-Footnote-5101109
+Ref: Generators-Footnote-6101171
+Ref: Generators-Footnote-7101248
+Ref: Generators-Footnote-8101319
+Ref: Generators-Footnote-9101390
+Ref: Generators-Footnote-10101468
+Ref: Generators-Footnote-11101546
+Ref: Generators-Footnote-12101625
+Ref: Generators-Footnote-13101697
+Ref: Generators-Footnote-14101768
+Node: Class basics101839
+Ref: class_basics doc101949
+Ref: 7f101949
+Ref: class_basics class-basics101949
+Ref: 80101949
+Node: Instance and class attributes102319
+Ref: class_basics instance-and-class-attributes102431
+Ref: 81102431
+Ref: Instance and class attributes-Footnote-1104561
+Ref: Instance and class attributes-Footnote-2104638
+Node: Annotating __init__ methods104708
+Ref: class_basics annotating-init-methods104856
+Ref: 82104856
+Ref: Annotating __init__ methods-Footnote-1105723
+Ref: Annotating __init__ methods-Footnote-2105799
+Ref: Annotating __init__ methods-Footnote-3105875
+Ref: Annotating __init__ methods-Footnote-4105951
+Node: Class attribute annotations106027
+Ref: class_basics class-attribute-annotations106181
+Ref: 83106181
+Ref: Class attribute annotations-Footnote-1107886
+Ref: Class attribute annotations-Footnote-2107956
+Ref: Class attribute annotations-Footnote-3108026
+Ref: Class attribute annotations-Footnote-4108096
+Ref: Class attribute annotations-Footnote-5108166
+Ref: Class attribute annotations-Footnote-6108234
+Ref: Class attribute annotations-Footnote-7108302
+Ref: Class attribute annotations-Footnote-8108372
+Node: Overriding statically typed methods108442
+Ref: class_basics overriding-statically-typed-methods108615
+Ref: 85108615
+Node: Abstract base classes and multiple inheritance110508
+Ref: class_basics abstract-base-classes-and-multiple-inheritance110659
+Ref: 86110659
+Ref: Abstract base classes and multiple inheritance-Footnote-1113716
+Ref: Abstract base classes and multiple inheritance-Footnote-2113767
+Ref: Abstract base classes and multiple inheritance-Footnote-3113830
+Ref: Abstract base classes and multiple inheritance-Footnote-4113900
+Ref: Abstract base classes and multiple inheritance-Footnote-5113972
+Node: Slots114035
+Ref: class_basics slots114142
+Ref: 87114142
+Ref: Slots-Footnote-1115200
+Node: Annotation issues at runtime115265
+Ref: runtime_troubles doc115395
+Ref: 88115395
+Ref: runtime_troubles annotation-issues-at-runtime115395
+Ref: 89115395
+Ref: runtime_troubles runtime-troubles115395
+Ref: 6e115395
+Ref: Annotation issues at runtime-Footnote-1116532
+Node: String literal types116574
+Ref: runtime_troubles id1116699
+Ref: 8a116699
+Ref: runtime_troubles string-literal-types116699
+Ref: 8b116699
+Node: Future annotations import PEP 563117512
+Ref: runtime_troubles future-annotations117666
+Ref: 8d117666
+Ref: runtime_troubles future-annotations-import-pep-563117666
+Ref: 8e117666
+Ref: Future annotations import PEP 563-Footnote-1119243
+Ref: Future annotations import PEP 563-Footnote-2119285
+Ref: Future annotations import PEP 563-Footnote-3119354
+Ref: Future annotations import PEP 563-Footnote-4119426
+Node: typing TYPE_CHECKING119468
+Ref: runtime_troubles id2119631
+Ref: 90119631
+Ref: runtime_troubles typing-type-checking119631
+Ref: 91119631
+Ref: typing TYPE_CHECKING-Footnote-1120084
+Ref: typing TYPE_CHECKING-Footnote-2120152
+Node: Class name forward references120228
+Ref: runtime_troubles class-name-forward-references120371
+Ref: 92120371
+Node: Import cycles121305
+Ref: runtime_troubles id3121486
+Ref: 93121486
+Ref: runtime_troubles import-cycles121486
+Ref: 8c121486
+Node: Using classes that are generic in stubs but not at runtime122685
+Ref: runtime_troubles not-generic-runtime122884
+Ref: 94122884
+Ref: runtime_troubles using-classes-that-are-generic-in-stubs-but-not-at-runtime122884
+Ref: 95122884
+Ref: Using classes that are generic in stubs but not at runtime-Footnote-1124867
+Ref: Using classes that are generic in stubs but not at runtime-Footnote-2124929
+Ref: Using classes that are generic in stubs but not at runtime-Footnote-3124994
+Node: Using types defined in stubs but not at runtime125059
+Ref: runtime_troubles using-types-defined-in-stubs-but-not-at-runtime125267
+Ref: 96125267
+Node: Using generic builtins125808
+Ref: runtime_troubles generic-builtins125987
+Ref: 4d125987
+Ref: runtime_troubles using-generic-builtins125987
+Ref: 97125987
+Ref: Using generic builtins-Footnote-1126848
+Ref: Using generic builtins-Footnote-2126890
+Ref: Using generic builtins-Footnote-3126958
+Node: Using X | Y syntax for Unions127045
+Ref: runtime_troubles using-x-y-syntax-for-unions127217
+Ref: 98127217
+Ref: Using X | Y syntax for Unions-Footnote-1127992
+Node: Using new additions to the typing module128034
+Ref: runtime_troubles using-new-additions-to-the-typing-module128175
+Ref: 99128175
+Ref: Using new additions to the typing module-Footnote-1129156
+Ref: Using new additions to the typing module-Footnote-2129224
+Node: Protocols and structural subtyping129266
+Ref: protocols doc129406
+Ref: 9a129406
+Ref: protocols protocol-types129406
+Ref: 37129406
+Ref: protocols protocols-and-structural-subtyping129406
+Ref: 9b129406
+Ref: Protocols and structural subtyping-Footnote-1130803
+Ref: Protocols and structural subtyping-Footnote-2130871
+Node: Predefined protocols130913
+Ref: protocols id1131040
+Ref: 9c131040
+Ref: protocols predefined-protocols131040
+Ref: 9d131040
+Ref: Predefined protocols-Footnote-1132488
+Ref: Predefined protocols-Footnote-2132556
+Ref: Predefined protocols-Footnote-3132626
+Ref: Predefined protocols-Footnote-4132702
+Ref: Predefined protocols-Footnote-5132772
+Node: Iteration protocols132840
+Ref: protocols iteration-protocols132943
+Ref: 9e132943
+Node: Iterable[T]133154
+Ref: protocols iterable-t133239
+Ref: 9f133239
+Ref: Iterable[T]-Footnote-1133465
+Ref: Iterable[T]-Footnote-2133541
+Node: Iterator[T]133611
+Ref: protocols iterator-t133696
+Ref: a0133696
+Ref: Iterator[T]-Footnote-1133867
+Node: Collection protocols133937
+Ref: protocols collection-protocols134066
+Ref: a1134066
+Ref: Collection protocols-Footnote-1134365
+Ref: Collection protocols-Footnote-2134426
+Node: Sized134487
+Ref: protocols sized134568
+Ref: a2134568
+Ref: Sized-Footnote-1134738
+Ref: Sized-Footnote-2134799
+Node: Container[T]134866
+Ref: protocols container-t134969
+Ref: a3134969
+Ref: Container[T]-Footnote-1135186
+Node: Collection[T]135257
+Ref: protocols collection-t135346
+Ref: a4135346
+Ref: Collection[T]-Footnote-1135571
+Node: One-off protocols135643
+Ref: protocols one-off-protocols135768
+Ref: a5135768
+Node: Reversible[T]136052
+Ref: protocols reversible-t136140
+Ref: a6136140
+Ref: Reversible[T]-Footnote-1136349
+Ref: Reversible[T]-Footnote-2136415
+Node: SupportsAbs[T]136487
+Ref: protocols supportsabs-t136597
+Ref: a7136597
+Ref: SupportsAbs[T]-Footnote-1136842
+Ref: SupportsAbs[T]-Footnote-2136903
+Ref: SupportsAbs[T]-Footnote-3136964
+Node: SupportsBytes137037
+Ref: protocols supportsbytes137149
+Ref: a8137149
+Ref: SupportsBytes-Footnote-1137349
+Ref: SupportsBytes-Footnote-2137411
+Node: SupportsComplex137487
+Ref: protocols supports-int-etc137598
+Ref: a9137598
+Ref: protocols supportscomplex137598
+Ref: aa137598
+Ref: SupportsComplex-Footnote-1137861
+Ref: SupportsComplex-Footnote-2137926
+Node: SupportsFloat138004
+Ref: protocols supportsfloat138113
+Ref: ab138113
+Ref: SupportsFloat-Footnote-1138364
+Ref: SupportsFloat-Footnote-2138427
+Node: SupportsInt138503
+Ref: protocols supportsint138613
+Ref: ac138613
+Ref: SupportsInt-Footnote-1138852
+Ref: SupportsInt-Footnote-2138913
+Node: SupportsRound[T]138986
+Ref: protocols supportsround-t139074
+Ref: ad139074
+Ref: SupportsRound[T]-Footnote-1139276
+Ref: SupportsRound[T]-Footnote-2139339
+Node: Async protocols139415
+Ref: protocols async-protocols139545
+Ref: ae139545
+Node: Awaitable[T]139764
+Ref: protocols awaitable-t139851
+Ref: af139851
+Ref: Awaitable[T]-Footnote-1140009
+Node: AsyncIterable[T]140080
+Ref: protocols asynciterable-t140192
+Ref: b0140192
+Ref: AsyncIterable[T]-Footnote-1140355
+Node: AsyncIterator[T]140431
+Ref: protocols asynciterator-t140522
+Ref: b1140522
+Ref: AsyncIterator[T]-Footnote-1140726
+Node: Context manager protocols140802
+Ref: protocols context-manager-protocols140906
+Ref: b2140906
+Node: ContextManager[T]141233
+Ref: protocols contextmanager-t141341
+Ref: b3141341
+Ref: ContextManager[T]-Footnote-1141701
+Node: AsyncContextManager[T]141778
+Ref: protocols asynccontextmanager-t141886
+Ref: b4141886
+Ref: AsyncContextManager[T]-Footnote-1142288
+Node: Simple user-defined protocols142370
+Ref: protocols simple-user-defined-protocols142553
+Ref: b5142553
+Ref: Simple user-defined protocols-Footnote-1143728
+Node: Defining subprotocols and subclassing protocols143790
+Ref: protocols defining-subprotocols-and-subclassing-protocols143972
+Ref: b6143972
+Ref: Defining subprotocols and subclassing protocols-Footnote-1145967
+Node: Recursive protocols146009
+Ref: protocols recursive-protocols146193
+Ref: b7146193
+Node: Using isinstance with protocols146950
+Ref: protocols using-isinstance-with-protocols147105
+Ref: b8147105
+Ref: Using isinstance with protocols-Footnote-1148114
+Ref: Using isinstance with protocols-Footnote-2148182
+Ref: Using isinstance with protocols-Footnote-3148250
+Ref: Using isinstance with protocols-Footnote-4148318
+Ref: Using isinstance with protocols-Footnote-5148388
+Node: Callback protocols148456
+Ref: protocols callback-protocols148583
+Ref: 65148583
+Ref: protocols id2148583
+Ref: b9148583
+Ref: Callback protocols-Footnote-1150110
+Ref: Callback protocols-Footnote-2150180
+Ref: Callback protocols-Footnote-3150256
+Ref: Callback protocols-Footnote-4150326
+Node: Dynamically typed code150402
+Ref: dynamic_typing doc150541
+Ref: ba150541
+Ref: dynamic_typing dynamic-typing150541
+Ref: 4b150541
+Ref: dynamic_typing dynamically-typed-code150541
+Ref: bb150541
+Node: Operations on Any values151258
+Ref: dynamic_typing operations-on-any-values151361
+Ref: bc151361
+Node: Any vs object152180
+Ref: dynamic_typing any-vs-object152283
+Ref: bd152283
+Ref: Any vs object-Footnote-1153285
+Ref: Any vs object-Footnote-2153349
+Ref: Any vs object-Footnote-3153413
+Ref: Any vs object-Footnote-4153477
+Node: Type checking Python 2 code153541
+Ref: python2 doc153660
+Ref: be153660
+Ref: python2 python2153660
+Ref: 9153660
+Ref: python2 type-checking-python-2-code153660
+Ref: bf153660
+Ref: Type checking Python 2 code-Footnote-1155829
+Ref: Type checking Python 2 code-Footnote-2155871
+Node: Multi-line Python 2 function annotations155939
+Ref: python2 multi-line-annotation156066
+Ref: c0156066
+Ref: python2 multi-line-python-2-function-annotations156066
+Ref: c1156066
+Ref: Multi-line Python 2 function annotations-Footnote-1158197
+Node: Additional notes158239
+Ref: python2 additional-notes158366
+Ref: c2158366
+Ref: Additional notes-Footnote-1159147
+Node: Type narrowing159190
+Ref: type_narrowing doc159310
+Ref: c3159310
+Ref: type_narrowing id1159310
+Ref: c4159310
+Ref: type_narrowing type-narrowing159310
+Ref: 8f159310
+Node: Type narrowing expressions159715
+Ref: type_narrowing type-narrowing-expressions159804
+Ref: c5159804
+Ref: Type narrowing expressions-Footnote-1162596
+Ref: Type narrowing expressions-Footnote-2162664
+Ref: Type narrowing expressions-Footnote-3162732
+Node: issubclass162798
+Ref: type_narrowing issubclass162886
+Ref: c8162886
+Ref: issubclass-Footnote-1163488
+Node: callable163556
+Ref: type_narrowing callable163644
+Ref: c9163644
+Node: Casts164413
+Ref: type_narrowing casts164535
+Ref: ca164535
+Ref: type_narrowing id2164535
+Ref: cb164535
+Ref: Casts-Footnote-1166069
+Node: User-Defined Type Guards166135
+Ref: type_narrowing type-guards166222
+Ref: cc166222
+Ref: type_narrowing user-defined-type-guards166222
+Ref: cd166222
+Ref: User-Defined Type Guards-Footnote-1168468
+Ref: User-Defined Type Guards-Footnote-2168510
+Node: Generic TypeGuards168588
+Ref: type_narrowing generic-typeguards168700
+Ref: ce168700
+Node: Typeguards with parameters169250
+Ref: type_narrowing typeguards-with-parameters169392
+Ref: cf169392
+Node: TypeGuards as methods169875
+Ref: type_narrowing typeguards-as-methods170035
+Ref: d0170035
+Ref: TypeGuards as methods-Footnote-1171140
+Node: Assignment expressions as TypeGuards171237
+Ref: type_narrowing assignment-expressions-as-typeguards171362
+Ref: d1171362
+Ref: Assignment expressions as TypeGuards-Footnote-1172492
+Node: Duck type compatibility172568
+Ref: duck_type_compatibility doc172671
+Ref: d2172671
+Ref: duck_type_compatibility duck-type-compatibility172671
+Ref: d3172671
+Node: Stub files174705
+Ref: stubs doc174802
+Ref: d4174802
+Ref: stubs id1174802
+Ref: d5174802
+Ref: stubs stub-files174802
+Ref: 16174802
+Ref: Stub files-Footnote-1175297
+Node: Creating a stub175340
+Ref: stubs creating-a-stub175425
+Ref: d6175425
+Ref: Creating a stub-Footnote-1177690
+Node: Stub file syntax177732
+Ref: stubs stub-file-syntax177859
+Ref: d9177859
+Node: Using stub file syntax at runtime179033
+Ref: stubs using-stub-file-syntax-at-runtime179136
+Ref: da179136
+Ref: Using stub file syntax at runtime-Footnote-1180819
+Ref: Using stub file syntax at runtime-Footnote-2180898
+Node: Generics180977
+Ref: generics doc181061
+Ref: db181061
+Ref: generics generics181061
+Ref: dc181061
+Node: Defining generic classes181749
+Ref: generics defining-generic-classes181848
+Ref: dd181848
+Ref: generics generic-classes181848
+Ref: 84181848
+Node: Generic class internals183548
+Ref: generics generic-class-internals183695
+Ref: de183695
+Ref: Generic class internals-Footnote-1185580
+Ref: Generic class internals-Footnote-2185641
+Ref: Generic class internals-Footnote-3185702
+Ref: Generic class internals-Footnote-4185768
+Ref: Generic class internals-Footnote-5185834
+Node: Defining sub-classes of generic classes185902
+Ref: generics defining-sub-classes-of-generic-classes186042
+Ref: df186042
+Ref: generics generic-subclasses186042
+Ref: e0186042
+Ref: Defining sub-classes of generic classes-Footnote-1188598
+Ref: Defining sub-classes of generic classes-Footnote-2188666
+Ref: Defining sub-classes of generic classes-Footnote-3188735
+Ref: Defining sub-classes of generic classes-Footnote-4188805
+Ref: Defining sub-classes of generic classes-Footnote-5188875
+Node: Generic functions188944
+Ref: generics generic-functions189093
+Ref: e1189093
+Ref: generics id1189093
+Ref: e2189093
+Node: Generic methods and generic self190284
+Ref: generics generic-methods-and-generic-self190419
+Ref: e3190419
+Ref: generics id2190419
+Ref: e4190419
+Ref: Generic methods and generic self-Footnote-1192877
+Node: Variance of generic types192943
+Ref: generics variance-of-generic-types193098
+Ref: e6193098
+Ref: generics variance-of-generics193098
+Ref: e7193098
+Ref: Variance of generic types-Footnote-1196128
+Ref: Variance of generic types-Footnote-2196195
+Ref: Variance of generic types-Footnote-3196265
+Ref: Variance of generic types-Footnote-4196336
+Ref: Variance of generic types-Footnote-5196406
+Ref: Variance of generic types-Footnote-6196472
+Node: Type variables with value restriction196538
+Ref: generics type-variable-value-restriction196693
+Ref: 7c196693
+Ref: generics type-variables-with-value-restriction196693
+Ref: e8196693
+Ref: Type variables with value restriction-Footnote-1199032
+Ref: Type variables with value restriction-Footnote-2199100
+Ref: Type variables with value restriction-Footnote-3199168
+Ref: Type variables with value restriction-Footnote-4199236
+Ref: Type variables with value restriction-Footnote-5199305
+Ref: Type variables with value restriction-Footnote-6199374
+Node: Type variables with upper bounds199435
+Ref: generics type-variable-upper-bound199585
+Ref: 79199585
+Ref: generics type-variables-with-upper-bounds199585
+Ref: e9199585
+Ref: Type variables with upper bounds-Footnote-1201039
+Node: Declaring decorators201108
+Ref: generics declaring-decorators201238
+Ref: 3d201238
+Ref: generics id3201238
+Ref: ea201238
+Ref: Declaring decorators-Footnote-1202911
+Node: Decorator factories202977
+Ref: generics decorator-factories203051
+Ref: eb203051
+Ref: generics id4203051
+Ref: ec203051
+Ref: Decorator factories-Footnote-1204377
+Node: Generic protocols204447
+Ref: generics generic-protocols204565
+Ref: ed204565
+Ref: Generic protocols-Footnote-1207174
+Ref: Generic protocols-Footnote-2207244
+Node: Generic type aliases207304
+Ref: generics generic-type-aliases207393
+Ref: 75207393
+Ref: generics id5207393
+Ref: ee207393
+Ref: Generic type aliases-Footnote-1209690
+Node: More types209745
+Ref: more_types doc209842
+Ref: ef209842
+Ref: more_types more-types209842
+Ref: f0209842
+Ref: More types-Footnote-1211286
+Ref: More types-Footnote-2211356
+Ref: More types-Footnote-3211426
+Node: The NoReturn type211496
+Ref: more_types noreturn211575
+Ref: f1211575
+Ref: more_types the-noreturn-type211575
+Ref: f2211575
+Ref: The NoReturn type-Footnote-1212538
+Ref: The NoReturn type-Footnote-2212608
+Node: NewTypes212678
+Ref: more_types id1212786
+Ref: f3212786
+Ref: more_types newtypes212786
+Ref: f4212786
+Ref: NewTypes-Footnote-1216004
+Ref: NewTypes-Footnote-2216071
+Ref: NewTypes-Footnote-3216139
+Node: Function overloading216207
+Ref: more_types function-overloading216325
+Ref: 68216325
+Ref: more_types id2216325
+Ref: f5216325
+Ref: Function overloading-Footnote-1221053
+Ref: Function overloading-Footnote-2221120
+Ref: Function overloading-Footnote-3221190
+Ref: Function overloading-Footnote-4221269
+Node: Runtime behavior221339
+Ref: more_types runtime-behavior221451
+Ref: f6221451
+Ref: Runtime behavior-Footnote-1222524
+Node: Type checking calls to overloads222592
+Ref: more_types type-checking-calls-to-overloads222739
+Ref: f7222739
+Ref: Type checking calls to overloads-Footnote-1225456
+Node: Type checking the variants225524
+Ref: more_types type-checking-the-variants225687
+Ref: f8225687
+Ref: Type checking the variants-Footnote-1230759
+Node: Type checking the implementation230823
+Ref: more_types type-checking-the-implementation230975
+Ref: f9230975
+Node: Conditional overloads232772
+Ref: more_types conditional-overloads232889
+Ref: fc232889
+Ref: Conditional overloads-Footnote-1235566
+Node: Advanced uses of self-types235642
+Ref: more_types advanced-self235770
+Ref: e5235770
+Ref: more_types advanced-uses-of-self-types235770
+Ref: 101235770
+Node: Restricted methods in generic classes236153
+Ref: more_types restricted-methods-in-generic-classes236274
+Ref: 102236274
+Ref: Restricted methods in generic classes-Footnote-1238275
+Ref: Restricted methods in generic classes-Footnote-2238351
+Node: Mixin classes238427
+Ref: more_types mixin-classes238599
+Ref: 103238599
+Node: Precise typing of alternative constructors239790
+Ref: more_types precise-typing-of-alternative-constructors239916
+Ref: 104239916
+Node: Typing async/await240724
+Ref: more_types async-and-await240841
+Ref: 3a240841
+Ref: more_types typing-async-await240841
+Ref: 105240841
+Ref: Typing async/await-Footnote-1244718
+Ref: Typing async/await-Footnote-2244760
+Ref: Typing async/await-Footnote-3244831
+Ref: Typing async/await-Footnote-4244902
+Ref: Typing async/await-Footnote-5244973
+Ref: Typing async/await-Footnote-6245049
+Node: TypedDict245128
+Ref: more_types id3245209
+Ref: 107245209
+Ref: more_types typeddict245209
+Ref: 108245209
+Ref: TypedDict-Footnote-1249442
+Ref: TypedDict-Footnote-2249503
+Ref: TypedDict-Footnote-3249564
+Ref: TypedDict-Footnote-4249625
+Ref: TypedDict-Footnote-5249686
+Ref: TypedDict-Footnote-6249755
+Node: Totality249823
+Ref: more_types totality249904
+Ref: 109249904
+Ref: Totality-Footnote-1251405
+Ref: Totality-Footnote-2251470
+Ref: Totality-Footnote-3251537
+Ref: Totality-Footnote-4251602
+Node: Supported operations251667
+Ref: more_types supported-operations251775
+Ref: 10a251775
+Ref: Supported operations-Footnote-1252931
+Ref: Supported operations-Footnote-2253000
+Ref: Supported operations-Footnote-3253065
+Ref: Supported operations-Footnote-4253131
+Ref: Supported operations-Footnote-5253199
+Ref: Supported operations-Footnote-6253266
+Ref: Supported operations-Footnote-7253332
+Ref: Supported operations-Footnote-8253404
+Ref: Supported operations-Footnote-9253472
+Ref: Supported operations-Footnote-10253537
+Ref: Supported operations-Footnote-11253605
+Node: Class-based syntax253675
+Ref: more_types class-based-syntax253813
+Ref: 10b253813
+Node: Mixing required and non-required items254697
+Ref: more_types mixing-required-and-non-required-items254835
+Ref: 10c254835
+Node: Unions of TypedDicts255742
+Ref: more_types unions-of-typeddicts255853
+Ref: 10d255853
+Node: Literal types and Enums256448
+Ref: literal_types doc256568
+Ref: 110256568
+Ref: literal_types literal-types-and-enums256568
+Ref: 111256568
+Node: Literal types256661
+Ref: literal_types id1256746
+Ref: 112256746
+Ref: literal_types literal-types256746
+Ref: 10f256746
+Node: Parameterizing Literals258820
+Ref: literal_types parameterizing-literals258927
+Ref: 113258927
+Node: Declaring literal variables260412
+Ref: literal_types declaring-literal-variables260548
+Ref: 114260548
+Node: Intelligent indexing262957
+Ref: literal_types intelligent-indexing263083
+Ref: 116263083
+Node: Tagged unions264748
+Ref: literal_types id2264870
+Ref: 117264870
+Ref: literal_types tagged-unions264870
+Ref: 10e264870
+Node: Exhaustiveness checking267928
+Ref: literal_types exhaustiveness-checking268041
+Ref: 118268041
+Node: Limitations270598
+Ref: literal_types limitations270689
+Ref: 119270689
+Node: Enums271393
+Ref: literal_types enums271478
+Ref: 11a271478
+Ref: Enums-Footnote-1272388
+Ref: Enums-Footnote-2272450
+Ref: Enums-Footnote-3272515
+Ref: Enums-Footnote-4272577
+Node: Exhaustiveness checking<2>272642
+Ref: literal_types id3272734
+Ref: 11b272734
+Node: Extra Enum checks274091
+Ref: literal_types extra-enum-checks274183
+Ref: 11c274183
+Node: Final names methods and classes275525
+Ref: final_attrs doc275646
+Ref: 11d275646
+Ref: final_attrs final-attrs275646
+Ref: 115275646
+Ref: final_attrs final-names-methods-and-classes275646
+Ref: 11e275646
+Node: Final names276489
+Ref: final_attrs final-names276588
+Ref: 11f276588
+Ref: Final names-Footnote-1277745
+Node: Syntax variants277811
+Ref: final_attrs syntax-variants277903
+Ref: 120277903
+Ref: Syntax variants-Footnote-1278782
+Node: Details of using Final278858
+Ref: final_attrs details-of-using-final278950
+Ref: 121278950
+Ref: Details of using Final-Footnote-1280952
+Ref: Details of using Final-Footnote-2281028
+Ref: Details of using Final-Footnote-3281098
+Node: Final methods281174
+Ref: final_attrs final-methods281295
+Ref: 122281295
+Node: Final classes282217
+Ref: final_attrs final-classes282318
+Ref: 123282318
+Node: Metaclasses283729
+Ref: metaclasses doc283860
+Ref: 124283860
+Ref: metaclasses id1283860
+Ref: 125283860
+Ref: metaclasses metaclasses283860
+Ref: 126283860
+Ref: Metaclasses-Footnote-1284473
+Ref: Metaclasses-Footnote-2284544
+Ref: Metaclasses-Footnote-3284606
+Ref: Metaclasses-Footnote-4284668
+Ref: Metaclasses-Footnote-5284740
+Node: Defining a metaclass284803
+Ref: metaclasses defining284901
+Ref: 127284901
+Ref: metaclasses defining-a-metaclass284901
+Ref: 128284901
+Ref: Defining a metaclass-Footnote-1285429
+Ref: Defining a metaclass-Footnote-2285494
+Node: Metaclass usage example285558
+Ref: metaclasses examples285709
+Ref: 129285709
+Ref: metaclasses metaclass-usage-example285709
+Ref: 12a285709
+Node: Gotchas and limitations of metaclass support286379
+Ref: metaclasses gotchas-and-limitations-of-metaclass-support286501
+Ref: 12b286501
+Ref: metaclasses limitations286501
+Ref: 12c286501
+Ref: Gotchas and limitations of metaclass support-Footnote-1287554
+Node: Running mypy and managing imports287616
+Ref: running_mypy doc287737
+Ref: 12d287737
+Ref: running_mypy running-mypy287737
+Ref: 12e287737
+Ref: running_mypy running-mypy-and-managing-imports287737
+Ref: 12f287737
+Node: Specifying code to be checked288747
+Ref: running_mypy id1288888
+Ref: 130288888
+Ref: running_mypy specifying-code-to-be-checked288888
+Ref: 131288888
+Node: Reading a list of files from a file291451
+Ref: running_mypy reading-a-list-of-files-from-a-file291625
+Ref: 138291625
+Node: How mypy handles imports292309
+Ref: running_mypy how-mypy-handles-imports292469
+Ref: 139292469
+Ref: running_mypy ignore-missing-imports293300
+Ref: 17293300
+Node: Missing imports293302
+Ref: running_mypy fix-missing-imports293444
+Ref: 14293444
+Ref: running_mypy missing-imports293444
+Ref: 13a293444
+Node: Missing library stubs or py typed marker294681
+Ref: running_mypy missing-library-stubs-or-py-typed-marker294807
+Ref: 13b294807
+Ref: Missing library stubs or py typed marker-Footnote-1298638
+Ref: Missing library stubs or py typed marker-Footnote-2298681
+Node: Library stubs not installed298728
+Ref: running_mypy library-stubs-not-installed298905
+Ref: 141298905
+Node: Cannot find implementation or library stub300411
+Ref: running_mypy cannot-find-implementation-or-library-stub300539
+Ref: 144300539
+Ref: running_mypy missing-type-hints-for-third-party-library300539
+Ref: 145300539
+Node: Following imports302897
+Ref: running_mypy follow-imports303044
+Ref: 22303044
+Ref: running_mypy following-imports303044
+Ref: 147303044
+Node: Mapping file paths to modules305943
+Ref: running_mypy mapping-file-paths-to-modules306096
+Ref: 14a306096
+Ref: running_mypy mapping-paths-to-modules306096
+Ref: 133306096
+Node: How imports are found309635
+Ref: running_mypy finding-imports309802
+Ref: 135309802
+Ref: running_mypy how-imports-are-found309802
+Ref: 14f309802
+Ref: How imports are found-Footnote-1311849
+Ref: How imports are found-Footnote-2311892
+Node: Other advice and best practices311934
+Ref: running_mypy other-advice-and-best-practices312113
+Ref: 150312113
+Node: Directories specific to Python 2 @python2313014
+Ref: running_mypy directories-specific-to-python-2-python2313163
+Ref: 151313163
+Node: The mypy command line313697
+Ref: command_line doc313834
+Ref: 152313834
+Ref: command_line command-line313834
+Ref: c313834
+Ref: command_line the-mypy-command-line313834
+Ref: 153313834
+Node: Specifying what to type check314515
+Ref: command_line specifying-what-to-type-check314627
+Ref: 155314627
+Ref: command_line cmdoption-mypy-m315119
+Ref: 134315119
+Ref: command_line cmdoption-mypy-module315119
+Ref: 156315119
+Ref: command_line cmdoption-mypy-p315347
+Ref: 136315347
+Ref: command_line cmdoption-mypy-package315347
+Ref: 157315347
+Ref: command_line cmdoption-mypy-c315656
+Ref: 137315656
+Ref: command_line cmdoption-mypy-command315656
+Ref: 158315656
+Ref: command_line cmdoption-mypy-exclude315773
+Ref: 14b315773
+Node: Optional arguments317472
+Ref: command_line optional-arguments317604
+Ref: 159317604
+Ref: command_line cmdoption-mypy-h317653
+Ref: 154317653
+Ref: command_line cmdoption-mypy-help317653
+Ref: 15a317653
+Ref: command_line cmdoption-mypy-v317711
+Ref: 14e317711
+Ref: command_line cmdoption-mypy-verbose317711
+Ref: 15b317711
+Ref: command_line cmdoption-mypy-V317767
+Ref: 15c317767
+Ref: command_line cmdoption-mypy-version317767
+Ref: 15d317767
+Node: Config file317842
+Ref: command_line config-file317961
+Ref: 15e317961
+Ref: command_line config-file-flag317961
+Ref: 15f317961
+Ref: command_line cmdoption-mypy-config-file317996
+Ref: 160317996
+Ref: command_line cmdoption-mypy-warn-unused-configs318556
+Ref: 161318556
+Node: Import discovery318773
+Ref: command_line id1318896
+Ref: 163318896
+Ref: command_line import-discovery318896
+Ref: 164318896
+Ref: command_line cmdoption-mypy-namespace-packages319020
+Ref: 132319020
+Ref: command_line cmdoption-mypy-explicit-package-bases319888
+Ref: 14c319888
+Ref: command_line cmdoption-mypy-ignore-missing-imports320286
+Ref: 140320286
+Ref: command_line cmdoption-mypy-follow-imports321172
+Ref: 148321172
+Ref: command_line cmdoption-mypy-python-executable321531
+Ref: 146321531
+Ref: command_line cmdoption-mypy-no-site-packages321942
+Ref: 165321942
+Ref: command_line cmdoption-mypy-no-silence-site-packages322330
+Ref: 166322330
+Ref: Import discovery-Footnote-1322566
+Ref: Import discovery-Footnote-2322608
+Ref: Import discovery-Footnote-3322650
+Ref: Import discovery-Footnote-4322692
+Node: Platform configuration322734
+Ref: command_line id2322869
+Ref: 167322869
+Ref: command_line platform-configuration322869
+Ref: 168322869
+Ref: command_line cmdoption-mypy-python-version323231
+Ref: 100323231
+Ref: command_line cmdoption-mypy-2323855
+Ref: 8323855
+Ref: command_line cmdoption-mypy-py2323855
+Ref: 169323855
+Ref: command_line cmdoption-mypy-platform324071
+Ref: 16a324071
+Ref: command_line always-true324405
+Ref: 16b324405
+Ref: command_line cmdoption-mypy-always-true324405
+Ref: fe324405
+Ref: command_line cmdoption-mypy-always-false324576
+Ref: ff324576
+Ref: Platform configuration-Footnote-1324785
+Ref: Platform configuration-Footnote-2324827
+Node: Disallow dynamic typing324891
+Ref: command_line disallow-dynamic-typing325039
+Ref: 16c325039
+Ref: command_line id3325039
+Ref: 16d325039
+Ref: command_line cmdoption-mypy-disallow-any-unimported325410
+Ref: 16e325410
+Ref: command_line cmdoption-mypy-disallow-any-expr325706
+Ref: 16f325706
+Ref: command_line cmdoption-mypy-disallow-any-decorated326263
+Ref: 170326263
+Ref: command_line cmdoption-mypy-disallow-any-explicit326413
+Ref: 171326413
+Ref: command_line cmdoption-mypy-disallow-any-generics326572
+Ref: 172326572
+Ref: command_line cmdoption-mypy-disallow-subclassing-any326838
+Ref: 173326838
+Ref: Disallow dynamic typing-Footnote-1327557
+Node: Untyped definitions and calls327623
+Ref: command_line id4327775
+Ref: 174327775
+Ref: command_line untyped-definitions-and-calls327775
+Ref: fb327775
+Ref: command_line cmdoption-mypy-disallow-untyped-calls327933
+Ref: 175327933
+Ref: command_line cmdoption-mypy-disallow-untyped-defs328097
+Ref: b328097
+Ref: command_line cmdoption-mypy-disallow-incomplete-defs328243
+Ref: 176328243
+Ref: command_line cmdoption-mypy-check-untyped-defs328384
+Ref: fa328384
+Ref: command_line cmdoption-mypy-disallow-untyped-decorators328775
+Ref: 177328775
+Node: None and Optional handling328949
+Ref: command_line id5329098
+Ref: 178329098
+Ref: command_line none-and-optional-handling329098
+Ref: 179329098
+Ref: command_line no-implicit-optional329302
+Ref: 17a329302
+Ref: command_line cmdoption-mypy-no-implicit-optional329302
+Ref: 6b329302
+Ref: command_line cmdoption-mypy-no-strict-optional329944
+Ref: 71329944
+Ref: None and Optional handling-Footnote-1330514
+Ref: None and Optional handling-Footnote-2330584
+Node: Configuring warnings330654
+Ref: command_line configuring-warnings330804
+Ref: 17b330804
+Ref: command_line id6330804
+Ref: 17c330804
+Ref: command_line cmdoption-mypy-warn-redundant-casts330974
+Ref: 17d330974
+Ref: command_line cmdoption-mypy-warn-unused-ignores331134
+Ref: 17e331134
+Ref: command_line cmdoption-mypy-no-warn-no-return331744
+Ref: 17f331744
+Ref: command_line cmdoption-mypy-warn-return-any332252
+Ref: 180332252
+Ref: command_line cmdoption-mypy-warn-unreachable332445
+Ref: c6332445
+Ref: Configuring warnings-Footnote-1334175
+Node: Miscellaneous strictness flags334245
+Ref: command_line id7334395
+Ref: 181334395
+Ref: command_line miscellaneous-strictness-flags334395
+Ref: 182334395
+Ref: command_line cmdoption-mypy-allow-untyped-globals334567
+Ref: 183334567
+Ref: command_line cmdoption-mypy-allow-redefinition334737
+Ref: 184334737
+Ref: command_line cmdoption-mypy-local-partial-types335665
+Ref: 185335665
+Ref: command_line cmdoption-mypy-no-implicit-reexport336776
+Ref: 186336776
+Ref: command_line cmdoption-mypy-strict-equality337502
+Ref: 187337502
+Ref: command_line cmdoption-mypy-strict338104
+Ref: 19338104
+Ref: command_line cmdoption-mypy-disable-error-code338402
+Ref: 188338402
+Ref: command_line cmdoption-mypy-enable-error-code338719
+Ref: 189338719
+Node: Configuring error messages339191
+Ref: command_line configuring-error-messages339337
+Ref: 18a339337
+Ref: command_line id8339337
+Ref: 18b339337
+Ref: command_line cmdoption-mypy-show-error-context339489
+Ref: 18c339489
+Ref: command_line cmdoption-mypy-show-column-numbers340136
+Ref: 18d340136
+Ref: command_line cmdoption-mypy-show-error-codes340430
+Ref: 5a340430
+Ref: command_line cmdoption-mypy-pretty340722
+Ref: 18f340722
+Ref: command_line cmdoption-mypy-no-color-output340880
+Ref: 190340880
+Ref: command_line cmdoption-mypy-no-error-summary340997
+Ref: 191340997
+Ref: command_line cmdoption-mypy-show-absolute-path341213
+Ref: 192341213
+Ref: command_line cmdoption-mypy-soft-error-limit341283
+Ref: 193341283
+Node: Incremental mode341647
+Ref: command_line incremental341779
+Ref: 194341779
+Ref: command_line incremental-mode341779
+Ref: 195341779
+Ref: command_line cmdoption-mypy-no-incremental342277
+Ref: 162342277
+Ref: command_line cmdoption-mypy-cache-dir342575
+Ref: 196342575
+Ref: command_line cmdoption-mypy-sqlite-cache343209
+Ref: 197343209
+Ref: command_line cmdoption-mypy-cache-fine-grained343289
+Ref: 198343289
+Ref: command_line cmdoption-mypy-skip-version-check343412
+Ref: 199343412
+Ref: command_line cmdoption-mypy-skip-cache-mtime-checks343574
+Ref: 19a343574
+Ref: Incremental mode-Footnote-1343710
+Node: Advanced options343742
+Ref: command_line advanced-options343865
+Ref: 19b343865
+Ref: command_line cmdoption-mypy-pdb344024
+Ref: 19c344024
+Ref: command_line cmdoption-mypy-show-traceback344132
+Ref: 19d344132
+Ref: command_line cmdoption-mypy-tb344132
+Ref: 19e344132
+Ref: command_line cmdoption-mypy-raise-exceptions344263
+Ref: 19f344263
+Ref: command_line cmdoption-mypy-custom-typing-module344333
+Ref: 1a0344333
+Ref: command_line cmdoption-mypy-custom-typeshed-dir344468
+Ref: 1a1344468
+Ref: command_line warn-incomplete-stub344892
+Ref: 1a2344892
+Ref: command_line cmdoption-mypy-warn-incomplete-stub344892
+Ref: 1a3344892
+Ref: command_line shadow-file345688
+Ref: 1a4345688
+Ref: command_line cmdoption-mypy-shadow-file345688
+Ref: 1a5345688
+Ref: Advanced options-Footnote-1346704
+Node: Report generation346772
+Ref: command_line report-generation346895
+Ref: 1a6346895
+Ref: command_line cmdoption-mypy-any-exprs-report347051
+Ref: 1a7347051
+Ref: command_line cmdoption-mypy-cobertura-xml-report347226
+Ref: 1a8347226
+Ref: command_line cmdoption-mypy-html-report347518
+Ref: 1a9347518
+Ref: command_line cmdoption-mypy-linecount-report347809
+Ref: 1aa347809
+Ref: command_line cmdoption-mypy-linecoverage-report347989
+Ref: 1ab347989
+Ref: command_line cmdoption-mypy-lineprecision-report348200
+Ref: 1ac348200
+Ref: command_line cmdoption-mypy-txt-report348365
+Ref: 1ad348365
+Ref: command_line cmdoption-mypy-xml-report348658
+Ref: 1ae348658
+Ref: Report generation-Footnote-1348962
+Ref: Report generation-Footnote-2349001
+Ref: Report generation-Footnote-3349040
+Ref: Report generation-Footnote-4349079
+Node: Miscellaneous<3>349118
+Ref: command_line miscellaneous349216
+Ref: 1af349216
+Ref: command_line cmdoption-mypy-install-types349257
+Ref: 142349257
+Ref: command_line cmdoption-mypy-non-interactive350284
+Ref: 143350284
+Ref: command_line cmdoption-mypy-junit-xml350923
+Ref: 1b0350923
+Ref: command_line cmdoption-mypy-find-occurrences351142
+Ref: 1b1351142
+Ref: command_line cmdoption-mypy-scripts-are-modules351327
+Ref: 14d351327
+Ref: Miscellaneous<3>-Footnote-1351887
+Ref: Miscellaneous<3>-Footnote-2351959
+Node: The mypy configuration file352031
+Ref: config_file doc352155
+Ref: 1b2352155
+Ref: config_file config-file352155
+Ref: 2e352155
+Ref: config_file sqlite352155
+Ref: 1b3352155
+Ref: config_file the-mypy-configuration-file352155
+Ref: 1b4352155
+Node: Config file format354327
+Ref: config_file config-file-format354445
+Ref: 1b5354445
+Ref: config_file config-precedence355802
+Ref: 1b6355802
+Ref: Config file format-Footnote-1356875
+Node: Per-module and global options356935
+Ref: config_file per-module-and-global-options357085
+Ref: 1b9357085
+Node: Inverting option values357742
+Ref: config_file inverting-option-values357882
+Ref: 1ba357882
+Node: Examples358125
+Ref: config_file examples358255
+Ref: 1bb358255
+Node: Import discovery<2>360197
+Ref: config_file config-file-import-discovery360329
+Ref: 13f360329
+Ref: config_file import-discovery360329
+Ref: 1bc360329
+Ref: config_file confval-mypy_path360468
+Ref: 13d360468
+Ref: config_file confval-files361368
+Ref: 13c361368
+Ref: config_file confval-exclude361929
+Ref: 1bd361929
+Ref: config_file confval-namespace_packages364041
+Ref: 1bf364041
+Ref: config_file confval-explicit_package_bases364341
+Ref: 1c0364341
+Ref: config_file confval-ignore_missing_imports364857
+Ref: 13e364857
+Ref: config_file confval-follow_imports365196
+Ref: 149365196
+Ref: config_file confval-follow_imports_for_stubs366030
+Ref: 1c1366030
+Ref: config_file confval-python_executable366622
+Ref: 1c2366622
+Ref: config_file confval-no_site_packages367004
+Ref: 1c3367004
+Ref: config_file confval-no_silence_site_packages367320
+Ref: 1c4367320
+Ref: Import discovery<2>-Footnote-1367797
+Ref: Import discovery<2>-Footnote-2367861
+Ref: Import discovery<2>-Footnote-3367916
+Ref: Import discovery<2>-Footnote-4367958
+Ref: Import discovery<2>-Footnote-5368000
+Node: Platform configuration<2>368042
+Ref: config_file platform-configuration368192
+Ref: 1c5368192
+Ref: config_file confval-python_version368249
+Ref: 1c6368249
+Ref: config_file confval-platform368629
+Ref: 1c7368629
+Ref: config_file confval-always_true368997
+Ref: 1c8368997
+Ref: config_file confval-always_false369190
+Ref: 1c9369190
+Ref: Platform configuration<2>-Footnote-1369421
+Node: Disallow dynamic typing<2>369485
+Ref: config_file disallow-dynamic-typing369648
+Ref: 1ca369648
+Ref: config_file confval-disallow_any_unimported369808
+Ref: 1cb369808
+Ref: config_file confval-disallow_any_expr370066
+Ref: 1cc370066
+Ref: config_file confval-disallow_any_decorated370225
+Ref: 1cd370225
+Ref: config_file confval-disallow_any_explicit370419
+Ref: 1ce370419
+Ref: config_file confval-disallow_any_generics370622
+Ref: 1cf370622
+Ref: config_file confval-disallow_subclassing_any370803
+Ref: 1d0370803
+Node: Untyped definitions and calls<2>370952
+Ref: config_file untyped-definitions-and-calls371119
+Ref: 1d1371119
+Ref: config_file confval-disallow_untyped_calls371296
+Ref: 1d2371296
+Ref: config_file confval-disallow_untyped_defs371490
+Ref: 2c371490
+Ref: config_file confval-disallow_incomplete_defs371683
+Ref: 1d3371683
+Ref: config_file confval-check_untyped_defs371846
+Ref: 2d371846
+Ref: config_file confval-disallow_untyped_decorators372004
+Ref: 1d4372004
+Node: None and Optional handling<2>372222
+Ref: config_file config-file-none-and-optional-handling372386
+Ref: 1d5372386
+Ref: config_file none-and-optional-handling372386
+Ref: 1d6372386
+Ref: config_file confval-no_implicit_optional372555
+Ref: 1d7372555
+Ref: config_file confval-strict_optional372775
+Ref: 72372775
+Ref: None and Optional handling<2>-Footnote-1373097
+Node: Configuring warnings<2>373167
+Ref: config_file configuring-warnings373317
+Ref: 1d8373317
+Ref: config_file confval-warn_redundant_casts373470
+Ref: 1d9373470
+Ref: config_file confval-warn_unused_ignores373694
+Ref: 1da373694
+Ref: config_file confval-warn_no_return373841
+Ref: 1db373841
+Ref: config_file confval-warn_return_any373998
+Ref: 1dc373998
+Ref: config_file confval-warn_unreachable374213
+Ref: 1dd374213
+Node: Suppressing errors374425
+Ref: config_file suppressing-errors374579
+Ref: 1de374579
+Ref: config_file confval-show_none_errors374763
+Ref: 1df374763
+Ref: config_file confval-ignore_errors374969
+Ref: 1e0374969
+Node: Miscellaneous strictness flags<2>375088
+Ref: config_file miscellaneous-strictness-flags375248
+Ref: 1e1375248
+Ref: config_file confval-allow_untyped_globals375431
+Ref: 1e2375431
+Ref: config_file confval-allow_redefinition375645
+Ref: 1e3375645
+Ref: config_file confval-local_partial_types376499
+Ref: 1e4376499
+Ref: config_file confval-disable_error_code376768
+Ref: 1e5376768
+Ref: config_file confval-implicit_reexport376919
+Ref: 1e6376919
+Ref: config_file confval-strict_equality377621
+Ref: 1e7377621
+Ref: config_file confval-strict377822
+Ref: 1e8377822
+Node: Configuring error messages<2>378158
+Ref: config_file configuring-error-messages378319
+Ref: 1e9378319
+Ref: config_file confval-show_error_context378559
+Ref: 1ea378559
+Ref: config_file confval-show_column_numbers378700
+Ref: 1eb378700
+Ref: config_file confval-show_error_codes378835
+Ref: 1ec378835
+Ref: config_file confval-pretty379020
+Ref: 1ed379020
+Ref: config_file confval-color_output379232
+Ref: 1ee379232
+Ref: config_file confval-error_summary379360
+Ref: 1ef379360
+Ref: config_file confval-show_absolute_path379497
+Ref: 1f0379497
+Node: Incremental mode<2>379621
+Ref: config_file incremental-mode379768
+Ref: 1f1379768
+Ref: config_file confval-incremental379884
+Ref: 1f2379884
+Ref: config_file confval-cache_dir380007
+Ref: 1f3380007
+Ref: config_file confval-sqlite_cache380511
+Ref: 1f4380511
+Ref: config_file confval-cache_fine_grained380645
+Ref: 1f5380645
+Ref: config_file confval-skip_version_check380822
+Ref: 1f6380822
+Ref: config_file confval-skip_cache_mtime_checks381145
+Ref: 1f7381145
+Ref: Incremental mode<2>-Footnote-1381335
+Node: Advanced options<2>381367
+Ref: config_file advanced-options381505
+Ref: 1f8381505
+Ref: config_file confval-plugins381621
+Ref: 1f9381621
+Ref: config_file confval-pdb381797
+Ref: 1fb381797
+Ref: config_file confval-show_traceback381907
+Ref: 1fc381907
+Ref: config_file confval-raise_exceptions382029
+Ref: 1fd382029
+Ref: config_file confval-custom_typing_module382153
+Ref: 1fe382153
+Ref: config_file confval-custom_typeshed_dir382306
+Ref: 1ff382306
+Ref: config_file confval-warn_incomplete_stub382555
+Ref: 200382555
+Ref: Advanced options<2>-Footnote-1382863
+Ref: Advanced options<2>-Footnote-2382925
+Node: Report generation<2>382993
+Ref: config_file report-generation383128
+Ref: 201383128
+Ref: config_file confval-any_exprs_report383286
+Ref: 202383286
+Ref: config_file confval-cobertura_xml_report383488
+Ref: 203383488
+Ref: config_file confval-html_report-xslt_html_report383807
+Ref: 204383807
+Ref: config_file confval-html_report / xslt_html_report383807
+Ref: 205383807
+Ref: config_file confval-linecount_report384123
+Ref: 206384123
+Ref: config_file confval-linecoverage_report384330
+Ref: 207384330
+Ref: config_file confval-lineprecision_report384568
+Ref: 208384568
+Ref: config_file confval-txt_report-xslt_txt_report384760
+Ref: 209384760
+Ref: config_file confval-txt_report / xslt_txt_report384760
+Ref: 20a384760
+Ref: config_file confval-xml_report385078
+Ref: 20b385078
+Ref: Report generation<2>-Footnote-1385409
+Ref: Report generation<2>-Footnote-2385448
+Ref: Report generation<2>-Footnote-3385487
+Ref: Report generation<2>-Footnote-4385526
+Node: Miscellaneous<4>385565
+Ref: config_file miscellaneous385708
+Ref: 20c385708
+Ref: config_file confval-junit_xml385818
+Ref: 20d385818
+Ref: config_file confval-scripts_are_modules386058
+Ref: 20e386058
+Ref: config_file confval-warn_unused_configs386292
+Ref: 1b8386292
+Ref: config_file confval-verbosity386590
+Ref: 20f386590
+Node: Using a pyproject toml file386760
+Ref: config_file using-a-pyproject-toml386905
+Ref: 1be386905
+Ref: config_file using-a-pyproject-toml-file386905
+Ref: 210386905
+Ref: Using a pyproject toml file-Footnote-1388380
+Ref: Using a pyproject toml file-Footnote-2388430
+Ref: Using a pyproject toml file-Footnote-3388455
+Node: Example pyproject toml388505
+Ref: config_file example-pyproject-toml388625
+Ref: 211388625
+Node: Inline configuration389592
+Ref: inline_config doc389718
+Ref: 212389718
+Ref: inline_config inline-config389718
+Ref: 1b7389718
+Ref: inline_config inline-configuration389718
+Ref: 213389718
+Ref: inline_config toml-documentation389718
+Ref: 214389718
+Node: Configuration comment format390056
+Ref: inline_config configuration-comment-format390139
+Ref: 215390139
+Node: Mypy daemon mypy server390929
+Ref: mypy_daemon doc391052
+Ref: 216391052
+Ref: mypy_daemon mypy-daemon391052
+Ref: 29391052
+Ref: mypy_daemon mypy-daemon-mypy-server391052
+Ref: 217391052
+Node: Basic usage392348
+Ref: mypy_daemon basic-usage392448
+Ref: 218392448
+Node: Daemon client commands393565
+Ref: mypy_daemon daemon-client-commands393697
+Ref: 219393697
+Node: Additional daemon flags395207
+Ref: mypy_daemon additional-daemon-flags395359
+Ref: 21c395359
+Ref: mypy_daemon cmdoption-dmypy-status-file395418
+Ref: 21d395418
+Ref: mypy_daemon cmdoption-dmypy-log-file395704
+Ref: 21e395704
+Ref: mypy_daemon cmdoption-dmypy-timeout395986
+Ref: 21f395986
+Ref: mypy_daemon cmdoption-dmypy-update396186
+Ref: 21a396186
+Ref: mypy_daemon cmdoption-dmypy-remove396977
+Ref: 21b396977
+Ref: mypy_daemon cmdoption-dmypy-fswatcher-dump-file397316
+Ref: 220397316
+Ref: mypy_daemon cmdoption-dmypy-perf-stats-file397729
+Ref: 221397729
+Ref: Additional daemon flags-Footnote-1397951
+Ref: Additional daemon flags-Footnote-2397996
+Node: Static inference of annotations398039
+Ref: mypy_daemon static-inference-of-annotations398160
+Ref: 222398160
+Ref: mypy_daemon cmdoption-dmypy-json399846
+Ref: 223399846
+Ref: mypy_daemon cmdoption-dmypy-no-errors400243
+Ref: 224400243
+Ref: mypy_daemon cmdoption-dmypy-no-any400444
+Ref: 225400444
+Ref: mypy_daemon cmdoption-dmypy-flex-any400642
+Ref: 226400642
+Ref: mypy_daemon cmdoption-dmypy-try-text400846
+Ref: 227400846
+Ref: mypy_daemon cmdoption-dmypy-callsites401010
+Ref: 228401010
+Ref: mypy_daemon cmdoption-dmypy-use-fixme401277
+Ref: 229401277
+Ref: mypy_daemon cmdoption-dmypy-max-guesses401520
+Ref: 22a401520
+Ref: Static inference of annotations-Footnote-1401676
+Ref: Static inference of annotations-Footnote-2401731
+Node: Using installed packages401777
+Ref: installed_packages doc401910
+Ref: 22b401910
+Ref: installed_packages installed-packages401910
+Ref: 15401910
+Ref: installed_packages mypy-plugin-for-pycharm401910
+Ref: 22c401910
+Ref: installed_packages using-installed-packages401910
+Ref: 22d401910
+Ref: Using installed packages-Footnote-1402887
+Ref: Using installed packages-Footnote-2402931
+Ref: Using installed packages-Footnote-3402982
+Ref: Using installed packages-Footnote-4403025
+Node: Using installed packages with mypy PEP 561403067
+Ref: installed_packages using-installed-packages-with-mypy-pep-561403213
+Ref: 22e403213
+Ref: Using installed packages with mypy PEP 561-Footnote-1404869
+Node: Creating PEP 561 compatible packages404930
+Ref: installed_packages creating-pep-561-compatible-packages405076
+Ref: 22f405076
+Ref: Creating PEP 561 compatible packages-Footnote-1408731
+Ref: Creating PEP 561 compatible packages-Footnote-2408773
+Ref: Creating PEP 561 compatible packages-Footnote-3408816
+Node: Extending and integrating mypy408872
+Ref: extending_mypy doc409015
+Ref: 230409015
+Ref: extending_mypy extending-and-integrating-mypy409015
+Ref: 231409015
+Ref: extending_mypy extending-mypy409015
+Ref: 232409015
+Node: Integrating mypy into another Python application409311
+Ref: extending_mypy integrating-mypy409461
+Ref: 233409461
+Ref: extending_mypy integrating-mypy-into-another-python-application409461
+Ref: 234409461
+Ref: Integrating mypy into another Python application-Footnote-1410576
+Ref: Integrating mypy into another Python application-Footnote-2410638
+Node: Extending mypy using plugins410700
+Ref: extending_mypy extending-mypy-using-plugins410890
+Ref: 1fa410890
+Ref: extending_mypy id1410890
+Ref: 235410890
+Ref: Extending mypy using plugins-Footnote-1412195
+Ref: Extending mypy using plugins-Footnote-2412237
+Ref: Extending mypy using plugins-Footnote-3412279
+Ref: Extending mypy using plugins-Footnote-4412319
+Node: Configuring mypy to use plugins412370
+Ref: extending_mypy configuring-mypy-to-use-plugins412531
+Ref: 236412531
+Ref: Configuring mypy to use plugins-Footnote-1413584
+Ref: Configuring mypy to use plugins-Footnote-2413650
+Node: High-level overview413714
+Ref: extending_mypy high-level-overview413875
+Ref: 237413875
+Node: Current list of plugin hooks415530
+Ref: extending_mypy current-list-of-plugin-hooks415693
+Ref: 239415693
+Ref: extending_mypy plugin-hooks415693
+Ref: 238415693
+Ref: Current list of plugin hooks-Footnote-1419768
+Ref: Current list of plugin hooks-Footnote-2419810
+Ref: Current list of plugin hooks-Footnote-3419886
+Ref: Current list of plugin hooks-Footnote-4419960
+Ref: Current list of plugin hooks-Footnote-5420028
+Ref: Current list of plugin hooks-Footnote-6420107
+Node: Notes about the semantic analyzer420191
+Ref: extending_mypy notes-about-the-semantic-analyzer420326
+Ref: 23a420326
+Ref: Notes about the semantic analyzer-Footnote-1421488
+Node: Automatic stub generation stubgen421554
+Ref: stubgen doc421704
+Ref: 23b421704
+Ref: stubgen automatic-stub-generation-stubgen421704
+Ref: 23c421704
+Ref: stubgen stubgen421704
+Ref: d7421704
+Ref: Automatic stub generation stubgen-Footnote-1423598
+Node: Specifying what to stub423640
+Ref: stubgen specifying-what-to-stub423772
+Ref: 23e423772
+Ref: stubgen cmdoption-stubgen-m424426
+Ref: 240424426
+Ref: stubgen cmdoption-stubgen-module424426
+Ref: 242424426
+Ref: stubgen cmdoption-stubgen-p424663
+Ref: 241424663
+Ref: stubgen cmdoption-stubgen-package424663
+Ref: 243424663
+Node: Specifying how to generate stubs425209
+Ref: stubgen specifying-how-to-generate-stubs425366
+Ref: 244425366
+Ref: stubgen cmdoption-stubgen-no-import425818
+Ref: 245425818
+Ref: stubgen cmdoption-stubgen-parse-only426432
+Ref: 246426432
+Ref: stubgen cmdoption-stubgen-doc-dir426765
+Ref: 247426765
+Node: Additional flags426972
+Ref: stubgen additional-flags427097
+Ref: 248427097
+Ref: stubgen cmdoption-stubgen-h427142
+Ref: 23d427142
+Ref: stubgen cmdoption-stubgen-help427142
+Ref: 249427142
+Ref: stubgen cmdoption-stubgen-py2427200
+Ref: 24a427200
+Ref: stubgen cmdoption-stubgen-ignore-errors427286
+Ref: 24b427286
+Ref: stubgen cmdoption-stubgen-include-private427470
+Ref: 24c427470
+Ref: stubgen cmdoption-stubgen-export-less427666
+Ref: 24d427666
+Ref: stubgen cmdoption-stubgen-search-path427888
+Ref: 24e427888
+Ref: stubgen cmdoption-stubgen-python-executable428036
+Ref: 24f428036
+Ref: stubgen cmdoption-stubgen-o428351
+Ref: 23f428351
+Ref: stubgen cmdoption-stubgen-output428351
+Ref: 250428351
+Ref: stubgen cmdoption-stubgen-v428639
+Ref: 251428639
+Ref: stubgen cmdoption-stubgen-verbose428639
+Ref: 252428639
+Ref: stubgen cmdoption-stubgen-q428701
+Ref: 253428701
+Ref: stubgen cmdoption-stubgen-quiet428701
+Ref: 254428701
+Node: Automatic stub testing stubtest428761
+Ref: stubtest doc428908
+Ref: 255428908
+Ref: stubtest automatic-stub-testing-stubtest428908
+Ref: 256428908
+Ref: stubtest stubtest428908
+Ref: d8428908
+Ref: Automatic stub testing stubtest-Footnote-1429424
+Node: What stubtest does and does not do429485
+Ref: stubtest what-stubtest-does-and-does-not-do429601
+Ref: 257429601
+Ref: What stubtest does and does not do-Footnote-1431059
+Ref: What stubtest does and does not do-Footnote-2431129
+Node: Example431172
+Ref: stubtest example431302
+Ref: 258431302
+Node: Usage431998
+Ref: stubtest usage432085
+Ref: 259432085
+Ref: stubtest cmdoption-stubtest-concise432781
+Ref: 25b432781
+Ref: stubtest cmdoption-stubtest-ignore-missing-stub432869
+Ref: 25c432869
+Ref: stubtest cmdoption-stubtest-ignore-positional-only432976
+Ref: 25d432976
+Ref: stubtest cmdoption-stubtest-allowlist433104
+Ref: 25e433104
+Ref: stubtest cmdoption-stubtest-generate-allowlist433334
+Ref: 25f433334
+Ref: stubtest cmdoption-stubtest-ignore-unused-allowlist433434
+Ref: 260433434
+Ref: stubtest cmdoption-stubtest-mypy-config-file433511
+Ref: 261433511
+Ref: stubtest cmdoption-stubtest-custom-typeshed-dir433630
+Ref: 262433630
+Ref: stubtest cmdoption-stubtest-check-typeshed433706
+Ref: 263433706
+Ref: stubtest cmdoption-stubtest-help433779
+Ref: 25a433779
+Node: Common issues and solutions433829
+Ref: common_issues doc433968
+Ref: 264433968
+Ref: common_issues common-issues433968
+Ref: 1e433968
+Ref: common_issues common-issues-and-solutions433968
+Ref: 265433968
+Node: Can’t install mypy using pip435166
+Ref: common_issues can-t-install-mypy-using-pip435310
+Ref: 266435310
+Node: No errors reported for obviously wrong code435569
+Ref: common_issues annotations-needed435771
+Ref: 267435771
+Ref: common_issues no-errors-reported-for-obviously-wrong-code435771
+Ref: 268435771
+Ref: No errors reported for obviously wrong code-Footnote-1439674
+Ref: No errors reported for obviously wrong code-Footnote-2439735
+Ref: No errors reported for obviously wrong code-Footnote-3439789
+Ref: No errors reported for obviously wrong code-Footnote-4439865
+Ref: No errors reported for obviously wrong code-Footnote-5439941
+Ref: No errors reported for obviously wrong code-Footnote-6440017
+Node: Spurious errors and locally silencing the checker440093
+Ref: common_issues silencing-checker440286
+Ref: 269440286
+Ref: common_issues spurious-errors-and-locally-silencing-the-checker440286
+Ref: 26a440286
+Ref: Spurious errors and locally silencing the checker-Footnote-1442356
+Node: Ignoring a whole file442435
+Ref: common_issues ignoring-a-whole-file442647
+Ref: 26b442647
+Node: Unexpected errors about ‘None’ and/or ‘Optional’ types442916
+Ref: common_issues unexpected-errors-about-none-and-or-optional-types443106
+Ref: 26c443106
+Node: Issues with code at runtime443783
+Ref: common_issues issues-with-code-at-runtime443970
+Ref: 26d443970
+Node: Mypy runs are slow444742
+Ref: common_issues mypy-runs-are-slow444893
+Ref: 26e444893
+Node: Types of empty collections445168
+Ref: common_issues types-of-empty-collections445329
+Ref: 26f445329
+Node: Redefinitions with incompatible types446294
+Ref: common_issues redefinitions-with-incompatible-types446461
+Ref: 270446461
+Node: Invariance vs covariance447362
+Ref: common_issues invariance-vs-covariance447541
+Ref: 271447541
+Ref: common_issues variance447541
+Ref: 55447541
+Node: Declaring a supertype as variable type448604
+Ref: common_issues declaring-a-supertype-as-variable-type448764
+Ref: 272448764
+Node: Complex type tests449486
+Ref: common_issues complex-type-tests449663
+Ref: 273449663
+Ref: Complex type tests-Footnote-1451832
+Ref: Complex type tests-Footnote-2451900
+Ref: Complex type tests-Footnote-3451968
+Ref: Complex type tests-Footnote-4452032
+Node: Python version and system platform checks452100
+Ref: common_issues python-version-and-system-platform-checks452275
+Ref: 274452275
+Ref: common_issues version-and-platform-checks452275
+Ref: fd452275
+Ref: Python version and system platform checks-Footnote-1455019
+Ref: Python version and system platform checks-Footnote-2455087
+Ref: Python version and system platform checks-Footnote-3455151
+Ref: Python version and system platform checks-Footnote-4455227
+Ref: Python version and system platform checks-Footnote-5455295
+Ref: Python version and system platform checks-Footnote-6455359
+Ref: Python version and system platform checks-Footnote-7455427
+Ref: Python version and system platform checks-Footnote-8455491
+Node: Displaying the type of an expression455555
+Ref: common_issues displaying-the-type-of-an-expression455729
+Ref: 275455729
+Ref: common_issues reveal-type455729
+Ref: 106455729
+Node: Silencing linters456706
+Ref: common_issues id1456898
+Ref: 276456898
+Ref: common_issues silencing-linters456898
+Ref: 277456898
+Node: Covariant subtyping of mutable protocol members is rejected457407
+Ref: common_issues covariant-subtyping-of-mutable-protocol-members-is-rejected457593
+Ref: 278457593
+Ref: Covariant subtyping of mutable protocol members is rejected-Footnote-1458491
+Node: Dealing with conflicting names458557
+Ref: common_issues dealing-with-conflicting-names458756
+Ref: 279458756
+Node: Using a development mypy build459495
+Ref: common_issues using-a-development-mypy-build459660
+Ref: 27a459660
+Ref: Using a development mypy build-Footnote-1460029
+Node: Variables vs type aliases460068
+Ref: common_issues variables-vs-type-aliases460225
+Ref: 27b460225
+Ref: Variables vs type aliases-Footnote-1462042
+Node: Incompatible overrides462084
+Ref: common_issues incompatible-overrides462227
+Ref: 27c462227
+Ref: Incompatible overrides-Footnote-1464104
+Node: Unreachable code464211
+Ref: common_issues unreachable464358
+Ref: c7464358
+Ref: common_issues unreachable-code464358
+Ref: 27d464358
+Node: Narrowing and inner functions465885
+Ref: common_issues narrowing-and-inner-functions466001
+Ref: 27e466001
+Node: Supported Python features466910
+Ref: supported_python_features doc467029
+Ref: 27f467029
+Ref: supported_python_features supported-python-features467029
+Ref: 280467029
+Ref: Supported Python features-Footnote-1467290
+Node: Runtime definition of methods and functions467362
+Ref: supported_python_features runtime-definition-of-methods-and-functions467465
+Ref: 281467465
+Ref: Runtime definition of methods and functions-Footnote-1468225
+Node: Error codes468290
+Ref: error_codes doc468412
+Ref: 282468412
+Ref: error_codes error-codes468412
+Ref: 18e468412
+Ref: error_codes id1468412
+Ref: 283468412
+Node: Displaying error codes469211
+Ref: error_codes displaying-error-codes469325
+Ref: 286469325
+Node: Silencing errors based on error codes469817
+Ref: error_codes silence-error-codes469931
+Ref: 5b469931
+Ref: error_codes silencing-errors-based-on-error-codes469931
+Ref: 288469931
+Node: Error codes enabled by default470799
+Ref: error_code_list doc470927
+Ref: 289470927
+Ref: error_code_list error-code-list470927
+Ref: 284470927
+Ref: error_code_list error-codes-enabled-by-default470927
+Ref: 28a470927
+Node: Check that attribute exists [attr-defined]472673
+Ref: error_code_list check-that-attribute-exists-attr-defined472848
+Ref: 28b472848
+Node: Check that attribute exists in each union item [union-attr]474039
+Ref: error_code_list check-that-attribute-exists-in-each-union-item-union-attr474264
+Ref: 28c474264
+Node: Check that name is defined [name-defined]475294
+Ref: error_code_list check-that-name-is-defined-name-defined475512
+Ref: 28d475512
+Ref: Check that name is defined [name-defined]-Footnote-1476009
+Node: Check arguments in calls [call-arg]476073
+Ref: error_code_list check-arguments-in-calls-call-arg476263
+Ref: 28e476263
+Node: Check argument types [arg-type]476718
+Ref: error_code_list check-argument-types-arg-type476918
+Ref: 28f476918
+Node: Check calls to overloaded functions [call-overload]477414
+Ref: error_code_list check-calls-to-overloaded-functions-call-overload477615
+Ref: 290477615
+Node: Check validity of types [valid-type]478361
+Ref: error_code_list check-validity-of-types-valid-type478593
+Ref: 291478593
+Ref: Check validity of types [valid-type]-Footnote-1479526
+Node: Require annotation if variable type is unclear [var-annotated]479596
+Ref: error_code_list require-annotation-if-variable-type-is-unclear-var-annotated479815
+Ref: 292479815
+Node: Check validity of overrides [override]480800
+Ref: error_code_list check-validity-of-overrides-override481027
+Ref: 293481027
+Node: Check that function returns a value [return]482201
+Ref: error_code_list check-that-function-returns-a-value-return482418
+Ref: 294482418
+Node: Check that return value is compatible [return-value]483136
+Ref: error_code_list check-that-return-value-is-compatible-return-value483363
+Ref: 295483363
+Node: Check types in assignment statement [assignment]483730
+Ref: error_code_list check-types-in-assignment-statement-assignment483950
+Ref: 296483950
+Node: Check type variable values [type-var]484462
+Ref: error_code_list check-type-variable-values-type-var484672
+Ref: 297484672
+Node: Check uses of various operators [operator]485128
+Ref: error_code_list check-uses-of-various-operators-operator485323
+Ref: 298485323
+Node: Check indexing operations [index]485710
+Ref: error_code_list check-indexing-operations-index485896
+Ref: 299485896
+Node: Check list items [list-item]486395
+Ref: error_code_list check-list-items-list-item486567
+Ref: 29a486567
+Node: Check dict items [dict-item]486914
+Ref: error_code_list check-dict-items-dict-item487091
+Ref: 29b487091
+Node: Check TypedDict items [typeddict-item]487528
+Ref: error_code_list check-typeddict-items-typeddict-item487722
+Ref: 29c487722
+Node: Check that type of target is known [has-type]488433
+Ref: error_code_list check-that-type-of-target-is-known-has-type488645
+Ref: 29d488645
+Node: Check that import target can be found [import]489921
+Ref: error_code_list check-that-import-target-can-be-found-import490142
+Ref: 29e490142
+Node: Check that each name is defined once [no-redef]490536
+Ref: error_code_list check-that-each-name-is-defined-once-no-redef490775
+Ref: 29f490775
+Node: Check that called function returns a value [func-returns-value]491649
+Ref: error_code_list check-that-called-function-returns-a-value-func-returns-value491892
+Ref: 2a0491892
+Node: Check instantiation of abstract classes [abstract]492501
+Ref: error_code_list check-instantiation-of-abstract-classes-abstract492740
+Ref: 2a1492740
+Ref: Check instantiation of abstract classes [abstract]-Footnote-1493705
+Node: Check the target of NewType [valid-newtype]493767
+Ref: error_code_list check-the-target-of-newtype-valid-newtype493990
+Ref: 2a2493990
+Node: Check the return type of __exit__ [exit-return]494877
+Ref: error_code_list check-the-return-type-of-exit-exit-return495094
+Ref: 2a3495094
+Ref: Check the return type of __exit__ [exit-return]-Footnote-1496840
+Ref: Check the return type of __exit__ [exit-return]-Footnote-2496916
+Node: Check that naming is consistent [name-match]496992
+Ref: error_code_list check-that-naming-is-consistent-name-match497239
+Ref: 2a4497239
+Node: Check that overloaded functions have an implementation [no-overload-impl]497637
+Ref: error_code_list check-that-overloaded-functions-have-an-implementation-no-overload-impl497866
+Ref: 2a5497866
+Node: Report syntax errors [syntax]498400
+Ref: error_code_list report-syntax-errors-syntax498612
+Ref: 2a6498612
+Node: Miscellaneous checks [misc]498886
+Ref: error_code_list miscellaneous-checks-misc499016
+Ref: 2a7499016
+Node: Error codes for optional checks499757
+Ref: error_code_list2 doc499893
+Ref: 2a8499893
+Ref: error_code_list2 error-codes-for-optional-checks499893
+Ref: 2a9499893
+Ref: error_code_list2 error-codes-optional499893
+Ref: 285499893
+Node: Check that type arguments exist [type-arg]501269
+Ref: error_code_list2 check-that-type-arguments-exist-type-arg501446
+Ref: 2aa501446
+Node: Check that every function has an annotation [no-untyped-def]502118
+Ref: error_code_list2 check-that-every-function-has-an-annotation-no-untyped-def502353
+Ref: 2ab502353
+Node: Check that cast is not redundant [redundant-cast]503172
+Ref: error_code_list2 check-that-cast-is-not-redundant-redundant-cast503424
+Ref: 2ac503424
+Node: Check that comparisons are overlapping [comparison-overlap]503890
+Ref: error_code_list2 check-that-comparisons-are-overlapping-comparison-overlap504142
+Ref: 2ad504142
+Node: Check that no untyped functions are called [no-untyped-call]505093
+Ref: error_code_list2 check-that-no-untyped-functions-are-called-no-untyped-call505357
+Ref: 2ae505357
+Node: Check that function does not return Any value [no-any-return]505832
+Ref: error_code_list2 check-that-function-does-not-return-any-value-no-any-return506119
+Ref: 2af506119
+Node: Check that types have no Any components due to missing imports [no-any-unimported]506677
+Ref: error_code_list2 check-that-types-have-no-any-components-due-to-missing-imports-no-any-unimported506967
+Ref: 2b0506967
+Node: Check that statement or expression is unreachable [unreachable]507787
+Ref: error_code_list2 check-that-statement-or-expression-is-unreachable-unreachable508067
+Ref: 2b1508067
+Node: Check that expression is redundant [redundant-expr]508758
+Ref: error_code_list2 check-that-expression-is-redundant-redundant-expr509033
+Ref: 2b2509033
+Node: Check that expression is not implicitly true in boolean context [truthy-bool]509733
+Ref: error_code_list2 check-that-expression-is-not-implicitly-true-in-boolean-context-truthy-bool510013
+Ref: 2b3510013
+Node: Check that # type ignore include an error code [ignore-without-code]511814
+Ref: error_code_list2 check-that-type-ignore-include-an-error-code-ignore-without-code512034
+Ref: 2b4512034
+Ref: error_code_list2 ignore-without-code512034
+Ref: 287512034
+Node: Additional features513030
+Ref: additional_features doc513162
+Ref: 2b5513162
+Ref: additional_features additional-features513162
+Ref: 2b6513162
+Node: Dataclasses513436
+Ref: additional_features dataclasses513527
+Ref: 2b7513527
+Ref: additional_features dataclasses-support513527
+Ref: 2b8513527
+Ref: Dataclasses-Footnote-1515094
+Ref: Dataclasses-Footnote-2515173
+Ref: Dataclasses-Footnote-3515255
+Ref: Dataclasses-Footnote-4515328
+Ref: Dataclasses-Footnote-5515387
+Node: Caveats/Known Issues515429
+Ref: additional_features caveats-known-issues515495
+Ref: 2b9515495
+Ref: Caveats/Known Issues-Footnote-1516697
+Ref: Caveats/Known Issues-Footnote-2516776
+Ref: Caveats/Known Issues-Footnote-3516856
+Ref: Caveats/Known Issues-Footnote-4516935
+Node: The attrs package517017
+Ref: additional_features attrs-package517159
+Ref: 2ba517159
+Ref: additional_features the-attrs-package517159
+Ref: 2bb517159
+Ref: The attrs package-Footnote-1518523
+Ref: The attrs package-Footnote-2518574
+Node: Caveats/Known Issues<2>518631
+Ref: additional_features id1518706
+Ref: 2bc518706
+Ref: Caveats/Known Issues<2>-Footnote-1519714
+Ref: Caveats/Known Issues<2>-Footnote-2519790
+Ref: Caveats/Known Issues<2>-Footnote-3519864
+Node: Using a remote cache to speed up mypy runs519926
+Ref: additional_features remote-cache520080
+Ref: 2a520080
+Ref: additional_features using-a-remote-cache-to-speed-up-mypy-runs520080
+Ref: 2bd520080
+Node: Shared repository for cache files521836
+Ref: additional_features shared-repository-for-cache-files521983
+Ref: 2be521983
+Node: Continuous Integration build522529
+Ref: additional_features continuous-integration-build522704
+Ref: 2bf522704
+Node: Mypy wrapper script523440
+Ref: additional_features mypy-wrapper-script523606
+Ref: 2c0523606
+Node: Caching with mypy daemon524538
+Ref: additional_features caching-with-mypy-daemon524687
+Ref: 2c1524687
+Node: Refinements525622
+Ref: additional_features refinements525743
+Ref: 2c2525743
+Node: Extended Callable types527773
+Ref: additional_features extended-callable527901
+Ref: 2c3527901
+Ref: additional_features extended-callable-types527901
+Ref: 2c4527901
+Ref: Extended Callable types-Footnote-1531752
+Ref: Extended Callable types-Footnote-2531822
+Ref: Extended Callable types-Footnote-3531892
+Ref: Extended Callable types-Footnote-4531962
+Ref: Extended Callable types-Footnote-5532032
+Node: Frequently Asked Questions532102
+Ref: faq doc532221
+Ref: 2c5532221
+Ref: faq frequently-asked-questions532221
+Ref: 2c6532221
+Node: Why have both dynamic and static typing?532843
+Ref: faq why-have-both-dynamic-and-static-typing532997
+Ref: 2c7532997
+Ref: Why have both dynamic and static typing?-Footnote-1534661
+Node: Would my project benefit from static typing?534694
+Ref: faq would-my-project-benefit-from-static-typing534910
+Ref: 2c8534910
+Node: Can I use mypy to type check my existing Python code?535982
+Ref: faq can-i-use-mypy-to-type-check-my-existing-python-code536205
+Ref: 2c9536205
+Node: Will static typing make my programs run faster?536628
+Ref: faq will-static-typing-make-my-programs-run-faster536844
+Ref: 2ca536844
+Node: How do I type check my Python 2 code?537256
+Ref: faq how-do-i-type-check-my-python-2-code537432
+Ref: 2cb537432
+Ref: How do I type check my Python 2 code?-Footnote-1537783
+Node: Is mypy free?537878
+Ref: faq is-mypy-free538039
+Ref: 2cc538039
+Node: Can I use duck typing with mypy?538215
+Ref: faq can-i-use-duck-typing-with-mypy538389
+Ref: 2cd538389
+Ref: Can I use duck typing with mypy?-Footnote-1540046
+Ref: Can I use duck typing with mypy?-Footnote-2540107
+Ref: Can I use duck typing with mypy?-Footnote-3540168
+Ref: Can I use duck typing with mypy?-Footnote-4540238
+Ref: Can I use duck typing with mypy?-Footnote-5540306
+Ref: Can I use duck typing with mypy?-Footnote-6540374
+Node: I like Python and I have no need for static typing540416
+Ref: faq i-like-python-and-i-have-no-need-for-static-typing540628
+Ref: 2ce540628
+Node: How are mypy programs different from normal Python?541111
+Ref: faq how-are-mypy-programs-different-from-normal-python541325
+Ref: 2cf541325
+Node: How is mypy different from Cython?542189
+Ref: faq how-is-mypy-different-from-cython542373
+Ref: 2d0542373
+Ref: How is mypy different from Cython?-Footnote-1544271
+Node: Does it run on PyPy?544323
+Ref: faq does-it-run-on-pypy544490
+Ref: 2d1544490
+Ref: Does it run on PyPy?-Footnote-1544801
+Node: Mypy is a cool project Can I help?544845
+Ref: faq mypy-is-a-cool-project-can-i-help544969
+Ref: 2d2544969
+Ref: Mypy is a cool project Can I help?-Footnote-1545499
+Node: Indices and tables545545
+Ref: index indices-and-tables545650
+Ref: 2d3545650
+Node: Index545717
+
+End Tag Table
+
+
+Local Variables:
+coding: utf-8
+End:
diff --git a/info/dir b/info/dir
index b07696cd..2c67b9a8 100644
--- a/info/dir
+++ b/info/dir
@@ -28,3 +28,4 @@ Miscellaneous
 * Invoke: (invoke.info).        One line description of project
 * Pytest: (pytest.info).        One line description of project
 * Sphinx: (sphinx.info).        One line description of project
+* Mypy: (Mypy.info).            One line description of project
