Skip to content

Commit dcb5cb9

Browse files
committed
add basedpyright.analysis.useTypingExtensions setting so that users don't accidentally make their project depend on typing_extensions
1 parent 0c8937c commit dcb5cb9

File tree

10 files changed

+37
-10
lines changed

10 files changed

+37
-10
lines changed

docs/benefits-over-pyright/language-server-improvements.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,19 @@ autocomplete suggestions for method overrides will automatically add the `@overr
88

99
![](./override-decorator-completions.gif)
1010

11+
!!! info "for users targeting python <=3.11"
12+
13+
since the `@typing.override` decorator was introduced in python 3.12, this functionality is only enabled if either:
14+
15+
- you are targeting python 3.12 or above (see [`pythonVersion`](../configuration/config-files.md/#environment-options))
16+
- you have enabled [`basedpyright.analysis.useTypingExtensions`](../configuration/language-server-settings.md#based-settings)
17+
18+
!!! warning "important information for library developers"
19+
20+
using `typing_extensions` creates a runtime dependency on the [`typing_extensions`](https://pypi.org/project/typing-extensions/) pypi package, so you must declare it as a project dependency. this is why `basedpyright.analysis.useTypingExtensions` is disabled by default to prevent users from unknowingly adding a new dependency to their project.
21+
22+
such mistakes often go undetected until your package is released and causes a runtime error for your users because the module may be available in dev dependencies but not production dependencies. (we recommend using [tach](https://docs.gauge.sh/usage/commands#tach-check-external) to detect issues like these)
23+
1124
## improved diagnostic severity system
1225

1326
in pyright, certain diagnostics such as unreachable and unused code are always reported as a hint and cannot be disabled even when the associated diagnostic rule is disabled (and in the case of unreachable code, [there is no diagnostic rule at all](./new-diagnostic-rules.md#reportunreachable)).

docs/configuration/language-server-settings.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ the following settings are exclusive to basedpyright
5555

5656
![](inlayHints.genericTypes.png)
5757

58+
**basedpyright.analysis.useTypingExtensions** [boolean]: Whether to rely on imports from the `typing_extensions` module when targeting older versions of python that do not include certain typing features such as the `@override` decorator. Defaults to `false`. [more info](../benefits-over-pyright/language-server-improvements.md#autocomplete-improvements)
59+
5860
### discouraged settings
5961

6062
these options can also be configured [using a config file](./config-files.md). it's recommended to use either a `pyproject.toml` or `pyrightconfig.json` file instead of the language server to configure type checking for the following reasons:

packages/pyright-internal/src/common/languageServerInterface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export interface ServerSettings {
5050
taskListTokens?: TaskListToken[];
5151
functionSignatureDisplay?: SignatureDisplayType | undefined;
5252
inlayHints?: InlayHintSettings;
53+
useTypingExtensions?: boolean;
5354
}
5455

5556
export interface MessageAction {

packages/pyright-internal/src/languageServerBase.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
371371
workspace.disableTaggedHints = !!serverSettings.disableTaggedHints;
372372
workspace.disableOrganizeImports = !!serverSettings.disableOrganizeImports;
373373
workspace.inlayHints = serverSettings.inlayHints;
374+
workspace.useTypingExtensions = serverSettings.useTypingExtensions ?? false;
374375
} finally {
375376
// Don't use workspace.isInitialized directly since it might have been
376377
// reset due to pending config change event.
@@ -970,6 +971,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
970971
lazyEdit: false,
971972
triggerCharacter: params?.context?.triggerCharacter,
972973
checkDeprecatedWhenResolving: this.client.completionItemResolveSupportsTags,
974+
useTypingExtensions: workspace.useTypingExtensions,
973975
},
974976
token,
975977
false
@@ -1001,6 +1003,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface, Dis
10011003
snippet: this.client.completionSupportsSnippet,
10021004
lazyEdit: false,
10031005
checkDeprecatedWhenResolving: this.client.completionItemResolveSupportsTags,
1006+
useTypingExtensions: workspace.useTypingExtensions,
10041007
},
10051008
token,
10061009
false

packages/pyright-internal/src/languageService/codeActionProvider.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class CodeActionProvider {
8181
// we don't care about deprecations here so make sure they don't get evaluated unnecessarily
8282
// (we don't call resolveCompletionItem)
8383
checkDeprecatedWhenResolving: true,
84+
useTypingExtensions: workspace.useTypingExtensions,
8485
},
8586
token,
8687
true

packages/pyright-internal/src/languageService/completionProvider.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ export interface CompletionOptions {
252252
readonly lazyEdit: boolean;
253253
readonly triggerCharacter?: string;
254254
readonly checkDeprecatedWhenResolving: boolean;
255+
readonly useTypingExtensions: boolean;
255256
}
256257

257258
interface RecentCompletionInfo {
@@ -518,17 +519,9 @@ export class CompletionProvider {
518519
// this should always be true, but just in case
519520
overrideDecorator?.category === TypeCategory.Function &&
520521
// if targeting a python version that doesn't have typing.override, we don't want to insert the decorator unless
521-
// the user has actually installed the typing_extensions package
522+
// the user has explicitly enabled `basedpyright.analysis.useTypingExtensions`
522523
(overrideDecorator.shared.moduleName !== 'typing_extensions' ||
523-
!!this.importResolver.resolveImport(
524-
this.fileUri,
525-
this.configOptions.findExecEnvironment(this.fileUri),
526-
{
527-
leadingDots: 0,
528-
nameParts: ['typing_extensions'],
529-
importedSymbols: undefined,
530-
}
531-
).nonStubImportResult?.resolvedUris.length) &&
524+
this.options.useTypingExtensions) &&
532525
// check if the override decorator is already here
533526
!decorators?.some((decorator) => {
534527
const type = this.evaluator.getTypeOfExpression(decorator.d.expr).type;

packages/pyright-internal/src/realLanguageServer.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export abstract class RealLanguageServer extends LanguageServerBase {
117117
variableTypes: true,
118118
genericTypes: false,
119119
},
120+
useTypingExtensions: false,
120121
};
121122

122123
try {
@@ -209,6 +210,9 @@ export abstract class RealLanguageServer extends LanguageServerBase {
209210
if (inlayHintSection) {
210211
serverSettings.inlayHints = { ...serverSettings.inlayHints, ...inlayHintSection };
211212
}
213+
if (pythonAnalysisSection.useTypingExtensions) {
214+
serverSettings.useTypingExtensions = pythonAnalysisSection.useTypingExtensions;
215+
}
212216
} else {
213217
serverSettings.autoSearchPaths = true;
214218
}

packages/pyright-internal/src/tests/chainedSourceFiles.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ test('check chained files', () => {
5858
lazyEdit: false,
5959
snippet: false,
6060
checkDeprecatedWhenResolving: false,
61+
useTypingExtensions: true,
6162
},
6263
CancellationToken.None,
6364
false
@@ -107,6 +108,7 @@ test('modify chained files', () => {
107108
lazyEdit: false,
108109
snippet: false,
109110
checkDeprecatedWhenResolving: false,
111+
useTypingExtensions: true,
110112
},
111113
CancellationToken.None,
112114
false

packages/pyright-internal/src/workspaceFactory.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ export interface Workspace extends WorkspaceFolder {
9999
isInitialized: InitStatus;
100100
searchPathsToWatch: Uri[];
101101
inlayHints?: InlayHintSettings | undefined;
102+
useTypingExtensions: boolean;
102103
}
103104

104105
export interface NormalWorkspace extends Workspace {
@@ -286,6 +287,7 @@ export class WorkspaceFactory {
286287
disableWorkspaceSymbol: false,
287288
isInitialized: createInitStatus(),
288289
searchPathsToWatch: [],
290+
useTypingExtensions: false,
289291
};
290292

291293
// Stick in our map

packages/vscode-pyright/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1866,6 +1866,12 @@
18661866
"default": false,
18671867
"description": "Whether to show inlay hints on inferred generic types.",
18681868
"scope": "resource"
1869+
},
1870+
"basedpyright.analysis.useTypingExtensions": {
1871+
"type": "boolean",
1872+
"default": false,
1873+
"markdownDescription": "Whether to rely on imports from the `typing_extensions` module when targeting older versions of python that do not include certain typing features such as the `@override` decorator.",
1874+
"scope": "resource"
18691875
}
18701876
}
18711877
},

0 commit comments

Comments
 (0)