python / python/mypy

Please add documentation about needing to re-define inherited overload signatures

Aperta
#10,699 1 commento 2 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

documentation topic-inheritance topic-overloads topic-usability
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

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:

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia leggendo le sezioni collegate sulla validità degli override, i tipi letterali, le chiamate agli overload e le classi base astratte, quindi esamina le issue #5146 e typing#269 per il contesto del design. Aggiorna la documentazione pertinente per spiegare che le classi figlie o concrete devono ridichiarare le varianti di overload ereditate e che questo comportamento è intenzionale; l’esempio indicato dovrebbe essere trattato chiaramente.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
documentation
Tipo di issue
Documentazione
Difficoltà
2/5
Tempo stimato
1-3 ore
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
45/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.