Please add documentation about needing to re-define inherited overload signatures
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 20.6k
- Forks
- 3.3k
- PR merge metrics
- PR metrics pending
Description
Documentation
The documentation you have is pretty good, it usually saves me time.
I, unfortunately, spent too much time today trying to find the right keywords in your documentation, and the issues, trying to find the most pythonic solution for inherited overload signatures:
from __future__ import annotations
import abc
from typing import Literal, Mapping, overload
class AdapterBase(abc.ABC):
@overload
def get_map_or_value(self, *, as_dict: Literal[True]) -> Mapping[str, str]:
...
@overload
def get_map_or_value(self, *, as_dict: Literal[False] = ...) -> str:
...
@overload
def get_map_or_value(self, *, as_dict: bool = ...) -> Mapping[str, str] | str:
...
@abc.abstractmethod
def get_map_or_value(self, *, as_dict: bool = False) -> Mapping[str, str] | str:
raise NotImplementedError
class ConcreteAdapter1(AdapterBase):
# fails strict no-untyped-def checks
def get_map_or_value(self, *, as_dict):
if as_dict:
return {"somekey": "somevalue"}
return "somevalue"
class ConcreteAdapter2(AdapterBase):
# Signature of "get_map_or_value" incompatible with supertype "AdapterBase" [override]
def get_map_or_value(self, *, as_dict: bool = False) -> Mapping[str, str] | str:
if as_dict:
return {"someOtherKey": "someOtherValue"}
return "someOtherValue"
class DoSomethingElse:
def __init__(self, adapter: AdapterBase) -> None:
# needs to know about function names, parameters, and return types
self.adapter = adapter
My intuition in this scenario told me that the overloads could be inherited, and thus I just needed to provide the generic typedef and go on my merry way. That is, clearly, not the case and it took me a while to find #5146, and consequently, https://github.com/python/typing/issues/269.
It would be nice if the documentation could mention that overload variants need to be re-defined in child/concrete classes. It would also clarify that this "edge case", or ones similar to it, is not an edge case, it's by design.
Here are some places where I went looking for answers, and perhaps someone else might too:
- https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html#when-you-re-puzzled-or-when-things-are-complicated
- https://mypy.readthedocs.io/en/stable/error_code_list.html#check-validity-of-overrides-override
- https://mypy.readthedocs.io/en/stable/literal_types.html#literal-types
- https://mypy.readthedocs.io/en/stable/more_types.html#type-checking-calls-to-overloads
- https://mypy.readthedocs.io/en/stable/class_basics.html#abstract-base-classes-and-multiple-inheritance
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the linked sections on override validity, literal types, overload calls, and abstract base classes, then review issues #5146 and typing#269 for the design context. Update the relevant documentation to explain that child or concrete classes must redeclare inherited overload variants and that this behavior is intentional; the referenced example should be covered clearly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100