Movatterモバイル変換


[0]ホーム

URL:


Following system colour schemeSelected dark colour schemeSelected light colour scheme

Python Enhancement Proposals

PEP 561 – Distributing and Packaging Type Information

Author:
Emma Harper Smith <emma at python.org>
Status:
Final
Type:
Standards Track
Topic:
Packaging, Typing
Created:
09-Sep-2017
Python-Version:
3.7
Post-History:
10-Sep-2017, 12-Sep-2017, 06-Oct-2017, 26-Oct-2017, 12-Apr-2018

Table of Contents

Important

This PEP is a historical document: seeType information in libraries for up-to-date specs and documentation. Canonical typing specs are maintained at thetyping specs site; runtime typing behaviour is described in the CPython documentation.

×

See thetyping specification update process for how to propose changes to the typing spec.

Abstract

PEP 484 introduced type hinting to Python, with goals of making typinggradual and easy to adopt. Currently, typing information must be distributedmanually. This PEP provides a standardized means to leverage existing toolingto package and distribute type information with minimal work and an orderingfor type checkers to resolve modules and collect this information for typechecking.

Rationale

Currently, package authors wish to distribute code that has inline typeinformation. Additionally, maintainers would like to distribute stub filesto keep Python 2 compatibility while using newer annotation syntax. However,there is no standard method to distribute packages with type information.Also, if one wished to ship stub files privately the only method availablewould be via settingMYPYPATH or the equivalent to manually point tostubs. If the package can be released publicly, it can be added totypeshed[1]. However, this does not scale and becomes a burden on themaintainers of typeshed. In addition, it ties bug fixes in stubs to releasesof the tool using typeshed.

PEP 484 has a brief section on distributing typing information. In thissectionthe PEP recommends usingshared/typehints/pythonX.Y/ forshipping stub files. However, manually adding a path to stub files for eachthird party library does not scale. The simplest approach people have takenis to addsite-packages to theirMYPYPATH, but this causes typecheckers to fail on packages that are highly dynamic (e.g. sqlalchemyand Django).

Definition of Terms

The definition of “MAY”, “MUST”, and “SHOULD”, and “SHOULD NOT” areto be interpreted as described inRFC 2119.

“inline” - the types are part of the runtime code usingPEP 526 andPEP 3107 syntax (the filename ends in.py).

“stubs” - files containing only type information, empty of runtime code(the filename ends in.pyi).

“Distributions” are the packaged files which are used to publish and distributea release. (PEP 426)

“Module” a file containing Python runtime code or stubbed type information.

“Package” a directory or directories that namespace Python modules.(Note the distinction between packages and distributions. While mostdistributions are named after the one package they install, somedistributions install multiple packages.)

Specification

There are several motivations and methods of supporting typing in a package.This PEP recognizes three types of packages that users of typing wish tocreate:

  1. The package maintainer would like to add type information inline.
  2. The package maintainer would like to add type information via stubs.
  3. A third party or package maintainer would like to share stub files fora package, but the maintainer does not want to include them in the sourceof the package.

This PEP aims to support all three scenarios and make them simple to add topackaging and deployment.

The two major parts of this specification are the packaging specificationsand the resolution order for resolving module type information. The typechecking spec is meant to replace theshared/typehints/pythonX.Y/spec of PEP 484.

New third party stub libraries SHOULD distribute stubs via the third partypackaging methods proposed in this PEP in place of being added to typeshed.Typeshed will remain in use, but if maintainers are found, third party stubsin typeshed MAY be split into their own package.

Packaging Type Information

In order to make packaging and distributing type information as simple andeasy as possible, packaging and distribution is done through existingframeworks.

Package maintainers who wish to support type checking of their code MUST adda marker file namedpy.typed to their package supporting typing. This marker appliesrecursively: if a top-level package includes it, all its sub-packages MUST supporttype checking as well. To have this file installed with the package,maintainers can use existing packaging options such aspackage_data indistutils, shown below.

