From 45da3297895192d7391529a419988359f1772d46 Mon Sep 17 00:00:00 2001 From: Lucian Wischik Date: Wed, 23 Oct 2024 10:40:09 -0700 Subject: [PATCH 01/21] Specify return type for createHost (#9295) Currently the return type of PyrightServer.createHost is left blank, inferred by typescript to be FullAccessHost. Therefore anyone who inherits from PyrightServer must also return FullAccessHost. We should specify the return type explicitly. That way someone can inherit from it and return NoAccessHost, say. --- packages/pyright-internal/src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pyright-internal/src/server.ts b/packages/pyright-internal/src/server.ts index c347a4e02..e4738b0d7 100644 --- a/packages/pyright-internal/src/server.ts +++ b/packages/pyright-internal/src/server.ts @@ -225,7 +225,7 @@ export class PyrightServer extends LanguageServerBase { return new BackgroundAnalysis(this.serverOptions.serviceProvider); } - protected override createHost() { + protected override createHost(): Host { return new FullAccessHost(this.serverOptions.serviceProvider); } From 4180fa2162fb5c53257a5b794f8bcd7512603dce Mon Sep 17 00:00:00 2001 From: Bill Schnurr Date: Wed, 23 Oct 2024 13:37:31 -0700 Subject: [PATCH 02/21] Pull Pylance with Pyright 1.1.386 (#9302) Co-authored-by: Azure Piplines <41898282+github-actions[bot]@users.noreply.github.com> --- .../pyright-internal/src/localization/localize.ts | 12 +++++++++++- .../src/localization/package.nls.cs.json | 4 +++- .../src/localization/package.nls.de.json | 2 ++ .../src/localization/package.nls.es.json | 2 ++ .../src/localization/package.nls.fr.json | 2 ++ .../src/localization/package.nls.it.json | 4 +++- .../src/localization/package.nls.ja.json | 2 ++ .../src/localization/package.nls.ko.json | 2 ++ .../src/localization/package.nls.pl.json | 2 ++ .../src/localization/package.nls.pt-br.json | 4 +++- .../src/localization/package.nls.qps-ploc.json | 4 +++- .../src/localization/package.nls.ru.json | 4 +++- .../src/localization/package.nls.tr.json | 2 ++ .../src/localization/package.nls.zh-cn.json | 2 ++ .../src/localization/package.nls.zh-tw.json | 4 +++- 15 files changed, 45 insertions(+), 7 deletions(-) diff --git a/packages/pyright-internal/src/localization/localize.ts b/packages/pyright-internal/src/localization/localize.ts index 0016f6f8b..38ff00ee6 100644 --- a/packages/pyright-internal/src/localization/localize.ts +++ b/packages/pyright-internal/src/localization/localize.ts @@ -76,8 +76,13 @@ function getRawStringDefault(key: string): string { } const keyParts = key.split('.'); + const isDiagnostic = keyParts[0] === 'Diagnostic' || keyParts[0] === 'DiagnosticAddendum'; + + const str = + isDiagnostic && forceEnglishDiagnostics + ? getRawStringFromMap(defaultStrings, keyParts) + : getRawStringFromMap(localizedStrings, keyParts) || getRawStringFromMap(defaultStrings, keyParts); - const str = getRawStringFromMap(localizedStrings, keyParts) || getRawStringFromMap(defaultStrings, keyParts); if (str) { return str; } @@ -116,6 +121,7 @@ function initialize(): StringLookupMap { } let localeOverride: string | undefined; +let forceEnglishDiagnostics = false; export function setLocaleOverride(locale: string) { // Force a reload of the localized strings. @@ -123,6 +129,10 @@ export function setLocaleOverride(locale: string) { localeOverride = locale.toLowerCase(); } +export function setForceEnglishDiagnostics(force: boolean) { + forceEnglishDiagnostics = force; +} + export function getLocaleFromEnv(): string { if (localeOverride) { return localeOverride; diff --git a/packages/pyright-internal/src/localization/package.nls.cs.json b/packages/pyright-internal/src/localization/package.nls.cs.json index ae14fadc6..73d99815c 100644 --- a/packages/pyright-internal/src/localization/package.nls.cs.json +++ b/packages/pyright-internal/src/localization/package.nls.cs.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "Argument typu {argType} není platný převaděč pro pole {fieldName} typu {fieldType}", "dataClassConverterOverloads": "Žádná přetížení {funcName} nejsou platné převaděče pro pole {fieldName} typu {fieldType}", "dataClassFieldInheritedDefault": "{fieldName} přepíše pole se stejným názvem, ale chybí mu výchozí hodnota.", + "dataClassFieldInvalidAlias": "Název aliasu {aliasName} není platný identifikátor.", "dataClassFieldWithDefault": "Pole bez výchozích hodnot se nemůžou zobrazit po polích s výchozími hodnotami", "dataClassFieldWithPrivateName": "Pole datové třídy nemůže používat privátní název", "dataClassFieldWithoutAnnotation": "Pole dataclass bez poznámky typu způsobí výjimku modulu runtime", @@ -561,6 +562,7 @@ "typedDictEntryName": "Očekával se řetězcový literál pro název položky slovníku", "typedDictEntryUnique": "Názvy ve slovníku musí být jedinečné", "typedDictExtraArgs": "Nadbytečné argumenty TypedDict nejsou podporovány", + "typedDictExtraItemsClosed": "Objekt TypedDict nelze closed, pokud podporuje další položky.", "typedDictFieldNotRequiredRedefinition": "Položka TypedDict {name} nejde předefinovat jako NotRequired.", "typedDictFieldReadOnlyRedefinition": "Položka TypedDict {name} nejde předefinovat jako ReadOnly.", "typedDictFieldRequiredRedefinition": "Položka TypedDict {name} nejde předefinovat jako Required.", @@ -795,7 +797,7 @@ "typedDictClosedExtraTypeMismatch": "Nelze přidat položku {name} s typem {type}.", "typedDictClosedFieldNotRequired": "Nelze přidat položku {name}, protože musí být NotRequired.", "typedDictExtraFieldNotAllowed": "{name} není k dispozici v {type}", - "typedDictExtraFieldTypeMismatch": "Typ {name} není kompatibilní s typem extra_items v typu {type}.", + "typedDictExtraFieldTypeMismatch": "Typ {name} není kompatibilní s typem „extra_items“ v typu {type}.", "typedDictFieldMissing": "V {type} chybí {name}", "typedDictFieldNotReadOnly": "{name} není v {type} jen pro čtení", "typedDictFieldNotRequired": "{name} se v typu {type} nevyžaduje", diff --git a/packages/pyright-internal/src/localization/package.nls.de.json b/packages/pyright-internal/src/localization/package.nls.de.json index 9c2b50798..5f4924d10 100644 --- a/packages/pyright-internal/src/localization/package.nls.de.json +++ b/packages/pyright-internal/src/localization/package.nls.de.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "Das Argument vom Typ \"{argType}\" ist kein gültiger Konverter für das Feld \"{fieldName}\" vom Typ \"{fieldType}\"", "dataClassConverterOverloads": "Keine Überladungen von \"{funcName}\" sind gültige Konverter für das Feld \"{fieldName}\" vom Typ \"{fieldType}\"", "dataClassFieldInheritedDefault": "„{fieldName}“ überschreibt ein Feld mit demselben Namen, aber es fehlt ein Standardwert", + "dataClassFieldInvalidAlias": "Der Aliasname „{aliasName}“ ist kein gültiger Bezeichner.", "dataClassFieldWithDefault": "Felder ohne Standardwerte dürfen nicht nach Feldern mit Standardwerten angezeigt werden.", "dataClassFieldWithPrivateName": "Das Feld \"Dataclass\" kann keinen privaten Namen verwenden.", "dataClassFieldWithoutAnnotation": "Datenklassenfeld ohne Typanmerkung verursacht eine Laufzeitausnahme", @@ -561,6 +562,7 @@ "typedDictEntryName": "Für den Wörterbucheintragsnamen wurde ein Zeichenfolgenliteral erwartet.", "typedDictEntryUnique": "Namen innerhalb eines Wörterbuchs müssen eindeutig sein.", "typedDictExtraArgs": "Zusätzliche TypedDict-Argumente werden nicht unterstützt.", + "typedDictExtraItemsClosed": "A TypedDict cannot be closed if it supports extra items", "typedDictFieldNotRequiredRedefinition": "Das TypedDict-Element „{name}“ kann nicht als „NotRequired“ neu definiert werden.", "typedDictFieldReadOnlyRedefinition": "Das TypedDict-Element „{name}“ kann nicht als „ReadOnly“ neu definiert werden.", "typedDictFieldRequiredRedefinition": "Das TypedDict-Element „{name}“ kann nicht als „Required“ neu definiert werden.", diff --git a/packages/pyright-internal/src/localization/package.nls.es.json b/packages/pyright-internal/src/localization/package.nls.es.json index 9f9d296e6..078a0c1a7 100644 --- a/packages/pyright-internal/src/localization/package.nls.es.json +++ b/packages/pyright-internal/src/localization/package.nls.es.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "Argumento de tipo \"{argType}\" no es un convertidor válido para el campo \"{fieldName}\" de tipo \"{fieldType}\"", "dataClassConverterOverloads": "No hay sobrecargas de \"{funcName}\" que sean convertidores válidos para el campo \"{fieldName}\" de tipo \"{fieldType}\"", "dataClassFieldInheritedDefault": "\"{fieldName}\" invalida un campo con el mismo nombre, pero falta un valor predeterminado", + "dataClassFieldInvalidAlias": "El nombre de alias \"{aliasName}\" no es un identificador válido", "dataClassFieldWithDefault": "Los campos sin valores predeterminados no pueden aparecer después de los campos con valores predeterminados", "dataClassFieldWithPrivateName": "El campo Dataclass no puede utilizar un nombre privado", "dataClassFieldWithoutAnnotation": "El campo Dataclass sin anotación de tipo provocará una excepción en tiempo de ejecución", @@ -561,6 +562,7 @@ "typedDictEntryName": "Cadena literal esperada para el nombre de la entrada del diccionario", "typedDictEntryUnique": "Los nombres dentro de un diccionario deben ser únicos", "typedDictExtraArgs": "No se admiten argumentos TypedDict adicionales", + "typedDictExtraItemsClosed": "A TypedDict cannot be closed if it supports extra items", "typedDictFieldNotRequiredRedefinition": "El elemento TypedDict \"{name}\" no se puede redefinir como NotRequired", "typedDictFieldReadOnlyRedefinition": "El elemento TypedDict \"{name}\" no se puede redefinir como ReadOnly", "typedDictFieldRequiredRedefinition": "El elemento TypedDict \"{name}\" no se puede redefinir como Required", diff --git a/packages/pyright-internal/src/localization/package.nls.fr.json b/packages/pyright-internal/src/localization/package.nls.fr.json index 5f0f92e0d..7069ba60c 100644 --- a/packages/pyright-internal/src/localization/package.nls.fr.json +++ b/packages/pyright-internal/src/localization/package.nls.fr.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "L’argument de type « {argType} » n’est pas un convertisseur valide pour le champ « {fieldName} » de type « {fieldType} »", "dataClassConverterOverloads": "Aucune surcharge de « {funcName} » n’est valide pour le champ « {fieldName} » de type « {fieldType} »", "dataClassFieldInheritedDefault": "« {fieldName} » remplace un champ du même nom mais n’a pas de valeur par défaut", + "dataClassFieldInvalidAlias": "Le nom d’alias « {aliasName} » n’est pas un identificateur valide", "dataClassFieldWithDefault": "Les champs sans valeurs par défaut ne peuvent pas apparaître après les champs avec des valeurs par défaut", "dataClassFieldWithPrivateName": "Le champ Dataclass ne peut pas utiliser de nom privé", "dataClassFieldWithoutAnnotation": "Le champ Dataclass sans annotation de type provoquera une exception d'exécution", @@ -561,6 +562,7 @@ "typedDictEntryName": "Littéral de chaîne attendu pour le nom d’entrée du dictionnaire", "typedDictEntryUnique": "Les noms dans un dictionnaire doivent être uniques", "typedDictExtraArgs": "Arguments TypedDict supplémentaires non pris en charge", + "typedDictExtraItemsClosed": "Un TypedDict ne peut pas être closed s’il prend en charge les éléments supplémentaires", "typedDictFieldNotRequiredRedefinition": "L’élément TypedDict « {name} » ne peut pas être redéfini comme étant NotRequired", "typedDictFieldReadOnlyRedefinition": "L’élément TypedDict « {name} » ne peut pas être redéfini comme état En ReadOnly", "typedDictFieldRequiredRedefinition": "L’élément TypedDict « {name} » ne peut pas être redéfini comme étant Required", diff --git a/packages/pyright-internal/src/localization/package.nls.it.json b/packages/pyright-internal/src/localization/package.nls.it.json index cf8e4a34a..61d20841d 100644 --- a/packages/pyright-internal/src/localization/package.nls.it.json +++ b/packages/pyright-internal/src/localization/package.nls.it.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "L'argomento di tipo \"{argType}\" non è un convertitore valido per il campo \"{fieldName}\" di tipo \"{fieldType}\"", "dataClassConverterOverloads": "Nessun overload di \"{funcName}\" è un convertitore valido per il campo \"{fieldName}\" di tipo \"{fieldType}\"", "dataClassFieldInheritedDefault": "\"{fieldName}\" esegue l'override di un campo con lo stesso nome, ma manca un valore predefinito", + "dataClassFieldInvalidAlias": "Il nome alias \"{aliasName}\" non è un identificatore valido", "dataClassFieldWithDefault": "I campi senza valori predefiniti non possono essere visualizzati dopo i campi con valori predefiniti", "dataClassFieldWithPrivateName": "Il campo dataclass non può usare un nome privato", "dataClassFieldWithoutAnnotation": "Il campo dataclass senza annotazione del tipo causerà un'eccezione di runtime", @@ -561,6 +562,7 @@ "typedDictEntryName": "Valore letterale stringa previsto per il nome della voce del dizionario", "typedDictEntryUnique": "I nomi all'interno di un dizionario devono essere univoci", "typedDictExtraArgs": "Argomenti TypedDict aggiuntivi non supportati", + "typedDictExtraItemsClosed": "A TypedDict cannot be closed if it supports extra items", "typedDictFieldNotRequiredRedefinition": "Non è possibile ridefinire il campo TypedDict \"{name}\" come NotRequired", "typedDictFieldReadOnlyRedefinition": "Non è possibile ridefinire l’elemento TypedDict \"{name}\" come ReadOnly", "typedDictFieldRequiredRedefinition": "Non è possibile ridefinire il campo TypedDict \"{name}\" come Required", @@ -795,7 +797,7 @@ "typedDictClosedExtraTypeMismatch": "Non è possibile aggiungere l'elemento \"{name}\" con tipo \"{type}\"", "typedDictClosedFieldNotRequired": "Non è possibile aggiungere l'elemento \"{name}\" perché deve essere NotRequired", "typedDictExtraFieldNotAllowed": "\"{name}\" non è presente in \"{type}\"", - "typedDictExtraFieldTypeMismatch": "Il tipo di \"{name}\" non è compatibile con il tipo \"extra_items\" in \"{type}\"", + "typedDictExtraFieldTypeMismatch": "Il tipo di \"{name}\" non è compatibile con il tipo \"\"extra_items\" in \"{type}\"", "typedDictFieldMissing": "\"{name}\" mancante nel \"{type}\"", "typedDictFieldNotReadOnly": "\"{name}\" non è di sola lettura in \"{type}\"", "typedDictFieldNotRequired": "\"{name}\" non è obbligatorio in \"{type}\"", diff --git a/packages/pyright-internal/src/localization/package.nls.ja.json b/packages/pyright-internal/src/localization/package.nls.ja.json index 00a5f7390..0ec193de4 100644 --- a/packages/pyright-internal/src/localization/package.nls.ja.json +++ b/packages/pyright-internal/src/localization/package.nls.ja.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "型 \"{argType}\" の引数は、型 \"{fieldType}\" のフィールド \"{fieldName}\" の有効なコンバーターではありません", "dataClassConverterOverloads": "{funcName}\" のオーバーロードは、型 \"{fieldType}\" のフィールド \"{fieldName}\" に対して有効なコンバーターではありません", "dataClassFieldInheritedDefault": "\"{fieldName}\" は同じ名前のフィールドをオーバーライドしますが、既定値がありません", + "dataClassFieldInvalidAlias": "エイリアス名 \"{aliasName}\" は有効な識別子ではありません", "dataClassFieldWithDefault": "既定値のないフィールドは、既定値を持つフィールドの後に表示できません", "dataClassFieldWithPrivateName": "データクラス フィールドはプライベート名を使用できません", "dataClassFieldWithoutAnnotation": "型注釈のないデータクラス フィールドが原因でランタイム例外が発生する", @@ -561,6 +562,7 @@ "typedDictEntryName": "辞書エントリ名に文字列リテラルが必要です", "typedDictEntryUnique": "ディクショナリ内の名前は一意である必要があります", "typedDictExtraArgs": "追加の TypedDict 引数はサポートされていません", + "typedDictExtraItemsClosed": "追加の項目がサポートされている場合、TypedDict を closed にすることはできません", "typedDictFieldNotRequiredRedefinition": "TypedDict アイテム \"{name}\" を NotRequired として再定義することはできません", "typedDictFieldReadOnlyRedefinition": "TypedDict アイテム \"{name}\" を ReadOnly として再定義することはできません", "typedDictFieldRequiredRedefinition": "TypedDict アイテム \"{name}\" を Required として再定義することはできません", diff --git a/packages/pyright-internal/src/localization/package.nls.ko.json b/packages/pyright-internal/src/localization/package.nls.ko.json index 33dccee2b..230e3fa9d 100644 --- a/packages/pyright-internal/src/localization/package.nls.ko.json +++ b/packages/pyright-internal/src/localization/package.nls.ko.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "\"{argType}\" 형식의 인수는 \"{fieldType}\" 형식의 \"{fieldName}\" 필드에 유효한 변환기가 아닙니다.", "dataClassConverterOverloads": "\"{funcName}\"의 오버로드는 \"{fieldType}\" 형식의 \"{fieldName}\" 필드에 유효한 변환기가 아닙니다.", "dataClassFieldInheritedDefault": "\"{fieldName}\"이(가) 같은 이름의 필드를 재정의하지만 기본값이 없음", + "dataClassFieldInvalidAlias": "별칭 이름 \"{aliasName}\"은(는) 유효한 식별자가 아닙니다.", "dataClassFieldWithDefault": "기본값이 없는 필드는 기본값이 있는 필드 뒤에 나타날 수 없습니다.", "dataClassFieldWithPrivateName": "데이터 클래스 필드는 프라이빗 이름을 사용할 수 없습니다.", "dataClassFieldWithoutAnnotation": "형식 주석이 없는 데이터 클래스 필드를 사용하면 런타임 예외가 발생합니다.", @@ -561,6 +562,7 @@ "typedDictEntryName": "사전 항목 이름에 필요한 문자열 리터럴", "typedDictEntryUnique": "사전 내의 이름은 고유해야 합니다.", "typedDictExtraArgs": "추가 TypedDict 인수가 지원되지 않음", + "typedDictExtraItemsClosed": "추가 항목을 지원하는 경우 TypedDict를 closed 수 없습니다.", "typedDictFieldNotRequiredRedefinition": "TypedDict 항목 \"{name}\"은(는) NotRequired로 재정의될 수 없습니다.", "typedDictFieldReadOnlyRedefinition": "TypedDict 항목 \"{name}\"은(는) ReadOnly로 재정의될 수 없습니다.", "typedDictFieldRequiredRedefinition": "TypedDict 항목 \"{name}\"은(는) Required로 재정의될 수 없습니다.", diff --git a/packages/pyright-internal/src/localization/package.nls.pl.json b/packages/pyright-internal/src/localization/package.nls.pl.json index fde5f26c1..4dc4ca2cc 100644 --- a/packages/pyright-internal/src/localization/package.nls.pl.json +++ b/packages/pyright-internal/src/localization/package.nls.pl.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "Argument typu „{argType}” nie jest prawidłowym konwerterem pola „{fieldName}” typu „{fieldType}”", "dataClassConverterOverloads": "Żadne przeciążenia „{funcName}” nie są prawidłowymi konwerterami dla pola „{fieldName}” typu „{fieldType}”", "dataClassFieldInheritedDefault": "Pole „{fieldName}” zastępuje pole o tej samej nazwie, ale brakuje wartości domyślnej", + "dataClassFieldInvalidAlias": "Nazwa aliasu „{aliasName}” nie jest prawidłowym identyfikatorem", "dataClassFieldWithDefault": "Pola bez wartości domyślnych nie mogą występować po polach z wartościami domyślnymi", "dataClassFieldWithPrivateName": "Pole klasy danych nie może używać nazwy prywatnej", "dataClassFieldWithoutAnnotation": "Pole klasy danych bez adnotacji typu spowoduje wyjątek środowiska uruchomieniowego", @@ -561,6 +562,7 @@ "typedDictEntryName": "Oczekiwano literału ciągu dla nazwy wpisu słownika", "typedDictEntryUnique": "Nazwy w słowniku muszą być unikatowe", "typedDictExtraArgs": "Dodatkowe argumenty TypedDict nie są obsługiwane", + "typedDictExtraItemsClosed": "Element TypedDict nie może być „closed”, jeśli obsługuje dodatkowe elementy", "typedDictFieldNotRequiredRedefinition": "Element TypedDict „{name}” nie może zostać przedefiniowany jako NotRequired", "typedDictFieldReadOnlyRedefinition": "Element TypedDict „{name}” nie może być przedefiniowany jako ReadOnly.", "typedDictFieldRequiredRedefinition": "Element TypedDict „{name}” nie może zostać przedefiniowany jako Required", diff --git a/packages/pyright-internal/src/localization/package.nls.pt-br.json b/packages/pyright-internal/src/localization/package.nls.pt-br.json index c8538f8ed..d7795ca7f 100644 --- a/packages/pyright-internal/src/localization/package.nls.pt-br.json +++ b/packages/pyright-internal/src/localization/package.nls.pt-br.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "O argumento do tipo \"{argType}\" não é um conversor válido para o campo \"{fieldName}\" do tipo \"{fieldType}\"", "dataClassConverterOverloads": "Nenhuma sobrecarga de \"{funcName}\" são conversores válidos para o campo \"{fieldName}\" do tipo \"{fieldType}\"", "dataClassFieldInheritedDefault": "\"{fieldName}\" substitui um campo com o mesmo nome, mas não possui um valor padrão", + "dataClassFieldInvalidAlias": "O nome de alias \"{aliasName}\" não é um identificador válido", "dataClassFieldWithDefault": "Campos sem valores padrão não podem aparecer após campos com valores padrão", "dataClassFieldWithPrivateName": "O campo Dataclass não pode usar o nome privado", "dataClassFieldWithoutAnnotation": "O campo Dataclass sem anotação de tipo causará uma exceção de runtime", @@ -561,6 +562,7 @@ "typedDictEntryName": "Literal de cadeia de caracteres esperado para o nome da entrada do dicionário", "typedDictEntryUnique": "Os nomes dentro de um dicionário devem ser exclusivos", "typedDictExtraArgs": "Argumentos TypedDict extras são incompatíveis", + "typedDictExtraItemsClosed": "Um TypedDict não pode ser closed se der suporte a itens extras", "typedDictFieldNotRequiredRedefinition": "O item TypedDict \"{name}\" não pode ser redefinido como NotRequired", "typedDictFieldReadOnlyRedefinition": "O item TypedDict \"{name}\" não pode ser redefinido como ReadOnly", "typedDictFieldRequiredRedefinition": "O item TypedDict \"{name}\" não pode ser redefinido como Required", @@ -795,7 +797,7 @@ "typedDictClosedExtraTypeMismatch": "Não é possível adicionar o item \"{name}\" com o tipo \"{type}\"", "typedDictClosedFieldNotRequired": "Não é possível adicionar o item \"{name}\" porque ele deve ser NotRequired", "typedDictExtraFieldNotAllowed": "\"{name}\" não está presente em \"{type}\"", - "typedDictExtraFieldTypeMismatch": "O tipo de \"{name}\" é incompatível com o tipo de \"extra_items\" em \"{type}\"", + "typedDictExtraFieldTypeMismatch": "Tipo de \"{name}\" é incompatível com tipo de \"extra_items\" em \"{type}\"", "typedDictFieldMissing": "\"{name}\" está ausente de \"{type}\"", "typedDictFieldNotReadOnly": "\"{name}\" não é somente leitura em \"{type}\"", "typedDictFieldNotRequired": "\"{name}\" não é obrigatório em \"{type}\"", diff --git a/packages/pyright-internal/src/localization/package.nls.qps-ploc.json b/packages/pyright-internal/src/localization/package.nls.qps-ploc.json index 081fafcdb..d32a2ca12 100644 --- a/packages/pyright-internal/src/localization/package.nls.qps-ploc.json +++ b/packages/pyright-internal/src/localization/package.nls.qps-ploc.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "[FxD8r][นั้Ærgµmëñt øf tÿpë \"{ærgTÿpë}\" ïs ñøt æ vælïð çøñvërtër før fïëlð \"{fïëlðÑæmë}\" øf tÿpë \"{fïëlðTÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]", "dataClassConverterOverloads": "[ZJ0SE][นั้Ñø øvërløæðs øf \"{fµñçÑæmë}\" ærë vælïð çøñvërtërs før fïëlð \"{fïëlðÑæmë}\" øf tÿpë \"{fïëlðTÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]", "dataClassFieldInheritedDefault": "[BKxvn][นั้\"{fïëlðÑæmë}\" øvërrïðës æ fïëlð øf thë sæmë ñæmë þµt ïs mïssïñg æ ðëfæµlt vælµëẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğ倪İนั้ढूँ]", + "dataClassFieldInvalidAlias": "[Yie5U][นั้Ælïæs ñæmë \"{ælïæsÑæmë}\" ïs ñøt æ vælïð ïðëñtïfïërẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰนั้ढूँ]", "dataClassFieldWithDefault": "[iJuju][นั้Fïëlðs wïthøµt ðëfæµlt vælµës çæññøt æppëær æftër fïëlðs wïth ðëfæµlt vælµësẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğนั้ढूँ]", "dataClassFieldWithPrivateName": "[miQYb][นั้Ðætæçlæss fïëlð çæññøt µsë prïvætë ñæmëẤğ倪İЂҰक्र्तिृまẤğนั้ढूँ]", "dataClassFieldWithoutAnnotation": "[zq5t5][นั้Ðætæçlæss fïëlð wïthøµt tÿpë æññøtætïøñ wïll çæµsë rµñtïmë ëxçëptïøñẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृนั้ढूँ]", @@ -561,6 +562,7 @@ "typedDictEntryName": "[NT4np][นั้Ëxpëçtëð strïñg lïtëræl før ðïçtïøñærÿ ëñtrÿ ñæmëẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰนั้ढूँ]", "typedDictEntryUnique": "[nWy0L][นั้Ñæmës wïthïñ æ ðïçtïøñærÿ mµst þë µñïqµëẤğ倪İЂҰक्र्तिृまẤğนั้ढूँ]", "typedDictExtraArgs": "[0gX32][นั้Ëxtræ TypedDict ærgµmëñts ñøt sµppørtëðẤğ倪İЂҰक्र्तिृまẤğนั้ढूँ]", + "typedDictExtraItemsClosed": "[5BDXE][นั้Æ TypedDict çæññøt þë closed ïf ït sµppørts ëxtræ ïtëmsẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "typedDictFieldNotRequiredRedefinition": "[rNYD1][นั้TypedDict ïtëm \"{ñæmë}\" çæññøt þë rëðëfïñëð æs NotRequiredẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्นั้ढूँ]", "typedDictFieldReadOnlyRedefinition": "[8IFAz][นั้TypedDict ïtëm \"{ñæmë}\" çæññøt þë rëðëfïñëð æs ReadOnlyẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "typedDictFieldRequiredRedefinition": "[lpw97][นั้TypedDict ïtëm \"{ñæmë}\" çæññøt þë rëðëfïñëð æs RequiredẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", @@ -795,7 +797,7 @@ "typedDictClosedExtraTypeMismatch": "[blC1e][นั้Çæññøt æðð ïtëm \"{ñæmë}\" wïth tÿpë \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪นั้ढूँ]", "typedDictClosedFieldNotRequired": "[6rtDR][นั้Çæññøt æðð ïtëm \"{ñæmë}\" þëçæµsë ït mµst þë NotRequiredẤğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्นั้ढूँ]", "typedDictExtraFieldNotAllowed": "[kFDh9][นั้\"{ñæmë}\" ïs ñøt prësëñt ïñ \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまนั้ढूँ]", - "typedDictExtraFieldTypeMismatch": "[DnAhM][นั้Tÿpë øf \"{ñæmë}\" ïs ïñçømpætïþlë wïth tÿpë øf \"extra_items\" ïñ \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまẤğนั้ढूँ]", + "typedDictExtraFieldTypeMismatch": "[DnAhM][นั้Tÿpë øf \"{ñæmë}\" ïs ïñçømpætïþlë wïth tÿpë øf \"extra_items\" ïñ \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤğ倪İЂҰक्र्तिृまนั้ढूँ]", "typedDictFieldMissing": "[rNzn7][นั้\"{ñæmë}\" ïs mïssïñg frøm \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृนั้ढूँ]", "typedDictFieldNotReadOnly": "[BJy1V][นั้\"{ñæmë}\" ïs ñøt rëæð-øñlÿ ïñ \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまẤนั้ढूँ]", "typedDictFieldNotRequired": "[eqatW][นั้\"{ñæmë}\" ïs ñøt rëqµïrëð ïñ \"{tÿpë}\"Ấğ倪İЂҰक्र्तिृまนั้ढूँ]", diff --git a/packages/pyright-internal/src/localization/package.nls.ru.json b/packages/pyright-internal/src/localization/package.nls.ru.json index 053168e1f..b52f3bb73 100644 --- a/packages/pyright-internal/src/localization/package.nls.ru.json +++ b/packages/pyright-internal/src/localization/package.nls.ru.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "Аргумент типа \"{argType}\" не является допустимым преобразователем для поля \"{fieldName}\" типа \"{fieldType}\"", "dataClassConverterOverloads": "Ни одна перегрузка \"{funcName}\" не является допустимым преобразователем поля \"{fieldName}\" типа \"{fieldType}\"", "dataClassFieldInheritedDefault": "\"{fieldName}\" переопределяет поле с тем же именем, но в нем отсутствует значение по умолчанию", + "dataClassFieldInvalidAlias": "Псевдоним \"{aliasName}\" не является допустимым идентификатором", "dataClassFieldWithDefault": "Поля без значений по умолчанию не могут отображаться после полей со значениями по умолчанию.", "dataClassFieldWithPrivateName": "Поле класса данных не может использовать закрытое имя", "dataClassFieldWithoutAnnotation": "Поле dataclass без заметки с типом вызовет исключение среды выполнения", @@ -561,6 +562,7 @@ "typedDictEntryName": "Для имени записи словаря ожидается строковый литерал", "typedDictEntryUnique": "Имена в словаре должны быть уникальными", "typedDictExtraArgs": "Дополнительные аргументы TypedDict не поддерживаются", + "typedDictExtraItemsClosed": "TypedDict не может быть \"closed\", если он поддерживает дополнительные элементы", "typedDictFieldNotRequiredRedefinition": "Элемент TypedDict \"{name}\" нельзя переопределить как NotRequired", "typedDictFieldReadOnlyRedefinition": "Элемент TypedDict \"{name}\" нельзя переопределить как доступный ReadOnly", "typedDictFieldRequiredRedefinition": "Элемент TypedDict \"{name}\" нельзя переопределить как Required", @@ -795,7 +797,7 @@ "typedDictClosedExtraTypeMismatch": "Не удается добавить элемент \"{name}\" типа \"{type}\"", "typedDictClosedFieldNotRequired": "Не удается добавить элемент \"{name}\", так как он должен быть помечен как NotRequired", "typedDictExtraFieldNotAllowed": "Элемент \"{name}\" отсутствует в типе \"{type}\"", - "typedDictExtraFieldTypeMismatch": "Тип элемента \"{name}\" несовместим с типом \"extra_items\" в \"{type}\"", + "typedDictExtraFieldTypeMismatch": "Тип \"{name}\" несовместим с типом \"extra_items\" в \"{type}\"", "typedDictFieldMissing": "\"{name}\" отсутствует в \"{type}\"", "typedDictFieldNotReadOnly": "\"{name}\" не является элементом \"{type}\" только для чтения", "typedDictFieldNotRequired": "\"{name}\" не является обязательным в \"{type}\"", diff --git a/packages/pyright-internal/src/localization/package.nls.tr.json b/packages/pyright-internal/src/localization/package.nls.tr.json index 252cd8d81..7056a298c 100644 --- a/packages/pyright-internal/src/localization/package.nls.tr.json +++ b/packages/pyright-internal/src/localization/package.nls.tr.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "\"{argType}\" türündeki bağımsız değişken, \"{fieldName}\" türündeki \"{fieldType}\" alanı için geçerli bir dönüştürücü değil", "dataClassConverterOverloads": "\"{funcName}\" işlevinin aşırı yüklemelerinden hiçbiri \"{fieldType}\" türündeki \"{fieldName}\" alanı için geçerli dönüştürücüler değil", "dataClassFieldInheritedDefault": "\"{fieldName}\", aynı ada sahip bir alanı geçersiz kılıyor ancak varsayılan değeri yok", + "dataClassFieldInvalidAlias": "\"{aliasName}\" diğer adı geçerli bir tanımlayıcı değil", "dataClassFieldWithDefault": "Varsayılan değerleri olmayan alanlar, varsayılan değerleri olan alanlardan sonra gelemez", "dataClassFieldWithPrivateName": "Veri sınıfı alanı özel ad kullanamıyor", "dataClassFieldWithoutAnnotation": "Tür ek açıklaması olmayan veri sınıfı alanı çalışma zamanı özel durumuna neden olur", @@ -561,6 +562,7 @@ "typedDictEntryName": "Sözlük girdisi adı için sabit değerli dize bekleniyordu", "typedDictEntryUnique": "Sözlük içindeki adlar benzersiz olmalıdır", "typedDictExtraArgs": "Ekstra TypedDict bağımsız değişkenleri desteklenmiyor", + "typedDictExtraItemsClosed": "Bir TypedDict ek öğeleri destekliyorsa closed olamaz", "typedDictFieldNotRequiredRedefinition": "\"{name}\" TypedDict öğesi NotRequired olarak yeniden tanımlanamaz", "typedDictFieldReadOnlyRedefinition": "\"{name}\" TypedDict öğesi ReadOnly olarak yeniden tanımlanamaz", "typedDictFieldRequiredRedefinition": "\"{name}\" TypedDict öğesi Required olarak yeniden tanımlanamaz", diff --git a/packages/pyright-internal/src/localization/package.nls.zh-cn.json b/packages/pyright-internal/src/localization/package.nls.zh-cn.json index cebded934..5b961feb1 100644 --- a/packages/pyright-internal/src/localization/package.nls.zh-cn.json +++ b/packages/pyright-internal/src/localization/package.nls.zh-cn.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "类型“{argType}”的参数不是类型为“{fieldType}”的字段“{fieldName}”的有效转换器", "dataClassConverterOverloads": "“{funcName}”的重载不是类型为“{fieldType}”的字段“{fieldName}”的有效转换器", "dataClassFieldInheritedDefault": "“{fieldName}”替代同名字段,但缺少默认值", + "dataClassFieldInvalidAlias": "别名“{aliasName}”不是有效的标识符", "dataClassFieldWithDefault": "没有默认值的字段不能出现在具有默认值的字段之后", "dataClassFieldWithPrivateName": "数据类字段不能使用专用名称", "dataClassFieldWithoutAnnotation": "不带类型批注的数据类字段将导致运行时异常", @@ -561,6 +562,7 @@ "typedDictEntryName": "字典条目名称的预期字符串文本", "typedDictEntryUnique": "字典中的名称必须唯一", "typedDictExtraArgs": "不支持额外的 TypedDict 参数", + "typedDictExtraItemsClosed": "如果 TypedDict 支持额外项目,则无法将其 closed", "typedDictFieldNotRequiredRedefinition": "无法将 TypedDict 项“{name}”重新定义为 NotRequired", "typedDictFieldReadOnlyRedefinition": "无法将 TypedDict 项“{name}”重新定义为 ReadOnly", "typedDictFieldRequiredRedefinition": "无法将 TypedDict 项“{name}”重新定义为 Required", diff --git a/packages/pyright-internal/src/localization/package.nls.zh-tw.json b/packages/pyright-internal/src/localization/package.nls.zh-tw.json index 9c35f4a3c..d061f01ae 100644 --- a/packages/pyright-internal/src/localization/package.nls.zh-tw.json +++ b/packages/pyright-internal/src/localization/package.nls.zh-tw.json @@ -104,6 +104,7 @@ "dataClassConverterFunction": "類型 \"{argType}\" 的引數不是類型 \"{fieldType}\" 欄位 \"{fieldName}\" 的有效轉換程式", "dataClassConverterOverloads": "\"{funcName}\" 沒有任何多載是類型 \"{fieldType}\" 欄位 \"{fieldName}\" 的有效轉換程式", "dataClassFieldInheritedDefault": "\"{fieldName}\" 覆寫相同名稱的欄位,但缺少預設值", + "dataClassFieldInvalidAlias": "別名名稱 \"{aliasName}\" 並非有效的識別碼", "dataClassFieldWithDefault": "沒有預設值的欄位無法出現在具有預設值的欄位後面", "dataClassFieldWithPrivateName": "Dataclass 欄位不能使用私人名稱", "dataClassFieldWithoutAnnotation": "沒有型別註釋的 Dataclass 欄位會造成執行階段例外狀況", @@ -561,6 +562,7 @@ "typedDictEntryName": "字典項目名稱預期為字串常值", "typedDictEntryUnique": "字典內的名稱必須是唯一的", "typedDictExtraArgs": "不支援額外的 TypedDict 引數", + "typedDictExtraItemsClosed": "如果 TypedDict 支援額外項目,就不能是 closed", "typedDictFieldNotRequiredRedefinition": "TypedDict 項目 \"{name}\" 不能重新定義為 NotRequired", "typedDictFieldReadOnlyRedefinition": "TypedDict 項目 \"{name}\" 不能重新定義為 ReadOnly", "typedDictFieldRequiredRedefinition": "TypedDict 項目 \"{name}\" 不能重新定義為 Required", @@ -795,7 +797,7 @@ "typedDictClosedExtraTypeMismatch": "無法新增型別為 \"{type}\" 的項目 \"{name}\"", "typedDictClosedFieldNotRequired": "無法新增項目 \"{name}\",因為它必須是 NotRequired", "typedDictExtraFieldNotAllowed": "\"{name}\" 不存在於 \"{type}\"", - "typedDictExtraFieldTypeMismatch": "\"{name}\" 型別與 \"{type}\" 中的 \"extra_items\" 型別不相容", + "typedDictExtraFieldTypeMismatch": "\"{name}\" 的類型與 \"{type}\" 中 \"extra_items\" 的類型不相容", "typedDictFieldMissing": "\"{type}\" 遺失 \"{name}\"", "typedDictFieldNotReadOnly": "\"{name}\" 在 \"{type}\" 中不是唯讀", "typedDictFieldNotRequired": "\"{type}\" 中不需要 \"{name}\"", From e7f0d3651cf7efee10a6d87595f1dda6b70d9d43 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 24 Oct 2024 11:32:50 -0700 Subject: [PATCH 03/21] Enhanced type narrowing logic for "x == " type guard pattern to handle the case where `x` is a type variable with a literal upper bound or value constraints that are literals. This addresses #9300. (#9318) --- .../src/analyzer/typeGuards.ts | 2 +- .../tests/samples/typeNarrowingLiteral1.py | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeGuards.ts b/packages/pyright-internal/src/analyzer/typeGuards.ts index 8530284a5..3db90d2c5 100644 --- a/packages/pyright-internal/src/analyzer/typeGuards.ts +++ b/packages/pyright-internal/src/analyzer/typeGuards.ts @@ -2468,7 +2468,7 @@ function narrowTypeForLiteralComparison( isPositiveTest: boolean, isIsOperator: boolean ): Type { - return mapSubtypes(referenceType, (subtype) => { + return evaluator.mapSubtypesExpandTypeVars(referenceType, /* options */ undefined, (subtype) => { subtype = evaluator.makeTopLevelTypeVarsConcrete(subtype); if (isAnyOrUnknown(subtype)) { diff --git a/packages/pyright-internal/src/tests/samples/typeNarrowingLiteral1.py b/packages/pyright-internal/src/tests/samples/typeNarrowingLiteral1.py index b7733d5c7..fffe72513 100644 --- a/packages/pyright-internal/src/tests/samples/typeNarrowingLiteral1.py +++ b/packages/pyright-internal/src/tests/samples/typeNarrowingLiteral1.py @@ -1,7 +1,7 @@ # This sample tests the type analyzer's type narrowing # logic for literals. -from typing import Literal, Union +from typing import Literal, TypeVar, Union def func1(p1: Literal["a", "b", "c"]): @@ -28,3 +28,27 @@ def func2(p1: Literal[1, 4, 7]): def func3(a: Union[int, None]): if a == 1 or a == 2: reveal_type(a, expected_text="Literal[1, 2]") + + +T = TypeVar("T", bound=Literal["a", "b"]) + + +def func4(x: T) -> T: + if x == "a": + reveal_type(x, expected_text="Literal['a']") + return x + else: + reveal_type(x, expected_text="Literal['b']") + return x + + +S = TypeVar("S", Literal["a"], Literal["b"]) + + +def func5(x: S) -> S: + if x == "a": + reveal_type(x, expected_text="Literal['a']") + return x + else: + reveal_type(x, expected_text="Literal['b']") + return x From a32674516ff06dda31702264390218227b65e684 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 24 Oct 2024 14:49:25 -0700 Subject: [PATCH 04/21] Fixed bug that leads to a false negative when passing multiple `*args` or `**kwargs` arguments to a callable parameterized by a ParamSpec. This addresses #9319. (#9322) --- .../src/analyzer/typeEvaluator.ts | 16 +++++++++++++++ .../src/localization/localize.ts | 2 ++ .../src/localization/package.nls.en-us.json | 4 ++++ .../src/tests/samples/paramSpec49.py | 3 +++ .../src/tests/samples/paramSpec8.py | 20 ++++++++++++------- .../src/tests/typeEvaluator4.test.ts | 4 ++-- 6 files changed, 40 insertions(+), 9 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index ae504d03a..f5dc12135 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -11792,12 +11792,28 @@ export function createTypeEvaluator( if (paramSpec) { if (argParam.argument.argCategory === ArgCategory.UnpackedList) { if (isParamSpecArgs(paramSpec, argResult.argType)) { + if (sawParamSpecArgs) { + addDiagnostic( + DiagnosticRule.reportCallIssue, + LocMessage.paramSpecArgsKwargsDuplicate().format({ type: printType(paramSpec) }), + argParam.errorNode + ); + } + sawParamSpecArgs = true; } } if (argParam.argument.argCategory === ArgCategory.UnpackedDictionary) { if (isParamSpecKwargs(paramSpec, argResult.argType)) { + if (sawParamSpecKwargs) { + addDiagnostic( + DiagnosticRule.reportCallIssue, + LocMessage.paramSpecArgsKwargsDuplicate().format({ type: printType(paramSpec) }), + argParam.errorNode + ); + } + sawParamSpecKwargs = true; } } diff --git a/packages/pyright-internal/src/localization/localize.ts b/packages/pyright-internal/src/localization/localize.ts index 38ff00ee6..9e2058727 100644 --- a/packages/pyright-internal/src/localization/localize.ts +++ b/packages/pyright-internal/src/localization/localize.ts @@ -775,6 +775,8 @@ export namespace Localizer { new ParameterizedString<{ name: string }>(getRawString('Diagnostic.paramAnnotationMissing')); export const paramNameMissing = () => new ParameterizedString<{ name: string }>(getRawString('Diagnostic.paramNameMissing')); + export const paramSpecArgsKwargsDuplicate = () => + new ParameterizedString<{ type: string }>(getRawString('Diagnostic.paramSpecArgsKwargsDuplicate')); export const paramSpecArgsKwargsUsage = () => getRawString('Diagnostic.paramSpecArgsKwargsUsage'); export const paramSpecArgsMissing = () => new ParameterizedString<{ type: string }>(getRawString('Diagnostic.paramSpecArgsMissing')); diff --git a/packages/pyright-internal/src/localization/package.nls.en-us.json b/packages/pyright-internal/src/localization/package.nls.en-us.json index 0630fb87d..3b1463395 100644 --- a/packages/pyright-internal/src/localization/package.nls.en-us.json +++ b/packages/pyright-internal/src/localization/package.nls.en-us.json @@ -920,6 +920,10 @@ "paramAnnotationMissing": "Type annotation is missing for parameter \"{name}\"", "paramAssignmentMismatch": "Expression of type \"{sourceType}\" cannot be assigned to parameter of type \"{paramType}\"", "paramNameMissing": "No parameter named \"{name}\"", + "paramSpecArgsKwargsDuplicate": { + "message": "Arguments for ParamSpec \"{type}\" have already been provided", + "comment": "{Locked='ParamSpec'}" + }, "paramSpecArgsKwargsUsage": { "message": "\"args\" and \"kwargs\" attributes of ParamSpec must both appear within a function signature", "comment": "{Locked='args','kwargs','ParamSpec'}" diff --git a/packages/pyright-internal/src/tests/samples/paramSpec49.py b/packages/pyright-internal/src/tests/samples/paramSpec49.py index 44ce563f5..a12574f6c 100644 --- a/packages/pyright-internal/src/tests/samples/paramSpec49.py +++ b/packages/pyright-internal/src/tests/samples/paramSpec49.py @@ -57,3 +57,6 @@ def inner6(*args: P.args, **kwargs: P.kwargs) -> None: # extra *args argument. self.dispatcher.dispatch(stub, 1, *args, *args, **kwargs) + # This should generate an error because it has an + # extra **kwargs argument. + self.dispatcher.dispatch(stub, 1, *args, **kwargs, **kwargs) diff --git a/packages/pyright-internal/src/tests/samples/paramSpec8.py b/packages/pyright-internal/src/tests/samples/paramSpec8.py index 7f6f0e726..c548d8fd4 100644 --- a/packages/pyright-internal/src/tests/samples/paramSpec8.py +++ b/packages/pyright-internal/src/tests/samples/paramSpec8.py @@ -17,7 +17,7 @@ def func2(*args: P.args, s: str, t: int, **kwargs: P.kwargs) -> None: # Rejecte def remove(f: Callable[Concatenate[int, P], int]) -> Callable[P, None]: - def foo(*args: P.args, **kwargs: P.kwargs) -> None: + def func1(*args: P.args, **kwargs: P.kwargs) -> None: f(1, *args, **kwargs) # Accepted # Should generate an error because positional parameter @@ -28,18 +28,24 @@ def foo(*args: P.args, **kwargs: P.kwargs) -> None: # is missing. f(*args, **kwargs) # Rejected - return foo + return func1 def outer(f: Callable[P, None]) -> Callable[P, None]: - def foo(x: int, *args: P.args, **kwargs: P.kwargs) -> None: + def func1(x: int, *args: P.args, **kwargs: P.kwargs) -> None: f(*args, **kwargs) - def bar(*args: P.args, **kwargs: P.kwargs) -> None: - foo(1, *args, **kwargs) # Accepted + def func2(*args: P.args, **kwargs: P.kwargs) -> None: + func1(1, *args, **kwargs) # Accepted # This should generate an error because keyword parameters # are not allowed in this situation. - foo(x=1, *args, **kwargs) # Rejected + func1(x=1, *args, **kwargs) # Rejected - return bar + # This should generate an error because *args is duplicated. + func1(1, *args, *args, **kwargs) + + # This should generate an error because **kwargs is duplicated. + func1(1, *args, **kwargs, **kwargs) + + return func2 diff --git a/packages/pyright-internal/src/tests/typeEvaluator4.test.ts b/packages/pyright-internal/src/tests/typeEvaluator4.test.ts index 0648f0257..0e30d6773 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator4.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator4.test.ts @@ -607,7 +607,7 @@ test('ParamSpec7', () => { test('ParamSpec8', () => { const results = TestUtils.typeAnalyzeSampleFiles(['paramSpec8.py']); - TestUtils.validateResults(results, 5); + TestUtils.validateResults(results, 7); }); test('ParamSpec9', () => { @@ -812,7 +812,7 @@ test('ParamSpec48', () => { test('ParamSpec49', () => { const results = TestUtils.typeAnalyzeSampleFiles(['paramSpec49.py']); - TestUtils.validateResults(results, 5); + TestUtils.validateResults(results, 7); }); test('ParamSpec50', () => { From 5537ec9bcfeffdac543735fdf94e6d80318b5513 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Thu, 24 Oct 2024 15:57:03 -0700 Subject: [PATCH 05/21] Fixed issue that results in a false positive "type could not be determined because it refers to itself" error caused by a false dependency due to narrowing logic. This may also improve type analysis performance in some code. This addresses #9139. (#9323) --- .../pyright-internal/src/analyzer/binder.ts | 156 ++++++++---------- .../src/tests/samples/loop51.py | 21 +++ .../src/tests/typeEvaluator3.test.ts | 6 + 3 files changed, 94 insertions(+), 89 deletions(-) create mode 100644 packages/pyright-internal/src/tests/samples/loop51.py diff --git a/packages/pyright-internal/src/analyzer/binder.ts b/packages/pyright-internal/src/analyzer/binder.ts index 17c9c8a97..c1585aacd 100644 --- a/packages/pyright-internal/src/analyzer/binder.ts +++ b/packages/pyright-internal/src/analyzer/binder.ts @@ -150,6 +150,12 @@ interface ClassVarInfo { classVarTypeNode: ExpressionNode | undefined; } +interface NarrowExprOptions { + filterForNeverNarrowing?: boolean; + isComplexExpression?: boolean; + allowDiscriminatedNarrowing?: boolean; +} + // For each flow node within an execution context, we'll add a small // amount to the complexity factor. Without this, the complexity // calculation fails to take into account large numbers of non-cyclical @@ -2870,7 +2876,7 @@ export class Binder extends ParseTreeWalker { // Limit only to expressions that contain a narrowable subexpression // that is a name. This avoids complexities with composite expressions like // member access or index expressions. - if (this._isNarrowingExpression(node, expressionList, /* neverNarrowingExpressions */ true)) { + if (this._isNarrowingExpression(node, expressionList, { filterForNeverNarrowing: true })) { const filteredExprList = expressionList.filter((expr) => expr.nodeType === ParseNodeType.Name); if (filteredExprList.length > 0) { this._currentFlowNode = this._createFlowConditional( @@ -2942,13 +2948,9 @@ export class Binder extends ParseTreeWalker { const expressionList: CodeFlowReferenceExpressionNode[] = []; if ( - !this._isNarrowingExpression( - expression, - expressionList, - /* filterForNeverNarrowing */ (flags & - (FlowFlags.TrueNeverCondition | FlowFlags.FalseNeverCondition)) !== - 0 - ) + !this._isNarrowingExpression(expression, expressionList, { + filterForNeverNarrowing: (flags & (FlowFlags.TrueNeverCondition | FlowFlags.FalseNeverCondition)) !== 0, + }) ) { return antecedent; } @@ -3000,14 +3002,13 @@ export class Binder extends ParseTreeWalker { private _isNarrowingExpression( expression: ExpressionNode, expressionList: CodeFlowReferenceExpressionNode[], - filterForNeverNarrowing = false, - isComplexExpression = false + options: NarrowExprOptions = {} ): boolean { switch (expression.nodeType) { case ParseNodeType.Name: case ParseNodeType.MemberAccess: case ParseNodeType.Index: { - if (filterForNeverNarrowing) { + if (options.filterForNeverNarrowing) { // Never narrowing doesn't support member access or index // expressions. if (expression.nodeType !== ParseNodeType.Name) { @@ -3017,7 +3018,7 @@ export class Binder extends ParseTreeWalker { // Never narrowing doesn't support simple names (falsy // or truthy narrowing) because it's too expensive and // provides relatively little utility. - if (!isComplexExpression) { + if (!options.isComplexExpression) { return false; } } @@ -3025,11 +3026,11 @@ export class Binder extends ParseTreeWalker { if (isCodeFlowSupportedForReference(expression)) { expressionList.push(expression); - if (!filterForNeverNarrowing) { + if (!options.filterForNeverNarrowing) { // If the expression is a member access expression, add its // leftExpression to the expression list because that expression // can be narrowed based on the attribute type. - if (expression.nodeType === ParseNodeType.MemberAccess) { + if (expression.nodeType === ParseNodeType.MemberAccess && options.allowDiscriminatedNarrowing) { if (isCodeFlowSupportedForReference(expression.d.leftExpr)) { expressionList.push(expression.d.leftExpr); } @@ -3057,12 +3058,10 @@ export class Binder extends ParseTreeWalker { case ParseNodeType.AssignmentExpression: { expressionList.push(expression.d.name); - this._isNarrowingExpression( - expression.d.rightExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + this._isNarrowingExpression(expression.d.rightExpr, expressionList, { + ...options, + isComplexExpression: true, + }); return true; } @@ -3079,12 +3078,11 @@ export class Binder extends ParseTreeWalker { expression.d.rightExpr.nodeType === ParseNodeType.Constant && expression.d.rightExpr.d.constType === KeywordType.None ) { - return this._isNarrowingExpression( - expression.d.leftExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + return this._isNarrowingExpression(expression.d.leftExpr, expressionList, { + ...options, + isComplexExpression: true, + allowDiscriminatedNarrowing: true, + }); } // Look for "type(X) is Y" or "type(X) is not Y". @@ -3099,17 +3097,15 @@ export class Binder extends ParseTreeWalker { return this._isNarrowingExpression( expression.d.leftExpr.d.args[0].d.valueExpr, expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true + { ...options, isComplexExpression: true } ); } - const isLeftNarrowing = this._isNarrowingExpression( - expression.d.leftExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + const isLeftNarrowing = this._isNarrowingExpression(expression.d.leftExpr, expressionList, { + ...options, + isComplexExpression: true, + allowDiscriminatedNarrowing: true, + }); // Look for "X is Y" or "X is not Y". // Look for X == or X != @@ -3125,12 +3121,10 @@ export class Binder extends ParseTreeWalker { expression.d.operator === OperatorType.GreaterThan || expression.d.operator === OperatorType.GreaterThanOrEqual ) { - const isLeftNarrowing = this._isNarrowingExpression( - expression.d.leftExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + const isLeftNarrowing = this._isNarrowingExpression(expression.d.leftExpr, expressionList, { + ...options, + isComplexExpression: true, + }); return isLeftNarrowing; } @@ -3140,12 +3134,10 @@ export class Binder extends ParseTreeWalker { if (expression.d.operator === OperatorType.In || expression.d.operator === OperatorType.NotIn) { if ( expression.d.leftExpr.nodeType === ParseNodeType.StringList && - this._isNarrowingExpression( - expression.d.rightExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ) + this._isNarrowingExpression(expression.d.rightExpr, expressionList, { + ...options, + isComplexExpression: true, + }) ) { return true; } @@ -3153,19 +3145,15 @@ export class Binder extends ParseTreeWalker { // Look for "X in Y" or "X not in Y". if (expression.d.operator === OperatorType.In || expression.d.operator === OperatorType.NotIn) { - const isLeftNarrowable = this._isNarrowingExpression( - expression.d.leftExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + const isLeftNarrowable = this._isNarrowingExpression(expression.d.leftExpr, expressionList, { + ...options, + isComplexExpression: true, + }); - const isRightNarrowable = this._isNarrowingExpression( - expression.d.rightExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + const isRightNarrowable = this._isNarrowingExpression(expression.d.rightExpr, expressionList, { + ...options, + isComplexExpression: true, + }); return isLeftNarrowable || isRightNarrowable; } @@ -3176,22 +3164,18 @@ export class Binder extends ParseTreeWalker { case ParseNodeType.UnaryOperation: { return ( expression.d.operator === OperatorType.Not && - this._isNarrowingExpression( - expression.d.expr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ false - ) + this._isNarrowingExpression(expression.d.expr, expressionList, { + ...options, + isComplexExpression: false, + }) ); } case ParseNodeType.AugmentedAssignment: { - return this._isNarrowingExpression( - expression.d.rightExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + return this._isNarrowingExpression(expression.d.rightExpr, expressionList, { + ...options, + isComplexExpression: true, + }); } case ParseNodeType.Call: { @@ -3201,12 +3185,10 @@ export class Binder extends ParseTreeWalker { expression.d.leftExpr.d.value === 'issubclass') && expression.d.args.length === 2 ) { - return this._isNarrowingExpression( - expression.d.args[0].d.valueExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + return this._isNarrowingExpression(expression.d.args[0].d.valueExpr, expressionList, { + ...options, + isComplexExpression: true, + }); } if ( @@ -3214,28 +3196,24 @@ export class Binder extends ParseTreeWalker { expression.d.leftExpr.d.value === 'callable' && expression.d.args.length === 1 ) { - return this._isNarrowingExpression( - expression.d.args[0].d.valueExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + return this._isNarrowingExpression(expression.d.args[0].d.valueExpr, expressionList, { + ...options, + isComplexExpression: true, + }); } // Is this potentially a call to a user-defined type guard function? if (expression.d.args.length >= 1) { // Never narrowing doesn't support type guards because they do not // offer negative narrowing. - if (filterForNeverNarrowing) { + if (options.filterForNeverNarrowing) { return false; } - return this._isNarrowingExpression( - expression.d.args[0].d.valueExpr, - expressionList, - filterForNeverNarrowing, - /* isComplexExpression */ true - ); + return this._isNarrowingExpression(expression.d.args[0].d.valueExpr, expressionList, { + ...options, + isComplexExpression: true, + }); } } } diff --git a/packages/pyright-internal/src/tests/samples/loop51.py b/packages/pyright-internal/src/tests/samples/loop51.py new file mode 100644 index 000000000..1f3b41310 --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/loop51.py @@ -0,0 +1,21 @@ +# This sample tests a case where type evaluation for a type guard +# within a loop may trigger a false positive "type depends on itself" +# error message. + +# For details, see https://github.com/microsoft/pyright/issues/9139. + +from enum import StrEnum + + +class MyEnum(StrEnum): + A = "A" + + +for _ in range(2): + x: dict[MyEnum, int] = {} + + if MyEnum.A in x: + ... + + for _ in x.values(): + ... diff --git a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts index 1080cd597..7b57a9fd1 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts @@ -485,6 +485,12 @@ test('Loop50', () => { TestUtils.validateResults(analysisResults, 0); }); +test('Loop51', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['loop51.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + test('ForLoop1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['forLoop1.py']); From 662ebf5a2e47661943866148e811fb926366233e Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 25 Oct 2024 11:12:57 -0700 Subject: [PATCH 06/21] Switched to a different toml parser to avoid incompatibility with the latest toml standard. This addresses #9296. --- packages/pyright-internal/package-lock.json | 103 +++++++++++++++++- packages/pyright-internal/package.json | 2 +- .../pyright-internal/src/analyzer/service.ts | 8 +- 3 files changed, 102 insertions(+), 11 deletions(-) diff --git a/packages/pyright-internal/package-lock.json b/packages/pyright-internal/package-lock.json index 37d5db4a0..bd84857b8 100644 --- a/packages/pyright-internal/package-lock.json +++ b/packages/pyright-internal/package-lock.json @@ -9,12 +9,12 @@ "version": "1.1.386", "license": "MIT", "dependencies": { - "@iarna/toml": "3.0.0", "@yarnpkg/fslib": "2.10.4", "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.2", "chokidar": "^3.6.0", "command-line-args": "^5.2.1", + "js-toml": "^1.0.0", "jsonc-parser": "^3.3.1", "leven": "3.1.0", "source-map-support": "^0.5.21", @@ -558,6 +558,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.0.tgz", + "integrity": "sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", @@ -610,6 +622,40 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@chevrotain/cst-dts-gen": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", + "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", + "dependencies": { + "@chevrotain/gast": "11.0.3", + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/gast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", + "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", + "dependencies": { + "@chevrotain/types": "11.0.3", + "lodash-es": "4.17.21" + } + }, + "node_modules/@chevrotain/regexp-to-ast": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", + "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==" + }, + "node_modules/@chevrotain/types": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", + "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==" + }, + "node_modules/@chevrotain/utils": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", + "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==" + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -987,11 +1033,6 @@ "node": ">=12" } }, - "node_modules/@iarna/toml": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@iarna/toml/-/toml-3.0.0.tgz", - "integrity": "sha512-td6ZUkz2oS3VeleBcN+m//Q6HlCFCPrnI0FZhrt/h4XqLEdOyYp2u21nd8MdsR+WJy5r9PTDaHTDDfhf4H4l6Q==" - }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2276,6 +2317,19 @@ "node": ">=10" } }, + "node_modules/chevrotain": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", + "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", + "dependencies": { + "@chevrotain/cst-dts-gen": "11.0.3", + "@chevrotain/gast": "11.0.3", + "@chevrotain/regexp-to-ast": "11.0.3", + "@chevrotain/types": "11.0.3", + "@chevrotain/utils": "11.0.3", + "lodash-es": "4.17.21" + } + }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2463,6 +2517,16 @@ "node": ">=10.13.0" } }, + "node_modules/core-js-pure": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", + "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -4082,6 +4146,15 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, + "node_modules/js-toml": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/js-toml/-/js-toml-1.0.0.tgz", + "integrity": "sha512-G757004huuG5Cjg8KUoVTS4zNRR4449KG8kjtFQS0yyQnceq3KfxcArThcqUV2cwdpd0C9I+e1WciK3Xm4cWJw==", + "dependencies": { + "chevrotain": "^11.0.3", + "xregexp": "^5.1.1" + } + }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -4203,6 +4276,11 @@ "node": ">=8" } }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -4701,6 +4779,11 @@ "node": ">= 0.10" } }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5831,6 +5914,14 @@ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true }, + "node_modules/xregexp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz", + "integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==", + "dependencies": { + "@babel/runtime-corejs3": "^7.16.5" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/packages/pyright-internal/package.json b/packages/pyright-internal/package.json index 45174b985..461ea2ad8 100644 --- a/packages/pyright-internal/package.json +++ b/packages/pyright-internal/package.json @@ -19,12 +19,12 @@ "test:imports": "jest importResolver.test --forceExit --runInBand" }, "dependencies": { - "@iarna/toml": "3.0.0", "@yarnpkg/fslib": "2.10.4", "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.2", "chokidar": "^3.6.0", "command-line-args": "^5.2.1", + "js-toml": "^1.0.0", "jsonc-parser": "^3.3.1", "leven": "3.1.0", "source-map-support": "^0.5.21", diff --git a/packages/pyright-internal/src/analyzer/service.ts b/packages/pyright-internal/src/analyzer/service.ts index 1324ce21d..fca567fd8 100644 --- a/packages/pyright-internal/src/analyzer/service.ts +++ b/packages/pyright-internal/src/analyzer/service.ts @@ -8,7 +8,7 @@ * Python files. */ -import * as TOML from '@iarna/toml'; +import * as TOML from 'js-toml'; import * as JSONC from 'jsonc-parser'; import { AbstractCancellationTokenSource, CancellationToken } from 'vscode-languageserver'; @@ -1137,9 +1137,9 @@ export class AnalyzerService { private _parsePyprojectTomlFile(pyprojectPath: Uri): object | undefined { return this._attemptParseFile(pyprojectPath, (fileContents, attemptCount) => { try { - const configObj = TOML.parse(fileContents); - if (configObj && configObj.tool && (configObj.tool as TOML.JsonMap).pyright) { - return (configObj.tool as TOML.JsonMap).pyright as object; + const configObj = TOML.load(fileContents); + if (configObj && 'tool' in configObj) { + return (configObj.tool as Record).pyright as object; } } catch (e: any) { this._console.error(`Pyproject file parse attempt ${attemptCount} error: ${JSON.stringify(e)}`); From 1579b06da1fee9e0660e5f1d8094e43ed703783d Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Fri, 25 Oct 2024 14:48:09 -0700 Subject: [PATCH 07/21] Changed the evaluated type of an `in` or `not in` operator to be `bool` if the LHS doesn't support containment. Previously, the expression evaluated to `Never`. This addresses #9327. (#9328) --- packages/pyright-internal/src/analyzer/operations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pyright-internal/src/analyzer/operations.ts b/packages/pyright-internal/src/analyzer/operations.ts index fceccba4a..d71c582b1 100644 --- a/packages/pyright-internal/src/analyzer/operations.ts +++ b/packages/pyright-internal/src/analyzer/operations.ts @@ -1198,7 +1198,7 @@ function validateContainmentOperation( deprecatedInfo = returnTypeResult.magicMethodDeprecationInfo; } - return returnTypeResult?.type; + return returnTypeResult?.type ?? evaluator.getBuiltInObject(errorNode, 'bool'); } ); } From 471f76b82d4b58e570c448dd53a6c2b93013dc4d Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 28 Oct 2024 09:10:14 -0700 Subject: [PATCH 08/21] Fixed a bug that results in a false positive when a class parameterized by a TypeVarTuple is used in conjunction with a Self type. This addresses #9340. (#9342) --- packages/pyright-internal/src/analyzer/typeUtils.ts | 4 ++++ .../src/tests/samples/typeVarTuple30.py | 11 +++++++++++ .../pyright-internal/src/tests/typeEvaluator6.test.ts | 8 ++++++++ 3 files changed, 23 insertions(+) create mode 100644 packages/pyright-internal/src/tests/samples/typeVarTuple30.py diff --git a/packages/pyright-internal/src/analyzer/typeUtils.ts b/packages/pyright-internal/src/analyzer/typeUtils.ts index 82423da35..a6c742d48 100644 --- a/packages/pyright-internal/src/analyzer/typeUtils.ts +++ b/packages/pyright-internal/src/analyzer/typeUtils.ts @@ -1156,6 +1156,10 @@ export function selfSpecializeClass(type: ClassType, options?: SelfSpecializeOpt } const typeParams = type.shared.typeParams.map((typeParam) => { + if (isTypeVarTuple(typeParam)) { + typeParam = TypeVarType.cloneForUnpacked(typeParam); + } + return options?.useBoundTypeVars ? TypeVarType.cloneAsBound(typeParam) : typeParam; }); return ClassType.specialize(type, typeParams); diff --git a/packages/pyright-internal/src/tests/samples/typeVarTuple30.py b/packages/pyright-internal/src/tests/samples/typeVarTuple30.py new file mode 100644 index 000000000..8a33f999b --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/typeVarTuple30.py @@ -0,0 +1,11 @@ +# This sample tests the case where a TypeVarTuple is used in a class +# and a `Self` type is involved. + +class Parent[*Ts]: + def __init__(self, *args: *Ts): ... + + def method(self): + Child(self) + + +class Child(Parent[*tuple[Parent, ...]]): ... diff --git a/packages/pyright-internal/src/tests/typeEvaluator6.test.ts b/packages/pyright-internal/src/tests/typeEvaluator6.test.ts index cd8f2e1cb..5551158ef 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator6.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator6.test.ts @@ -419,6 +419,14 @@ test('TypeVarTuple29', () => { TestUtils.validateResults(analysisResults, 0); }); +test('TypeVarTuple30', () => { + const configOptions = new ConfigOptions(Uri.empty()); + + configOptions.defaultPythonVersion = pythonVersion3_12; + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeVarTuple30.py'], configOptions); + TestUtils.validateResults(analysisResults, 0); +}); + test('Match1', () => { const configOptions = new ConfigOptions(Uri.empty()); From 901c75f6c0b864b9155a0e7072a259f47ec9720c Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 28 Oct 2024 11:27:23 -0700 Subject: [PATCH 09/21] Fixed bug that results in incorrect type evaluation when performing protocol matching that involves an attribute with a callable type parameterized by a ParamSpec. This addresses #9330. (#9344) --- .../src/analyzer/protocols.ts | 2 +- .../src/tests/samples/protocol52.py | 24 +++++++++++++++++++ .../src/tests/typeEvaluator7.test.ts | 6 +++++ 3 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 packages/pyright-internal/src/tests/samples/protocol52.py diff --git a/packages/pyright-internal/src/analyzer/protocols.ts b/packages/pyright-internal/src/analyzer/protocols.ts index 7518a15b0..4c908c193 100644 --- a/packages/pyright-internal/src/analyzer/protocols.ts +++ b/packages/pyright-internal/src/analyzer/protocols.ts @@ -569,7 +569,7 @@ function assignToProtocolInternal( destMemberType = applySolvedTypeVars(destMemberType, selfSolution); // If the dest is a method, bind it. - if (isFunction(destMemberType) || isOverloaded(destMemberType)) { + if (!destSymbol.isInstanceMember() && (isFunction(destMemberType) || isOverloaded(destMemberType))) { let boundDeclaredType: FunctionType | OverloadedType | undefined; // Functions are considered read-only. diff --git a/packages/pyright-internal/src/tests/samples/protocol52.py b/packages/pyright-internal/src/tests/samples/protocol52.py new file mode 100644 index 000000000..ebd0437dd --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/protocol52.py @@ -0,0 +1,24 @@ +# This sample tests the case where a protocol includes a callable +# attribute that is an instance variable. It shouldn't be bound +# to the concrete class in this case. + +from typing import Callable, Protocol + + +class A: + def __init__(self, *, p1: int, p2: str) -> None: ... + + +class ProtoB[**P, T](Protocol): + x: Callable[P, T] + + +class B: + x: type[A] + + +def func1[**P, T](v: ProtoB[P, T]) -> Callable[P, T]: ... + + +x1 = func1(B()) +reveal_type(x1, expected_text="(*, p1: int, p2: str) -> A") diff --git a/packages/pyright-internal/src/tests/typeEvaluator7.test.ts b/packages/pyright-internal/src/tests/typeEvaluator7.test.ts index a354f6a00..08a2a7ce0 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator7.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator7.test.ts @@ -605,6 +605,12 @@ test('Protocol51', () => { TestUtils.validateResults(analysisResults, 0); }); +test('Protocol52', () => { + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocol52.py']); + + TestUtils.validateResults(analysisResults, 0); +}); + test('ProtocolExplicit1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocolExplicit1.py']); From bd766f86198818261dffb11e38049b3bf0692271 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 28 Oct 2024 13:23:37 -0700 Subject: [PATCH 10/21] Improved detection of asymmetric descriptors to handle the case where the `__set__` and `__get__` methods are overloaded. This addresses #9332. (#9345) --- .../src/analyzer/typeEvaluator.ts | 24 +++++- .../src/tests/samples/descriptor1.py | 74 +++++++++++-------- 2 files changed, 68 insertions(+), 30 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index f5dc12135..df5f539a2 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -6566,9 +6566,31 @@ export function createTypeEvaluator( if (!getterSymbolResult || !setterSymbolResult) { isAsymmetric = false; } else { - const getterType = getEffectiveTypeOfSymbol(getterSymbolResult.symbol); + let getterType = getEffectiveTypeOfSymbol(getterSymbolResult.symbol); const setterType = getEffectiveTypeOfSymbol(setterSymbolResult.symbol); + // If this is an overload, find the appropriate overload. + if (isOverloaded(getterType)) { + const getOverloads = OverloadedType.getOverloads(getterType).filter((overload) => { + if (overload.shared.parameters.length < 2) { + return false; + } + const param1Type = FunctionType.getParamType(overload, 1); + return !isNoneInstance(param1Type); + }); + + if (getOverloads.length === 1) { + getterType = getOverloads[0]; + } else { + isAsymmetric = true; + } + } + + // If this is an overload, find the appropriate overload. + if (isOverloaded(setterType)) { + isAsymmetric = true; + } + // If either the setter or getter is an overload (or some other non-function type), // conservatively assume that it's not asymmetric. if (isFunction(getterType) && isFunction(setterType)) { diff --git a/packages/pyright-internal/src/tests/samples/descriptor1.py b/packages/pyright-internal/src/tests/samples/descriptor1.py index b7f10f040..b92833c3f 100644 --- a/packages/pyright-internal/src/tests/samples/descriptor1.py +++ b/packages/pyright-internal/src/tests/samples/descriptor1.py @@ -1,41 +1,33 @@ # This sample tests the detection and handling of asymmetric descriptors # and properties. Type narrowing should be disabled in these cases. -from typing import Any, Literal +from typing import Any, Hashable, Iterable, Literal, overload class A: @property - def prop1(self) -> int | None: - ... + def prop1(self) -> int | None: ... @prop1.setter - def prop1(self, val: int | None) -> None: - ... + def prop1(self, val: int | None) -> None: ... @property - def prop2(self) -> int | None: - ... + def prop2(self) -> int | None: ... @prop2.setter - def prop2(self, val: int) -> None: - ... + def prop2(self, val: int) -> None: ... @prop2.deleter - def prop2(self) -> None: - ... + def prop2(self) -> None: ... @property - def prop3(self) -> int: - ... + def prop3(self) -> int: ... @prop3.setter - def prop3(self, val: int | None) -> None: - ... + def prop3(self, val: int | None) -> None: ... @prop3.deleter - def prop3(self) -> None: - ... + def prop3(self) -> None: ... def func1(obj: A) -> Literal[3]: @@ -72,33 +64,49 @@ def func3(obj: A) -> Literal[3]: class Descriptor1: - def __get__(self, instance: Any, owner: Any) -> int | None: - ... + def __get__(self, instance: Any, owner: Any) -> int | None: ... - def __set__(self, owner: Any, value: int | None) -> None: - ... + def __set__(self, owner: Any, value: int | None) -> None: ... class Descriptor2: - def __get__(self, instance: Any, owner: Any) -> int | None: - ... + def __get__(self, instance: Any, owner: Any) -> int | None: ... - def __set__(self, owner: Any, value: int) -> None: - ... + def __set__(self, owner: Any, value: int) -> None: ... class Descriptor3: - def __get__(self, instance: Any, owner: Any) -> int: - ... + def __get__(self, instance: Any, owner: Any) -> int: ... - def __set__(self, owner: Any, value: int | None) -> None: - ... + def __set__(self, owner: Any, value: int | None) -> None: ... + + +class Descriptor4: + @overload + def __get__(self, instance: None, owner: Any) -> int: ... + @overload + def __get__(self, instance: Any, owner: Any) -> str: ... + def __get__(self, instance: Any, owner: Any) -> int | str: ... + + def __set__(self, owner: Any, value: int | None) -> None: ... + + +class Descriptor5: + def __get__(self, instance: Any, owner: Any) -> int: ... + + @overload + def __set__(self, owner: bytes, value: int | None) -> None: ... + @overload + def __set__(self, owner: "B", value: int | None) -> None: ... + def __set__(self, owner: Any, value: int | None) -> None: ... class B: desc1: Descriptor1 desc2: Descriptor2 desc3: Descriptor3 + desc4: Descriptor4 + desc5: Descriptor5 def func4(obj: B) -> Literal[3]: @@ -132,3 +140,11 @@ def func6(obj: B) -> Literal[3]: # This should generate an error because prop2 isn't # narrowed in this case. return obj.desc3 + + +def func7(obj: B): + obj.desc4 = 3 + reveal_type(obj.desc4, expected_text="str") + + obj.desc5 = 3 + reveal_type(obj.desc5, expected_text="int") From 2ffc5f1ec5a446695dcd4eca6e1fb211b6116483 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 28 Oct 2024 13:50:07 -0700 Subject: [PATCH 11/21] Added protection for an internal call stack overflow when inferring return types in deep call hierarchies within untyped code. This addresses #9283. (#9346) --- .../pyright-internal/src/analyzer/typeEvaluator.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index df5f539a2..618f3d2cc 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -19229,6 +19229,20 @@ export function createTypeEvaluator( } writeTypeCache(node.d.suite, { type: inferredReturnType, isIncomplete }, EvalFlags.None); + } catch (err) { + // Attempt to handle a stack overflow without crashing. In rare + // cases, we can get very deep stacks when inferring return types + // within untyped code. + if ((err as any)?.message === 'Maximum call stack size exceeded') { + const fileInfo = AnalyzerNodeInfo.getFileInfo(node); + console.error( + `Overflowed stack when inferring return type for function: ${ + node.d.name.d.value + } in file ${fileInfo.fileUri.toUserVisibleString()}` + ); + return; + } + throw err; } finally { functionRecursionMap.delete(node.id); } From 84b77b03fc284c969811b6468c68f29ec95dfb62 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Mon, 28 Oct 2024 17:19:00 -0700 Subject: [PATCH 12/21] Fixed a false positive "incompatible method override" error in a case that involves both class-scoped and method-scoped type variables. This addresses #9347. (#9348) --- .../pyright-internal/src/analyzer/checker.ts | 7 +- .../src/analyzer/typeEvaluator.ts | 19 +- .../src/tests/samples/methodOverride1.py | 266 +++++++----------- .../src/tests/typeEvaluator3.test.ts | 2 +- 4 files changed, 114 insertions(+), 180 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/checker.ts b/packages/pyright-internal/src/analyzer/checker.ts index ca4d5b36b..83c81d8f6 100644 --- a/packages/pyright-internal/src/analyzer/checker.ts +++ b/packages/pyright-internal/src/analyzer/checker.ts @@ -6558,9 +6558,11 @@ export class Checker extends ParseTreeWalker { } const baseClass = baseClassAndSymbol.classType; - const childClassSelf = ClassType.cloneAsInstance(selfSpecializeClass(childClassType)); + const childClassSelf = ClassType.cloneAsInstance( + selfSpecializeClass(childClassType, { useBoundTypeVars: true }) + ); - let baseType = partiallySpecializeType( + const baseType = partiallySpecializeType( this._evaluator.getEffectiveTypeOfSymbol(baseClassAndSymbol.symbol), baseClass, this._evaluator.getTypeClassType(), @@ -6575,7 +6577,6 @@ export class Checker extends ParseTreeWalker { ); if (childClassType.shared.typeVarScopeId) { - baseType = makeTypeVarsBound(baseType, [childClassType.shared.typeVarScopeId]); overrideType = makeTypeVarsBound(overrideType, [childClassType.shared.typeVarScopeId]); } diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 618f3d2cc..78b9d8f2a 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -26812,6 +26812,7 @@ export function createTypeEvaluator( ): boolean { const baseParamDetails = getParamListDetails(baseMethod); const overrideParamDetails = getParamListDetails(overrideMethod); + const constraints = new ConstraintTracker(); let canOverride = true; @@ -26853,8 +26854,8 @@ export function createTypeEvaluator( overrideArgsType, baseParamDetails.params[i].type, diag?.createAddendum(), - /* constraints */ undefined, - AssignTypeFlags.Default + constraints, + AssignTypeFlags.Contravariant ) ) { LocAddendum.overrideParamType().format({ @@ -26976,8 +26977,8 @@ export function createTypeEvaluator( overrideParamType, baseParamType, diag?.createAddendum(), - /* constraints */ undefined, - AssignTypeFlags.Default + constraints, + AssignTypeFlags.Contravariant ) ) { diag?.addMessage( @@ -27038,8 +27039,8 @@ export function createTypeEvaluator( overrideParamType, baseParamType, diag?.createAddendum(), - /* constraints */ undefined, - AssignTypeFlags.Default + constraints, + AssignTypeFlags.Contravariant ) ) { diag?.addMessage( @@ -27083,8 +27084,8 @@ export function createTypeEvaluator( targetParamType, paramInfo.type, diag?.createAddendum(), - /* constraints */ undefined, - AssignTypeFlags.Default + constraints, + AssignTypeFlags.Contravariant ) ) { diag?.addMessage( @@ -27164,7 +27165,7 @@ export function createTypeEvaluator( baseReturnType, overrideReturnType, diag?.createAddendum(), - /* constraints */ undefined, + constraints, AssignTypeFlags.Default ) ) { diff --git a/packages/pyright-internal/src/tests/samples/methodOverride1.py b/packages/pyright-internal/src/tests/samples/methodOverride1.py index b4df2b747..06b00cd1c 100644 --- a/packages/pyright-internal/src/tests/samples/methodOverride1.py +++ b/packages/pyright-internal/src/tests/samples/methodOverride1.py @@ -18,10 +18,10 @@ P = ParamSpec("P") T = TypeVar("T") S = TypeVar("S") +U = TypeVar("U", bound=int) -def decorator(func: Callable[P, None]) -> Callable[P, int]: - ... +def decorator(func: Callable[P, None]) -> Callable[P, int]: ... class ParentClass: @@ -73,21 +73,16 @@ def my_method15(self, a: int) -> int: def my_method16(self, a: int) -> int: return 1 - def my_method17(self, a: str, b: int, c: float, d: bool) -> None: - ... + def my_method17(self, a: str, b: int, c: float, d: bool) -> None: ... - def my_method18(self, a: str, b: int, c: float, d: bool) -> None: - ... + def my_method18(self, a: str, b: int, c: float, d: bool) -> None: ... - def my_method19(self, a: str, b: int, c: float, d: bool) -> None: - ... + def my_method19(self, a: str, b: int, c: float, d: bool) -> None: ... @classmethod - def my_method20(cls: type[T_ParentClass], a: str) -> T_ParentClass: - ... + def my_method20(cls: type[T_ParentClass], a: str) -> T_ParentClass: ... - def my_method21(self, var: int) -> None: - ... + def my_method21(self, var: int) -> None: ... def _protected_method1(self, a: int): return 1 @@ -95,86 +90,61 @@ def _protected_method1(self, a: int): def __private_method1(self, a: int): return 1 - def my_method22(self, a: str, b: int, c: float, d: bool) -> None: - ... + def my_method22(self, a: str, b: int, c: float, d: bool) -> None: ... - def my_method23(self, a: str = "") -> None: - ... + def my_method23(self, a: str = "") -> None: ... - def my_method24(self, a: str) -> None: - ... + def my_method24(self, a: str) -> None: ... - def my_method25(self, *, a: str = "") -> None: - ... + def my_method25(self, *, a: str = "") -> None: ... - def my_method26(self, *, a: str) -> None: - ... + def my_method26(self, *, a: str) -> None: ... - def my_method27(self, a: object, /) -> None: - ... + def my_method27(self, a: object, /) -> None: ... - def my_method28(self, __a: object) -> None: - ... + def my_method28(self, __a: object) -> None: ... @classmethod - def my_method29(cls, /) -> None: - ... + def my_method29(cls, /) -> None: ... @classmethod - def my_method30(cls, /) -> None: - ... + def my_method30(cls, /) -> None: ... @staticmethod - def my_method31(a: "type[ParentClass]", /) -> None: - ... + def my_method31(a: "type[ParentClass]", /) -> None: ... @staticmethod - def my_method32(a: "type[ParentClass]", /) -> None: - ... + def my_method32(a: "type[ParentClass]", /) -> None: ... - def my_method33(self, /) -> None: - ... + def my_method33(self, /) -> None: ... - def my_method34(self, /) -> None: - ... + def my_method34(self, /) -> None: ... - def my_method35(self, *, a: int) -> None: - ... + def my_method35(self, *, a: int) -> None: ... - def my_method36(self, *, a: int) -> None: - ... + def my_method36(self, *, a: int) -> None: ... - def my_method37(self, a: int, /) -> None: - ... + def my_method37(self, a: int, /) -> None: ... - def my_method38(self, a: int, /) -> None: - ... + def my_method38(self, a: int, /) -> None: ... - def my_method39(self, a: int, /) -> None: - ... + def my_method39(self, a: int, /) -> None: ... - def my_method40(self, a: int, /) -> None: - ... + def my_method40(self, a: int, /) -> None: ... - def my_method41(self, a: int, b: str, c: str) -> None: - ... + def my_method41(self, a: int, b: str, c: str) -> None: ... - def my_method42(self, a: int, b: int, c: str) -> None: - ... + def my_method42(self, a: int, b: int, c: str) -> None: ... my_method43: Callable[..., None] - def my_method44(self, *args: object, **kwargs: object) -> None: - ... + def my_method44(self, *args: object, **kwargs: object) -> None: ... - def my_method45(self, __i: int) -> None: - ... + def my_method45(self, __i: int) -> None: ... - def __my_method46__(self, x: int) -> None: - ... + def __my_method46__(self, x: int) -> None: ... - def __my_method47__(self, x: int) -> None: - ... + def __my_method47__(self, x: int) -> None: ... T_ChildClass = TypeVar("T_ChildClass", bound="ChildClass") @@ -243,24 +213,19 @@ def my_method14(self, a: int) -> int | str: class my_method16: pass - def my_method17(self, *args: object, **kwargs: object) -> None: - ... + def my_method17(self, *args: object, **kwargs: object) -> None: ... - def my_method18(self, a: str, *args: object, **kwargs: object) -> None: - ... + def my_method18(self, a: str, *args: object, **kwargs: object) -> None: ... # This should generate an error because b param doesn't match a in name. - def my_method19(self, b: str, *args: object, **kwargs: object) -> None: - ... + def my_method19(self, b: str, *args: object, **kwargs: object) -> None: ... @classmethod - def my_method20(cls: type[T_ChildClass], a: str) -> T_ChildClass: - ... + def my_method20(cls: type[T_ChildClass], a: str) -> T_ChildClass: ... # This should generate an error. @decorator - def my_method21(self, var: int) -> None: - ... + def my_method21(self, var: int) -> None: ... # This should generate an error. def _protected_method1(self): @@ -270,143 +235,111 @@ def __private_method1(self): return 1 # This should generate an error. - def my_method22(self, a: str, b: int, c: float, d: bool, /) -> None: - ... + def my_method22(self, a: str, b: int, c: float, d: bool, /) -> None: ... # This should generate an error because a is missing a default value. - def my_method23(self, a: str) -> None: - ... + def my_method23(self, a: str) -> None: ... - def my_method24(self, a: str = "") -> None: - ... + def my_method24(self, a: str = "") -> None: ... # This should generate an error because a is missing a default value. - def my_method25(self, *, a: str) -> None: - ... + def my_method25(self, *, a: str) -> None: ... - def my_method26(self, *, a: str = "") -> None: - ... + def my_method26(self, *, a: str = "") -> None: ... - def my_method27(self, __a: object) -> None: - ... + def my_method27(self, __a: object) -> None: ... - def my_method28(self, a: object, /) -> None: - ... + def my_method28(self, a: object, /) -> None: ... # This should generate an error because it is not a classmethod. - def my_method29(self, /) -> None: - ... + def my_method29(self, /) -> None: ... # This should generate an error because it is not a classmethod. @staticmethod - def my_method30(a: type[ParentClass], /) -> None: - ... + def my_method30(a: type[ParentClass], /) -> None: ... # This should generate an error because it is not a staticmethod. @classmethod - def my_method31(cls, /) -> None: - ... + def my_method31(cls, /) -> None: ... # This should generate an error because it is not a staticmethod. - def my_method32(self, /) -> None: - ... + def my_method32(self, /) -> None: ... # This should generate an error because it is not an instance method. @classmethod - def my_method33(cls, /) -> None: - ... + def my_method33(cls, /) -> None: ... # This should generate an error because it is not an instance method. @staticmethod - def my_method34(a: type[ParentClass], /) -> None: - ... + def my_method34(a: type[ParentClass], /) -> None: ... - def my_method35(self, **kwargs: int) -> None: - ... + def my_method35(self, **kwargs: int) -> None: ... # This should generate an error because the method in the parent # class has a keyword-only parameter that is type 'int', and this # isn't compatible with 'str'. - def my_method36(self, **kwargs: str) -> None: - ... + def my_method36(self, **kwargs: str) -> None: ... - def my_method37(self, *args: Any) -> None: - ... + def my_method37(self, *args: Any) -> None: ... # This should generate an error because the number of position-only # parameters doesn't match. - def my_method38(self, **kwargs: Any) -> None: - ... + def my_method38(self, **kwargs: Any) -> None: ... - def my_method39(self, *args: Any) -> None: - ... + def my_method39(self, *args: Any) -> None: ... # This should generate an error because the number of position-only # parameters doesn't match. - def my_method40(self, **kwargs: Any) -> None: - ... + def my_method40(self, **kwargs: Any) -> None: ... # This should generate an error because keyword parameters "a" # and "b" are missing. - def my_method41(self, a: int, *args: str) -> None: - ... + def my_method41(self, a: int, *args: str) -> None: ... # This should generate an error because args doesn't have the right type. - def my_method42(self, a: int, *args: int) -> None: - ... + def my_method42(self, a: int, *args: int) -> None: ... - def my_method43(self, a: int, b: str, c: str) -> None: - ... + def my_method43(self, a: int, b: str, c: str) -> None: ... # This should generate an error because kwargs is missing. - def my_method44(self, *object) -> None: - ... + def my_method44(self, *object) -> None: ... - def my_method45(self, i: int, /) -> None: - ... + def my_method45(self, i: int, /) -> None: ... - def __my_method46__(self, y: int) -> None: - ... + def __my_method46__(self, y: int) -> None: ... # This should generate an error because of a type mismatch. - def __my_method47__(self, y: str) -> None: - ... + def __my_method47__(self, y: str) -> None: ... class A: - def test(self, t: Sequence[int]) -> Sequence[str]: - ... + def test(self, t: Sequence[int]) -> Sequence[str]: ... class GeneralizedArgument(A): - def test(self, t: Iterable[int], bbb: str = "") -> Sequence[str]: - ... + def test(self, t: Iterable[int], bbb: str = "") -> Sequence[str]: ... class NarrowerArgument(A): # This should generate error because list[int] is narrower # than Iterable[int]. - def test(self, t: list[int]) -> Sequence[str]: - ... + def test(self, t: list[int]) -> Sequence[str]: ... class NarrowerReturn(A): - def test(self, t: Sequence[int]) -> list[str]: - ... + def test(self, t: Sequence[int]) -> list[str]: ... class GeneralizedReturn1(A): # This should generate an error because Iterable[str] is # wider than Sequence[str]. - def test(self, t: Sequence[int]) -> Iterable[str]: - ... + def test(self, t: Sequence[int]) -> Iterable[str]: ... class GeneralizedReturn2(A): # This should generate an error because list[int] is # incompatible with Sequence[str]. - def test(self, t: Sequence[int]) -> list[int]: - ... + def test(self, t: Sequence[int]) -> list[int]: ... _T1 = TypeVar("_T1") @@ -529,32 +462,27 @@ def case(self, value: Any) -> Iterable[Any]: class Derived3(Base3): @overload - def case(self, value: int) -> Iterable[int]: - ... + def case(self, value: int) -> Iterable[int]: ... @overload - def case(self, value: float) -> Iterable[float]: - ... + def case(self, value: float) -> Iterable[float]: ... def case(self, value: Any) -> Iterable[Any]: return [] class Base4: - def a(self) -> int: - ... + def a(self) -> int: ... class Base5: - def a(self) -> int: - ... + def a(self) -> int: ... class C(Base4, Base5): # This should generate two error if reportIncompatibleMethodOverride # is enabled. - def a(self) -> float: - ... + def a(self) -> float: ... class MyObject(TypedDict): @@ -562,37 +490,41 @@ class MyObject(TypedDict): class Base6(Generic["T"]): - def method1(self, v: int) -> None: - ... + def method1(self, v: int) -> None: ... - def method2(self, v: T) -> None: - ... + def method2(self, v: T) -> None: ... - def method3(self, v: T) -> None: - ... + def method3(self, v: T) -> None: ... - def method4(self, v: S) -> S: - ... + def method4(self, v: S) -> S: ... - def method5(self, v: S) -> S: - ... + def method5(self, v: S) -> S: ... class Derived6(Base6[int], Generic["T"]): # This should generate an error. - def method1(self, v: T): - ... + def method1(self, v: T): ... # This should generate an error. - def method2(self, v: T) -> None: - ... + def method2(self, v: T) -> None: ... - def method3(self, v: int) -> None: - ... + def method3(self, v: int) -> None: ... + + def method4(self, v: T) -> T: ... + + def method5(self, v: S) -> S: ... + + +class Base7(Generic[T]): + def method1(self, x: T) -> T: + return x + + +class Derived7_1(Base7[T]): + def method1(self, x: S) -> S: + return x - # This should generate an error. - def method4(self, v: T) -> T: - ... - def method5(self, v: S) -> S: - ... +class Derived7_2(Base7[int]): + def method1(self, x: U) -> U: + return x diff --git a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts index 7b57a9fd1..c6f2890d2 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator3.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator3.test.ts @@ -925,7 +925,7 @@ test('MethodOverride1', () => { configOptions.diagnosticRuleSet.reportIncompatibleMethodOverride = 'error'; analysisResults = TestUtils.typeAnalyzeSampleFiles(['methodOverride1.py'], configOptions); - TestUtils.validateResults(analysisResults, 41); + TestUtils.validateResults(analysisResults, 40); }); test('MethodOverride2', () => { From d0b4eb574aed15e2ae3229dcd56f0e01d87a4f08 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 29 Oct 2024 09:34:28 -0700 Subject: [PATCH 13/21] Added experimental support for draft PEP 764: Inlined typed dictionaries. (#9350) --- .../src/analyzer/declaration.ts | 3 + .../src/analyzer/typeEvaluator.ts | 73 ++++++++++++++++--- .../src/analyzer/typeEvaluatorTypes.ts | 3 + .../src/analyzer/typedDicts.ts | 29 ++++++++ .../src/tests/samples/typedDictInline1.py | 40 ++++++++++ .../src/tests/typeEvaluator7.test.ts | 8 ++ 6 files changed, 144 insertions(+), 12 deletions(-) create mode 100644 packages/pyright-internal/src/tests/samples/typedDictInline1.py diff --git a/packages/pyright-internal/src/analyzer/declaration.ts b/packages/pyright-internal/src/analyzer/declaration.ts index 1eeffc929..dca2d6456 100644 --- a/packages/pyright-internal/src/analyzer/declaration.ts +++ b/packages/pyright-internal/src/analyzer/declaration.ts @@ -72,6 +72,9 @@ export interface DeclarationBase { // The declaration is within an except clause of a try // statement. We may want to ignore such declarations. isInExceptSuite: boolean; + + // This declaration is within an inlined TypedDict definition. + isInInlinedTypedDict?: boolean; } export interface IntrinsicDeclaration extends DeclarationBase { diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index 78b9d8f2a..b41f7478f 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -174,6 +174,7 @@ import { assignToTypedDict, assignTypedDictToTypedDict, createTypedDictType, + createTypedDictTypeInlined, getTypedDictDictEquivalent, getTypedDictMappingEquivalent, getTypedDictMembersForClass, @@ -368,6 +369,7 @@ interface GetTypeArgsOptions { hasCustomClassGetItem?: boolean; isFinalAnnotation?: boolean; isClassVarAnnotation?: boolean; + supportsTypedDictTypeArg?: boolean; } interface MatchArgsToParamsResult { @@ -654,6 +656,7 @@ export function createTypeEvaluator( let strClass: Type | undefined; let dictClass: Type | undefined; let moduleTypeClass: Type | undefined; + let typedDictClass: Type | undefined; let typedDictPrivateClass: Type | undefined; let supportsKeysAndGetItemClass: Type | undefined; let mappingClass: Type | undefined; @@ -1022,6 +1025,7 @@ export function createTypeEvaluator( strClass = getBuiltInType(node, 'str'); dictClass = getBuiltInType(node, 'dict'); moduleTypeClass = getTypingType(node, 'ModuleType'); + typedDictClass = getTypingType(node, 'TypedDict'); typedDictPrivateClass = getTypingType(node, '_TypedDict'); awaitableClass = getTypingType(node, 'Awaitable'); mappingClass = getTypingType(node, 'Mapping'); @@ -7523,11 +7527,17 @@ export function createTypeEvaluator( const isClassVarAnnotation = isInstantiableClass(concreteSubtype) && ClassType.isBuiltIn(concreteSubtype, 'ClassVar'); + // This feature is currently experimental. + const supportsTypedDictTypeArg = + AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.enableExperimentalFeatures && + ClassType.isBuiltIn(concreteSubtype, 'TypedDict'); + let typeArgs = getTypeArgs(node, flags, { isAnnotatedClass, hasCustomClassGetItem: hasCustomClassGetItem || !isGenericClass, isFinalAnnotation, isClassVarAnnotation, + supportsTypedDictTypeArg, }); if (!isAnnotatedClass) { @@ -8014,7 +8024,7 @@ export function createTypeEvaluator( node: expr, }; } else { - typeResult = getTypeArg(expr, adjFlags); + typeResult = getTypeArg(expr, adjFlags, !!options?.supportsTypedDictTypeArg && argIndex === 0); } return typeResult; @@ -8120,7 +8130,7 @@ export function createTypeEvaluator( return undefined; } - function getTypeArg(node: ExpressionNode, flags: EvalFlags): TypeResultWithNode { + function getTypeArg(node: ExpressionNode, flags: EvalFlags, supportsDictExpression: boolean): TypeResultWithNode { let typeResult: TypeResultWithNode; let adjustedFlags = @@ -8142,6 +8152,18 @@ export function createTypeEvaluator( // Set the node's type so it isn't reevaluated later. setTypeResultForNode(node, { type: UnknownType.create() }); + } else if (node.nodeType === ParseNodeType.Dictionary && supportsDictExpression) { + const inlinedTypeDict = + typedDictClass && isInstantiableClass(typedDictClass) + ? createTypedDictTypeInlined(evaluatorInterface, node, typedDictClass) + : undefined; + const keyTypeFallback = strClass && isInstantiableClass(strClass) ? strClass : UnknownType.create(); + + typeResult = { + type: keyTypeFallback, + inlinedTypeDict, + node, + }; } else { typeResult = { ...getTypeOfExpression(node, adjustedFlags), node }; @@ -20577,11 +20599,17 @@ export function createTypeEvaluator( case 'TypedDict': { if ((flags & (EvalFlags.NoNonTypeSpecialForms | EvalFlags.TypeExpression)) !== 0) { - addDiagnostic( - DiagnosticRule.reportInvalidTypeForm, - LocMessage.typedDictNotAllowed(), - errorNode - ); + const isInlinedTypedDict = + AnalyzerNodeInfo.getFileInfo(errorNode).diagnosticRuleSet.enableExperimentalFeatures && + !!typeArgs; + + if (!isInlinedTypedDict) { + addDiagnostic( + DiagnosticRule.reportInvalidTypeForm, + LocMessage.typedDictNotAllowed(), + errorNode + ); + } } isValidTypeForm = false; break; @@ -20746,7 +20774,22 @@ export function createTypeEvaluator( minTypeArgCount = firstDefaultParamIndex; } - if (typeArgCount > typeParams.length) { + // Classes that accept inlined type dict type args allow only one. + if (typeArgs.length > 0 && typeArgs[0].inlinedTypeDict) { + if (typeArgs.length > 1) { + addDiagnostic( + DiagnosticRule.reportInvalidTypeArguments, + LocMessage.typeArgsTooMany().format({ + name: classType.priv.aliasName || classType.shared.name, + expected: 1, + received: typeArgCount, + }), + typeArgs[1].node + ); + } + + return { type: typeArgs[0].inlinedTypeDict }; + } else if (typeArgCount > typeParams.length) { if (!ClassType.isPartiallyEvaluated(classType) && !ClassType.isTupleClass(classType)) { if (typeParams.length === 0) { isValidTypeForm = false; @@ -21862,12 +21905,18 @@ export function createTypeEvaluator( declaration.node.parent?.nodeType === ParseNodeType.MemberAccess ? declaration.node.parent : declaration.node; + const allowClassVar = ParseTreeUtils.isClassVarAllowedForAssignmentTarget(declNode); + const allowFinal = ParseTreeUtils.isFinalAllowedForAssignmentTarget(declNode); + const allowRequired = + ParseTreeUtils.isRequiredAllowedForAssignmentTarget(declNode) || + !!declaration.isInInlinedTypedDict; + declaredType = getTypeOfAnnotation(typeAnnotationNode, { varTypeAnnotation: true, - allowClassVar: ParseTreeUtils.isClassVarAllowedForAssignmentTarget(declNode), - allowFinal: ParseTreeUtils.isFinalAllowedForAssignmentTarget(declNode), - allowRequired: ParseTreeUtils.isRequiredAllowedForAssignmentTarget(declNode), - allowReadOnly: ParseTreeUtils.isRequiredAllowedForAssignmentTarget(declNode), + allowClassVar, + allowFinal, + allowRequired, + allowReadOnly: allowRequired, enforceClassTypeVarScope: declaration.isDefinedByMemberAccess, }); } diff --git a/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts b/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts index 0d57d180e..572b38d7b 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts @@ -221,6 +221,9 @@ export interface TypeResult { // Type consistency errors detected when evaluating this type. typeErrors?: boolean | undefined; + // For inlined TypedDict definitions. + inlinedTypeDict?: ClassType; + // Used for getTypeOfBoundMember to indicate that class // that declares the member. classType?: ClassType | UnknownType | AnyType; diff --git a/packages/pyright-internal/src/analyzer/typedDicts.ts b/packages/pyright-internal/src/analyzer/typedDicts.ts index a1fdce373..caa2fd9b1 100644 --- a/packages/pyright-internal/src/analyzer/typedDicts.ts +++ b/packages/pyright-internal/src/analyzer/typedDicts.ts @@ -259,6 +259,34 @@ export function createTypedDictType( return classType; } +// Creates a new anonymous TypedDict class from an inlined dict[{}] type annotation. +export function createTypedDictTypeInlined( + evaluator: TypeEvaluator, + dictNode: DictionaryNode, + typedDictClass: ClassType +): ClassType { + const fileInfo = AnalyzerNodeInfo.getFileInfo(dictNode); + const className = ''; + + const classType = ClassType.createInstantiable( + className, + ParseTreeUtils.getClassFullName(dictNode, fileInfo.moduleName, className), + fileInfo.moduleName, + fileInfo.fileUri, + ClassTypeFlags.TypedDictClass, + ParseTreeUtils.getTypeSourceId(dictNode), + /* declaredMetaclass */ undefined, + typedDictClass.shared.effectiveMetaclass + ); + classType.shared.baseClasses.push(typedDictClass); + computeMroLinearization(classType); + + getTypedDictFieldsFromDictSyntax(evaluator, dictNode, ClassType.getSymbolTable(classType), /* isInline */ true); + synthesizeTypedDictClassMethods(evaluator, dictNode, classType); + + return classType; +} + export function synthesizeTypedDictClassMethods( evaluator: TypeEvaluator, node: ClassNode | ExpressionNode, @@ -964,6 +992,7 @@ function getTypedDictFieldsFromDictSyntax( range: convertOffsetsToRange(entry.d.keyExpr.start, TextRange.getEnd(entry.d.keyExpr), fileInfo.lines), moduleName: fileInfo.moduleName, isInExceptSuite: false, + isInInlinedTypedDict: true, }; newSymbol.addDeclaration(declaration); diff --git a/packages/pyright-internal/src/tests/samples/typedDictInline1.py b/packages/pyright-internal/src/tests/samples/typedDictInline1.py new file mode 100644 index 000000000..8e1be9da0 --- /dev/null +++ b/packages/pyright-internal/src/tests/samples/typedDictInline1.py @@ -0,0 +1,40 @@ +# This sample tests support for inlined TypedDict definitions. + +from typing import NotRequired, ReadOnly, Required, TypedDict + + +td1: TypedDict[{"a": int, "b": str}] = {"a": 0, "b": ""} + +td2: TypedDict[{"a": TypedDict[{"b": int}]}] = {"a": {"b": 0}} + +td3: TypedDict[{"a": "list[float]"}] = {"a": [3]} + +td4: TypedDict[ + {"a": NotRequired[int], "b": Required[int], "c": NotRequired[ReadOnly[int]]} +] = {"b": 3} + +# This should generate an error because dictionary comprehensions +# are not allowed. +err1: TypedDict[{"a": int for _ in range(1)}] + +# This should generate an error because unpacked dictionary +# entries are not allowed. +err2: TypedDict[{**{"a": int}}] + +# This should generate an error because an extra type argument is provided. +err3: TypedDict[{"a": int}, str] + +# This should generate an error because TypedDict cannot be used without +# a subscript in this context. +err4: TypedDict + +# This should generate an error because a dict expression is not a +# valid type expression by itself. +err5: TypedDict[{"a": {"b": int}}] = {"a": {"b": 0}} + + +def func1(val: TypedDict[{"a": int}]) -> TypedDict[{"a": int}]: + return {"a": val["a"] + 1} + + +func1({"a": 3}) diff --git a/packages/pyright-internal/src/tests/typeEvaluator7.test.ts b/packages/pyright-internal/src/tests/typeEvaluator7.test.ts index 08a2a7ce0..0ad4003e9 100644 --- a/packages/pyright-internal/src/tests/typeEvaluator7.test.ts +++ b/packages/pyright-internal/src/tests/typeEvaluator7.test.ts @@ -767,6 +767,14 @@ test('TypedDict24', () => { TestUtils.validateResults(analysisResults, 1); }); +test('TypedDictInline1', () => { + const configOptions = new ConfigOptions(Uri.empty()); + configOptions.diagnosticRuleSet.enableExperimentalFeatures = true; + + const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typedDictInline1.py'], configOptions); + TestUtils.validateResults(analysisResults, 6); +}); + test('ClassVar1', () => { const analysisResults = TestUtils.typeAnalyzeSampleFiles(['classVar1.py']); From 55adfbd1a0aa830258bf064813df96c8ff28ab35 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 29 Oct 2024 12:31:41 -0700 Subject: [PATCH 14/21] Added test cases for inlined TypedDict definitions that use generics. --- .../src/tests/samples/typedDictInline1.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/pyright-internal/src/tests/samples/typedDictInline1.py b/packages/pyright-internal/src/tests/samples/typedDictInline1.py index 8e1be9da0..77524544c 100644 --- a/packages/pyright-internal/src/tests/samples/typedDictInline1.py +++ b/packages/pyright-internal/src/tests/samples/typedDictInline1.py @@ -38,3 +38,13 @@ def func1(val: TypedDict[{"a": int}]) -> TypedDict[{"a": int}]: func1({"a": 3}) + + +type TA1[T] = TypedDict[{"a": int, "b": T, "c": NotRequired[int]}] + + +class Outer1[T]: + attr1: TypedDict[{"a": list[T]}] + + def __init__(self, v: T) -> None: + self.attr1 = {"a": [v]} From c7231709802fec8aa12058f82a32df5089621426 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 29 Oct 2024 13:35:49 -0700 Subject: [PATCH 15/21] Changed check in the pyright VS Code extension for the presence of Pylance. If Pylance is installed in the workspace but is not configured to be loaded (i.e. the "python.languageServer" is set to "None"), then pyright will allow itself to be loaded. This addresses #9325. --- packages/vscode-pyright/src/extension.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/vscode-pyright/src/extension.ts b/packages/vscode-pyright/src/extension.ts index 01461690d..2ae822835 100644 --- a/packages/vscode-pyright/src/extension.ts +++ b/packages/vscode-pyright/src/extension.ts @@ -53,11 +53,14 @@ const pythonPathChangedListenerMap = new Map(); const defaultHeapSize = 3072; export async function activate(context: ExtensionContext) { + const pythonSettings = workspace.getConfiguration('python'); + const langServer = pythonSettings.get('languageServer'); + // See if Pylance is installed. If so, don't activate the Pyright extension. // Doing so will generate "command already registered" errors and redundant // hover text, etc.because the two extensions overlap in functionality. const pylanceExtension = extensions.getExtension('ms-python.vscode-pylance'); - if (pylanceExtension) { + if (pylanceExtension && langServer !== 'None') { window.showErrorMessage( 'Pyright has detected that the Pylance extension is installed. ' + 'Pylance includes the functionality of Pyright, and running both of ' + From e7f69eea86d99bc074e0cceaa81971550c946ea7 Mon Sep 17 00:00:00 2001 From: Erik De Bonte Date: Tue, 29 Oct 2024 17:52:49 -0700 Subject: [PATCH 16/21] Fix hover on `.get()` of `TypedDict` instance (#9357) * Fix * Unit test --- .../src/languageService/hoverProvider.ts | 18 ++++++++++-------- .../fourslash/hover.typedDict.get.fourslash.ts | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 8 deletions(-) create mode 100644 packages/pyright-internal/src/tests/fourslash/hover.typedDict.get.fourslash.ts diff --git a/packages/pyright-internal/src/languageService/hoverProvider.ts b/packages/pyright-internal/src/languageService/hoverProvider.ts index a39fde025..3a04d75c9 100644 --- a/packages/pyright-internal/src/languageService/hoverProvider.ts +++ b/packages/pyright-internal/src/languageService/hoverProvider.ts @@ -263,9 +263,9 @@ export class HoverProvider { const primaryDeclaration = HoverProvider.getPrimaryDeclaration(declarations); this._addResultsForDeclaration(results.parts, primaryDeclaration, node); } else if (declInfo && declInfo.synthesizedTypes.length > 0) { - const name = node.d.value; + const nameNode = node; declInfo?.synthesizedTypes.forEach((type) => { - this._addResultsForSynthesizedType(results.parts, type, name); + this._addResultsForSynthesizedType(results.parts, type, nameNode); }); this._addDocumentationPart(results.parts, node, /* resolvedDecl */ undefined); } else if (!node.parent || node.parent.nodeType !== ParseNodeType.ModuleName) { @@ -458,19 +458,21 @@ export class HoverProvider { } } - private _addResultsForSynthesizedType(parts: HoverTextPart[], typeInfo: SynthesizedTypeInfo, name: string) { + private _addResultsForSynthesizedType(parts: HoverTextPart[], typeInfo: SynthesizedTypeInfo, hoverNode: NameNode) { let typeText: string | undefined; if (isModule(typeInfo.type)) { - typeText = '(module) ' + name; - } else if (typeInfo.node) { - const type = this._getType(typeInfo.node); + typeText = '(module) ' + hoverNode.d.value; + } else { + const node = typeInfo.node ?? hoverNode; + + const type = this._getType(node); typeText = getVariableTypeText( this._evaluator, /* declaration */ undefined, - typeInfo.node.d.value, + node.d.value, type, - typeInfo.node, + node, this._functionSignatureDisplay ); } diff --git a/packages/pyright-internal/src/tests/fourslash/hover.typedDict.get.fourslash.ts b/packages/pyright-internal/src/tests/fourslash/hover.typedDict.get.fourslash.ts new file mode 100644 index 000000000..7314cd602 --- /dev/null +++ b/packages/pyright-internal/src/tests/fourslash/hover.typedDict.get.fourslash.ts @@ -0,0 +1,15 @@ +/// + +// @filename: test.py +//// from typing_extensions import TypedDict +//// +//// class Cls(TypedDict): +//// a: int +//// b: str +//// +//// dct: Cls = {"a": 1, "b": "2"} +//// dct.[|/*marker1*/get|]("a") + +helper.verifyHover('markdown', { + marker1: "```python\n(variable) def get(k: Literal['a']) -> int\n```", +}); From 605453f5053c3fe4ade9f7f34a73581222bc9366 Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 29 Oct 2024 17:55:30 -0700 Subject: [PATCH 17/21] Fixed a bug that causes a false positive error when a class uses `type(Protocol)` as a base class. This addresses #9217. (#9356) This fix involves a change to the internal isSameGenericClass method, which was previously too permissive. This change required dozens of downstream changes, and it has a high risk of regression. --- .../pyright-internal/src/analyzer/checker.ts | 4 +- .../src/analyzer/codeFlowEngine.ts | 4 +- .../src/analyzer/constructors.ts | 6 ++- .../pyright-internal/src/analyzer/enums.ts | 6 ++- .../src/analyzer/patternMatching.ts | 2 +- .../src/analyzer/typeEvaluator.ts | 37 ++++++++++++++----- .../src/analyzer/typeGuards.ts | 19 +++++++--- .../src/analyzer/typePrinter.ts | 8 ++++ .../src/analyzer/typeUtils.ts | 8 ++-- .../pyright-internal/src/analyzer/types.ts | 9 ++--- .../src/languageService/completionProvider.ts | 5 ++- 11 files changed, 77 insertions(+), 31 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/checker.ts b/packages/pyright-internal/src/analyzer/checker.ts index 83c81d8f6..e3bdba5c1 100644 --- a/packages/pyright-internal/src/analyzer/checker.ts +++ b/packages/pyright-internal/src/analyzer/checker.ts @@ -3846,7 +3846,7 @@ export class Checker extends ParseTreeWalker { if (isInstantiableClass(filterType)) { this._validateUnsafeProtocolOverlap( node.d.args[0].d.valueExpr, - convertToInstance(filterType), + ClassType.cloneAsInstance(filterType), isInstanceCheck ? arg0Type : convertToInstance(arg0Type) ); } @@ -4898,7 +4898,7 @@ export class Checker extends ParseTreeWalker { if ( !symbolType || !isClassInstance(symbolType) || - !ClassType.isSameGenericClass(symbolType, classType) || + !ClassType.isSameGenericClass(symbolType, ClassType.cloneAsInstance(classType)) || !(symbolType.priv.literalValue instanceof EnumLiteral) ) { return; diff --git a/packages/pyright-internal/src/analyzer/codeFlowEngine.ts b/packages/pyright-internal/src/analyzer/codeFlowEngine.ts index 9d01a3460..017225fb4 100644 --- a/packages/pyright-internal/src/analyzer/codeFlowEngine.ts +++ b/packages/pyright-internal/src/analyzer/codeFlowEngine.ts @@ -1583,7 +1583,7 @@ export function getCodeFlowEngine( ); return priorRemainingConstraints.filter((subtype) => - ClassType.isSameGenericClass(subtype, classType) + ClassType.isSameGenericClass(subtype, ClassType.cloneAsInstance(classType)) ); } } @@ -1632,7 +1632,7 @@ export function getCodeFlowEngine( if (isInstantiableClass(arg1Type)) { return priorRemainingConstraints.filter((subtype) => { - if (ClassType.isSameGenericClass(subtype, arg1Type)) { + if (ClassType.isSameGenericClass(subtype, ClassType.cloneAsInstance(arg1Type))) { return isPositiveTest; } else { return !isPositiveTest; diff --git a/packages/pyright-internal/src/analyzer/constructors.ts b/packages/pyright-internal/src/analyzer/constructors.ts index 3b06cff78..effdb91f1 100644 --- a/packages/pyright-internal/src/analyzer/constructors.ts +++ b/packages/pyright-internal/src/analyzer/constructors.ts @@ -1068,7 +1068,11 @@ function shouldSkipInitEvaluation(evaluator: TypeEvaluator, classType: ClassType if (isClassInstance(subtype)) { const inheritanceChain: InheritanceChain = []; - const isDerivedFrom = ClassType.isDerivedFrom(subtype, classType, inheritanceChain); + const isDerivedFrom = ClassType.isDerivedFrom( + ClassType.cloneAsInstantiable(subtype), + classType, + inheritanceChain + ); if (!isDerivedFrom) { skipInitCheck = true; diff --git a/packages/pyright-internal/src/analyzer/enums.ts b/packages/pyright-internal/src/analyzer/enums.ts index 683e2990a..d5b325e6b 100644 --- a/packages/pyright-internal/src/analyzer/enums.ts +++ b/packages/pyright-internal/src/analyzer/enums.ts @@ -56,7 +56,11 @@ export function isEnumClassWithMembers(evaluator: TypeEvaluator, classType: Clas ClassType.getSymbolTable(classType).forEach((symbol, name) => { const symbolType = transformTypeForEnumMember(evaluator, classType, name); - if (symbolType && isClassInstance(symbolType) && ClassType.isSameGenericClass(symbolType, classType)) { + if ( + symbolType && + isClassInstance(symbolType) && + ClassType.isSameGenericClass(symbolType, ClassType.cloneAsInstance(classType)) + ) { definesMember = true; } }); diff --git a/packages/pyright-internal/src/analyzer/patternMatching.ts b/packages/pyright-internal/src/analyzer/patternMatching.ts index ccc4ebeaf..3dd371077 100644 --- a/packages/pyright-internal/src/analyzer/patternMatching.ts +++ b/packages/pyright-internal/src/analyzer/patternMatching.ts @@ -760,7 +760,7 @@ function narrowTypeBasedOnClassPattern( classType = ClassType.specialize(classType, /* typeArgs */ undefined); } - const classInstance = convertToInstance(classType); + const classInstance = ClassType.cloneAsInstance(classType); const isPatternMetaclass = isMetaclassInstance(classInstance); return evaluator.mapSubtypesExpandTypeVars( diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index b41f7478f..f78ae9c69 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -3584,7 +3584,12 @@ export function createTypeEvaluator( enclosingClass = classTypeResults.classType; if (isClassInstance(baseType)) { - if (ClassType.isSameGenericClass(baseType, classTypeResults.classType)) { + if ( + ClassType.isSameGenericClass( + ClassType.cloneAsInstantiable(baseType), + classTypeResults.classType + ) + ) { assignTypeToMemberVariable(target, typeResult, /* isInstanceMember */ true, srcExpr); } } else if (isInstantiableClass(baseType)) { @@ -5603,7 +5608,7 @@ export function createTypeEvaluator( // Is this an attempt to delete or overwrite an enum member? if ( isClassInstance(enumMemberResult.type) && - ClassType.isSameGenericClass(enumMemberResult.type, baseType) && + ClassType.isSameGenericClass(enumMemberResult.type, ClassType.cloneAsInstance(baseType)) && enumMemberResult.type.priv.literalValue !== undefined ) { const diagMessage = @@ -5995,7 +6000,10 @@ export function createTypeEvaluator( if ( containingClassType && isInstantiableClass(containingClassType) && - ClassType.isSameGenericClass(containingClassType, classType) + ClassType.isSameGenericClass( + isAccessedThroughObject ? ClassType.cloneAsInstance(containingClassType) : containingClassType, + classType + ) ) { type = getDeclaredTypeOfSymbol(memberInfo.symbol)?.type; if (type && isInstantiableClass(memberInfo.classType)) { @@ -6069,7 +6077,10 @@ export function createTypeEvaluator( if ( errorNode && isInstantiableClass(memberInfo.classType) && - ClassType.isSameGenericClass(memberInfo.classType, classType) + ClassType.isSameGenericClass( + memberInfo.classType, + isAccessedThroughObject ? ClassType.cloneAsInstantiable(classType) : classType + ) ) { setSymbolAccessed(AnalyzerNodeInfo.getFileInfo(errorNode), memberInfo.symbol, errorNode); } @@ -8837,7 +8848,10 @@ export function createTypeEvaluator( bindToType && ClassType.isProtocolClass(bindToType) && effectiveTargetClass && - !ClassType.isSameGenericClass(bindToType, effectiveTargetClass) + !ClassType.isSameGenericClass( + TypeBase.isInstance(bindToType) ? ClassType.cloneAsInstantiable(bindToType) : bindToType, + effectiveTargetClass + ) ) { isProtocolClass = true; effectiveTargetClass = undefined; @@ -8909,7 +8923,12 @@ export function createTypeEvaluator( if (bindToType) { let nextBaseClassType: Type | undefined; - if (ClassType.isSameGenericClass(bindToType, concreteTargetClassType)) { + if ( + ClassType.isSameGenericClass( + TypeBase.isInstance(bindToType) ? ClassType.cloneAsInstantiable(bindToType) : bindToType, + concreteTargetClassType + ) + ) { if (bindToType.shared.baseClasses.length > 0) { nextBaseClassType = bindToType.shared.baseClasses[0]; } @@ -13475,7 +13494,7 @@ export function createTypeEvaluator( if (isNoneInstance(subtype)) { if (objectClass && isInstantiableClass(objectClass)) { // Use 'object' for 'None'. - return handleSubtype(convertToInstance(objectClass)); + return handleSubtype(ClassType.cloneAsInstance(objectClass)); } } @@ -24344,8 +24363,8 @@ export function createTypeEvaluator( if (destMetaclass && isInstantiableClass(destMetaclass)) { if ( assignClass( - ClassType.cloneAsInstance(destMetaclass), - expandedSrcType, + destMetaclass, + ClassType.cloneAsInstantiable(expandedSrcType), diag, constraints, flags, diff --git a/packages/pyright-internal/src/analyzer/typeGuards.ts b/packages/pyright-internal/src/analyzer/typeGuards.ts index 3db90d2c5..2f08cdf8f 100644 --- a/packages/pyright-internal/src/analyzer/typeGuards.ts +++ b/packages/pyright-internal/src/analyzer/typeGuards.ts @@ -1348,7 +1348,7 @@ function narrowTypeForInstance( // any metaclass, but we specifically want to treat type as the class // type[object] in this case. if (ClassType.isBuiltIn(filterMetaclass, 'type') && !filterMetaclass.priv.isTypeArgExplicit) { - if (!ClassType.isBuiltIn(metaclassType, 'type')) { + if (!isClass(metaclassType) || !ClassType.isBuiltIn(metaclassType, 'type')) { isMetaclassOverlap = false; } } @@ -1435,7 +1435,14 @@ function narrowTypeForInstance( } if (filterIsSubclass && !ClassType.isSameGenericClass(runtimeVarType, concreteFilterType)) { - isClassRelationshipIndeterminate = true; + // If the runtime variable type is a type[T], handle a filter + // of 'type' as a special case. + if ( + !ClassType.isBuiltIn(concreteFilterType, 'type') || + TypeBase.getInstantiableDepth(runtimeVarType) === 0 + ) { + isClassRelationshipIndeterminate = true; + } } } @@ -1479,8 +1486,8 @@ function narrowTypeForInstance( if ( addConstraintsForExpectedType( evaluator, - convertToInstance(unspecializedFilterType), - convertToInstance(concreteVarType), + ClassType.cloneAsInstance(unspecializedFilterType), + ClassType.cloneAsInstance(concreteVarType), constraints, /* liveTypeVarScopes */ undefined, errorNode.start @@ -1664,7 +1671,7 @@ function narrowTypeForInstance( const isFilterTypeCallbackProtocol = (filterType: Type) => { return ( isInstantiableClass(filterType) && - evaluator.getCallbackProtocolType(convertToInstance(filterType)) !== undefined + evaluator.getCallbackProtocolType(ClassType.cloneAsInstance(filterType)) !== undefined ); }; @@ -2324,7 +2331,7 @@ function narrowTypeForTypeIs(evaluator: TypeEvaluator, type: Type, classType: Cl const matches = ClassType.isDerivedFrom(classType, ClassType.cloneAsInstantiable(subtype)); if (isPositiveTest) { if (matches) { - if (ClassType.isSameGenericClass(subtype, classType)) { + if (ClassType.isSameGenericClass(ClassType.cloneAsInstantiable(subtype), classType)) { return addConditionToType(subtype, classType.props?.condition); } diff --git a/packages/pyright-internal/src/analyzer/typePrinter.ts b/packages/pyright-internal/src/analyzer/typePrinter.ts index 69861afd0..6d924c6de 100644 --- a/packages/pyright-internal/src/analyzer/typePrinter.ts +++ b/packages/pyright-internal/src/analyzer/typePrinter.ts @@ -1466,6 +1466,14 @@ class UniqueNameMap { } if (isClass(type1) && isClass(type2)) { + while (TypeBase.isInstantiable(type1)) { + type1 = ClassType.cloneAsInstance(type1); + } + + while (TypeBase.isInstantiable(type2)) { + type2 = ClassType.cloneAsInstance(type2); + } + return ClassType.isSameGenericClass(type1, type2); } diff --git a/packages/pyright-internal/src/analyzer/typeUtils.ts b/packages/pyright-internal/src/analyzer/typeUtils.ts index a6c742d48..23524b713 100644 --- a/packages/pyright-internal/src/analyzer/typeUtils.ts +++ b/packages/pyright-internal/src/analyzer/typeUtils.ts @@ -1742,7 +1742,7 @@ export function* getClassMemberIterator( let classFlags = ClassIteratorFlags.Default; if (flags & MemberAccessFlags.SkipOriginalClass) { if (isClass(classType)) { - skipMroClass = classType; + skipMroClass = isClassInstance(classType) ? ClassType.cloneAsInstantiable(classType) : classType; } } if (flags & MemberAccessFlags.SkipBaseClasses) { @@ -1839,7 +1839,10 @@ export function* getClassMemberIterator( if ( memberName === '__call__' && classType.priv.partialCallType && - ClassType.isSameGenericClass(classType, specializedMroClass) + ClassType.isSameGenericClass( + TypeBase.isInstance(classType) ? ClassType.cloneAsInstantiable(classType) : classType, + specializedMroClass + ) ) { symbol = Symbol.createWithType(SymbolFlags.ClassMember, classType.priv.partialCallType); } @@ -2298,7 +2301,6 @@ export function isEffectivelyInstantiable(type: Type, options?: IsInstantiableOp return false; } -export function convertToInstance(type: ClassType, includeSubclasses?: boolean): ClassType; export function convertToInstance(type: ParamSpecType, includeSubclasses?: boolean): ParamSpecType; export function convertToInstance(type: TypeVarTupleType, includeSubclasses?: boolean): TypeVarTupleType; export function convertToInstance(type: TypeVarType, includeSubclasses?: boolean): TypeVarType; diff --git a/packages/pyright-internal/src/analyzer/types.ts b/packages/pyright-internal/src/analyzer/types.ts index 109742351..c0c7bfbb8 100644 --- a/packages/pyright-internal/src/analyzer/types.ts +++ b/packages/pyright-internal/src/analyzer/types.ts @@ -1324,13 +1324,12 @@ export namespace ClassType { return false; } - // Handle type[] specially. - if (TypeBase.getInstantiableDepth(classType) > 0) { - return TypeBase.isInstantiable(type2) || ClassType.isBuiltIn(type2, 'type'); + if (TypeBase.isInstance(classType) !== TypeBase.isInstance(type2)) { + return false; } - if (TypeBase.getInstantiableDepth(type2) > 0) { - return TypeBase.isInstantiable(classType) || ClassType.isBuiltIn(classType, 'type'); + if (TypeBase.getInstantiableDepth(classType) !== TypeBase.getInstantiableDepth(type2)) { + return false; } const class1Details = classType.shared; diff --git a/packages/pyright-internal/src/languageService/completionProvider.ts b/packages/pyright-internal/src/languageService/completionProvider.ts index 6f50c68b2..2bf0b1dbe 100644 --- a/packages/pyright-internal/src/languageService/completionProvider.ts +++ b/packages/pyright-internal/src/languageService/completionProvider.ts @@ -3183,7 +3183,10 @@ export class CompletionProvider { return ( symbolType && isClassInstance(symbolType) && - ClassType.isSameGenericClass(symbolType, containingType) && + ClassType.isSameGenericClass( + symbolType, + TypeBase.isInstance(containingType) ? containingType : ClassType.cloneAsInstance(containingType) + ) && symbolType.priv.literalValue instanceof EnumLiteral ); } From 50063239c9adb2d01c7502f22a1b5b4b6e0957dc Mon Sep 17 00:00:00 2001 From: Eric Traut Date: Tue, 29 Oct 2024 17:58:27 -0700 Subject: [PATCH 18/21] Published 1.1.387 --- lerna.json | 2 +- packages/pyright-internal/package-lock.json | 4 ++-- packages/pyright-internal/package.json | 2 +- packages/pyright/package-lock.json | 4 ++-- packages/pyright/package.json | 2 +- packages/vscode-pyright/package-lock.json | 4 ++-- packages/vscode-pyright/package.json | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lerna.json b/lerna.json index 4210f3589..47e628a9e 100644 --- a/lerna.json +++ b/lerna.json @@ -2,7 +2,7 @@ "packages": [ "packages/*" ], - "version": "1.1.386", + "version": "1.1.387", "command": { "version": { "push": false, diff --git a/packages/pyright-internal/package-lock.json b/packages/pyright-internal/package-lock.json index bd84857b8..b8527a9ed 100644 --- a/packages/pyright-internal/package-lock.json +++ b/packages/pyright-internal/package-lock.json @@ -1,12 +1,12 @@ { "name": "pyright-internal", - "version": "1.1.386", + "version": "1.1.387", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pyright-internal", - "version": "1.1.386", + "version": "1.1.387", "license": "MIT", "dependencies": { "@yarnpkg/fslib": "2.10.4", diff --git a/packages/pyright-internal/package.json b/packages/pyright-internal/package.json index 461ea2ad8..19bf3dfe7 100644 --- a/packages/pyright-internal/package.json +++ b/packages/pyright-internal/package.json @@ -2,7 +2,7 @@ "name": "pyright-internal", "displayName": "pyright", "description": "Type checker for the Python language", - "version": "1.1.386", + "version": "1.1.387", "license": "MIT", "private": true, "files": [ diff --git a/packages/pyright/package-lock.json b/packages/pyright/package-lock.json index 524ccad5e..ea20b561f 100644 --- a/packages/pyright/package-lock.json +++ b/packages/pyright/package-lock.json @@ -1,12 +1,12 @@ { "name": "pyright", - "version": "1.1.386", + "version": "1.1.387", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pyright", - "version": "1.1.386", + "version": "1.1.387", "license": "MIT", "bin": { "pyright": "index.js", diff --git a/packages/pyright/package.json b/packages/pyright/package.json index eb34847e4..4a96eaa11 100644 --- a/packages/pyright/package.json +++ b/packages/pyright/package.json @@ -2,7 +2,7 @@ "name": "pyright", "displayName": "Pyright", "description": "Type checker for the Python language", - "version": "1.1.386", + "version": "1.1.387", "license": "MIT", "author": { "name": "Microsoft Corporation" diff --git a/packages/vscode-pyright/package-lock.json b/packages/vscode-pyright/package-lock.json index 397ff36b9..3a1bfe22f 100644 --- a/packages/vscode-pyright/package-lock.json +++ b/packages/vscode-pyright/package-lock.json @@ -1,12 +1,12 @@ { "name": "vscode-pyright", - "version": "1.1.386", + "version": "1.1.387", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "vscode-pyright", - "version": "1.1.386", + "version": "1.1.387", "license": "MIT", "dependencies": { "vscode-jsonrpc": "^9.0.0-next.5", diff --git a/packages/vscode-pyright/package.json b/packages/vscode-pyright/package.json index a9061c883..20f6e5976 100644 --- a/packages/vscode-pyright/package.json +++ b/packages/vscode-pyright/package.json @@ -2,7 +2,7 @@ "name": "vscode-pyright", "displayName": "Pyright", "description": "VS Code static type checking for Python", - "version": "1.1.386", + "version": "1.1.387", "private": true, "license": "MIT", "author": { From 943aa3b168429b75c7ee3cbef8db0100726a93a2 Mon Sep 17 00:00:00 2001 From: detachhead Date: Wed, 30 Oct 2024 18:36:52 +1000 Subject: [PATCH 19/21] fix duplicated variables from the previous inline `TypedDict` implementation --- packages/pyright-internal/src/analyzer/typeEvaluator.ts | 1 - packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts | 3 --- 2 files changed, 4 deletions(-) diff --git a/packages/pyright-internal/src/analyzer/typeEvaluator.ts b/packages/pyright-internal/src/analyzer/typeEvaluator.ts index bfeb76840..9307241be 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluator.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluator.ts @@ -643,7 +643,6 @@ export function createTypeEvaluator( let intClass: Type | undefined; let strClass: Type | undefined; let dictClass: Type | undefined; - let typedDictClass: Type | undefined; let moduleTypeClass: Type | undefined; let typedDictClass: Type | undefined; let typedDictPrivateClass: Type | undefined; diff --git a/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts b/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts index 73957ce1a..1a1816e30 100644 --- a/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts +++ b/packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts @@ -222,9 +222,6 @@ export interface TypeResult { unpackedType?: Type | undefined; typeList?: TypeResultWithNode[] | undefined; - // For inlined TypedDict definitions. - inlinedTypeDict?: ClassType; - // Type consistency errors detected when evaluating this type. typeErrors?: boolean | undefined; From 699be4217b64948975643311be37a24de577b8eb Mon Sep 17 00:00:00 2001 From: detachhead Date: Wed, 30 Oct 2024 18:37:25 +1000 Subject: [PATCH 20/21] remove some stuff from the docs that now exist upstream --- docs/benefits-over-pyright/inline-typed-dict.md | 11 ----------- docs/installation/ides.md | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) delete mode 100644 docs/benefits-over-pyright/inline-typed-dict.md diff --git a/docs/benefits-over-pyright/inline-typed-dict.md b/docs/benefits-over-pyright/inline-typed-dict.md deleted file mode 100644 index d48f484cc..000000000 --- a/docs/benefits-over-pyright/inline-typed-dict.md +++ /dev/null @@ -1,11 +0,0 @@ -# inline `TypedDict` support - -pyright used to support defining `TypedDict`s inline, like so: - -```py -foo: dict[{"foo": int, "bar": str}] = {"foo": "a", "bar": 1} -``` - -this was an experimental feature and was removed because it never made it into a PEP. but this functionality is very convenient and we see no reason not to continue supporting it, so we added it back in basedpyright. - -this can be disabled by setting `enableExperimentalFeatures` to `false`. diff --git a/docs/installation/ides.md b/docs/installation/ides.md index b888a4ca8..9169c23ea 100644 --- a/docs/installation/ides.md +++ b/docs/installation/ides.md @@ -14,7 +14,7 @@ install the extension from [the vscode extension marketplace](https://marketplac unless you depend on any pylance-exclusive features that haven't yet been re-implemented in basedpyright, it's recommended to disable/uninstall the pylance extension. - if you do want to continue using pylance, all of the options and commands in basedpyright have been renamed to avoid any conflicts with the pylance extension, and the restriction that prevents both extensions from being enabled at the same time has been removed. + if you do want to continue using pylance, all of the options and commands in basedpyright have been renamed to avoid any conflicts with the pylance extension. if basedpyright detects that pylance is installed, you will see a popup prompting you to choose whether to uninstall pylance or fix your settings to allow both extensions to work without overlapping functionality: From 6978ffca9dd9586198824cfa023e5fc2d9a0e97f Mon Sep 17 00:00:00 2001 From: detachhead Date: Wed, 30 Oct 2024 18:38:13 +1000 Subject: [PATCH 21/21] regenerate npm lockfiles --- packages/pyright-internal/package-lock.json | 403 +++++++++++++++----- packages/pyright/package-lock.json | 4 +- 2 files changed, 309 insertions(+), 98 deletions(-) diff --git a/packages/pyright-internal/package-lock.json b/packages/pyright-internal/package-lock.json index b8527a9ed..e007c0141 100644 --- a/packages/pyright-internal/package-lock.json +++ b/packages/pyright-internal/package-lock.json @@ -9,14 +9,17 @@ "version": "1.1.387", "license": "MIT", "dependencies": { + "@actions/core": "^1.10.1", "@yarnpkg/fslib": "2.10.4", "@yarnpkg/libzip": "2.3.0", "chalk": "^4.1.2", "chokidar": "^3.6.0", "command-line-args": "^5.2.1", - "js-toml": "^1.0.0", + "diff": "^7.0.0", "jsonc-parser": "^3.3.1", "leven": "3.1.0", + "pyright-to-gitlab-ci": "^0.1.3", + "smol-toml": "^1.3.0", "source-map-support": "^0.5.21", "tmp": "^0.2.3", "vscode-jsonrpc": "^9.0.0-next.5", @@ -28,6 +31,7 @@ }, "devDependencies": { "@types/command-line-args": "^5.2.3", + "@types/diff": "^5.2.2", "@types/fs-extra": "^11.0.4", "@types/jest": "^29.5.13", "@types/lodash": "^4.17.7", @@ -46,6 +50,41 @@ "word-wrap": "1.2.5" } }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "license": "MIT", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "node_modules/@actions/exec": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz", + "integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==", + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "node_modules/@actions/io": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz", + "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", + "license": "MIT" + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -558,18 +597,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/runtime-corejs3": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.0.tgz", - "integrity": "sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w==", - "dependencies": { - "core-js-pure": "^3.30.2", - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/template": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", @@ -622,40 +649,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@chevrotain/cst-dts-gen": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-11.0.3.tgz", - "integrity": "sha512-BvIKpRLeS/8UbfxXxgC33xOumsacaeCKAjAeLyOn7Pcp95HiRbrpl14S+9vaZLolnbssPIUuiUd8IvgkRyt6NQ==", - "dependencies": { - "@chevrotain/gast": "11.0.3", - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" - } - }, - "node_modules/@chevrotain/gast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-11.0.3.tgz", - "integrity": "sha512-+qNfcoNk70PyS/uxmj3li5NiECO+2YKZZQMbmjTqRI3Qchu8Hig/Q9vgkHpI3alNjr7M+a2St5pw5w5F6NL5/Q==", - "dependencies": { - "@chevrotain/types": "11.0.3", - "lodash-es": "4.17.21" - } - }, - "node_modules/@chevrotain/regexp-to-ast": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/regexp-to-ast/-/regexp-to-ast-11.0.3.tgz", - "integrity": "sha512-1fMHaBZxLFvWI067AVbGJav1eRY7N8DDvYCTwGBiE/ytKBgP8azTdgyrKyWZ9Mfh09eHWb5PgTSO8wi7U824RA==" - }, - "node_modules/@chevrotain/types": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-11.0.3.tgz", - "integrity": "sha512-gsiM3G8b58kZC2HaWR50gu6Y1440cHiJ+i3JUvcp/35JchYejb2+5MVeJK0iKThYpAa/P2PYFV4hoi44HD+aHQ==" - }, - "node_modules/@chevrotain/utils": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-11.0.3.tgz", - "integrity": "sha512-YslZMgtJUyuMbZ+aKvfF3x1f5liK4mWNxghFRv7jqRR9C3R3fAOGTTKvxXDa2Y1s9zSbcpuO0cAxDYsc9SrXoQ==" - }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -1033,6 +1026,15 @@ "node": ">=12" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1545,6 +1547,13 @@ "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==", "dev": true }, + "node_modules/@types/diff": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.3.tgz", + "integrity": "sha512-K0Oqlrq3kQMaO2RhfrNQX5trmt+XLyom88zS0u84nnIcLvFnRUMRRHmrGny5GSM+kNO9IZLARsdQHDzkhAgmrQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/emscripten": { "version": "1.39.13", "resolved": "https://registry.npmjs.org/@types/emscripten/-/emscripten-1.39.13.tgz", @@ -2317,19 +2326,6 @@ "node": ">=10" } }, - "node_modules/chevrotain": { - "version": "11.0.3", - "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", - "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", - "dependencies": { - "@chevrotain/cst-dts-gen": "11.0.3", - "@chevrotain/gast": "11.0.3", - "@chevrotain/regexp-to-ast": "11.0.3", - "@chevrotain/types": "11.0.3", - "@chevrotain/utils": "11.0.3", - "lodash-es": "4.17.21" - } - }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", @@ -2463,6 +2459,110 @@ "node": ">=4.0.0" } }, + "node_modules/command-line-usage": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", + "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", + "license": "MIT", + "dependencies": { + "array-back": "^4.0.2", + "chalk": "^2.4.2", + "table-layout": "^1.0.2", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/command-line-usage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-usage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/command-line-usage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/command-line-usage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -2517,16 +2617,6 @@ "node": ">=10.13.0" } }, - "node_modules/core-js-pure": { - "version": "3.38.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz", - "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -2593,6 +2683,15 @@ } } }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deepmerge": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", @@ -2611,6 +2710,15 @@ "node": ">=8" } }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -4146,15 +4254,6 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, - "node_modules/js-toml": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/js-toml/-/js-toml-1.0.0.tgz", - "integrity": "sha512-G757004huuG5Cjg8KUoVTS4zNRR4449KG8kjtFQS0yyQnceq3KfxcArThcqUV2cwdpd0C9I+e1WciK3Xm4cWJw==", - "dependencies": { - "chevrotain": "^11.0.3", - "xregexp": "^5.1.1" - } - }, "node_modules/js-yaml": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", @@ -4276,11 +4375,6 @@ "node": ">=8" } }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -4721,6 +4815,18 @@ } ] }, + "node_modules/pyright-to-gitlab-ci": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pyright-to-gitlab-ci/-/pyright-to-gitlab-ci-0.1.3.tgz", + "integrity": "sha512-fojkoQGVbPYyTPHq6R8XsS6vcokLh1OJjxEA6DRisvv1rAaEe3OrwaJp1qdey5ML9szTM2pDv66VMuYz/ostdw==", + "license": "ISC", + "dependencies": { + "ts-command-line-args": "^2.4.2" + }, + "bin": { + "pyright-to-gitlab-ci": "dist/index.js" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -4779,10 +4885,14 @@ "node": ">= 0.10" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + "node_modules/reduce-flatten": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", + "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", + "license": "MIT", + "engines": { + "node": ">=6" + } }, "node_modules/require-directory": { "version": "2.1.1", @@ -5038,6 +5148,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/smol-toml": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.0.tgz", + "integrity": "sha512-tWpi2TsODPScmi48b/OQZGi2lgUmBCHy6SZrhi/FdnnHiU1GwebbCfuQuxsC3nHaLwtYeJGPrDZDIeodDOc4pA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, "node_modules/source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -5079,6 +5201,12 @@ "node": ">=10" } }, + "node_modules/string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", + "license": "WTFPL OR MIT" + }, "node_modules/string-length": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", @@ -5171,6 +5299,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/table-layout": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", + "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", + "license": "MIT", + "dependencies": { + "array-back": "^4.0.1", + "deep-extend": "~0.6.0", + "typical": "^5.2.0", + "wordwrapjs": "^4.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", @@ -5358,6 +5519,21 @@ "node": ">=8.0" } }, + "node_modules/ts-command-line-args": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", + "license": "ISC", + "dependencies": { + "chalk": "^4.1.0", + "command-line-args": "^5.1.1", + "command-line-usage": "^6.1.0", + "string-format": "^2.0.0" + }, + "bin": { + "write-markdown": "dist/write-markdown.js" + } + }, "node_modules/ts-jest": { "version": "29.2.5", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz", @@ -5464,6 +5640,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", @@ -5506,6 +5691,18 @@ "node": ">=8" } }, + "node_modules/undici": { + "version": "5.28.4", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", + "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", @@ -5872,6 +6069,28 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrapjs": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", + "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", + "license": "MIT", + "dependencies": { + "reduce-flatten": "^2.0.0", + "typical": "^5.2.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/typical": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", + "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -5914,14 +6133,6 @@ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true }, - "node_modules/xregexp": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-5.1.1.tgz", - "integrity": "sha512-fKXeVorD+CzWvFs7VBuKTYIW63YD1e1osxwQ8caZ6o1jg6pDAbABDG54LCIq0j5cy7PjRvGIq6sef9DYPXpncg==", - "dependencies": { - "@babel/runtime-corejs3": "^7.16.5" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/packages/pyright/package-lock.json b/packages/pyright/package-lock.json index ea20b561f..09ec5ea6d 100644 --- a/packages/pyright/package-lock.json +++ b/packages/pyright/package-lock.json @@ -1,11 +1,11 @@ { - "name": "pyright", + "name": "basedpyright", "version": "1.1.387", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "pyright", + "name": "basedpyright", "version": "1.1.387", "license": "MIT", "bin": {