Closed
Description
For a variable cls
annotated as cls: type[A]
where A
is an ABC, the semantics from #2853 suggest that mypy resolves the type of the variable to concrete subclasses of A. The semantics do not seem to apply if the referenced concrete subclass is not instantiated directly via cls()
, but rather via a partial
as in partial(cls, *args, **kwargs)()
.
Mypy complains with cannot instantiate abstract class
errors if a class variable referencing a presumed-concrete subclass of an ABC is invoked via partial
:
To Reproduce
from abc import ABC, abstractmethod
from functools import partial
from typing import final
class A(ABC):
@final
def __init__(self, *, x: object, y: object) -> None:
self.x = x
self.y = y
@abstractmethod
def m(self) -> None:
pass
class C(A):
def m(self) -> None:
"""Implementation."""
def fun(cls: type[A]) -> None:
cls(x=3, y=5) # allowed
partial_cls = partial(cls, x=3, y=5) # cannot instantiate abstract class A
partial_cls() # cannot instantiate abstract class A
Expected Behavior
I'd have expected this to work, since if cls
in the above example refers to a concrete subclass per #2853, it should be legal to use partial
on it.
Instead, we get
Cannot instantiate abstract class "A" with abstract attribute "m"Mypy[abstract](https://mypy.readthedocs.io/en/latest/_refs.html#code-abstract)
Your Environment
- Mypy version used: 1.11
- Mypy configuration options from
mypy.ini
(and other config files):
[tool.mypy]
disallow_any_generics = true
disallow_subclassing_any = true
disallow_incomplete_defs = true
disallow_untyped_decorators = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_return_any = true
warn_unreachable = true
implicit_reexport = false
strict_equality = true
show_column_numbers = true
enable_incomplete_feature = ["NewGenericSyntax"]
plugins = [
'pydantic.mypy',
'pydantic.v1.mypy'
]
- Python version used: 3.12