Distutils option example:

setup(...,package_data={'foopkg':['py.typed'],},...,)

For namespace packages (seePEP 420), thepy.typed file should be in thesubmodules of the namespace, to avoid conflicts and for clarity.

This PEP does not support distributing typing information as part ofmodule-only distributions or single-file modules within namespace packages.

The single-file module should be refactored into a packageand indicate that the package supports typing as describedabove.

Stub-only Packages

For package maintainers wishing to ship stub files containing all of theirtype information, it is preferred that the*.pyi stubs are alongside thecorresponding*.py files. However, the stubs can also be put in a separatepackage and distributed separately. Third parties can also find this methoduseful if they wish to distribute stub files. The name of the stub packageMUST follow the schemefoopkg-stubs for type stubs for the package namedfoopkg. Note that for stub-only packages adding apy.typed marker is notneeded since the name*-stubs is enough to indicate it is a source of typinginformation.

Third parties seeking to distribute stub files are encouraged to contact themaintainer of the package about distribution alongside the package. If themaintainer does not wish to maintain or package stub files or type informationinline, then a third party stub-only package can be created.

In addition, stub-only distributions SHOULD indicate which version(s)of the runtime package are supported by indicating the runtime distribution’sversion(s) through normal dependency data. For example, thestub packageflyingcircus-stubs can indicate the versions of theruntimeflyingcircus distribution it supports throughinstall_requiresin distutils-based tools, or the equivalent in other packaging tools. Note thatin pip 9.0, if you updateflyingcircus-stubs, it will updateflyingcircus. In pip 9.0, you can use the--upgrade-strategy=only-if-needed flag. In pip 10.0 this is the defaultbehavior.

For namespace packages (seePEP 420), stub-only packages shoulduse the-stubs suffix on only the root namespace package.All stub-only namespace packages should omit__init__.pyi files.py.typedmarker files are not necessary for stub-only packages, but similarlyto packages with inline types, if used, they should be in submodules of the namespace toavoid conflicts and for clarity.

For example, if thepentagon andhexagon are separate distributionsinstalling within the namespace packageshapes.polygonsThe corresponding types-only distributions should produce packageslaid out as follows:

shapes-stubs└── polygons    └── pentagon        └── __init__.pyishapes-stubs└── polygons    └── hexagon        └── __init__.pyi

Type Checker Module Resolution Order

The following is the order in which type checkers supporting this PEP SHOULDresolve modules containing type information:

  1. Stubs or Python source manually put in the beginning of the path. Typecheckers SHOULD provide this to allow the user complete control of whichstubs to use, and to patch broken stubs/inline types from packages.In mypy the$MYPYPATH environment variable can be used for this.
  2. User code - the files the type checker is running on.
  3. Stub packages - these packages SHOULD supersede any installed inlinepackage. They can be found atfoopkg-stubs for packagefoopkg.
  4. Packages with apy.typed marker file - if there is nothing overridingthe installed package,and it opts into type checking, the typesbundled with the package SHOULD be used (be they in.pyi typestub files or inline in.py files).
  5. Typeshed (if used) - Provides the stdlib types and several third partylibraries.

If typecheckers identify a stub-only namespace package without the desired modulein step 3, they should continue to step 4/5. Typecheckers should identify namespace packagesby the absence of__init__.pyi. This allows different subpackages toindependently opt for inline vs stub-only.

Type checkers that check a different Python version than the version they runon MUST find the type information in thesite-packages/dist-packagesof that Python version. This can be queried e.g.pythonX.Y-c'importsite;print(site.getsitepackages())'. It is also recommendedthat the type checker allow for the user to point to a particular Pythonbinary, in case it is not in the path.

Partial Stub Packages

Many stub packages will only have part of the type interface for librariescompleted, especially initially. For the benefit of type checking and codeeditors, packages can be “partial”. This means modules not found in the stubpackage SHOULD be searched for in parts four and five of the module resolutionorder above, namely inline packages and typeshed.

