Multi-level type resolution
Dieses Issue hat noch niemand übernommen.
- Vorherrschende Sprache
- Python
- Sterne
- 20.6k
- Forks
- 3.3k
- PR-Merge-Kennzahlen
- PR-Kennzahlen ausstehend
Beschreibung
Feature
It would be nice if Mypy was able to resolve the types in the below snippet:
import os
import typing as t
T = t.TypeVar('T')
R = t.TypeVar('R')
class flatmap(t.Generic[T, R]):
def __init__(self, func: t.Callable[[T], R]) -> None:
self.func = func
def __ror__(self, value: t.Optional[T]) -> t.Optional[R]:
if value is not None:
return self.func(value)
return None
# error: Cannot infer type argument 1 of "flatmap"
# error: "object" has no attribute "upper"
print(os.getenv('VARNAME') | flatmap(lambda m: m.upper()))
print(os.getenv('VARNAME') | flatmap(str.upper)) # ok
Pitch
Looking at just flatmap(lambda m: m.upper()), neither T nor R can be immediately determined.
However, it should be possible to deduce the type variables by taking into account the broader
context.
T = strcan be derived from the__ror__()call- After propagating
Tinto theflatmap()andlambda,R = strcan be deduced from the lambda body
One potential use case is already highlighted in the example above. Being able to chain the flatmap() function using ror adds a lot of readability compared to a normal call:
# 1)
os.getenv('VARNAME') | flatmap(lambda m: m.upper())
# 2)
flatmap(os.getenv('VARNAME'), lambda m: m.upper())
The obvious workaround in this example would be to use str.upper which would satisfy Mypy because the function is already typed. However, there are other example where the there is no already-typed alternative, like accessing an attribute of an optional object. Nr. 1 would be preferred over 2 for it's better readability. 3 is an alternative without a helper function, though that also gets harder to read as you start to work with more optional values.
# 1)
email = maybe_get_user() | flatmap(lambda user: user.email) | flatmap(sanitize_email_address)
# 2)
email = flatmap(flatmap(maybe_get_user(), lambda user: user.email), sanitize_email_address)
# 3)
user = maybe_get_user()
email = sanitize_email_address(user.email) if user and user.email else None
Beitragsleitfaden
Erste Schritte
- Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
- Forke das Repository und arbeite in einem Branch.
- Öffne einen Pull Request, der die Issue-Nummer nennt.
Rechercherichtung
Reproduziere das Problem mit dem bereitgestellten Python-Snippet und vergleiche den lambda-Fall mit dem funktionierenden str.upper-Fall. Verfolge die Behandlung der generischen flatmap-Konstruktion durch mypy, den ror-Aufruf und die Weitergabe durch das lambda; abgeschlossen ist die Aufgabe, wenn die Beispiele die erwarteten Optional[str]-Ergebnisse ohne Fehler inferieren.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- compilers, devtools
- Issue-Typ
- Feature
- Schwierigkeit
- 5/5
- Geschätzter Aufwand
- Über eine Woche
- Aktivitätsstatus
- Veraltet
- Klarheit
- Größtenteils klar
- Anfängerfreundlichkeit
- 35/100