-
I have class hierarchy for a simple tree-structured DSL that uses CRTP-style generics to provide typing for the "children" of a node. Distilled: from __future__ import annotations
from typing import Any
__all__ = [
"Expr", "NonTerminal", "Terminal", "OneLevel",
]
class Node[T: Node[Any]]:
children: tuple[T, ...]
class Expr(Node["Expr"]):
pass
class Other(Node["Other"]):
pass
class NonTerminal(Expr):
def __init__(self, *exprs: Expr):
self.children = exprs
class Terminal(Expr):
def __init__(self):
self.children = ()
class OneLevel(Expr):
def __init__(self, *terminal: Terminal):
self.children = terminal
# reveal_type(Expr().children)
# reveal_type(NonTerminal().children)
# reveal_type(Terminal().children)
# reveal_type(OneLevel().children) If I ask pyright to Additionally, as expected, if I introduce: class OtherExpr(Node["OtherExpr"]):
pass
class Bad(Expr):
def __init__(self, *bad: OtherExpr):
self.children = bad Then pyright complains because However, if I install this as a package, call the above file # __init__.py
from myexample.baseoverride import Node, Expr, NonTerminal, OneLevel
__all__ = ["Node", "Expr", "NonTerminal", "OneLevel"] # pyproject.toml
[project]
name = "myexample"
requires-python = ">=3.12"
version = "1.0" Then
I think these are all the same class of error, so let's consider the
I think I agree that the type of the For the other two cases, I suppose that the assignments to My rationale for having this setup is to avoid having to explicitly provide type annotations for the |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Thanks, I agree this is a bug. I didn't consider this case when implementing the original type verification logic. I've created this bug report to track the issue. |
Beta Was this translation helpful? Give feedback.
Thanks, I agree this is a bug. I didn't consider this case when implementing the original type verification logic.
I've created this bug report to track the issue.