Type checkers should merge the stub package and runtime package or typesheddirectories. This can be thought of as the functional equivalent of copying thestub package into the same directory as the corresponding runtime package ortypeshed folder and type checking the combined directory structure. Thus typecheckers MUST maintain the normal resolution order of checking*.pyi before*.py files.

If a stub package distribution is partial it MUST includepartial\n in apy.typed file. For stub-packages distributing within a namespacepackage (seePEP 420), thepy.typed file should be in thesubmodules of the namespace.

Type checkers should treat namespace packages within stub-packages asincomplete since multiple distributions may populate them.Regular packages within namespace packages in stub-package distributionsare considered complete unless apy.typed withpartial\n is included.

Implementation

The proposed scheme of indicating support for typing is completely backwardscompatible, and requires no modification to package tooling. A sample packagewith inline types is available[typed_package], as well as a[stub_package]. Asample package checker[pkg_checker] which reads the metadata of installedpackages and reports on their status as either not typed, inline typed, or astub package.

The mypy type checker has an implementation ofPEP 561 searching which can beread about in the mypy docs[4].

[numpy-stubs] is an example of a real stub-only package for the numpydistribution.

Acknowledgements

This PEP would not have been possible without the ideas, feedback, and supportof Ivan Levkivskyi, Jelle Zijlstra, Alyssa Coghlan, Daniel F Moisset, AndreyVlasovskikh, Nathaniel Smith, and Guido van Rossum.

Version History

  • 2023-01-13
    • Clarify that the 4th step of theModule Resolution Order appliesto any package with apy.typed marker file (and not justinline packages).
  • 2021-09-20
    • Clarify expectations and typechecker behavior for stub-only namespace packages
    • Clarify handling of single-file modules within namespace packages.
  • 2018-07-09
    • Add links to sample stub-only packages
  • 2018-06-19
    • Partial stub packages can look at typeshed as well as runtime packages
  • 2018-05-15
    • Add partial stub package spec.
  • 2018-04-09
    • Add reference to mypy implementation
    • Clarify stub package priority.
  • 2018-02-02
    • Change stub-only package suffix to be -stubs not _stubs.
    • Note that py.typed is not needed for stub-only packages.
    • Add note about pip and upgrading stub packages.
  • 2017-11-12
    • Rewritten to use existing tooling only
    • No need to indicate kind of type information in metadata
    • Name of marker file changed from.typeinfo topy.typed
  • 2017-11-10
    • Specification re-written to use package metadata instead of distributionmetadata.
    • Removed stub-only packages and merged into third party packages spec.
    • Removed suggestion for typecheckers to consider checking runtime versions
    • Implementations updated to reflect PEP changes.
  • 2017-10-26
    • Added implementation references.
    • Added acknowledgements and version history.
  • 2017-10-06
    • Rewritten to use .distinfo/METADATA over a distutils specific command.
    • Clarify versioning of third party stub packages.
  • 2017-09-11
    • Added information about current solutions and typeshed.
    • Clarify rationale.

References

[1]
Typeshed (https://github.com/python/typeshed)
[4]
Example implementation in a type checker(https://mypy.readthedocs.io/en/latest/installed_packages.html)
[stub_package]
A stub-only package(https://github.com/emmatyping/stub-package)
[typed_package]
Sample typed package(https://github.com/emmatyping/pep-561)
[numpy-stubs]
Stubs for numpy(https://github.com/numpy/numpy-stubs)
[pkg_checker]
Sample package checker(https://github.com/emmatyping/check_typedpkg)

Copyright

This document has been placed in the public domain.


Source:https://github.com/python/peps/blob/main/peps/pep-0561.rst

Last modified:2025-02-01 08:55:40 GMT


[8]ページ先頭

©2009-2025 Movatter.jp