Подсказка правильного типа для атрибута IntEnum dataclass?

#python #enums #pycharm #python-typing #python-dataclasses

#python #перечисления #pycharm #python-типизация #python-классы данных

Вопрос:

Я создаю класс данных в 3.8.8 для хранения результата от вызова REST API, и один из его атрибутов используется для хранения статуса HTTP-ответа:

 from dataclasses import dataclass
from http import HTTPStatus


@dataclass
class APICallResult:
    response_text: str
    http_status: HTTPStatus
 

Когда я пытаюсь создать объект этого класса, как показано ниже:

 result = APICallResult('foo', HTTPStatus.OK)
 

PyCharm 2020.3.3 просто выдает HTTPStatus.OK ошибку:

 Expected type 'HTTPStatus', got 'int' instead`.
 

Теперь мне интересно, для чего IntEnum в этом случае нужна подсказка правильного типа? Я думаю Literal , что здесь может быть неудобный вариант.

Комментарии:

1. Это кажется мне ошибкой в реализации анализа Pycharm (есть пара). Я бы ожидал, что то, что у вас уже есть, должно быть правильным.

2. @Carcigenicate Ах, я об этом не думал. Я попробовал использовать mypy, он не обнаружил никаких проблем с моим кодом.

Ответ №1:

HTTPStatus.OK является членом HTTPStatus подкласса IntEnum:

класс http.HttpStatus

Подкласс enum.IntEnum, который определяет набор кодов состояния HTTP, фраз причины и длинных описаний, написанных на английском языке.

Ошибка, которую вы получаете, — это ошибка в PyCharm static type checker, если вы напишете подсказку типа атрибута, как в примере ниже, и протестируете ее с помощью mypy, вы увидите, что ошибки нет:

 from dataclasses import dataclass
from http import HTTPStatus
from typing import Literal


@dataclass
class APICallResult:
    response_text: str
    http_status: Literal[HTTPStatus.OK]


result = APICallResult('foo', HTTPStatus.OK)
 

mypy выдает никаких предупреждений

 Success: no issues found in 1 source file
 

Если вы попытаетесь аннотировать атрибут dataclass следующим образом:

 from dataclasses import dataclass
from http import HTTPStatus


@dataclass
class APICallResult:
    response_text: str
    http_status: HTTPStatus.OK


result = APICallResult('foo', HTTPStatus.OK)
 

mypy выдает следующее предупреждение:

 main.py:9: error: Invalid type: try using Literal[HTTPStatus.OK] instead?
Found 1 error in 1 file (checked 1 source file)
 

Правила для аннотирования элемента Enum приведены в PEP 586 — Литеральные типы:

Допустимые параметры для литерала во время проверки типа

Литерал [Color.RED] # Предполагая, что Color — это некоторое перечисление

Комментарии:

1. Спасибо за подробный ответ! В моем эксперименте с mypy http_status: HTTPStatus работает для меня. Я неохотно использую Literal здесь, потому что API может возвращать другие коды состояния, отличные HTTPStatus.OK от .

2. @JerryWang Я написал этот пост в спешке, я перепишу позже сегодня.