Skip to content

How to type NodeNG.parent #2017

Open
Open
@DanielNoord

Description

@DanielNoord
from __future__ import annotations

from typing import Generic

from typing_extensions import TypeVar

_NodeParent = TypeVar(
    "_NodeParent", bound="LocalsDictNode | None", default="LocalsDictNode"
)


class Node(Generic[_NodeParent]):
    def __init__(self, parent: _NodeParent) -> None:
        self.parent = parent


class LocalsDictNode(Node["LocalsDictNode" | None]):
    ...


class Module(LocalsDictNode):
    def __init__(self) -> None:
        super().__init__(None)
        self.parent: None = None
        reveal_type(self.parent)

    def method(self) -> None:
        reveal_type(self.parent)


class FunctionDef(LocalsDictNode):
    def method(self) -> None:
        if isinstance(self.parent, Module):
            reveal_type(self.parent.parent)
        else:
            reveal_type(self.parent.parent)


class Arguments(Node[FunctionDef]):
    def __init__(self, parent: FunctionDef) -> None:
        super().__init__(parent)
        reveal_type(self.parent)


class AssignName(Node[LocalsDictNode]):
    def __init__(self, parent: LocalsDictNode) -> None:
        super().__init__(parent)
        reveal_type(self.parent)

    def method(self, attr: Node) -> None:
        reveal_type(attr)

The above code almost meets all requirements we would have for .parent except for one. I'll list them in the hopes of getting any good ideas on how to fix this. Note that this uses the proposed PEP 696 as I saw no other way to even get this far without.

  1. Node itself should not need any type parameters (because of its genericness) and should be useable without any
  2. Unless otherwise specified NodeNG.parent should be a LocalsDictNode
  3. A LocalsDictNode.parent should also be a LocalsDictNode
  4. Except for Module.parent. That should be None.

The above design almost meets that requirement except for that in FunctionDef.method the second reveal_typeshowsLocalsDictNode | None, which should be LocalsDictNodeas we know thatnode.parentisn't aModuleand thereforenode.parent.parentshould beLocalsDictNode`.

/CC @cdce8p as you might have a good idea for this. Hopefully...

Metadata

Metadata

Assignees

No one assigned

    Labels

    MaintenanceDiscussion or action around maintaining astroid or the dev workflow

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions