mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 07:55:56 +03:00
Added a new configuration option deprecateTypingAliases
that enables deprecation detection and reporting for symbols imported from the typing
module that are deprecated according to PEP 585 and 604. The option is currently disabled by default (even in strict mode) but can be enabled manually. This addresses #3598. (#5812)
Co-authored-by: Eric Traut <erictr@microsoft.com>
This commit is contained in:
parent
6cc5e3c255
commit
4474b7d36b
@ -56,6 +56,8 @@ The following settings control pyright’s diagnostic output (warnings or errors
|
||||
|
||||
<a name="enableTypeIgnoreComments"></a> **enableTypeIgnoreComments** [boolean]: PEP 484 defines support for "# type: ignore" comments. This switch enables or disables support for these comments. The default value for this setting is `true`. This does not affect "# pyright: ignore" comments.
|
||||
|
||||
<a name="deprecateTypingAliases"></a> **deprecateTypingAliases** [boolean]: PEP 585 indicates that aliases to types in standard collections that were introduced solely to support generics are deprecated as of Python 3.9. This switch controls whether these are treated as deprecated. This applies only when pythonVersion is 3.9 or newer. The default value for this setting is `false` but may be switched to `true` in the future.
|
||||
|
||||
<a name="enableExperimentalFeatures"></a> **enableExperimentalFeatures** [boolean]: Enables a set of experimental (mostly undocumented) features that correspond to proposed or exploratory changes to the Python typing standard. These features will likely change or be removed, so they should not be used except for experimentation purposes.
|
||||
|
||||
<a name="reportGeneralTypeIssues"></a> **reportGeneralTypeIssues** [boolean or string, optional]: Generate or suppress diagnostics for general type inconsistencies, unsupported operations, argument/parameter mismatches, etc. This covers all of the basic type-checking rules not covered by other rules. It does not include syntax errors. The default value for this setting is `"error"`.
|
||||
@ -304,6 +306,7 @@ The following table lists the default severity levels for each diagnostic rule w
|
||||
| strictListInference | false | false | true |
|
||||
| strictDictionaryInference | false | false | true |
|
||||
| strictSetInference | false | false | true |
|
||||
| deprecateTypingAliases | false | false | false |
|
||||
| enableExperimentalFeatures | false | false | false |
|
||||
| reportMissingModuleSource | "warning" | "warning" | "warning" |
|
||||
| reportMissingImports | "warning" | "error" | "error" |
|
||||
|
@ -95,6 +95,7 @@ import { AnalyzerFileInfo } from './analyzerFileInfo';
|
||||
import * as AnalyzerNodeInfo from './analyzerNodeInfo';
|
||||
import { Declaration, DeclarationType, isAliasDeclaration } from './declaration';
|
||||
import { getNameNodeForDeclaration } from './declarationUtils';
|
||||
import { deprecatedAliases, deprecatedSpecialForms } from './deprecatedSymbols';
|
||||
import { ImportResolver, ImportedModuleDescriptor, createImportedModuleDescriptor } from './importResolver';
|
||||
import { ImportResult, ImportType } from './importResult';
|
||||
import { getRelativeModuleName, getTopLevelImports } from './importStatementUtils';
|
||||
@ -189,51 +190,6 @@ interface TypeVarUsageInfo {
|
||||
nodes: NameNode[];
|
||||
}
|
||||
|
||||
interface DeprecatedForm {
|
||||
version: PythonVersion;
|
||||
fullName: string;
|
||||
replacementText: string;
|
||||
}
|
||||
|
||||
const deprecatedAliases = new Map<string, DeprecatedForm>([
|
||||
['Tuple', { version: PythonVersion.V3_9, fullName: 'builtins.tuple', replacementText: 'tuple' }],
|
||||
['List', { version: PythonVersion.V3_9, fullName: 'builtins.list', replacementText: 'list' }],
|
||||
['Dict', { version: PythonVersion.V3_9, fullName: 'builtins.dict', replacementText: 'dict' }],
|
||||
['Set', { version: PythonVersion.V3_9, fullName: 'builtins.set', replacementText: 'set' }],
|
||||
['FrozenSet', { version: PythonVersion.V3_9, fullName: 'builtins.frozenset', replacementText: 'frozenset' }],
|
||||
['Type', { version: PythonVersion.V3_9, fullName: 'builtins.type', replacementText: 'type' }],
|
||||
['Deque', { version: PythonVersion.V3_9, fullName: 'collections.deque', replacementText: 'collections.deque' }],
|
||||
[
|
||||
'DefaultDict',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'collections.defaultdict',
|
||||
replacementText: 'collections.defaultdict',
|
||||
},
|
||||
],
|
||||
[
|
||||
'OrderedDict',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'collections.OrderedDict',
|
||||
replacementText: 'collections.OrderedDict',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Counter',
|
||||
{ version: PythonVersion.V3_9, fullName: 'collections.Counter', replacementText: 'collections.Counter' },
|
||||
],
|
||||
[
|
||||
'ChainMap',
|
||||
{ version: PythonVersion.V3_9, fullName: 'collections.ChainMap', replacementText: 'collections.ChainMap' },
|
||||
],
|
||||
]);
|
||||
|
||||
const deprecatedSpecialForms = new Map<string, DeprecatedForm>([
|
||||
['Optional', { version: PythonVersion.V3_10, fullName: 'typing.Optional', replacementText: '| None' }],
|
||||
['Union', { version: PythonVersion.V3_10, fullName: 'typing.Union', replacementText: '|' }],
|
||||
]);
|
||||
|
||||
// When enabled, this debug flag causes the code complexity of
|
||||
// functions to be emitted.
|
||||
const isPrintCodeComplexityEnabled = false;
|
||||
@ -1471,7 +1427,13 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
override visitMemberAccess(node: MemberAccessNode) {
|
||||
const type = this._evaluator.getType(node);
|
||||
this._reportDeprecatedUse(node.memberName, type);
|
||||
|
||||
const leftExprType = this._evaluator.getType(node.leftExpression);
|
||||
this._reportDeprecatedUse(
|
||||
node.memberName,
|
||||
type,
|
||||
leftExprType && isModule(leftExprType) && leftExprType.moduleName === 'typing'
|
||||
);
|
||||
|
||||
this._conditionallyReportPrivateUsage(node.memberName);
|
||||
|
||||
@ -1558,8 +1520,17 @@ export class Checker extends ParseTreeWalker {
|
||||
break;
|
||||
}
|
||||
|
||||
let isImportFromTyping = false;
|
||||
if (node.parent?.nodeType === ParseNodeType.ImportFrom) {
|
||||
if (node.parent.module.leadingDots === 0 && node.parent.module.nameParts.length === 1) {
|
||||
if (node.parent.module.nameParts[0].value === 'typing') {
|
||||
isImportFromTyping = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const type = this._evaluator.getType(node.alias ?? node.name);
|
||||
this._reportDeprecatedUse(node.name, type);
|
||||
this._reportDeprecatedUse(node.name, type, isImportFromTyping);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -3765,7 +3736,7 @@ export class Checker extends ParseTreeWalker {
|
||||
return false;
|
||||
}
|
||||
|
||||
private _reportDeprecatedUse(node: NameNode, type: Type | undefined) {
|
||||
private _reportDeprecatedUse(node: NameNode, type: Type | undefined, isImportFromTyping = false) {
|
||||
if (!type) {
|
||||
return;
|
||||
}
|
||||
@ -3854,32 +3825,35 @@ export class Checker extends ParseTreeWalker {
|
||||
}
|
||||
}
|
||||
|
||||
// We'll leave this disabled for now because this would be too noisy for most
|
||||
// code bases. We may want to add it at some future date.
|
||||
if (0) {
|
||||
if (this._fileInfo.diagnosticRuleSet.deprecateTypingAliases) {
|
||||
const deprecatedForm = deprecatedAliases.get(node.value) ?? deprecatedSpecialForms.get(node.value);
|
||||
|
||||
if (deprecatedForm) {
|
||||
if (isInstantiableClass(type) && type.details.fullName === deprecatedForm.fullName) {
|
||||
if (
|
||||
(isInstantiableClass(type) && type.details.fullName === deprecatedForm.fullName) ||
|
||||
type.typeAliasInfo?.fullName === deprecatedForm.fullName
|
||||
) {
|
||||
if (this._fileInfo.executionEnvironment.pythonVersion >= deprecatedForm.version) {
|
||||
if (this._fileInfo.diagnosticRuleSet.reportDeprecated === 'none') {
|
||||
this._evaluator.addDeprecated(
|
||||
Localizer.Diagnostic.deprecatedType().format({
|
||||
version: versionToString(deprecatedForm.version),
|
||||
replacement: deprecatedForm.replacementText,
|
||||
}),
|
||||
node
|
||||
);
|
||||
} else {
|
||||
this._evaluator.addDiagnostic(
|
||||
this._fileInfo.diagnosticRuleSet.reportDeprecated,
|
||||
DiagnosticRule.reportDeprecated,
|
||||
Localizer.Diagnostic.deprecatedType().format({
|
||||
version: versionToString(deprecatedForm.version),
|
||||
replacement: deprecatedForm.replacementText,
|
||||
}),
|
||||
node
|
||||
);
|
||||
if (!deprecatedForm.typingImportOnly || isImportFromTyping) {
|
||||
if (this._fileInfo.diagnosticRuleSet.reportDeprecated === 'none') {
|
||||
this._evaluator.addDeprecated(
|
||||
Localizer.Diagnostic.deprecatedType().format({
|
||||
version: versionToString(deprecatedForm.version),
|
||||
replacement: deprecatedForm.replacementText,
|
||||
}),
|
||||
node
|
||||
);
|
||||
} else {
|
||||
this._evaluator.addDiagnostic(
|
||||
this._fileInfo.diagnosticRuleSet.reportDeprecated,
|
||||
DiagnosticRule.reportDeprecated,
|
||||
Localizer.Diagnostic.deprecatedType().format({
|
||||
version: versionToString(deprecatedForm.version),
|
||||
replacement: deprecatedForm.replacementText,
|
||||
}),
|
||||
node
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
305
packages/pyright-internal/src/analyzer/deprecatedSymbols.ts
Normal file
305
packages/pyright-internal/src/analyzer/deprecatedSymbols.ts
Normal file
@ -0,0 +1,305 @@
|
||||
/*
|
||||
* deprecatedSymbols.ts
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
* Licensed under the MIT license.
|
||||
* Author: Eric Traut
|
||||
*
|
||||
* A list of implicitly-deprecated symbols as defined in PEP 585, etc.
|
||||
*/
|
||||
|
||||
import { PythonVersion } from '../common/pythonVersion';
|
||||
|
||||
export interface DeprecatedForm {
|
||||
// The version of Python where this symbol becomes deprecated
|
||||
version: PythonVersion;
|
||||
|
||||
// The full name of the deprecated type
|
||||
fullName: string;
|
||||
|
||||
// The replacement form
|
||||
replacementText: string;
|
||||
|
||||
// Indicates that the symbol is deprecated only if imported from `typing`
|
||||
typingImportOnly?: boolean;
|
||||
}
|
||||
|
||||
export const deprecatedAliases = new Map<string, DeprecatedForm>([
|
||||
['Tuple', { version: PythonVersion.V3_9, fullName: 'builtins.tuple', replacementText: 'tuple' }],
|
||||
['List', { version: PythonVersion.V3_9, fullName: 'builtins.list', replacementText: 'list' }],
|
||||
['Dict', { version: PythonVersion.V3_9, fullName: 'builtins.dict', replacementText: 'dict' }],
|
||||
['Set', { version: PythonVersion.V3_9, fullName: 'builtins.set', replacementText: 'set' }],
|
||||
['FrozenSet', { version: PythonVersion.V3_9, fullName: 'builtins.frozenset', replacementText: 'frozenset' }],
|
||||
['Type', { version: PythonVersion.V3_9, fullName: 'builtins.type', replacementText: 'type' }],
|
||||
['Deque', { version: PythonVersion.V3_9, fullName: 'collections.deque', replacementText: 'collections.deque' }],
|
||||
[
|
||||
'DefaultDict',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'collections.defaultdict',
|
||||
replacementText: 'collections.defaultdict',
|
||||
},
|
||||
],
|
||||
[
|
||||
'OrderedDict',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'collections.OrderedDict',
|
||||
replacementText: 'collections.OrderedDict',
|
||||
},
|
||||
],
|
||||
[
|
||||
'Counter',
|
||||
{ version: PythonVersion.V3_9, fullName: 'collections.Counter', replacementText: 'collections.Counter' },
|
||||
],
|
||||
[
|
||||
'ChainMap',
|
||||
{ version: PythonVersion.V3_9, fullName: 'collections.ChainMap', replacementText: 'collections.ChainMap' },
|
||||
],
|
||||
[
|
||||
'Awaitable',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Awaitable',
|
||||
replacementText: 'collections.abc.Awaitable',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Coroutine',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Coroutine',
|
||||
replacementText: 'collections.abc.Coroutine',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'AsyncIterable',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.AsyncIterable',
|
||||
replacementText: 'collections.abc.AsyncIterable',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'AsyncIterator',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.AsyncIterator',
|
||||
replacementText: 'collections.abc.AsyncIterator',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'AsyncGenerator',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.AsyncGenerator',
|
||||
replacementText: 'collections.abc.AsyncGenerator',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Iterable',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Iterable',
|
||||
replacementText: 'collections.abc.Iterable',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Iterator',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Iterator',
|
||||
replacementText: 'collections.abc.Iterator',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Generator',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Generator',
|
||||
replacementText: 'collections.abc.Generator',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Reversible',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Reversible',
|
||||
replacementText: 'collections.abc.Reversible',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Container',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Container',
|
||||
replacementText: 'collections.abc.Container',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Collection',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Collection',
|
||||
replacementText: 'collections.abc.Collection',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'AbstractSet',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.AbstractSet',
|
||||
replacementText: 'collections.abc.Set',
|
||||
},
|
||||
],
|
||||
[
|
||||
'MutableSet',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.MutableSet',
|
||||
replacementText: 'collections.abc.MutableSet',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Mapping',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Mapping',
|
||||
replacementText: 'collections.abc.Mapping',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'MutableMapping',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.MutableMapping',
|
||||
replacementText: 'collections.abc.MutableMapping',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Sequence',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Sequence',
|
||||
replacementText: 'collections.abc.Sequence',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'MutableSequence',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.MutableSequence',
|
||||
replacementText: 'collections.abc.MutableSequence',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'ByteString',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.ByteString',
|
||||
replacementText: 'collections.abc.ByteString',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'MappingView',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.MappingView',
|
||||
replacementText: 'collections.abc.MappingView',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'KeysView',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.KeysView',
|
||||
replacementText: 'collections.abc.KeysView',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'ItemsView',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.ItemsView',
|
||||
replacementText: 'collections.abc.ItemsView',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'ValuesView',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.ValuesView',
|
||||
replacementText: 'collections.abc.ValuesView',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'ContextManager',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'contextlib.AbstractContextManager',
|
||||
replacementText: 'contextlib.AbstractContextManager',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'AsyncContextManager',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'contextlib.AbstractAsyncContextManager',
|
||||
replacementText: 'contextlib.AbstractAsyncContextManager',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Pattern',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 're.Pattern',
|
||||
replacementText: 're.Pattern',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
'Match',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 're.Match',
|
||||
replacementText: 're.Match',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
export const deprecatedSpecialForms = new Map<string, DeprecatedForm>([
|
||||
['Optional', { version: PythonVersion.V3_10, fullName: 'typing.Optional', replacementText: '| None' }],
|
||||
['Union', { version: PythonVersion.V3_10, fullName: 'typing.Union', replacementText: '|' }],
|
||||
[
|
||||
'Callable',
|
||||
{
|
||||
version: PythonVersion.V3_9,
|
||||
fullName: 'typing.Callable',
|
||||
replacementText: 'collections.abc.Callable',
|
||||
typingImportOnly: true,
|
||||
},
|
||||
],
|
||||
]);
|
@ -111,6 +111,9 @@ export interface DiagnosticRuleSet {
|
||||
// Enable support for type: ignore comments?
|
||||
enableTypeIgnoreComments: boolean;
|
||||
|
||||
// Treat old typing aliases as deprecated if pythonVersion >= 3.9?
|
||||
deprecateTypingAliases: boolean;
|
||||
|
||||
// Report general type issues?
|
||||
reportGeneralTypeIssues: DiagnosticLevel;
|
||||
|
||||
@ -333,6 +336,7 @@ export function getBooleanDiagnosticRules(includeNonOverridable = false) {
|
||||
DiagnosticRule.strictDictionaryInference,
|
||||
DiagnosticRule.analyzeUnannotatedFunctions,
|
||||
DiagnosticRule.strictParameterNoneValue,
|
||||
DiagnosticRule.deprecateTypingAliases,
|
||||
];
|
||||
|
||||
if (includeNonOverridable) {
|
||||
@ -340,7 +344,6 @@ export function getBooleanDiagnosticRules(includeNonOverridable = false) {
|
||||
// want to override it in strict mode or support
|
||||
// it within pyright comments.
|
||||
boolRules.push(DiagnosticRule.enableTypeIgnoreComments);
|
||||
boolRules.push(DiagnosticRule.enableExperimentalFeatures);
|
||||
}
|
||||
|
||||
return boolRules;
|
||||
@ -437,6 +440,7 @@ export function getOffDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
strictParameterNoneValue: true,
|
||||
enableExperimentalFeatures: false,
|
||||
enableTypeIgnoreComments: true,
|
||||
deprecateTypingAliases: false,
|
||||
reportGeneralTypeIssues: 'none',
|
||||
reportPropertyTypeMismatch: 'none',
|
||||
reportFunctionMemberAccess: 'none',
|
||||
@ -520,6 +524,7 @@ export function getBasicDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
strictParameterNoneValue: true,
|
||||
enableExperimentalFeatures: false,
|
||||
enableTypeIgnoreComments: true,
|
||||
deprecateTypingAliases: false,
|
||||
reportGeneralTypeIssues: 'error',
|
||||
reportPropertyTypeMismatch: 'none',
|
||||
reportFunctionMemberAccess: 'none',
|
||||
@ -601,8 +606,9 @@ export function getStrictDiagnosticRuleSet(): DiagnosticRuleSet {
|
||||
strictDictionaryInference: true,
|
||||
analyzeUnannotatedFunctions: true,
|
||||
strictParameterNoneValue: true,
|
||||
enableExperimentalFeatures: false, // Not overridden by strict mode
|
||||
enableExperimentalFeatures: false,
|
||||
enableTypeIgnoreComments: true, // Not overridden by strict mode
|
||||
deprecateTypingAliases: false,
|
||||
reportGeneralTypeIssues: 'error',
|
||||
reportPropertyTypeMismatch: 'none',
|
||||
reportFunctionMemberAccess: 'error',
|
||||
|
@ -18,6 +18,7 @@ export enum DiagnosticRule {
|
||||
strictParameterNoneValue = 'strictParameterNoneValue',
|
||||
enableExperimentalFeatures = 'enableExperimentalFeatures',
|
||||
enableTypeIgnoreComments = 'enableTypeIgnoreComments',
|
||||
deprecateTypingAliases = 'deprecateTypingAliases',
|
||||
|
||||
reportGeneralTypeIssues = 'reportGeneralTypeIssues',
|
||||
reportPropertyTypeMismatch = 'reportPropertyTypeMismatch',
|
||||
|
@ -501,23 +501,51 @@ test('RegionComments1', () => {
|
||||
TestUtils.validateResults(analysisResults, 2);
|
||||
});
|
||||
|
||||
// For now, this functionality is disabled.
|
||||
test('Deprecated1', () => {
|
||||
const configOptions = new ConfigOptions('.');
|
||||
|
||||
// test('Deprecated1', () => {
|
||||
// const configOptions = new ConfigOptions('.');
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_8;
|
||||
const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults1, 0, 0, 0, 31, 0, 0);
|
||||
|
||||
// configOptions.defaultPythonVersion = PythonVersion.V3_8;
|
||||
// const analysisResults1 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
// TestUtils.validateResults(analysisResults1, 0, 0, 0, 0, 0);
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_9;
|
||||
const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults2, 0, 0, 0, 31, 0, 0);
|
||||
|
||||
// configOptions.defaultPythonVersion = PythonVersion.V3_9;
|
||||
// const analysisResults2 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
// TestUtils.validateResults(analysisResults2, 0, 0, 0, 0, 11);
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
const analysisResults3 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults3, 0, 0, 0, 31, 0, 0);
|
||||
|
||||
// configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
// const analysisResults3 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
// TestUtils.validateResults(analysisResults3, 0, 0, 0, 0, 13);
|
||||
// });
|
||||
// Now enable the deprecateTypingAliases setting.
|
||||
configOptions.diagnosticRuleSet.deprecateTypingAliases = true;
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_8;
|
||||
const analysisResults4 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults4, 0, 0, 0, 31, 0, 0);
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_9;
|
||||
const analysisResults5 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults5, 0, 0, 0, 31, 0, 48);
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
const analysisResults6 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults6, 0, 0, 0, 31, 0, 52);
|
||||
|
||||
// Now change reportDeprecated to emit an error.
|
||||
configOptions.diagnosticRuleSet.reportDeprecated = 'error';
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_8;
|
||||
const analysisResults7 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults7, 0, 0, 0, 31, 0, 0);
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_9;
|
||||
const analysisResults8 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults8, 48, 0, 0, 31, 0, 0);
|
||||
|
||||
configOptions.defaultPythonVersion = PythonVersion.V3_10;
|
||||
const analysisResults9 = TestUtils.typeAnalyzeSampleFiles(['deprecated1.py'], configOptions);
|
||||
TestUtils.validateResults(analysisResults9, 52, 0, 0, 31, 0, 0);
|
||||
});
|
||||
|
||||
test('Deprecated2', () => {
|
||||
const configOptions = new ConfigOptions('.');
|
||||
|
@ -16,8 +16,37 @@ from typing import (
|
||||
Tuple,
|
||||
Type,
|
||||
Union,
|
||||
Awaitable,
|
||||
Coroutine,
|
||||
AsyncIterable,
|
||||
AsyncGenerator,
|
||||
Iterable,
|
||||
Iterator,
|
||||
Generator,
|
||||
Reversible,
|
||||
Container,
|
||||
Collection as C1,
|
||||
Callable,
|
||||
AbstractSet,
|
||||
MutableSet,
|
||||
Mapping,
|
||||
MutableMapping,
|
||||
Sequence,
|
||||
MutableSequence,
|
||||
ByteString as BS1,
|
||||
MappingView,
|
||||
KeysView,
|
||||
ItemsView,
|
||||
ValuesView,
|
||||
ContextManager as CM1,
|
||||
AsyncContextManager,
|
||||
Pattern as P1,
|
||||
Match as M1,
|
||||
)
|
||||
|
||||
from collections.abc import Collection, ByteString
|
||||
from contextlib import AbstractContextManager
|
||||
from re import Pattern, Match
|
||||
|
||||
# These should be marked deprecated for Python >= 3.9
|
||||
v1: List[int] = [1, 2, 3]
|
||||
|
@ -154,6 +154,12 @@
|
||||
"title": "Allow \"# type: ignore\" comments",
|
||||
"default": true
|
||||
},
|
||||
"deprecateTypingAliases": {
|
||||
"$id": "#/properties/deprecateTypingAliases",
|
||||
"type": "boolean",
|
||||
"title": "Treat typing-specific aliases to standard types as deprecated",
|
||||
"default": true
|
||||
},
|
||||
"reportGeneralTypeIssues": {
|
||||
"$id": "#/properties/reportGeneralTypeIssues",
|
||||
"$ref": "#/definitions/diagnostic",
|
||||
|
Loading…
Reference in New Issue
Block a user