mypy 在错误使用从外部包导入的函数时不会检测到错误

问题描述 投票:0回答:1

我运行了一个简单的实验,创建了一个非常简单的 python 包,其中包含以下文件:
在文件夹

my_package

# example.py
def foo(number: int, text: str) -> None:
    print(number)
    print(text)

__init__.py

在根文件夹中,有一个

setup.py
文件:

from setuptools import setup

setup(
    name='ExamplePackage',
    version='0.1.0',
    author='An Awesome Coder',
    author_email='[email protected]',
    packages=['my_package'],
    description='An awesome package that does something',
)

使用

python ./setup.py bdist_wheel
构建包后,我已将
.whl
文件复制到另一个 python 项目,运行
pip install ExamplePackage-0.1.0-py3-none-any.whl
并创建以下文件
main.py

from my_package.example import foo

# No mypy errors at all!
x = foo()

def internal_foo(number: int, text: str) -> None:
    print(number)
    print(text)


# Missing positional arguments "number", "text" in call to "internal_foo"  [call-arg]
# "internal_foo" does not return a value  [func-returns-value]
y = internal_foo()

我的

mypy.ini
看起来像这样:

[mypy]
ignore_missing_imports = True
show_error_codes = True
strict = True
check_untyped_defs = True
raise_exceptions = True

我很难理解为什么 mypy 可以轻松推断导入的

foo
函数的签名,但不会显示任何有关错误用法的错误

任何帮助将不胜感激

python python-typing mypy
1个回答
2
投票

根据PEP-561(规范包类型数据使用的Python标准),有两种声明包类型的通用方法。

第一个(适用于您的情况)是

py.typed
标记。它是一个名为
py.typed
的空文件,放置在包根目录中(与最顶层
__init__.py
所在的位置相同;对于命名空间包,更喜欢将
py.typed
添加到每个子模块以避免不一致的解释)。它声明包包含内联类型信息。

重要的是不要忘记将其添加为包数据。您需要将其添加为

MANIFEST.in
条目 + 启用它所需的任何配置 - 对于基于
pyproject.toml
的软件包没有任何内容,
include_package_data = True
用于
setup.py
setup.cfg
,对于非 setuptools 发行版还有其他内容(类似?) (诗歌、轻快、孵化或出于某种原因你需要的任何东西)。或者,它可以在
[tool.setuptools.package-data]
pyproject.toml
部分、
package_data
中的
setup.py
[options.package_data]
中的
setup.cfg
以及其他构建系统的类似声明中声明。还有其他选项,例如带有适当插件的 VCS 集成(来自
.gitignore
和类似文件),请参阅 setuptools 文档 here 或您选择的系统的文档。

另一个受支持的解决方案是使用存根文件 - 这些是带有

.pyi
扩展名的单独文件,仅提供函数/方法和变量/属性的类型。它们具有更高的优先级(例如,如果同时存在存根和
py.typed
,则使用存根类型),但这种情况不应该发生(如果代码可以内联注释,则不需要单独的存根)。存根包被命名为
<package>-stubs
。还有“并排”方法,允许将
.py
.pyi
彼此靠近。

© www.soinside.com 2019 - 2024. All rights reserved.