Skip to content

Commit 94db537

Browse files
committed
Added the ability to add new symbols to builtins by simply adding a type stub file named __builtins__.pyi locally.
1 parent 9d7a3cb commit 94db537

File tree

5 files changed

+63
-5
lines changed

5 files changed

+63
-5
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ To update to the latest version:
111111
* [Comments](/docs/comments.md)
112112
* [Type Inference](/docs/type-inference.md)
113113
* [Import Resolution](/docs/import-resolution.md)
114+
* [Extending Builtins](/docs/builtins.md)
114115
* [Type Stubs](/docs/type-stubs.md)
115116
* [Types in Libraries](/docs/typed-libraries.md)
116117
* [Commands](/docs/commands.md)

docs/builtins.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Extending Builtins
2+
3+
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”.
4+
5+
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.
6+
7+
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).
8+

packages/pyright-internal/src/analyzer/program.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,15 @@ export class Program {
359359
filePaths.forEach((filePath) => {
360360
const sourceFileInfo = this._getSourceFileInfoFromPath(filePath);
361361
if (sourceFileInfo) {
362+
const fileName = getFileName(filePath);
363+
364+
// Handle builtins and __builtins__ specially. They are implicitly
365+
// included by all source files.
366+
if (fileName === 'builtins.pyi' || fileName === '__builtins__.pyi') {
367+
this.markAllFilesDirty(evenIfContentsAreSame, indexingNeeded);
368+
return;
369+
}
370+
362371
// If !evenIfContentsAreSame, see if the on-disk contents have
363372
// changed. If the file is open, the on-disk contents don't matter
364373
// because we'll receive updates directly from the client.

packages/pyright-internal/src/analyzer/sourceFile.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,11 +1214,29 @@ export class SourceFile {
12141214
const imports: ImportResult[] = [];
12151215

12161216
// Always include an implicit import of the builtins module.
1217-
let builtinsImportResult: ImportResult | undefined = importResolver.resolveImport(this._filePath, execEnv, {
1218-
leadingDots: 0,
1219-
nameParts: ['builtins'],
1220-
importedSymbols: undefined,
1221-
});
1217+
let builtinsImportResult: ImportResult | undefined;
1218+
1219+
// If this is a project source file (not a stub), try to resolve
1220+
// the __builtins__ stub first.
1221+
if (!this._isThirdPartyImport && !this._isStubFile) {
1222+
builtinsImportResult = importResolver.resolveImport(this._filePath, execEnv, {
1223+
leadingDots: 0,
1224+
nameParts: ['__builtins__'],
1225+
importedSymbols: undefined,
1226+
});
1227+
1228+
if (builtinsImportResult && !builtinsImportResult.isImportFound) {
1229+
builtinsImportResult = undefined;
1230+
}
1231+
}
1232+
1233+
if (!builtinsImportResult) {
1234+
builtinsImportResult = importResolver.resolveImport(this._filePath, execEnv, {
1235+
leadingDots: 0,
1236+
nameParts: ['builtins'],
1237+
importedSymbols: undefined,
1238+
});
1239+
}
12221240

12231241
// Avoid importing builtins from the builtins.pyi file itself.
12241242
if (
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/// <reference path="fourslash.ts" />
2+
3+
// @filename: test.py
4+
//// Cust[|/*marker1*/|]
5+
//// my_v[|/*marker2*/|]
6+
7+
// @filename: __builtins__.pyi
8+
//// class CustomClass: ...
9+
//// my_var: int = ...
10+
11+
// @ts-ignore
12+
await helper.verifyCompletion('exact', 'markdown', {
13+
marker1: {
14+
completions: [
15+
{
16+
label: 'CustomClass',
17+
kind: Consts.CompletionItemKind.Class,
18+
},
19+
],
20+
},
21+
marker2: { completions: [{ label: 'my_var', kind: Consts.CompletionItemKind.Variable }] },
22+
});

0 commit comments

Comments
 (0)