为os.DirEntry添加类型提示

时间:2018-02-10 15:51:41

标签: python python-3.x mypy

我正在努力为接受os.DirEntry对象的函数添加类型提示(这些由os.scandir()生成)。这是一个接受DirEntry个对象的简单访问者类:

class FileSystemVisitor:
    def visit_dir(self, entry) -> None:
        ...
    def visit_file(self, entry) -> None:
        ...

FileSystemVisitor的实例正被送到visit()函数,该函数遍历给定目录的子树:

def traverse(path: Union[str, pathlib.Path], visitor: FileSystemVisitor) -> None:
    for entry in os.scandir(str(path)):
        if entry.is_dir(follow_symlinks=False):
            visitor.visit_dir(entry)
            traverse(entry.path, visitor)
        else:
            visitor.visit_file(entry)

如何在entry函数中为FileSystemVisitor.visit_{dir(),file()}参数添加类型提示?我无法导入DirEntry

$ python3.5 -c "from os import DirEntry"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: cannot import name 'DirEntry'

我能想到的一件事是编写一个模仿DirEntry的虚拟类并将其用于类型提示:

class DirEntryType:
    name = None  # type: str
    path = None  # type: str

    def inode(self) -> int:
        ...
    def is_dir(self) -> bool:
        ...
    def is_file(self) -> bool:
        ...
    def is_symlink(self) -> bool:
        ...
    def stat(self) -> os.stat_result:
        ...

然而,是否只为聪明的类型提示添加了一个完整的类?

如果这很重要,我会遇到python3.5,因此无法使用python3.6的功能。

修改

正如avigil在评论中指出的那样,DirEntry可以导入python3.6

$ python3.6 -c "from os import DirEntry; print(DirEntry)"
<class 'posix.DirEntry'>

向后兼容的解决方案因此可以是例如:

# typing_utils.py

class DirEntryStub:
    name = None  # type: str
    path = None  # type: str

    def inode(self) -> int:
        raise NotImplementedError('This class is used for type hints only')
    def is_dir(self, follow_symlinks: bool = False) -> bool:
        raise NotImplementedError('This class is used for type hints only')
    def is_file(self, follow_symlinks: bool = False) -> bool:
        raise NotImplementedError('This class is used for type hints only')
    def is_symlink(self) -> bool:
        raise NotImplementedError('This class is used for type hints only')
    def stat(self) -> os.stat_result:
        raise NotImplementedError('This class is used for type hints only')

现在我可以输入FileSystemVisitor

try:
    from os import DirEntry
except ImportError:
    from typing_utils import DirEntryStub as DirEntry

class FileSystemVisitor:
    def visit_dir(self, entry: DirEntry) -> None:
        ...
    def visit_file(self, entry: DirEntry) -> None:
        ...

1 个答案:

答案 0 :(得分:1)

DirEntry在posix模块中的C中实现,但不幸的是,在3.6版本发布之前,它未在python中保留。有关相关的python bug跟踪器问题,请参阅bpo-27038

对于早期版本,您可以按照建议进行操作并将其删除,除非您足够谨慎地完成编译自己patched version的工作。由于scandir实现最初来自scandir包,可以修补并作为依赖项引入,以支持标准,因此实际上不会图书馆实施。