Skip to content

Circular dependencies in Python < 3.7 string annotations #453

@crusaderky

Description

@crusaderky

When a function of module A needs to use and return an object of module B, but module B already imports module A, you will typically see this pattern in Python >=3.5.2, <3.7:

from typing import TYPE_CHECKING
if TYPE_CHECKING:
    # Circular dependency; module_b imports this module in its header
    from module_b import SomeClass

def f() -> "SomeClass":
    from module_b import SomeClass
    return SomeClass(1, 2, 3)

pyflakes 2.1.1 produces errors when parsing this file:

module_a.py:4: 'module_b.SomeClass' imported but unused
module_a.py:7: redefinition of unused 'SomeClass' from line 4

Notably, pyflakes does not complain when the same is rewritten using delayed annotation, which however requires Python 3.7:

from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
    # Circular dependency; module_b imports this module in its header
    from module_b import SomeClass

def f() -> SomeClass:
    from module_b import SomeClass
    return SomeClass(1, 2, 3)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions