From b1031fc1564b4956ccc34bc5987b12a664d87ff9 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 3 May 2021 19:14:38 +0900 Subject: [PATCH 1/3] Support frozen on config --- src/com/koxudaxi/pydantic/Pydantic.kt | 2 + .../koxudaxi/pydantic/PydanticInspection.kt | 11 ++-- testData/inspectionv18/readOnlyProperty.py | 55 +++++++++++++++++++ .../inspectionv18/readOnlyPropertyFrozen.py | 55 +++++++++++++++++++ testData/mock/pydanticv18/main.py | 1 + .../pydantic/PydanticInspectionV18Test.kt | 8 +++ 6 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 testData/inspectionv18/readOnlyProperty.py create mode 100644 testData/inspectionv18/readOnlyPropertyFrozen.py diff --git a/src/com/koxudaxi/pydantic/Pydantic.kt b/src/com/koxudaxi/pydantic/Pydantic.kt index 1abe55be..bf93b2fc 100644 --- a/src/com/koxudaxi/pydantic/Pydantic.kt +++ b/src/com/koxudaxi/pydantic/Pydantic.kt @@ -97,6 +97,7 @@ val DEFAULT_CONFIG = mapOf( "allow_population_by_field_name" to false, "orm_mode" to false, "allow_mutation" to true, + "frozen" to false, "keep_untouched" to listOf() ) @@ -105,6 +106,7 @@ val CONFIG_TYPES = mapOf( "allow_population_by_field_name" to ConfigType.BOOLEAN, "orm_mode" to ConfigType.BOOLEAN, "allow_mutation" to ConfigType.BOOLEAN, + "frozen" to ConfigType.BOOLEAN, "keep_untouched" to ConfigType.LIST_PYTYPE ) diff --git a/src/com/koxudaxi/pydantic/PydanticInspection.kt b/src/com/koxudaxi/pydantic/PydanticInspection.kt index eeaae362..3c7aea97 100644 --- a/src/com/koxudaxi/pydantic/PydanticInspection.kt +++ b/src/com/koxudaxi/pydantic/PydanticInspection.kt @@ -131,11 +131,12 @@ class PydanticInspection : PyInspection() { if (!isPydanticModel(pyClass, false, myTypeEvalContext)) return val attributeName = (node.leftHandSideExpression as? PyTargetExpressionImpl)?.name ?: return val config = getConfig(pyClass, myTypeEvalContext, true) - if (config["allow_mutation"] != false) return - registerProblem(node, - "Property \"${attributeName}\" defined in \"${pyClass.name}\" is read-only", - ProblemHighlightType.GENERIC_ERROR) - + val version = PydanticVersionService.getVersion(pyClass.project, myTypeEvalContext) + if (config["allow_mutation"] == false || (version?.isAtLeast(1, 8) == true && config["frozen"] == true)) { + registerProblem(node, + "Property \"${attributeName}\" defined in \"${pyClass.name}\" is read-only", + ProblemHighlightType.GENERIC_ERROR) + } } private fun inspectWarnUntypedFields(node: PyAssignmentStatement) { diff --git a/testData/inspectionv18/readOnlyProperty.py b/testData/inspectionv18/readOnlyProperty.py new file mode 100644 index 00000000..2fc0b865 --- /dev/null +++ b/testData/inspectionv18/readOnlyProperty.py @@ -0,0 +1,55 @@ +from pydantic import BaseModel + + +class A(BaseModel): + abc: str = '123' +A.abc = '456' +A().abc = '456' + +class B(BaseModel): + abc: str = '123' + class Config: + allow_mutation=False +B.abc = '456' +B().abc = '456' + +class C(BaseModel): + abc: str = '123' + class Config: + allow_mutation=True +C.abc = '456' +C().abc = '456' + +class D(BaseModel): + class Config: + allow_mutation=False +D.abc = '456' +D().abc = '456' + +allow_mutation = True +class E(BaseModel): + class Config: + allow_mutation=allow_mutation +E.abc = '456' +E().abc = '456' + + +class F(D): + class Config: + allow_mutation=False +F.abc = '456' +F().abc = '456' + + +class G(BaseModel): + class Config: + allow_mutation=False +G.abc = +G.abc.lower() +G.abc.lower() = 'efg' + + +class H: + class Config: + allow_mutation=False +H.abc = '123' \ No newline at end of file diff --git a/testData/inspectionv18/readOnlyPropertyFrozen.py b/testData/inspectionv18/readOnlyPropertyFrozen.py new file mode 100644 index 00000000..8c5b62da --- /dev/null +++ b/testData/inspectionv18/readOnlyPropertyFrozen.py @@ -0,0 +1,55 @@ +from pydantic import BaseModel + + +class A(BaseModel): + abc: str = '123' +A.abc = '456' +A().abc = '456' + +class B(BaseModel): + abc: str = '123' + class Config: + frozen=True +B.abc = '456' +B().abc = '456' + +class C(BaseModel): + abc: str = '123' + class Config: + frozen=False +C.abc = '456' +C().abc = '456' + +class D(BaseModel): + class Config: + frozen=True +D.abc = '456' +D().abc = '456' + +frozen = False +class E(BaseModel): + class Config: + frozen=frozen +E.abc = '456' +E().abc = '456' + + +class F(D): + class Config: + frozen=True +F.abc = '456' +F().abc = '456' + + +class G(BaseModel): + class Config: + frozen=False +G.abc = +G.abc.lower() +G.abc.lower() = 'efg' + + +class H: + class Config: + frozen=True +H.abc = '123' \ No newline at end of file diff --git a/testData/mock/pydanticv18/main.py b/testData/mock/pydanticv18/main.py index e7f188af..6d93828a 100644 --- a/testData/mock/pydanticv18/main.py +++ b/testData/mock/pydanticv18/main.py @@ -38,6 +38,7 @@ class BaseConfig: validate_all = False extra = Extra.ignore allow_mutation = True + frozen = False allow_population_by_field_name = False use_enum_values = False fields = {} diff --git a/testSrc/com/koxudaxi/pydantic/PydanticInspectionV18Test.kt b/testSrc/com/koxudaxi/pydantic/PydanticInspectionV18Test.kt index 7207f755..59fe77e9 100644 --- a/testSrc/com/koxudaxi/pydantic/PydanticInspectionV18Test.kt +++ b/testSrc/com/koxudaxi/pydantic/PydanticInspectionV18Test.kt @@ -16,4 +16,12 @@ open class PydanticInspectionV18Test : PydanticInspectionBase(version = "v18") { fun testKwargConfig() { doTest() } + + fun testReadOnlyProperty() { + doTest() + } + + fun testReadOnlyPropertyFrozen() { + doTest() + } } From 411726f0f1a12374809dda23ba760ad3806f3c0e Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 3 May 2021 19:16:43 +0900 Subject: [PATCH 2/3] Update history --- resources/META-INF/plugin.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/META-INF/plugin.xml b/resources/META-INF/plugin.xml index 8733db4e..2adb21fa 100644 --- a/resources/META-INF/plugin.xml +++ b/resources/META-INF/plugin.xml @@ -7,6 +7,7 @@

version 0.3.1

Features

    +
  • Support frozen on config [#288]
  • Fix format [#287]
  • Improve handling pydantic version [#286]
  • Support config parameters on class kwargs [#285]
  • From f8956bbeaa7e0792508613656b83f17c7d4629db Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Mon, 3 May 2021 19:26:24 +0900 Subject: [PATCH 3/3] Add test case --- testData/inspection/readOnlyProperty.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/testData/inspection/readOnlyProperty.py b/testData/inspection/readOnlyProperty.py index 2fc0b865..e57bb6f6 100644 --- a/testData/inspection/readOnlyProperty.py +++ b/testData/inspection/readOnlyProperty.py @@ -52,4 +52,10 @@ class Config: class H: class Config: allow_mutation=False -H.abc = '123' \ No newline at end of file +H.abc = '123' + +class I(BaseModel): + abc: str = '123' + class Config: + frozen=False +I.abc = '456' \ No newline at end of file