python / python/mypy

Add support for control flow analysis of aliased conditions

Offen
#13,807 1 Kommentar 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen

Dieses Issue hat noch niemand übernommen.

feature
Vorherrschende Sprache
Python
Sterne
20.6k
Forks
3.3k
PR-Merge-Kennzahlen
PR-Kennzahlen ausstehend

Beschreibung

Feature

I think it would be great if mypy supported control flow analysis of aliased conditions like, e.g., introduced in TypeScript v4.4.

Currently, mypy works as follows:

from typing import Sequence, Union

def f(value: Union[str, Sequence[str]]):
    is_string = isinstance(value, str)
    if is_string:
        reveal_type(value)  # Revealed type is "Union[builtins.str, typing.Sequence[builtins.str]]"
    else:
        reveal_type(value)  # Revealed type is "Union[builtins.str, typing.Sequence[builtins.str]]"

But it would be nice if it could infer the type of value correctly in the condition:

from typing import Sequence, Union

def f(value: Union[str, Sequence[str]]):
    is_string = isinstance(value, str)
    if is_string:
        reveal_type(value)  # Revealed type is "builtins.str"
    else:
        reveal_type(value)  # Revealed type is "typing.Sequence[builtins.str]"

Pitch

See, e.g., https://github.com/copier-org/copier/pull/812:

def _execute_tasks(self, tasks: Sequence[Task]) -> None:
    # ...
    for i, task in enumerate(tasks):
        task_cmd = task.cmd
        if isinstance(task_cmd, str):
            task_cmd = self._render_string(task_cmd)
            use_shell = True
        else:
            task_cmd = [self._render_string(str(part)) for part in task_cmd]
            use_shell = False
        # ...
        with local.cwd(self.subproject.local_abspath), local.env(**task.extra_env):
            subprocess.run(task_cmd, shell=use_shell, check=True, env=local.env)

Source: https://github.com/copier-org/copier/blob/1f40ddaac2cc1b1d90ab08c681a3109e329c0206/copier/main.py#L193-L214

It would be nice to rewrite the above snippet as follows:

 def _execute_tasks(self, tasks: Sequence[Task]) -> None:
     # ...
     for i, task in enumerate(tasks):
         task_cmd = task.cmd
+        use_shell = isinstance(task_cmd, str)
+        if use_shell:
-        if isinstance(task_cmd, str):
             task_cmd = self._render_string(task_cmd)
-            use_shell = True
         else:
             task_cmd = [self._render_string(str(part)) for part in task_cmd]
-            use_shell = False
         # ...
         with local.cwd(self.subproject.local_abspath), local.env(**task.extra_env):
             subprocess.run(task_cmd, shell=use_shell, check=True, env=local.env)

Beitragsleitfaden

Beitragsleitfaden öffnen

Erste Schritte

  1. Lies das ganze Issue und danach den Beitragsleitfaden des Projekts.
  2. Schreib ins Issue, dass du es übernimmst — das erspart doppelte Arbeit.
  3. Forke das Repository und arbeite in einem Branch.
  4. Öffne einen Pull Request, der die Issue-Nummer nennt.

Rechercherichtung

Beginne mit den isinstance/reveal_type-Beispielen im Issue und der verlinkten TypeScript-Referenz zur control-flow-analysis. Verfolge, wie mypy die aliased condition derzeit behandelt; als erledigt gilt, wenn value in den beiden Zweigen auf str und Sequence[str] eingegrenzt wird und das umgeschriebene copier-Beispiel unterstützt wird.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
python
Bereich
compilers
Issue-Typ
Feature
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.