mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-06 12:57:14 +03:00
Fixed a bug that leads to a crash when --pythonversion
and --threads
CLI options are used together. This addresses #8775. (#8776)
This commit is contained in:
parent
c42a1587b4
commit
bea4dc91b5
@ -10,7 +10,7 @@
|
||||
|
||||
import { DiagnosticRuleSet, ExecutionEnvironment } from '../common/configOptions';
|
||||
import { TextRangeDiagnosticSink } from '../common/diagnosticSink';
|
||||
import { pythonVersion3_14 } from '../common/pythonVersion';
|
||||
import { PythonVersion, pythonVersion3_14 } from '../common/pythonVersion';
|
||||
import { TextRange } from '../common/textRange';
|
||||
import { TextRangeCollection } from '../common/textRangeCollection';
|
||||
import { Uri } from '../common/uri/uri';
|
||||
@ -78,7 +78,7 @@ export function isAnnotationEvaluationPostponed(fileInfo: AnalyzerFileInfo) {
|
||||
// release to reduce the risk. As of May 8, 2024, the change did not make it into
|
||||
// Python 3.13beta1, so it has been deferred to Python 3.14.
|
||||
// https://discuss.python.org/t/pep-649-deferred-evaluation-of-annotations-tentatively-accepted/21331
|
||||
if (fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_14)) {
|
||||
if (PythonVersion.isGreaterOrEqualTo(fileInfo.executionEnvironment.pythonVersion, pythonVersion3_14)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ import { DiagnosticLevel } from '../common/configOptions';
|
||||
import { assert, assertNever } from '../common/debug';
|
||||
import { ActionKind, Diagnostic, DiagnosticAddendum, RenameShadowedFileAction } from '../common/diagnostic';
|
||||
import { DiagnosticRule } from '../common/diagnosticRules';
|
||||
import { pythonVersion3_12, pythonVersion3_5, pythonVersion3_6 } from '../common/pythonVersion';
|
||||
import { PythonVersion, pythonVersion3_12, pythonVersion3_5, pythonVersion3_6 } from '../common/pythonVersion';
|
||||
import { TextRange } from '../common/textRange';
|
||||
import { Uri } from '../common/uri/uri';
|
||||
import { DefinitionProvider } from '../languageService/definitionProvider';
|
||||
@ -628,7 +628,7 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
if (
|
||||
this._fileInfo.diagnosticRuleSet.reportTypeCommentUsage !== 'none' &&
|
||||
this._fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_5)
|
||||
PythonVersion.isGreaterOrEqualTo(this._fileInfo.executionEnvironment.pythonVersion, pythonVersion3_5)
|
||||
) {
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportTypeCommentUsage,
|
||||
@ -1184,7 +1184,7 @@ export class Checker extends ParseTreeWalker {
|
||||
|
||||
if (
|
||||
this._fileInfo.diagnosticRuleSet.reportTypeCommentUsage !== 'none' &&
|
||||
this._fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_6)
|
||||
PythonVersion.isGreaterOrEqualTo(this._fileInfo.executionEnvironment.pythonVersion, pythonVersion3_6)
|
||||
) {
|
||||
this._evaluator.addDiagnostic(
|
||||
DiagnosticRule.reportTypeCommentUsage,
|
||||
@ -1361,7 +1361,7 @@ export class Checker extends ParseTreeWalker {
|
||||
// associated with f-strings that we need to validate. Determine whether
|
||||
// we're within an f-string (or multiple f-strings if nesting is used).
|
||||
const fStringContainers: FormatStringNode[] = [];
|
||||
if (this._fileInfo.executionEnvironment.pythonVersion.isLessThan(pythonVersion3_12)) {
|
||||
if (PythonVersion.isLessThan(this._fileInfo.executionEnvironment.pythonVersion, pythonVersion3_12)) {
|
||||
let curNode: ParseNode | undefined = node;
|
||||
while (curNode) {
|
||||
if (curNode.nodeType === ParseNodeType.FormatString) {
|
||||
@ -4456,7 +4456,12 @@ export class Checker extends ParseTreeWalker {
|
||||
(isInstantiableClass(type) && type.shared.fullName === deprecatedForm.fullName) ||
|
||||
type.props?.typeAliasInfo?.fullName === deprecatedForm.fullName
|
||||
) {
|
||||
if (this._fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(deprecatedForm.version)) {
|
||||
if (
|
||||
PythonVersion.isGreaterOrEqualTo(
|
||||
this._fileInfo.executionEnvironment.pythonVersion,
|
||||
deprecatedForm.version
|
||||
)
|
||||
) {
|
||||
if (!deprecatedForm.typingImportOnly || isImportFromTyping) {
|
||||
this._reportDeprecatedDiagnostic(
|
||||
node,
|
||||
|
@ -11,7 +11,7 @@
|
||||
import { assert } from '../common/debug';
|
||||
import { DiagnosticAddendum } from '../common/diagnostic';
|
||||
import { DiagnosticRule } from '../common/diagnosticRules';
|
||||
import { pythonVersion3_13 } from '../common/pythonVersion';
|
||||
import { PythonVersion, pythonVersion3_13 } from '../common/pythonVersion';
|
||||
import { LocMessage } from '../localization/localize';
|
||||
import {
|
||||
ArgCategory,
|
||||
@ -122,7 +122,12 @@ export function synthesizeDataClassMethods(
|
||||
|
||||
// For Python 3.13 and newer, synthesize a __replace__ method.
|
||||
let replaceType: FunctionType | undefined;
|
||||
if (AnalyzerNodeInfo.getFileInfo(node).executionEnvironment.pythonVersion >= pythonVersion3_13) {
|
||||
if (
|
||||
PythonVersion.isGreaterOrEqualTo(
|
||||
AnalyzerNodeInfo.getFileInfo(node).executionEnvironment.pythonVersion,
|
||||
pythonVersion3_13
|
||||
)
|
||||
) {
|
||||
replaceType = FunctionType.createSynthesizedInstance('__replace__');
|
||||
FunctionType.addParam(replaceType, selfParam);
|
||||
FunctionType.addKeywordOnlyParamSeparator(replaceType);
|
||||
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
import { assert } from '../common/debug';
|
||||
import { pythonVersion3_13 } from '../common/pythonVersion';
|
||||
import { PythonVersion, pythonVersion3_13 } from '../common/pythonVersion';
|
||||
import { ArgCategory, ExpressionNode, NameNode, ParseNode, ParseNodeType } from '../parser/parseNodes';
|
||||
import { getFileInfo } from './analyzerNodeInfo';
|
||||
import { VariableDeclaration } from './declaration';
|
||||
@ -413,7 +413,10 @@ export function transformTypeForEnumMember(
|
||||
// are treated as members.
|
||||
if (isInstantiableClass(assignedType)) {
|
||||
const fileInfo = getFileInfo(primaryDecl.node);
|
||||
isMemberOfEnumeration = fileInfo.executionEnvironment.pythonVersion.isLessThan(pythonVersion3_13);
|
||||
isMemberOfEnumeration = PythonVersion.isLessThan(
|
||||
fileInfo.executionEnvironment.pythonVersion,
|
||||
pythonVersion3_13
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +472,7 @@ export class ImportResolver {
|
||||
this._cachedTypeshedStdLibModuleVersionInfo.forEach((versionInfo, moduleName) => {
|
||||
let shouldExcludeModule = false;
|
||||
|
||||
if (versionInfo.max !== undefined && pythonVersion.isGreaterThan(versionInfo.max)) {
|
||||
if (versionInfo.max !== undefined && PythonVersion.isGreaterThan(pythonVersion, versionInfo.max)) {
|
||||
shouldExcludeModule = true;
|
||||
}
|
||||
|
||||
@ -1999,11 +1999,11 @@ export class ImportResolver {
|
||||
const versionInfo = this._cachedTypeshedStdLibModuleVersionInfo.get(namePartsToConsider.join('.'));
|
||||
|
||||
if (versionInfo) {
|
||||
if (pythonVersion.isLessThan(versionInfo.min)) {
|
||||
if (PythonVersion.isLessThan(pythonVersion, versionInfo.min)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (versionInfo.max !== undefined && pythonVersion.isGreaterThan(versionInfo.max)) {
|
||||
if (versionInfo.max !== undefined && PythonVersion.isGreaterThan(pythonVersion, versionInfo.max)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
import { DiagnosticAddendum } from '../common/diagnostic';
|
||||
import { DiagnosticRule } from '../common/diagnosticRules';
|
||||
import { pythonVersion3_10 } from '../common/pythonVersion';
|
||||
import { PythonVersion, pythonVersion3_10 } from '../common/pythonVersion';
|
||||
import { LocMessage } from '../localization/localize';
|
||||
import {
|
||||
AugmentedAssignmentNode,
|
||||
@ -370,7 +370,7 @@ export function getTypeOfBinaryOperation(
|
||||
const unionNotationSupported =
|
||||
fileInfo.isStubFile ||
|
||||
(flags & EvalFlags.ForwardRefs) !== 0 ||
|
||||
fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_10);
|
||||
PythonVersion.isGreaterOrEqualTo(fileInfo.executionEnvironment.pythonVersion, pythonVersion3_10);
|
||||
|
||||
if (!unionNotationSupported) {
|
||||
// If the left type is Any, we can't say for sure whether this
|
||||
|
@ -156,7 +156,7 @@ function findSitePackagesPath(
|
||||
// version), prefer that over other python directories.
|
||||
if (pythonVersion) {
|
||||
const preferredDir = candidateDirs.find(
|
||||
(dirName) => dirName.fileName === `python${pythonVersion.toMajorMinorString()}`
|
||||
(dirName) => dirName.fileName === `python${PythonVersion.toMajorMinorString(pythonVersion)}`
|
||||
);
|
||||
if (preferredDir) {
|
||||
const dirPath = preferredDir.combinePaths(pathConsts.sitePackages);
|
||||
|
@ -100,8 +100,8 @@ export function evaluateStaticBoolExpression(
|
||||
// Handle the special case of "sys.version_info[0] >= X"
|
||||
return _evaluateVersionBinaryOperation(
|
||||
node.d.operator,
|
||||
new PythonVersion(execEnv.pythonVersion.major, 0),
|
||||
new PythonVersion(node.d.rightExpr.d.value, 0)
|
||||
PythonVersion.create(execEnv.pythonVersion.major, 0),
|
||||
PythonVersion.create(node.d.rightExpr.d.value, 0)
|
||||
);
|
||||
}
|
||||
|
||||
@ -238,12 +238,12 @@ function _convertTupleToVersion(node: TupleNode): PythonVersion | undefined {
|
||||
serial = node.d.items[4].d.value;
|
||||
}
|
||||
|
||||
return new PythonVersion(major, minor, micro, releaseLevel, serial);
|
||||
return PythonVersion.create(major, minor, micro, releaseLevel, serial);
|
||||
}
|
||||
} else if (node.d.items.length === 1) {
|
||||
const major = node.d.items[0] as NumberNode;
|
||||
if (typeof major.d.value === 'number') {
|
||||
return new PythonVersion(major.d.value, 0);
|
||||
return PythonVersion.create(major.d.value, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,27 +257,27 @@ function _evaluateVersionBinaryOperation(
|
||||
): any | undefined {
|
||||
if (leftValue !== undefined && rightValue !== undefined) {
|
||||
if (operatorType === OperatorType.LessThan) {
|
||||
return leftValue.isLessThan(rightValue);
|
||||
return PythonVersion.isLessThan(leftValue, rightValue);
|
||||
}
|
||||
|
||||
if (operatorType === OperatorType.LessThanOrEqual) {
|
||||
return leftValue.isLessOrEqualTo(rightValue);
|
||||
return PythonVersion.isLessOrEqualTo(leftValue, rightValue);
|
||||
}
|
||||
|
||||
if (operatorType === OperatorType.GreaterThan) {
|
||||
return leftValue.isGreaterThan(rightValue);
|
||||
return PythonVersion.isGreaterThan(leftValue, rightValue);
|
||||
}
|
||||
|
||||
if (operatorType === OperatorType.GreaterThanOrEqual) {
|
||||
return leftValue.isGreaterOrEqualTo(rightValue);
|
||||
return PythonVersion.isGreaterOrEqualTo(leftValue, rightValue);
|
||||
}
|
||||
|
||||
if (operatorType === OperatorType.Equals) {
|
||||
return leftValue.isEqualTo(rightValue);
|
||||
return PythonVersion.isEqualTo(leftValue, rightValue);
|
||||
}
|
||||
|
||||
if (operatorType === OperatorType.NotEquals) {
|
||||
return !leftValue.isEqualTo(rightValue);
|
||||
return !PythonVersion.isEqualTo(leftValue, rightValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5553,8 +5553,10 @@ export function createTypeEvaluator(
|
||||
const getAttrSymbol = ModuleType.getField(baseType, '__getattr__');
|
||||
if (getAttrSymbol) {
|
||||
const isModuleGetAttrSupported =
|
||||
fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_7) ||
|
||||
getAttrSymbol.getDeclarations().some((decl) => decl.uri.hasExtension('.pyi'));
|
||||
PythonVersion.isGreaterOrEqualTo(
|
||||
fileInfo.executionEnvironment.pythonVersion,
|
||||
pythonVersion3_7
|
||||
) || getAttrSymbol.getDeclarations().some((decl) => decl.uri.hasExtension('.pyi'));
|
||||
|
||||
if (isModuleGetAttrSupported) {
|
||||
const getAttrTypeResult = getEffectiveTypeOfSymbolForUsage(getAttrSymbol);
|
||||
@ -6583,7 +6585,7 @@ export function createTypeEvaluator(
|
||||
const minPythonVersion = nonSubscriptableBuiltinTypes.get(baseTypeResult.type.shared.fullName);
|
||||
if (
|
||||
minPythonVersion !== undefined &&
|
||||
fileInfo.executionEnvironment.pythonVersion.isLessThan(minPythonVersion) &&
|
||||
PythonVersion.isLessThan(fileInfo.executionEnvironment.pythonVersion, minPythonVersion) &&
|
||||
!fileInfo.isStubFile
|
||||
) {
|
||||
addDiagnostic(
|
||||
@ -12359,7 +12361,7 @@ export function createTypeEvaluator(
|
||||
const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode);
|
||||
if (
|
||||
!fileInfo.isStubFile &&
|
||||
fileInfo.executionEnvironment.pythonVersion.isLessThan(pythonVersion3_13) &&
|
||||
PythonVersion.isLessThan(fileInfo.executionEnvironment.pythonVersion, pythonVersion3_13) &&
|
||||
classType.shared.moduleName !== 'typing_extensions'
|
||||
) {
|
||||
addDiagnostic(
|
||||
@ -12518,7 +12520,7 @@ export function createTypeEvaluator(
|
||||
const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode);
|
||||
if (
|
||||
!fileInfo.isStubFile &&
|
||||
fileInfo.executionEnvironment.pythonVersion.isLessThan(pythonVersion3_13) &&
|
||||
PythonVersion.isLessThan(fileInfo.executionEnvironment.pythonVersion, pythonVersion3_13) &&
|
||||
classType.shared.moduleName !== 'typing_extensions'
|
||||
) {
|
||||
addDiagnostic(
|
||||
@ -12608,7 +12610,7 @@ export function createTypeEvaluator(
|
||||
const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode);
|
||||
if (
|
||||
!fileInfo.isStubFile &&
|
||||
fileInfo.executionEnvironment.pythonVersion.isLessThan(pythonVersion3_13) &&
|
||||
PythonVersion.isLessThan(fileInfo.executionEnvironment.pythonVersion, pythonVersion3_13) &&
|
||||
classType.shared.moduleName !== 'typing_extensions'
|
||||
) {
|
||||
addDiagnostic(
|
||||
@ -16635,7 +16637,10 @@ export function createTypeEvaluator(
|
||||
if (
|
||||
!fileInfo.isStubFile &&
|
||||
!ClassType.isTypingExtensionClass(argType) &&
|
||||
fileInfo.executionEnvironment.pythonVersion.isLessThan(pythonVersion3_7)
|
||||
PythonVersion.isLessThan(
|
||||
fileInfo.executionEnvironment.pythonVersion,
|
||||
pythonVersion3_7
|
||||
)
|
||||
) {
|
||||
addDiagnostic(
|
||||
DiagnosticRule.reportInvalidTypeForm,
|
||||
@ -16652,7 +16657,12 @@ export function createTypeEvaluator(
|
||||
|
||||
// If the class directly derives from NamedTuple (in Python 3.6 or
|
||||
// newer), it's considered a (read-only) dataclass.
|
||||
if (fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_6)) {
|
||||
if (
|
||||
PythonVersion.isGreaterOrEqualTo(
|
||||
fileInfo.executionEnvironment.pythonVersion,
|
||||
pythonVersion3_6
|
||||
)
|
||||
) {
|
||||
if (ClassType.isBuiltIn(argType, 'NamedTuple')) {
|
||||
isNamedTupleSubclass = true;
|
||||
classType.shared.flags |= ClassTypeFlags.ReadOnlyInstanceVariables;
|
||||
@ -19094,7 +19104,10 @@ export function createTypeEvaluator(
|
||||
// Handle PEP 562 support for module-level __getattr__ function,
|
||||
// introduced in Python 3.7.
|
||||
if (
|
||||
fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_7) ||
|
||||
PythonVersion.isGreaterOrEqualTo(
|
||||
fileInfo.executionEnvironment.pythonVersion,
|
||||
pythonVersion3_7
|
||||
) ||
|
||||
fileInfo.isStubFile
|
||||
) {
|
||||
const getAttrSymbol = importLookupInfo.symbolTable.get('__getattr__');
|
||||
@ -20174,7 +20187,7 @@ export function createTypeEvaluator(
|
||||
const fileInfo = AnalyzerNodeInfo.getFileInfo(errorNode);
|
||||
if (
|
||||
fileInfo.isStubFile ||
|
||||
fileInfo.executionEnvironment.pythonVersion.isGreaterOrEqualTo(pythonVersion3_9) ||
|
||||
PythonVersion.isGreaterOrEqualTo(fileInfo.executionEnvironment.pythonVersion, pythonVersion3_9) ||
|
||||
isAnnotationEvaluationPostponed(AnalyzerNodeInfo.getFileInfo(errorNode)) ||
|
||||
(flags & EvalFlags.ForwardRefs) !== 0
|
||||
) {
|
||||
|
@ -14,7 +14,6 @@ import { ConfigOptions } from './common/configOptions';
|
||||
import { ConsoleInterface, LogLevel } from './common/console';
|
||||
import { Disposable, isThenable } from './common/core';
|
||||
import * as debug from './common/debug';
|
||||
import { PythonVersion } from './common/pythonVersion';
|
||||
import { createFromRealFileSystem, RealTempFile } from './common/realFileSystem';
|
||||
import { ServiceKeys } from './common/serviceKeys';
|
||||
import { ServiceProvider } from './common/serviceProvider';
|
||||
@ -124,9 +123,6 @@ export function serializeReplacer(value: any) {
|
||||
if (Uri.is(value) && value.toJsonObj !== undefined) {
|
||||
return { __serialized_uri_val: value.toJsonObj() };
|
||||
}
|
||||
if (value instanceof PythonVersion) {
|
||||
return { __serialized_version_val: value.toString() };
|
||||
}
|
||||
if (value instanceof Map) {
|
||||
return { __serialized_map_val: [...value] };
|
||||
}
|
||||
@ -154,9 +150,6 @@ export function deserializeReviver(value: any) {
|
||||
if (value.__serialized_uri_val !== undefined) {
|
||||
return Uri.fromJsonObj(value.__serialized_uri_val);
|
||||
}
|
||||
if (value.__serialized_version_val) {
|
||||
return PythonVersion.fromString(value.__serialized_version_val);
|
||||
}
|
||||
if (value.__serialized_map_val) {
|
||||
return new Map(value.__serialized_map_val);
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ export class FullAccessHost extends LimitedAccessHost {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const version = new PythonVersion(
|
||||
const version = PythonVersion.create(
|
||||
versionJson[0],
|
||||
versionJson[1],
|
||||
versionJson[2],
|
||||
|
@ -9,77 +9,73 @@
|
||||
|
||||
export type PythonReleaseLevel = 'alpha' | 'beta' | 'candidate' | 'final';
|
||||
|
||||
export class PythonVersion {
|
||||
constructor(
|
||||
private _major: number,
|
||||
private _minor: number,
|
||||
private _micro?: number,
|
||||
private _releaseLevel?: PythonReleaseLevel,
|
||||
private _serial?: number
|
||||
) {}
|
||||
export interface PythonVersion {
|
||||
major: number;
|
||||
minor: number;
|
||||
micro?: number;
|
||||
releaseLevel?: PythonReleaseLevel;
|
||||
serial?: number;
|
||||
}
|
||||
|
||||
get major() {
|
||||
return this._major;
|
||||
export namespace PythonVersion {
|
||||
export function create(
|
||||
major: number,
|
||||
minor: number,
|
||||
micro?: number,
|
||||
releaseLevel?: PythonReleaseLevel,
|
||||
serial?: number
|
||||
): PythonVersion {
|
||||
return {
|
||||
major,
|
||||
minor,
|
||||
micro,
|
||||
releaseLevel,
|
||||
serial,
|
||||
};
|
||||
}
|
||||
|
||||
get minor() {
|
||||
return this._minor;
|
||||
}
|
||||
|
||||
get micro() {
|
||||
return this._micro;
|
||||
}
|
||||
|
||||
get releaseLevel() {
|
||||
return this._releaseLevel;
|
||||
}
|
||||
|
||||
get serial() {
|
||||
return this._serial;
|
||||
}
|
||||
|
||||
isEqualTo(other: PythonVersion) {
|
||||
if (this.major !== other.major || this.minor !== other.minor) {
|
||||
export function isEqualTo(version: PythonVersion, other: PythonVersion) {
|
||||
if (version.major !== other.major || version.minor !== other.minor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._micro === undefined || other._micro === undefined) {
|
||||
if (version.micro === undefined || other.micro === undefined) {
|
||||
return true;
|
||||
} else if (this._micro !== other._micro) {
|
||||
} else if (version.micro !== other.micro) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._releaseLevel === undefined || other._releaseLevel === undefined) {
|
||||
if (version.releaseLevel === undefined || other.releaseLevel === undefined) {
|
||||
return true;
|
||||
} else if (this._releaseLevel !== other._releaseLevel) {
|
||||
} else if (version.releaseLevel !== other.releaseLevel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._serial === undefined || other._serial === undefined) {
|
||||
if (version.serial === undefined || other.serial === undefined) {
|
||||
return true;
|
||||
} else if (this._serial !== other._serial) {
|
||||
} else if (version.serial !== other.serial) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
isGreaterThan(other: PythonVersion) {
|
||||
if (this.major > other.major) {
|
||||
export function isGreaterThan(version: PythonVersion, other: PythonVersion) {
|
||||
if (version.major > other.major) {
|
||||
return true;
|
||||
} else if (this.major < other.major) {
|
||||
} else if (version.major < other.major) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.minor > other.minor) {
|
||||
if (version.minor > other.minor) {
|
||||
return true;
|
||||
} else if (this.minor < other.minor) {
|
||||
} else if (version.minor < other.minor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this._micro === undefined || other._micro === undefined || this._micro < other._micro) {
|
||||
if (version.micro === undefined || other.micro === undefined || version.micro < other.micro) {
|
||||
return false;
|
||||
} else if (this._micro > other._micro) {
|
||||
} else if (version.micro > other.micro) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -87,18 +83,18 @@ export class PythonVersion {
|
||||
// of the release level designators are ordered by increasing
|
||||
// release level.
|
||||
if (
|
||||
this._releaseLevel === undefined ||
|
||||
other._releaseLevel === undefined ||
|
||||
this._releaseLevel < other._releaseLevel
|
||||
version.releaseLevel === undefined ||
|
||||
other.releaseLevel === undefined ||
|
||||
version.releaseLevel < other.releaseLevel
|
||||
) {
|
||||
return false;
|
||||
} else if (this._releaseLevel > other._releaseLevel) {
|
||||
} else if (version.releaseLevel > other.releaseLevel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this._serial === undefined || other._serial === undefined || this._serial < other._serial) {
|
||||
if (version.serial === undefined || other.serial === undefined || version.serial < other.serial) {
|
||||
return false;
|
||||
} else if (this._serial > other._serial) {
|
||||
} else if (version.serial > other.serial) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -106,46 +102,46 @@ export class PythonVersion {
|
||||
return false;
|
||||
}
|
||||
|
||||
isGreaterOrEqualTo(other: PythonVersion) {
|
||||
return this.isEqualTo(other) || this.isGreaterThan(other);
|
||||
export function isGreaterOrEqualTo(version: PythonVersion, other: PythonVersion) {
|
||||
return isEqualTo(version, other) || isGreaterThan(version, other);
|
||||
}
|
||||
|
||||
isLessThan(other: PythonVersion) {
|
||||
return !this.isGreaterOrEqualTo(other);
|
||||
export function isLessThan(version: PythonVersion, other: PythonVersion) {
|
||||
return !isGreaterOrEqualTo(version, other);
|
||||
}
|
||||
|
||||
isLessOrEqualTo(other: PythonVersion) {
|
||||
return !this.isGreaterThan(other);
|
||||
export function isLessOrEqualTo(version: PythonVersion, other: PythonVersion) {
|
||||
return !isGreaterThan(version, other);
|
||||
}
|
||||
|
||||
toMajorMinorString(): string {
|
||||
return `${this._major}.${this._minor}`;
|
||||
export function toMajorMinorString(version: PythonVersion): string {
|
||||
return `${version.major}.${version.minor}`;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
let version = this.toMajorMinorString();
|
||||
export function toString(version: PythonVersion): string {
|
||||
let versString = toMajorMinorString(version);
|
||||
|
||||
if (this._micro === undefined) {
|
||||
return version;
|
||||
if (version.micro === undefined) {
|
||||
return versString;
|
||||
}
|
||||
|
||||
version += `.${this._micro}`;
|
||||
versString += `.${version.micro}`;
|
||||
|
||||
if (this._releaseLevel === undefined) {
|
||||
return version;
|
||||
if (version.releaseLevel === undefined) {
|
||||
return versString;
|
||||
}
|
||||
|
||||
version += `.${this._releaseLevel}`;
|
||||
versString += `.${version.releaseLevel}`;
|
||||
|
||||
if (this._serial === undefined) {
|
||||
return version;
|
||||
if (version.serial === undefined) {
|
||||
return versString;
|
||||
}
|
||||
|
||||
version += `.${this._serial}`;
|
||||
return version;
|
||||
versString += `.${version.serial}`;
|
||||
return versString;
|
||||
}
|
||||
|
||||
static fromString(val: string): PythonVersion | undefined {
|
||||
export function fromString(val: string): PythonVersion | undefined {
|
||||
const split = val.split('.');
|
||||
|
||||
if (split.length < 2) {
|
||||
@ -183,25 +179,25 @@ export class PythonVersion {
|
||||
}
|
||||
}
|
||||
|
||||
return new PythonVersion(major, minor, micro, releaseLevel, serial);
|
||||
return create(major, minor, micro, releaseLevel, serial);
|
||||
}
|
||||
}
|
||||
|
||||
// Predefine some versions.
|
||||
export const pythonVersion3_0 = new PythonVersion(3, 0);
|
||||
export const pythonVersion3_1 = new PythonVersion(3, 1);
|
||||
export const pythonVersion3_2 = new PythonVersion(3, 2);
|
||||
export const pythonVersion3_3 = new PythonVersion(3, 3);
|
||||
export const pythonVersion3_4 = new PythonVersion(3, 4);
|
||||
export const pythonVersion3_5 = new PythonVersion(3, 5);
|
||||
export const pythonVersion3_6 = new PythonVersion(3, 6);
|
||||
export const pythonVersion3_7 = new PythonVersion(3, 7);
|
||||
export const pythonVersion3_8 = new PythonVersion(3, 8);
|
||||
export const pythonVersion3_9 = new PythonVersion(3, 9);
|
||||
export const pythonVersion3_10 = new PythonVersion(3, 10);
|
||||
export const pythonVersion3_11 = new PythonVersion(3, 11);
|
||||
export const pythonVersion3_12 = new PythonVersion(3, 12);
|
||||
export const pythonVersion3_13 = new PythonVersion(3, 13);
|
||||
export const pythonVersion3_14 = new PythonVersion(3, 14);
|
||||
export const pythonVersion3_0 = PythonVersion.create(3, 0);
|
||||
export const pythonVersion3_1 = PythonVersion.create(3, 1);
|
||||
export const pythonVersion3_2 = PythonVersion.create(3, 2);
|
||||
export const pythonVersion3_3 = PythonVersion.create(3, 3);
|
||||
export const pythonVersion3_4 = PythonVersion.create(3, 4);
|
||||
export const pythonVersion3_5 = PythonVersion.create(3, 5);
|
||||
export const pythonVersion3_6 = PythonVersion.create(3, 6);
|
||||
export const pythonVersion3_7 = PythonVersion.create(3, 7);
|
||||
export const pythonVersion3_8 = PythonVersion.create(3, 8);
|
||||
export const pythonVersion3_9 = PythonVersion.create(3, 9);
|
||||
export const pythonVersion3_10 = PythonVersion.create(3, 10);
|
||||
export const pythonVersion3_11 = PythonVersion.create(3, 11);
|
||||
export const pythonVersion3_12 = PythonVersion.create(3, 12);
|
||||
export const pythonVersion3_13 = PythonVersion.create(3, 13);
|
||||
export const pythonVersion3_14 = PythonVersion.create(3, 14);
|
||||
|
||||
export const latestStablePythonVersion = pythonVersion3_12;
|
||||
|
@ -175,10 +175,10 @@ namespace Keywords {
|
||||
const python3_10: string[] = [...python3_5, 'case', 'match'];
|
||||
|
||||
export function forVersion(version: PythonVersion): string[] {
|
||||
if (version.isGreaterOrEqualTo(pythonVersion3_10)) {
|
||||
if (PythonVersion.isGreaterOrEqualTo(version, pythonVersion3_10)) {
|
||||
return python3_10;
|
||||
}
|
||||
if (version.isGreaterOrEqualTo(pythonVersion3_5)) {
|
||||
if (PythonVersion.isGreaterOrEqualTo(version, pythonVersion3_5)) {
|
||||
return python3_5;
|
||||
}
|
||||
return base;
|
||||
|
@ -474,7 +474,7 @@ export class Parser {
|
||||
private _parseTypeAliasStatement(): TypeAliasNode {
|
||||
const typeToken = this._getKeywordToken(KeywordType.Type);
|
||||
|
||||
if (!this._parseOptions.isStubFile && this._getLanguageVersion().isLessThan(pythonVersion3_12)) {
|
||||
if (!this._parseOptions.isStubFile && PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_12)) {
|
||||
this._addSyntaxError(LocMessage.typeAliasStatementIllegal(), typeToken);
|
||||
}
|
||||
|
||||
@ -577,7 +577,10 @@ export class Parser {
|
||||
/* allowUnpack */ typeParamCategory === TypeParamKind.TypeVarTuple
|
||||
);
|
||||
|
||||
if (!this._parseOptions.isStubFile && this._getLanguageVersion().isLessThan(pythonVersion3_13)) {
|
||||
if (
|
||||
!this._parseOptions.isStubFile &&
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_13)
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.typeVarDefaultIllegal(), defaultExpression);
|
||||
}
|
||||
}
|
||||
@ -702,7 +705,7 @@ export class Parser {
|
||||
}
|
||||
|
||||
// This feature requires Python 3.10.
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_10)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_10)) {
|
||||
this._addSyntaxError(LocMessage.matchIncompatible(), matchToken);
|
||||
}
|
||||
|
||||
@ -1629,7 +1632,10 @@ export class Parser {
|
||||
|
||||
// Versions of Python earlier than 3.9 didn't allow unpack operators if the
|
||||
// tuple wasn't enclosed in parentheses.
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_9) && !this._parseOptions.isStubFile) {
|
||||
if (
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_9) &&
|
||||
!this._parseOptions.isStubFile
|
||||
) {
|
||||
if (seqExpr.nodeType === ParseNodeType.Tuple && !seqExpr.d.hasParens) {
|
||||
let sawStar = false;
|
||||
seqExpr.d.items.forEach((expr) => {
|
||||
@ -1805,7 +1811,10 @@ export class Parser {
|
||||
const possibleStarToken = this._peekToken();
|
||||
let isExceptGroup = false;
|
||||
if (this._consumeTokenIfOperator(OperatorType.Multiply)) {
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_11) && !this._parseOptions.isStubFile) {
|
||||
if (
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_11) &&
|
||||
!this._parseOptions.isStubFile
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.exceptionGroupIncompatible(), possibleStarToken);
|
||||
}
|
||||
isExceptGroup = true;
|
||||
@ -1904,7 +1913,10 @@ export class Parser {
|
||||
if (possibleOpenBracket.type === TokenType.OpenBracket) {
|
||||
typeParameters = this._parseTypeParameterList();
|
||||
|
||||
if (!this._parseOptions.isStubFile && this._getLanguageVersion().isLessThan(pythonVersion3_12)) {
|
||||
if (
|
||||
!this._parseOptions.isStubFile &&
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_12)
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.functionTypeParametersIllegal(), typeParameters);
|
||||
}
|
||||
}
|
||||
@ -2118,7 +2130,10 @@ export class Parser {
|
||||
} else if (this._consumeTokenIfOperator(OperatorType.Power)) {
|
||||
starCount = 2;
|
||||
} else if (this._consumeTokenIfOperator(OperatorType.Divide)) {
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_8) && !this._parseOptions.isStubFile) {
|
||||
if (
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_8) &&
|
||||
!this._parseOptions.isStubFile
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.positionOnlyIncompatible(), firstToken);
|
||||
}
|
||||
slashCount = 1;
|
||||
@ -2222,7 +2237,7 @@ export class Parser {
|
||||
|
||||
if (isParenthesizedWithItemList) {
|
||||
this._consumeTokenIfType(TokenType.OpenParenthesis);
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_9)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_9)) {
|
||||
this._addSyntaxError(LocMessage.parenthesizedContextManagerIllegal(), possibleParen);
|
||||
}
|
||||
}
|
||||
@ -2331,7 +2346,7 @@ export class Parser {
|
||||
|
||||
// Versions of Python prior to 3.9 support a limited set of
|
||||
// expression forms.
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_9)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_9)) {
|
||||
let isSupportedExpressionForm = false;
|
||||
if (this._isNameOrMemberAccessExpression(expression)) {
|
||||
isSupportedExpressionForm = true;
|
||||
@ -2382,7 +2397,10 @@ export class Parser {
|
||||
if (possibleOpenBracket.type === TokenType.OpenBracket) {
|
||||
typeParameters = this._parseTypeParameterList();
|
||||
|
||||
if (!this._parseOptions.isStubFile && this._getLanguageVersion().isLessThan(pythonVersion3_12)) {
|
||||
if (
|
||||
!this._parseOptions.isStubFile &&
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_12)
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.classTypeParametersIllegal(), typeParameters);
|
||||
}
|
||||
}
|
||||
@ -2848,7 +2866,7 @@ export class Parser {
|
||||
|
||||
const nextToken = this._peekToken();
|
||||
if (this._consumeTokenIfKeyword(KeywordType.From)) {
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_3)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_3)) {
|
||||
this._addSyntaxError(LocMessage.yieldFromIllegal(), nextToken);
|
||||
}
|
||||
return YieldFromNode.create(yieldToken, this._parseTestExpression(/* allowAssignmentExpression */ false));
|
||||
@ -3188,7 +3206,7 @@ export class Parser {
|
||||
this._addSyntaxError(LocMessage.walrusNotAllowed(), walrusToken);
|
||||
}
|
||||
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_8)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_8)) {
|
||||
this._addSyntaxError(LocMessage.walrusIllegal(), walrusToken);
|
||||
}
|
||||
|
||||
@ -3478,7 +3496,7 @@ export class Parser {
|
||||
let awaitToken: KeywordToken | undefined;
|
||||
if (this._peekKeywordType() === KeywordType.Await) {
|
||||
awaitToken = this._getKeywordToken(KeywordType.Await);
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_5)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_5)) {
|
||||
this._addSyntaxError(LocMessage.awaitIllegal(), awaitToken);
|
||||
}
|
||||
}
|
||||
@ -3671,7 +3689,10 @@ export class Parser {
|
||||
valueExpr = this._parseTestExpression(/* allowAssignmentExpression */ true);
|
||||
|
||||
// Python 3.10 and newer allow assignment expressions to be used inside of a subscript.
|
||||
if (!this._parseOptions.isStubFile && this._getLanguageVersion().isLessThan(pythonVersion3_10)) {
|
||||
if (
|
||||
!this._parseOptions.isStubFile &&
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_10)
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.assignmentExprInSubscript(), valueExpr);
|
||||
}
|
||||
}
|
||||
@ -3698,7 +3719,7 @@ export class Parser {
|
||||
const unpackListAllowed =
|
||||
this._parseOptions.isStubFile ||
|
||||
this._isParsingQuotedText ||
|
||||
this._getLanguageVersion().isGreaterOrEqualTo(pythonVersion3_11);
|
||||
PythonVersion.isGreaterOrEqualTo(this._getLanguageVersion(), pythonVersion3_11);
|
||||
|
||||
if (argType === ArgCategory.UnpackedList && !unpackListAllowed) {
|
||||
this._addSyntaxError(LocMessage.unpackedSubscriptIllegal(), argNode);
|
||||
@ -3752,7 +3773,8 @@ export class Parser {
|
||||
if (nextTokenType !== TokenType.Colon) {
|
||||
// Python 3.10 and newer allow assignment expressions to be used inside of a subscript.
|
||||
const allowAssignmentExpression =
|
||||
this._parseOptions.isStubFile || this._getLanguageVersion().isGreaterOrEqualTo(pythonVersion3_10);
|
||||
this._parseOptions.isStubFile ||
|
||||
PythonVersion.isGreaterOrEqualTo(this._getLanguageVersion(), pythonVersion3_10);
|
||||
sliceExpressions[sliceIndex] = this._parseTestExpression(allowAssignmentExpression);
|
||||
}
|
||||
sliceIndex++;
|
||||
@ -3861,7 +3883,7 @@ export class Parser {
|
||||
) {
|
||||
nameNode = NameNode.create(nameExpr.d.token);
|
||||
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_14)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_14)) {
|
||||
this._addSyntaxError(LocMessage.keywordArgShortcutIllegal(), assignmentToken);
|
||||
valueExpr = ErrorNode.create(assignmentToken, ErrorExpressionCategory.MissingKeywordArgValue);
|
||||
} else {
|
||||
@ -4187,7 +4209,7 @@ export class Parser {
|
||||
|
||||
// Allow walrus operators in this context only for Python 3.10 and newer.
|
||||
// Older versions of Python generated a syntax error in this context.
|
||||
let isWalrusAllowed = this._getLanguageVersion().isGreaterOrEqualTo(pythonVersion3_10);
|
||||
let isWalrusAllowed = PythonVersion.isGreaterOrEqualTo(this._getLanguageVersion(), pythonVersion3_10);
|
||||
|
||||
if (this._consumeTokenIfType(TokenType.Colon)) {
|
||||
valueExpression = this._parseTestExpression(/* allowAssignmentExpression */ false);
|
||||
@ -4391,7 +4413,10 @@ export class Parser {
|
||||
annotationExpr = this._parseTypeAnnotation();
|
||||
leftExpr = TypeAnnotationNode.create(leftExpr, annotationExpr);
|
||||
|
||||
if (!this._parseOptions.isStubFile && this._getLanguageVersion().isLessThan(pythonVersion3_6)) {
|
||||
if (
|
||||
!this._parseOptions.isStubFile &&
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_6)
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.varAnnotationIllegal(), annotationExpr);
|
||||
}
|
||||
|
||||
@ -4575,7 +4600,7 @@ export class Parser {
|
||||
allowUnpack &&
|
||||
!this._parseOptions.isStubFile &&
|
||||
!this._isParsingQuotedText &&
|
||||
this._getLanguageVersion().isLessThan(pythonVersion3_11)
|
||||
PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_11)
|
||||
) {
|
||||
this._addSyntaxError(LocMessage.unpackedSubscriptIllegal(), startToken);
|
||||
}
|
||||
@ -4603,7 +4628,7 @@ export class Parser {
|
||||
}
|
||||
|
||||
if (stringToken.flags & StringTokenFlags.Format) {
|
||||
if (this._getLanguageVersion().isLessThan(pythonVersion3_6)) {
|
||||
if (PythonVersion.isLessThan(this._getLanguageVersion(), pythonVersion3_6)) {
|
||||
this._addSyntaxError(LocMessage.formatStringIllegal(), stringToken);
|
||||
}
|
||||
|
||||
@ -4758,7 +4783,7 @@ export class Parser {
|
||||
(nextToken as OperatorToken).operatorType === OperatorType.Assign
|
||||
) {
|
||||
// This feature requires Python 3.8 or newer.
|
||||
if (this._parseOptions.pythonVersion.isLessThan(pythonVersion3_8)) {
|
||||
if (PythonVersion.isLessThan(this._parseOptions.pythonVersion, pythonVersion3_8)) {
|
||||
this._addSyntaxError(LocMessage.formatStringDebuggingIllegal(), nextToken);
|
||||
}
|
||||
|
||||
@ -5019,7 +5044,7 @@ export class Parser {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._parseOptions.pythonVersion.isGreaterOrEqualTo(pythonVersion)) {
|
||||
if (PythonVersion.isGreaterOrEqualTo(this._parseOptions.pythonVersion, pythonVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user