pylint-dev / pylint-dev/astroid
How to type ``NodeNG.parent``
- Dominant language
- Python
- Stars
- 582
- Forks
- 357
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 23
Description
```python
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](https://peps.python.org/pep-0696/#generic-typealiases) 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_type` shows `LocalsDictNode | None`, which should be `LocalsDictNode` as we know that `node.parent` isn't a `Module` and therefore `node.parent.parent` should be `LocalsDictNode`.
/CC @cdce8p as you might have a good idea for this. Hopefully...
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.