python / python/mypy

Add support for control flow analysis of aliased conditions

Aperta
#13,807 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

feature
Lingua principale
Python
Stelle
20.6k
Fork
3.3k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

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)

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 con gli esempi di isinstance/reveal_type nell’issue e con il riferimento collegato a TypeScript control-flow-analysis. Traccia il modo in cui mypy gestisce attualmente la aliased condition; il lavoro è completato quando value viene ristretto a str e Sequence[str] nei due rami e viene supportato l’esempio di copier riscritto.

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

Valutazione

Stack tecnologico
python
Ambito
compilers
Tipo di issue
Funzionalità
Difficoltà
5/5
Tempo stimato
Più di una settimana
Stato di attività
Ferma
Chiarezza
Abbastanza chiara
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.