2017-04-20 60 views
0

我一直在将类型信息添加到我的包的.py文件中,以支持对包的运行mypy。除此之外,允许为此第三方包生成typeshed信息。在不依赖打字模块的情况下添加类型信息

由于我的包必须是Python 2.7版兼容,我用注释的类型信息:

def __init__(self, s): 
    # type: (Text) -> None 

但为了运行mypy这需要我来导入打字:

from typing import Text, IO, BinaryIO, Union 

这导致两个问题:

  1. 这不适用于Python 3.5.0和3.5.1,因为它有一个模块typing但不包括Text。从PyPI安装typing不能解决这个问题。 (并且有些用户在该版本的Python上运行该软件包)。

  2. 这使得我的软件包依赖于typing进行2.7/3.3/3.4安装,需要额外的下载和安装。

  3. 我有我自己的Union类型定义:

    StreamType = Union[BinaryIO, IO[str], StringIO] 
    StreamTextType = Union[Text, StreamType] 
    

    的代码,这将不得不依赖于打字是用或不被有条件地执行。

对于第一个问题,因为我不Python的3.5.0/1下运行mypy,我可以这样做:

import sys 
if sys.version_info < (3, 5, 0) and sys.version_info >= (3, 5, 2): 
    from typing import Text, IO, BinaryIO, Union 

但这并不解决第二个问题。

注释掉import,就像是在注释类型的信息,

# from typing import Text, IO, BinaryIO, Union 

会导致mypy抛出异常Name 'Text' is not defined

第三个问题可以通过使用try-except(丑陋的,也许还是低效的)或例如通过测试一个环境变量(也可以用来解决第一个问题)。

运行时是否设置了环境变量mypy,我可以测试一下,这样导入语句只在运行mypy时执行? 根据环境变量进行测试也可以让我把我自己的类型的定义放在“守护”的范围内。

或其他一些解决方案?

回答

2

mypy相关联的唯一环境变量是MYPYPATH,并且由包的代码读取,而不是由其设置。虽然可能会设置MYPYPATH(尤其是在生成typeshed信息时,要提供“其他”类型的信息),但不能保证它是。

你不能注释掉import语句,但你可以把它从未执行块:

if False: # MYPY 
    from typing import Text, IO, BinaryIO, Union 

这有你没有导入os得到的好处环境变量(和/或sys得到version_info),如果你在你的特定Python文件中没有其他需要的话。

你的类型定义应像被指定为良好,并且在所有的使用的类型的已导入或定义可以在任何地方发生:

# import or define StringIO 

if False: # MYPY 
    StreamType = Union[BinaryIO, IO[str], StringIO] 
    StreamTextType = Union[Text, StreamType] 

如果上述是在mytypes.py,在任何其他的源文件你的包,在任何类型定义的使用StreamTypeText,应做到:

if False: # MYPY 
    from typing import Text, IO, BinaryIO, Union 
    from .mytypes StreamType 

以上将满足mypy,所以它不会对抛出一个错误10没有被定义。它也将在3.5.0/1工作,obliviates需要使你的包依赖typing

你可能还需要安装typing如果你要在Python 2.7环境中运行mypy,但你的正常包的用户不受此影响。

请注意,我在每个块的if之后添加了注释# MYPY。搜索from typing的文件很容易,但如果mypy更改其行为并且您的代码需要适应,那么StreamType的块不会很容易找到。

相关问题