Python类型存根的回滚版本
项目描述
unpy
统一Python
将Python 3.13的.pyi
存根转换到Python 3.10
[!IMPORTANT] 此项目处于alpha阶段:您可能不应该在生产环境中使用它。
安装
$ pip install unpy
使用
$ unpy --help
Usage: unpy [OPTIONS] SOURCE [OUTPUT]
Arguments:
SOURCE Path to the input .pyi file or '-' to read from stdin. [required]
[OUTPUT] Path to the output .pyi file. Defaults to stdout.
Options:
--version Show the version and exit
--diff Show the changes between the input and
output in unified diff format
--target [3.10|3.11|3.12|3.13] The minimum Python version that should be
supported. [default: 3.10]
--help Show this message and exit.
示例
一些Python 3.13存根的简单示例,这些存根被回滚到Python 3.10。
导入
$ unpy --target 3.10 --diff examples/imports.pyi
+++ -
@@ -1,6 +1,4 @@
- from types import CapsuleType
- from typing import override
- from warnings import deprecated
+ from typing_extensions import CapsuleType, deprecated, override
@deprecated("RTFM")
class Spam:
__pyx_capi__: dict[str, CapsuleType]
@override
def __hash__(self, /) -> int: ...
注意生成的导入的字母顺序。
类型别名
$ unpy --target 3.10 --diff examples/type_aliases.pyi
+++ -
@@ -1,7 +1,15 @@
from collections.abc import Callable
+ from typing import ParamSpec, TypeAlias, TypeVar
+ from typing_extensions import TypeAliasType, TypeVarTuple, Unpack
- type Binary = bytes | bytearray | memoryview
- type Vector[R: float] = tuple[R, ...]
- type tciD[V, K] = dict[K, V]
- type Things[*Ts] = tuple[*Ts]
- type Callback[**Tss] = Callable[Tss, None]
+ _R = TypeVar("_R", bound=float)
+ _V = TypeVar("_V")
+ _K = TypeVar("_K")
+ _Ts = TypeVarTuple("_Ts")
+ _Tss = ParamSpec("_Tss")
+
+ Binary: TypeAlias = bytes | bytearray | memoryview
+ Vector: TypeAlias = tuple[_R, ...]
+ tciD = TypeAliasType("tciD", dict[_K, _V], type_params=(_V, _K))
+ Things: TypeAlias = tuple[Unpack[_Ts]]
+ Callback: TypeAlias = Callable[_Tss, None]
请注意,TypeAlias
不能与tciD
一起使用,因为类型参数(在左侧)的定义顺序与它们被访问(在右侧)的顺序不匹配,必须使用回滚的TypeAliasType
。
函数
$ unpy --target 3.10 --diff examples/functions.pyi
+++ -
@@ -1,6 +1,11 @@
+ _T = TypeVar("_T")
+ _S = TypeVar("_S", str, bytes)
+ _X = TypeVar("_X")
+ _Theta = ParamSpec("_Theta")
+ _Y = TypeVar("_Y")
from collections.abc import Callable as Def
- from typing import Concatenate as Concat
+ from typing import Concatenate as Concat, ParamSpec, TypeVar
- def noop[T](x: T, /) -> T: ...
- def concat[S: (str, bytes)](left: S, right: S) -> S: ...
- def curry[X, **Theta, Y](f: Def[Concat[X, Theta], Y], /) -> Def[[X], Def[Theta, Y]]: ...
+ def noop(x: _T, /) -> _T: ...
+ def concat(left: _S, right: _S) -> _S: ...
+ def curry(f: Def[Concat[_X, _Theta], _Y], /) -> Def[[_X], Def[_Theta, _Y]]: ...
泛型类和协议
$ unpy --target 3.10 --diff examples/generics.pyi
+++ -
@@ -1,17 +1,25 @@
- from typing import Protocol, overload
+ from typing import Generic, Protocol, overload
+ from typing_extensions import TypeVar
+
+ _T_contra = TypeVar("_T_contra", contravariant=True)
+ _T_co = TypeVar("_T_co", covariant=True)
+ _T = TypeVar("_T", infer_variance=True)
+ _D = TypeVar("_D")
+ _NameT = TypeVar("_NameT", infer_variance=True, bound=str)
+ _QualNameT = TypeVar("_QualNameT", infer_variance=True, bound=str, default=_NameT)
class Boring: ...
- class CanGetItem[T_contra, T_co](Protocol):
- def __getitem__(self, k: T_contra, /) -> T_co: ...
+ class CanGetItem(Protocol[_T_contra, _T_co]):
+ def __getitem__(self, k: _T_contra, /) -> _T_co: ...
- class Stack[T]:
- def push(self, value: T, /) -> None: ...
+ class Stack(Generic[_T, _D]):
+ def push(self, value: _T, /) -> None: ...
@overload
- def pop(self, /) -> T: ...
+ def pop(self, /) -> _T: ...
@overload
- def pop[D](self, default: D, /) -> T | D: ...
+ def pop(self, default: _D, /) -> _T | _D: ...
- class Named[NameT: str, QualNameT: str = NameT]:
- __name__: NameT
- __qualname__: QualNameT
+ class Named(Generic[_NameT, _QualNameT]):
+ __name__: _NameT
+ __qualname__: _QualNameT
注意这里如何(仅)从typing_extensions
导入TypeVar
,这与上一个示例不同。这是由于添加了infer_variance
参数的结果,该参数在Python 3.12中已添加。
项目目标
这是unpy
潜在目标的初步想法的原型草图的alpha版本。
- 回顾过去
- 在存根scipy时感到沮丧
- 将Python 3.13的
.pyi
存根转换为Python 3.10存根 - 包级分析和转换
- 仅存根项目的集成工具
- 在
scipy-stubs
中使用此功能 - 逐步引入到
numpy
- 面向未来
- 超越Python: $\text{Unpy} \supset \text{Python}$
- 为所有
.py
项目提供语言支持和工具
- 相互靠近
- 统一类型检查:快速、合理且语言无关
功能
工具
- 目标Python版本
-
3.13
-
3.12
-
3.11
-
3.10
-
3.9
-
- 语言支持
-
.pyi
-
.py
-
- 转换
- stdin => stdout
- module => module
- package => package
- project => project (包括
pyproject.toml
)
- 配置
-
--diff
: 统一差异 -
--target
: 目标Python版本,默认为3.10
- 在
pyproject.toml
下的[tools.unpy]
中进行基于项目的配置 - ...
-
- 集成
- 文件监视器
- Pre-commit
- LSP
- UV
- VSCode 扩展
- (基于)mypy 插件
- 项目构建工具
- 可配置的类型检查器集成
- 可配置的格式化器集成,例如
ruff format
- 性能
- 限制转换到已更改的文件
存根回退
- Python 3.13 => 3.12
- PEP 742
typing.TypeIs
=>typing_extensions.TypeIs
- PEP 705
typing.ReadOnly
=>typing_extensions.ReadOnly
- PEP 702
warnings.deprecated
=>typing_extensions.deprecated
- PEP 696
- 回退带有默认值的 PEP 695 类型签名
typing.NoDefault
=>typing_extensions.NoDefault
- 异常
asyncio.QueueShutDown
=>builtins.Exception
pathlib.UnsupportedOperation
=>builtins.NotImplementedError
queue.ShutDown
=>builtins.Exception
re.PatternError
=>re.error
- 类型
types.CapsuleType
=>typing_extensions.CapsuleType
typing.{ClassVar,Final}
=>typing_extensions.{ClassVar,Final}
当嵌套时
- PEP 742
- Python 3.12 => 3.11
- Python 3.11 => 3.10
- PEP 681
typing.dataclass_transform
=>typing_extensions.dataclass_transform
- PEP 675
typing.LiteralString
=>typing_extensions.LiteralString
- PEP 673
typing.Self
=>typing_extensions.Self
- PEP 655
typing.[Not]Required
=>typing_extensions.[Not]Required
- PEP 654
builtins.BaseExceptionGroup
builtins.ExceptionGroup
- PEP 646
typing.TypeVarTuple
=>typing_extensions.TypeVarTuple
typing.Unpack
=>typing_extensions.Unpack
*Ts
=>typing_extensions.Unpack[Ts]
withTs: TypeVarTuple
asyncio
asyncio.TaskGroup
enum
enum.ReprEnum
=>enum.Enum
enum.StrEnum
=>str & enum.Enum
typing
typing.Any
=>typing_extensions.Any
if subclassed (not recommended)
- PEP 681
- 生成的
TypeVar
- 如果有相同名称且等效的提取类型变量,则去重
- 提取类型变量名称前缀为
_
- 重命名具有相同名称的不兼容类型变量(jorenham/unpy#86)
简化与重构
- 泛型类型参数
- 将
default=Any
与bound=T
转换为default=T
- 删除
bound=Any
和bound=object
- 推断 PEP 695 类型参数的方差(jorenham/unpy#44)
- 如果从未使用,它是多余的(且二价)
- 如果指定了约束,则是
invariant
- 如果后缀为
_co
/_contra
,则是covariant
/contravariant
- 如果用作公共实例属性,则是
invariant
- 如果仅用作返回类型(不包括
__init__
和__new__
),或用于只读属性,则是covariant
- 如果仅用作参数类型,则是
contravariant
- 否则,假设它是
invariant
- 将
- 方法
- 特定“特殊方法”的默认返回类型(jorenham/unpy#55)
- 将
self
方法参数转换为仅位置参数
- 类型运算符
-
type[S] | type[T]
=>type[S | T]
- 平展并去重字面量联合
- 移除冗余联合值,例如
bool | int
=>int
-
超越 Python
项目详情
下载文件
下载适用于您平台的应用程序。如果您不确定要选择哪个,请了解更多关于 安装包 的信息。
源分发
unpy-0.3.0.tar.gz (29.8 kB 查看哈希值)
构建分发
unpy-0.3.0-py3-none-any.whl (29.1 kB 查看哈希值)