Skip to content

Commit

Permalink
Merge pull request #288 from koxudaxi/support_frozen_on_config
Browse files Browse the repository at this point in the history
Support frozen on config
  • Loading branch information
koxudaxi authored May 3, 2021
2 parents 28abc47 + f8956bb commit c28836a
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 6 deletions.
1 change: 1 addition & 0 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<h2>version 0.3.1</h2>
<p>Features</p>
<ul>
<li>Support frozen on config [#288]</li>
<li>Fix format [#287]</li>
<li>Improve handling pydantic version [#286]</li>
<li>Support config parameters on class kwargs [#285]</li>
Expand Down
2 changes: 2 additions & 0 deletions src/com/koxudaxi/pydantic/Pydantic.kt
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ val DEFAULT_CONFIG = mapOf<String, Any?>(
"allow_population_by_field_name" to false,
"orm_mode" to false,
"allow_mutation" to true,
"frozen" to false,
"keep_untouched" to listOf<PyType>()
)

Expand All @@ -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
)

Expand Down
11 changes: 6 additions & 5 deletions src/com/koxudaxi/pydantic/PydanticInspection.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 7 additions & 1 deletion testData/inspection/readOnlyProperty.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,10 @@ class Config:
class H:
class Config:
allow_mutation=False
H.abc = '123'
H.abc = '123'

class I(BaseModel):
abc: str = '123'
class Config:
frozen=False
I.abc = '456'
55 changes: 55 additions & 0 deletions testData/inspectionv18/readOnlyProperty.py
Original file line number Diff line number Diff line change
@@ -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'
<error descr="Property \"abc\" defined in \"B\" is read-only">B().abc = '456'</error>

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'
<error descr="Property \"abc\" defined in \"D\" is read-only">D().abc = '456'</error>

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'
<error descr="Property \"abc\" defined in \"F\" is read-only">F().abc = '456'</error>


class G(BaseModel):
class Config:
allow_mutation=False
G.abc =<EOLError descr="Expression expected"></EOLError>
G.abc.lower()
<error descr="Cannot assign to function call">G.abc.lower()</error> = 'efg'


class H:
class Config:
allow_mutation=False
H.abc = '123'
55 changes: 55 additions & 0 deletions testData/inspectionv18/readOnlyPropertyFrozen.py
Original file line number Diff line number Diff line change
@@ -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'
<error descr="Property \"abc\" defined in \"B\" is read-only">B().abc = '456'</error>

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'
<error descr="Property \"abc\" defined in \"D\" is read-only">D().abc = '456'</error>

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'
<error descr="Property \"abc\" defined in \"F\" is read-only">F().abc = '456'</error>


class G(BaseModel):
class Config:
frozen=False
G.abc =<EOLError descr="Expression expected"></EOLError>
G.abc.lower()
<error descr="Cannot assign to function call">G.abc.lower()</error> = 'efg'


class H:
class Config:
frozen=True
H.abc = '123'
1 change: 1 addition & 0 deletions testData/mock/pydanticv18/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}
Expand Down
8 changes: 8 additions & 0 deletions testSrc/com/koxudaxi/pydantic/PydanticInspectionV18Test.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,12 @@ open class PydanticInspectionV18Test : PydanticInspectionBase(version = "v18") {
fun testKwargConfig() {
doTest()
}

fun testReadOnlyProperty() {
doTest()
}

fun testReadOnlyPropertyFrozen() {
doTest()
}
}

0 comments on commit c28836a

Please sign in to comment.