Skip to main content

A tool to automatically upgrade python code to the new type parameter syntax introduced in PEP 695

Rewriting your codebase manually to comply with PEP 695 can be very tiring and confusing, especially at a large scale as you have to keep track of all the TypeVars, ParamSpecs, TypeVarTuples used and more. This was also the motivation behind this project, which automatically rewrites any code using old type parameter syntax to the new type parameter syntax using square brackets [].

Installation

Using pip:

pip install autopep695

Using uv:

uv tool install autopep695

Or if you want to run the tool immediately you can use:

uvx autopep695

Usage

autopep695 has 2 important commands for you to use on your codebase

autopep695 check

Check whether the code makes use of the new type parameter syntax. If not, informative errors are shown that describe the problem (e.g. A class inherits from typing.Generic[T]) and include the "proper" implementation using the concepts described in PEP 695.

autopep695 check accepts multiple paths either pointing to a valid directory or a valid file that contains the code to be checked. A file is valid if it has one of the following extensions: .py, .pyi. Directories are traversed recursively.

Add the --report-assignments flag to enable type parameter assignment reports. Use --no-code to keep the output short and concise by removing code suggestions. You can also specify the --silent (-s) flag to silence the errors altogether and only show the number of errors reported.

autopep695 format

Rewrite the code to the new type parameter syntax by running the format subcommand. This will implement all the suggestions reported in autopep695 check, so running autopep695 check after autopep695 format will not report any errors. format however does not require you to run check beforehand, it just matches its behaviour.

It is recommended to specify the --parallel (-p) flag if you're running format against a large codebase as the tool is written in pure python and is not optimized for speed. This way, the workload is distributed across multiple subprocesses, each spawning a new python interpreter that formats the assigned files.

The following flags can be specified for additional features:

  • --remove-variance: Remove variance information from the name of the type parameter: T_co -> T, K_contra -> K.
  • --remove-private: Remove leading underscores that would have marked the type parameter as private: _T -> T, __T -> T, ...
  • --keep-assignments: Don't remove unused type parameter assignments

Excluding and including files

autopep695 by default ignores the following paths:
.bzr, .direnv, .eggs, .git, .git-rewrite, .hg, .mypy_cache, .nox, .pants.d, .pytype, .ruff_cache, .svn, .tox, .venv, __pypackages__, _build, buck-out, dist, node_modules, venv, __pycache__'

and includes the following file patterns: *.py, *.pyi

You can change this behaviour by specifying the --exclude and --include flags which take any number of patterns to match against. Typically you will want to use --extend-exclude or --extend-include though, especially if you just want to add patterns to exclude or include, for example a file extension in addition to .py and .pyi.

What autopep695 does and doesn't do

autopep695 does:

  • Remove assignments that instantiate TypeVars, ParamSpecs or TypeVarTuples from typing or typing_extensions
  • Rewrite type alias statements that are annotated using typing.TypeAlias or typing_extensions.TypeAlias to a type assigment e.g.:
import typing as t
StrOrInt: t.TypeAlias = str | int

is turned into

import typing as t
type StrOrInt = str | int

This rewrite is considered unsafe which is why you need to pass the --unsafe flag to autopep695 format for autopep695 to format TypeAlias annotated assignments.

  • Rewrite class definitions that use TypeVars, ParamSpecs or TypeVarTuples to conform to PEP 695 syntax e.g.:
import typing as t

K = t.TypeVar("K")
V = t.TypeVar("V")

class Map(dict[K, V]): ...

is rewritten into

import typing as t
class Map[K, V](dict[K, V]): ...
  • Rewrite function definitions that use TypeVars, ParamSpecs or TypeVarTuples to conform to PEP 695, as long as the type parameter is not inherited from the outer annotation scope e.g.
import typing as t
from collections.abc import Callable

T = t.TypeVar("T")
P = t.ParamSpec("P")

def func(callback: Callable[P, T]) -> T: ...

is converted to

import typing as t
from collections.abc import Callable

def func[T, **P](callback: Callable[P, T]) -> T: ...

and

import typing as t

T = t.TypeVar("T")

class Collection(t.Generic[T]):
    def add(self, item: T) -> None: ...

is correctly converted to

import typing as t

class Collection[T]():
    def add(self, item: T) -> None: ...
  • Remove typing.Generic or typing_extensions.Generic as base and the type subscript of typing.Protocol or typing_extensions.Protocol (class A(typing.Protocol[T]) -> class A[T](typing.Protocol))
  • Correctly compile arguments passed in TypeVar, ParamSpec or TypeVarTuple to the equivalent PEP 695 syntax e.g.:
import typing as t

class Undefined: ...

T = t.TypeVar("T", str, int, default=int)
UndefinedOr: t.TypeAlias = Undefined | T

is compiled to

import typing as t

class Undefined: ...

type UndefinedOr[T: (str, int) = int] = Undefined | T
  • allow you to ignore any type parameter related statement, simply add a # pep695-ignore comment to the line e.g.:
import typing as t

T = t.TypeVar("T")

class A(t.Generic[T]): ... # pep695-ignore

will remain the exact same.

import typing as t

T = t.TypeVar("T") # pep695-ignore
StrOr: t.TypeAlias = str | T

will compile to:

import typing as t

T = t.TypeVar("T") # pep695-ignore
type StrOr = str | T
  • account for codebases that mix old and new type parameter syntax, for those that found this tool in the midst of migrating
import typing as t

V = t.TypeVar("V")

class Hello[K](t.MutableMapping[K, V]):
    ...

is translated to:

import typing as t

class Hello[K, V](t.MutableMapping[K, V]):
    ...

autopep695 does not:

  • Remove unused imports once type assignments are removed, that's out of scope for this project.
  • Fix imports that try to import a type parameter variable from another module which has been deleted after running autopep695 format
  • Does not neccesarily follow the style of your next best linter

It is best to format the code with a tool like ruff after running autopep695 format.

Contributing to autopep695

If you would like to contribute, please read the contributing manual

Release files for autopep695 1.1.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for autopep695 1.1.4
File Size Uploaded
autopep695-1.1.4.tar.gz 65.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for autopep695 1.1.4
File Interpreter ABI Platform
autopep695-1.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 92.0 kB

Release files / autopep695-1.1.4.tar.gz

Download URL autopep695-1.1.4.tar.gz
Size 65.9 kB
Tags Source
SHA-256 checksum
How to use checksums
abf1cb7512af32c2166e4c541df7d66d0c4651315ffc00c33aa5d09194903fe2
BLAKE2b-256 checksum
How to use checksums
6b3298857ddd5a8a3f52e7610a0020c5853e94eedfe1870f2bf9d9e39b659506
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.3

Release files / autopep695-1.1.4-py3-none-any.whl

Download URL autopep695-1.1.4-py3-none-any.whl
Size 26.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
64581d52d32b977363f28bbc1fa2f2b644ebbe0254a855a74593e0f75fd8d84c
BLAKE2b-256 checksum
How to use checksums
8e53c2e5bfdd97b8499acbdfbb220c3f789d929753bc521cd3db2335a18ed713
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via python-requests/2.32.3

Release history Release notifications | RSS feed

This release

1.1.4 This release

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page