Automatically upgrade to the new type syntax introduced in PEP 695 using a single command
Project description
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 TypeVar
s, ParamSpec
s, TypeVarTuple
s 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 pep695
Using uv:
uv tool install pep695
Or if you want to run the tool immediately you can use:
uvx pep695
Usage
pep695
has 2 important commands for you to use on your codebase
pep695 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.
pep695 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.
You can also specify the --silent
(-s
) flag that silences the errors logged and only shows the number of errors reported.
pep695 format
Rewrite the code to the new type parameter syntax by running the format
subcommand. This will implement all the suggestions reported in pep695 check
, so running pep695 check
after pep695 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.
What pep695
does and what it doesn't
pep695
does:
- Remove assignments that instantiate
TypeVar
s,ParamSpec
s orTypeVarTuple
s fromtyping
ortyping_extensions
- Rewrite type alias statements that are annotated using
typing.TypeAlias
ortyping_extensions.TypeAlias
to atype
assigment e.g.:
import typing as t
StrOrInt: t.TypeAlias = str | int
is turned into
import typing as t
type StrOrInt = str | int
- Rewrite class definitions that use
TypeVar
s,ParamSpec
s orTypeVarTuple
s 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
TypeVar
s,ParamSpec
s orTypeVarTuple
s 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 = 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
ortyping_extensions.Generic
as base and the type subscript oftyping.Protocol
ortyping_extensions.Protocol
(class A(typing.Protocol[T])
->class A[T](typing.Protocol)
) - Correctly compile arguments passed in
TypeVar
,ParamSpec
orTypeVarTuple
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 specific type assignments, simply add a
# pep695-ignore
comment to the line e.g.:
import typing as t
T = t.TypeVar("T") # pep695-ignore
class A(t.Generic[T]): ...
will remain the exact same
pep695
does not:
- Remove unused imports once type assignments are removed, that's out of scope for this project.
- 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 pep695 format
.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pep695-0.0.1.tar.gz
.
File metadata
- Download URL: pep695-0.0.1.tar.gz
- Upload date:
- Size: 38.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.32.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3d0cca40719eca69b7a7b01730840a22ef29b727cf6646f0a80f3e61798af405 |
|
MD5 | 9837a7ddcd282261ae2df5d24840eac4 |
|
BLAKE2b-256 | 02dc86c7998175320ecac84f37993a1c836853b23c8c87647372d48e37e3f678 |
File details
Details for the file pep695-0.0.1-py3-none-any.whl
.
File metadata
- Download URL: pep695-0.0.1-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-requests/2.32.3
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 004e970422b84ea3593c382cd014f6d97213fe3dcadf5712438d3040dba13272 |
|
MD5 | 2dc695bae9a68891daeb30a591da794e |
|
BLAKE2b-256 | 3b3bd928d01913fa3107d0181cd40511447c3123a0f6db208cd7061764012d1d |