Skip to content

PEP Content

Rebecca Chen edited this page Jul 24, 2019 · 40 revisions

This page collects ideas for the content of the Type Stubs PEP. Please add to and adjust ideas freely.

Abstract

  • What are type stubs
    • Reference to PEP 484
    • Useful for modules without inline type hints
      • Because they are not desired
      • Because the module supports old versions of Python
      • Because they have not been implemented
      • Extension modules
  • What this PEP can do for type checker authors
    • Compliant type checkers are free to support additional constructs but should accept all the ones documented here. Accepting a construct means successfully parsing it; supporting the feature is not mandated.
    • It would be nice if deviations would be documented
  • What this PEP can do for stub authors

Syntax

  • Suffix .pyi
  • Syntax
    • Regular Python files
    • Python version? (#8)
    • Reference to PEP 526

What constructs are typically supported by type checkers

  • Which import formats
    • from x import * re-imports all names from a file
    • import x as x or from x import y as y re-exports a name
    • Imported sub-modules are re-exported
    • Otherwise follows standard import semantics
  • Module-level fields
  • Function definitions
    • Function bodies? (#7)
  • Class definitions
    • Nested classes
  • Aliasing
  • Platform and Python version checks
    • Supported boolean and comparison operators
    • Parentheses and binding
  • Special features
    • Enums
    • classmethod, staticmethod, abstractmethod, property (including .setter), overload, coroutine
    • NamedTuple
    • TypeVar
    • NewType
  • __getattr__, __setattr__
  • Module-level __getattr__()
  • How do type checkers handle unknown constructs?
  • Is __all__ meaningful in a stub? What does it do?
  • Forward references don't need quotes or a __future__ import
  • How to treat definitions with a leading underscore?
  • Callback protocols
  • Module-level asserts
  • @dataclass

What goes into a stub file

  • When to include private attributes
  • When to annotate self and cls
  • Whether to follow documented types or types accepted in reality. (Documentation may say a function takes "a list", but really it accepts any sequence or even iterable. What should the stub do?)
  • __getattr__, __setattr__: Don't include if they only allow limited fields
  • __getattr__: Include more specific methods and attributes as well
  • Use underscores and/or @typing.type_check_only for stub-only aliases
  • # undocumented
  • __getattr__() with and without # incomplete
  • Protocols

Style Guide

  • Use latest language features, even for older Python versions (e.g. variable annotations for Py 2 code)
  • Generally follow PEP 8, but with a few changes to make stubs more compact
  • Line length 130 characters
  • Function bodies should be just ... (per above) and one the same line as the colon
  • Don't use empty lines between functions, names, fields on a method or class level
  • Use one empty line for grouping and between classes (except for body-less classes)
  • No docstrings
  • Omit unnecessary details, such as actual default values for function parameters
  • Use explicit Optional[], instead of a None default
  • Use float instead of Union[int, float]
  • Prefer protocols and abstract types (Mapping, Sequence, Iterable etc.) in arguments and concrete types (List, Dict etc.) in return values
  • Avoid Union return types
  • Py 2: unicode vs Text
  • Py 3 only stubs: Don't use Text
  • Don't use quotes around forward references
  • Don't include __all__
  • Instances of a private class returned from a function: The stub should contain a public, stub-only class
  • Use foo: int without assignment for module-level attribute
  • Use class-based syntax for NamedTuple and TypedDict

Distributing

  • reference to PEP 561
  • Mention typeshed

Existing Tooling

Type Checkers

Other Tools