Added support for generic NamedTuple classes, which are now supported in Python 3.11.

This commit is contained in:
Eric Traut 2022-05-03 22:12:29 -07:00
parent c4c27d6474
commit c1d29bfdb5
4 changed files with 51 additions and 7 deletions

View File

@ -14533,11 +14533,22 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
// Check for NamedTuple multiple inheritance.
if (classType.details.baseClasses.length > 1) {
if (
classType.details.baseClasses.some(
(baseClass) => isInstantiableClass(baseClass) && ClassType.isBuiltIn(baseClass, 'NamedTuple')
)
) {
let derivesFromNamedTuple = false;
let foundIllegalBaseClass = false;
classType.details.baseClasses.forEach(
(baseClass) => {
if (isInstantiableClass(baseClass)) {
if (ClassType.isBuiltIn(baseClass, 'NamedTuple')) {
derivesFromNamedTuple = true;
} else if (!ClassType.isBuiltIn(baseClass, 'Generic')) {
foundIllegalBaseClass = true;
}
}
}
);
if (derivesFromNamedTuple && foundIllegalBaseClass) {
addDiagnostic(
fileInfo.diagnosticRuleSet.reportGeneralTypeIssues,
DiagnosticRule.reportGeneralTypeIssues,

View File

@ -10,6 +10,6 @@ class A(NamedTuple, object):
T = TypeVar("T")
# This should generate an error
class B(NamedTuple, Generic[T]):
x: int

View File

@ -0,0 +1,27 @@
# This sample tests the handling of NamedTuple classes with generics,
# which is supported in Python 3.11 and newer.
from typing import Generic, NamedTuple, TypeVar
_T1 = TypeVar("_T1")
class NT1(NamedTuple, Generic[_T1]):
a: _T1
b: int
c: list[_T1]
reveal_type(NT1(3, 4, ["hi"]), expected_text="NT1[int | str]")
reveal_type(NT1(3, 4, []), expected_text="NT1[int]")
reveal_type(NT1(3.4, 4, [1, 2]), expected_text="NT1[float]")
reveal_type(NT1(3.4, 4, [2j]), expected_text="NT1[complex]")
class NT2(NT1[str]): ...
reveal_type(NT2("", 4, []), expected_text="NT2")
# This should generate an error.
NT2(1, 4, [])

View File

@ -1123,7 +1123,7 @@ test('NamedTuples2', () => {
test('NamedTuples3', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['namedTuples3.py']);
TestUtils.validateResults(analysisResults, 2);
TestUtils.validateResults(analysisResults, 1);
});
test('NamedTuples4', () => {
@ -1144,6 +1144,12 @@ test('NamedTuples6', () => {
TestUtils.validateResults(analysisResults, 3);
});
test('NamedTuples7', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['namedTuples7.py']);
TestUtils.validateResults(analysisResults, 1);
});
test('Slots1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['slots1.py']);