Added the ability to add new symbols to builtins by simply adding a type stub file named __builtins__.pyi locally.

This commit is contained in:
Eric Traut 2022-02-02 19:27:12 -08:00
parent 9d7a3cb40e
commit 94db5376c1
5 changed files with 63 additions and 5 deletions

View File

@ -111,6 +111,7 @@ To update to the latest version:
* [Comments](/docs/comments.md)
* [Type Inference](/docs/type-inference.md)
* [Import Resolution](/docs/import-resolution.md)
* [Extending Builtins](/docs/builtins.md)
* [Type Stubs](/docs/type-stubs.md)
* [Types in Libraries](/docs/typed-libraries.md)
* [Commands](/docs/commands.md)

8
docs/builtins.md Normal file
View File

@ -0,0 +1,8 @@
# Extending Builtins
The Python interpreter implicitly adds a set of symbols that are available within every module even though they are not explicitly imported. These so-called “built in” symbols include commonly-used types and functions such as “list”, “dict”, “int”, “float”, “min”, and “len”.
Pyright gains knowledge of which types are included in “builtins” scope through the type stub file `builtins.pyi`. This stub file comes from the typeshed github repo and is bundled with pyright, along with type stubs that describe other stdlib modules.
Some Python environments are customized to include additional builtins symbols. If you are using such an environment, you may want to tell Pyright about these additional symbols that are available at runtime. To do so, you can add a local type stub file called `__builtins__.pyi`. This file can be placed at the root of your project directory or at the root of the subdirectory specified in the `stubPath` setting (which is named `typings` by default).

View File

@ -359,6 +359,15 @@ export class Program {
filePaths.forEach((filePath) => {
const sourceFileInfo = this._getSourceFileInfoFromPath(filePath);
if (sourceFileInfo) {
const fileName = getFileName(filePath);
// Handle builtins and __builtins__ specially. They are implicitly
// included by all source files.
if (fileName === 'builtins.pyi' || fileName === '__builtins__.pyi') {
this.markAllFilesDirty(evenIfContentsAreSame, indexingNeeded);
return;
}
// If !evenIfContentsAreSame, see if the on-disk contents have
// changed. If the file is open, the on-disk contents don't matter
// because we'll receive updates directly from the client.

View File

@ -1214,11 +1214,29 @@ export class SourceFile {
const imports: ImportResult[] = [];
// Always include an implicit import of the builtins module.
let builtinsImportResult: ImportResult | undefined = importResolver.resolveImport(this._filePath, execEnv, {
leadingDots: 0,
nameParts: ['builtins'],
importedSymbols: undefined,
});
let builtinsImportResult: ImportResult | undefined;
// If this is a project source file (not a stub), try to resolve
// the __builtins__ stub first.
if (!this._isThirdPartyImport && !this._isStubFile) {
builtinsImportResult = importResolver.resolveImport(this._filePath, execEnv, {
leadingDots: 0,
nameParts: ['__builtins__'],
importedSymbols: undefined,
});
if (builtinsImportResult && !builtinsImportResult.isImportFound) {
builtinsImportResult = undefined;
}
}
if (!builtinsImportResult) {
builtinsImportResult = importResolver.resolveImport(this._filePath, execEnv, {
leadingDots: 0,
nameParts: ['builtins'],
importedSymbols: undefined,
});
}
// Avoid importing builtins from the builtins.pyi file itself.
if (

View File

@ -0,0 +1,22 @@
/// <reference path="fourslash.ts" />
// @filename: test.py
//// Cust[|/*marker1*/|]
//// my_v[|/*marker2*/|]
// @filename: __builtins__.pyi
//// class CustomClass: ...
//// my_var: int = ...
// @ts-ignore
await helper.verifyCompletion('exact', 'markdown', {
marker1: {
completions: [
{
label: 'CustomClass',
kind: Consts.CompletionItemKind.Class,
},
],
},
marker2: { completions: [{ label: 'my_var', kind: Consts.CompletionItemKind.Variable }] },
});