Skip to content

Unable to track Literal type conditionally imported from third party library #11568

Closed as not planned
@johnthagen

Description

@johnthagen

Bug Report

mypy seems unable to track a Literal type when the Literal is conditionally imported from a third party library.

To Reproduce

# main.py
from drf_spectacular.utils import Direction


def go(direction: Direction) -> int:
    if direction == "request":
        return 1
    elif direction == "response":
        return 2

Run:

mypy --strict main.py
main.py:4: error: Missing return statement
Found 1 error in 1 file (checked 1 source file)

Expected Behavior

No type error because mypy can detect this is exhaustive.

Actual Behavior

Error printed above

Your Environment

$ pip freeze
asgiref==3.4.1
attrs==21.2.0
click==8.0.1
Django==3.2.9
djangorestframework==3.12.4
drf-spectacular==0.21.0
inflection==0.5.1
jsonschema==4.2.1
mypy==0.910
mypy-extensions==0.4.3
pep517==0.10.0
pip-tools==6.4.0
pyrsistent==0.18.0
pytz==2021.3
PyYAML==6.0
sqlparse==0.4.2
toml==0.10.2
typing_extensions==4.0.0
uritemplate==4.1.1
  • Mypy version used: 0.910
  • Mypy command-line flags: --strict
  • Mypy configuration options from mypy.ini (and other config files): N/A
  • Python version used: 3.9.6
  • Operating system and version: macOS 10.15

Third party code of interest:

from drf_spectacular.drainage import (
    Final, Literal, error, get_view_method_names, isolate_view_method, set_override, warn,
)
...
Direction = Literal['request', 'response']
if sys.version_info >= (3, 8):
    from typing import Final, Literal, _TypedDictMeta  # type: ignore[attr-defined] # noqa: F401
else:
    from typing_extensions import (  # type: ignore[attr-defined] # noqa: F401
        Final, Literal, _TypedDictMeta,
    )

I tried modifying the third party package locally to remove some of the conditional imports, but I could never get the mypy error to go away. The only way I was able to get the error to stop was to redeclare (duplicate) the type locally:

from typing import Literal

Direction = Literal['request', 'response']


def go(direction: Direction) -> int:
    if direction == "request":
        return 1
    elif direction == "response":
        return 2

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions