扳机
在我参与的一个项目中,有一个从 Python 操作 COM 的脚本。
为了处理那里发生的错误,我经常编写如下代码。
from _ctypes import COMError
try:
...
except COMError as e:
...
但,_ctypes 没有类型存根,所以在导入时就发出了 VSCode 的 pylance (pyright) 错误,即使被抑制了,COMError 也被视为 Unknown。
结果异常的信息没有传递给类型检查器,如果有COMError,类型检查器就会发出警告,很难做到。
很长一段时间我都把这种情况视作无可奈何,但我参与这个项目已经快两年了,我终于受不了了。
所以我决定为typeshed 做出贡献,他正在为 Python 库整理类型存根。
关于typeshed
有关角色描述,请参阅 PEP484。
https://peps.python.org/pep-0484/#the-typeshed-repo
点击这里翻译
问题讨论
现在,我犹豫要不要突然为一个模块添加一个存根,更不用说在标准库中公开某些内容而不与其他贡献者共享信息。
所以,我提出了一个问题,首先告诉他们我想做什么,然后问他们这与什么情况有关。
在我的项目中,我使用了一些 COM-ffi 包。
_ctypes.COMError和_ctypes.CopyComPointer也使用mypy类型检查器可以抛出Cannot find implementation or library stub for module named "_ctypes"错误,因为它们没有定义类型存根。我想添加这样的类型存根。
# githubのissueカンバンにあるスニペット但我对这些以外的 API 了解不多。
- 哪里需要
if sys.platform == "win32":?如果您有任何意见,请告诉我。
之后,贡献者
typeshed给了我各种建议。
下面是一个总结。
欢迎 PR
![]()
stdlib/下面已经有很多类似_foo.pyi的模块
- 阅读
CONTRIBUTING.md并将_ctypes标记为不完整- 我已经验证Linux环境下不存在COM元素,所以COM关系在
if sys.platform == "win32":下已定义为
stdlib/ctypes/__init__.pyi的元素实际上在运行时定义为_ctypes。如果添加了_ctypes存根,我认为最好将它移动到运行时(尽管第一个 PR 是最小的并且可以)请在
stdlib/VERSIONS中包含_ctypes信息公关合并前的故事
我根据建议做了一个存根并做了一个 PR。
存根中的文档字符串是不需要的,并且经过审查和修复以将其删除。
但是,即使在修复之后,CI 仍然无法正常工作!
看到CI报错信息,我很生气,原来在runtime中定义的
_ctypes._Pointer等都不在了。
CONTRIBUTING.md说,“当你创建一个不完整的存根时,在模块级别定义def __getattr__(name: str) -> Any: ... # incomplete。”当我不知所措时,审稿人指出了各种更正。
stubtest和allowlist的存在
stubtest是一个与类型检查器捆绑在一起的测试,例如mypy,它将运行时实现的命名空间与类型存根进行比较,如果类型存根丢失,则失败。大纲写在下面的问题“1)使用stubtest查找stubs中缺少的东西或有问题的东西。”
就这样,reviewer 将每个尚未添加到 stub 的对象添加到
allowlist,CI 通过并合并。现在的情况
mypy和pylance现在包括存根更新,不再是Unknown!
在那之后
我将继续致力于使存根与运行时定义保持同步。
其中,难免会出现循环导入,所以提了一个问题,咨询了下。
在类型存根中,即使进行循环导入也没有问题,与运行时不同,不会发生错误。我松了口气,因为我得到了答案,我即将发布PR来一点一点地移动定义。
但是,目前(截至 2022 年 9 月 20 日),即使您将定义写入
_ctypes并写入存根以导入到ctypes,pytype测试失败且 CI 未通过.
对此,pytype这边已经提了一个问题,计划近期更正。
(以上问题解决后)我们期待您的贡献。
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308626377.html