diff --git a/python/python-psi-impl/resources/messages/PyPsiBundle.properties b/python/python-psi-impl/resources/messages/PyPsiBundle.properties index a9baf97bb90a..8533501bfbd1 100644 --- a/python/python-psi-impl/resources/messages/PyPsiBundle.properties +++ b/python/python-psi-impl/resources/messages/PyPsiBundle.properties @@ -1095,6 +1095,7 @@ INSP.typeddict.qualifiers.cannot.be.used.outside.typeddict.definition=''{0}'' ca INSP.typeddict.required.and.not.required.cannot.be.nested=Required[] and NotRequired[] cannot be nested INSP.typeddict.read.only.cannot.be.nested=ReadOnly[] cannot be nested INSP.typeddict.required.notrequired.must.have.exactly.one.type.argument=''{0}'' must have exactly one type argument +INSP.typeddict.unexpected.argument.for.__init_subclass__.of.TypedDict=Unexpected argument ''{0}'' for __init_subclass__ of TypedDict # PyTypeHintsInspection INSP.NAME.type.hints=Invalid type hints definitions and usages diff --git a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypedDictInspection.kt b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypedDictInspection.kt index c95b7bb7cf26..2441bf6a50e3 100644 --- a/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypedDictInspection.kt +++ b/python/python-psi-impl/src/com/jetbrains/python/inspections/PyTypedDictInspection.kt @@ -69,14 +69,23 @@ class PyTypedDictInspection : PyInspection() { override fun visitPyArgumentList(node: PyArgumentList) { if (node.parent is PyClass && PyTypedDictTypeProvider.isTypingTypedDictInheritor(node.parent as PyClass, myTypeEvalContext)) { - val arguments = node.arguments - for (argument in arguments) { + for (argument in node.arguments) { val type = myTypeEvalContext.getType(argument) if (!isValidSuperclass(argument, type)) { registerProblem(argument, PyPsiBundle.message("INSP.typeddict.typeddict.cannot.inherit.from.non.typeddict.base.class")) } - if (argument is PyKeywordArgument && argument.keyword == TYPED_DICT_TOTAL_PARAMETER && argument.valueExpression != null) { - checkValidTotality(argument.valueExpression!!) + if (argument is PyKeywordArgument) { + val keyword = argument.keyword + if (keyword == TYPED_DICT_TOTAL_PARAMETER) { + val valueExpression = argument.valueExpression + if (valueExpression != null) { + checkValidTotality(valueExpression) + } + } + else if (keyword != PyNames.METACLASS) { + registerProblem(argument, + PyPsiBundle.message("INSP.typeddict.unexpected.argument.for.__init_subclass__.of.TypedDict", keyword)) + } } } } diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypedDictInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypedDictInspectionTest.java index 5f27b09e3da0..cec0db42cf77 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyTypedDictInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyTypedDictInspectionTest.java @@ -242,6 +242,13 @@ public class PyTypedDictInspectionTest extends PyInspectionTestCase { "X = TypedDict('X', {'x': int}, total=1)"); } + public void testUnexpectedInitClassArgument() { + doTestByText(""" + from typing import TypedDict + class A(TypedDict, ab=False): + i: int"""); + } + public void testGetWithIncorrectKeyType() { doTestByText(""" from typing import TypedDict