Совместимость хинтинга типа Python - PullRequest
0 голосов
/ 19 февраля 2019

Я пишу код, который обрабатывает узлы Python AST, который должен быть совместим как для Python 2, так и для Python 3.

Однако, Python 3 имеет ast.Try, где Python 2 имеет ast.TryFinally и ast.TryExcept, поэтому мне нужно использовать псевдонимы visit_ для обработки обоих случаев.

Если я напишу код посетителя узла с использованием псевдонимов совместимости, как показано ниже, моя проверка mypy перед фиксацией будет жаловаться при использовании Python 2, что error: Name 'ast.Try' is not defined:

import ast

class Visitor(ast.NodeVisitor):


    def visit_Try(self, node):  # type: (ast.Try) -> None
        ...
    visit_TryFinally = visit_Try  # python 2 compatible

Если я вместо этого использую ast.TryFinally в подсказке типа, он вместо этого будет жаловаться на error: Name 'ast.TryFinally' is not defined, если я запущу его в Python 3. Я знаю, что могу использовать болееобщий тип для узла, но это заставляет меня писать много кода # type: ignore в коде, который мне не нужен.

Как я могу решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Я думал, что вы можете создать скрипт, используя этот код

import sys
import ast

class visitor(ast.NodeVisitor):

    def visit_Try(self, node):
        ...

    if sys.version.startswith("2"):
        visit_TryFinally = visit_TryFinally
    elif sys.version.startswith("3"):
        visit_TryFinally = visit_Try

sys.version.startswith() проверяет версию Python.

0 голосов
/ 19 февраля 2019

Mypy знает , как обрабатывать проверки версий Python , и вы можете использовать условные псевдонимы типа , чтобы выбрать правильный тип для правильной версии Python:

if sys.version_info[0] >= 3:
    TryNode = ast.Try
else:
    TryNode = ast.TryFinally

class Visitor(ast.NodeVisitor):


    def visit_Try(self, node):  # type: (TryNode) -> None
        # ...
    visit_TryFinally = visit_Try  # python 2 compatible

Вы можете дополнительно сэкономить время выполнения тестов if sys.version_info, поместив этот код в if TYPE_CHECKING: тест .

В качестве примечания: если вы обрабатываете ast.Tryв Python 3 для отслеживания компонентов finally: и except ...: оператора try вы хотите обрабатывать как ast.TryFinally, так и ast.TryExcept в Python 2, так как до Python 2.5 вы могли использовать только try...finally или try...except в одном утверждении.

...