diff --git a/src/com/koxudaxi/pydantic/PydanticInspection.kt b/src/com/koxudaxi/pydantic/PydanticInspection.kt
index 177ba35c..6384120d 100644
--- a/src/com/koxudaxi/pydantic/PydanticInspection.kt
+++ b/src/com/koxudaxi/pydantic/PydanticInspection.kt
@@ -94,6 +94,31 @@ class PydanticInspection : PyInspection() {
inspectDefaultFactory(node)
}
+ override fun visitPyReferenceExpression(node: PyReferenceExpression) {
+ if(!pydanticCacheService.isV2) return
+ val pyFunction = node.reference.resolve() as? PyFunction ?: return
+
+ val qualifiedName = (pyFunction as? PyQualifiedNameOwner)?.qualifiedName ?: return
+ if (!qualifiedName.startsWith("pydantic.")) return
+ if (!isPydanticDeprecatedSince20(pyFunction)) return
+ registerProblem(
+ node.nameElement?.psi ?: node,
+ "
" +
+ "Pydantic V2 Migration Guide: " +
+ "" +
+ "https://docs.pydantic.dev/dev-v2/migration/" +
+ "" +
+ "",
+ ProblemHighlightType.LIKE_DEPRECATED
+ )
+
+ }
+ private fun isPydanticDeprecatedSince20(pyFunction: PyFunction): Boolean =
+ pyFunction.statementList.statements.filterIsInstance()
+ .mapNotNull { (it.expression as? PyCallExpression)?.getArgument(1, PyReferenceExpression::class.java) }
+ .any { (it.reference.resolve() as? PyTargetExpression)?.findAssignedValue()?.name == "PydanticDeprecatedSince20" }
+
+
private fun inspectCustomRootFieldV2(pyClass: PyClass) {
if (getRootField(pyClass) == null) return
if (!isPydanticModel(pyClass, false, myTypeEvalContext)) return
diff --git a/testData/inspectionv2/validators.py b/testData/inspectionv2/validators.py
new file mode 100644
index 00000000..41e01619
--- /dev/null
+++ b/testData/inspectionv2/validators.py
@@ -0,0 +1,26 @@
+from pydantic import BaseModel, validator, root_validator
+
+def check(func):
+ def inner():
+ func()
+ return inner
+
+class A(BaseModel):
+ a: str
+
+
+ @validator('a')
+ def validate_a(cls):
+ pass
+
+ @root_validator()
+ def validate_root(cls):
+ pass
+
+
+ def dummy(self):
+ pass
+
+ @check
+ def task(self):
+ pass
\ No newline at end of file
diff --git a/testData/mock/pydanticv2/__init__.py b/testData/mock/pydanticv2/__init__.py
index 27cd21f2..5d87cbbc 100644
--- a/testData/mock/pydanticv2/__init__.py
+++ b/testData/mock/pydanticv2/__init__.py
@@ -21,5 +21,6 @@
from .types import *
from .config import ConfigDict
from .version import VERSION
+from .deprecated import validator, root_validator
__version__ = VERSION
diff --git a/testData/mock/pydanticv2/deprecated/__init__.py b/testData/mock/pydanticv2/deprecated/__init__.py
new file mode 100644
index 00000000..b40d593b
--- /dev/null
+++ b/testData/mock/pydanticv2/deprecated/__init__.py
@@ -0,0 +1 @@
+from class_validators import validator, root_validator
\ No newline at end of file
diff --git a/testData/mock/pydanticv2/deprecated/class_validators.py b/testData/mock/pydanticv2/deprecated/class_validators.py
new file mode 100644
index 00000000..946b8341
--- /dev/null
+++ b/testData/mock/pydanticv2/deprecated/class_validators.py
@@ -0,0 +1,39 @@
+from warnings import warn
+
+from ..warnings import PydanticDeprecatedSince20
+
+DeprecationWarning = PydanticDeprecatedSince20
+
+
+def validator(
+ __field: str,
+ *fields: str,
+ pre: bool = False,
+ each_item: bool = False,
+ always: bool = False,
+ check_fields: bool | None = None,
+ allow_reuse: bool = False,
+) -> Callable[[_V1ValidatorType], _V1ValidatorType]:
+
+ warn(
+ 'Pydantic V1 style `@validator` validators are deprecated.'
+ ' You should migrate to Pydantic V2 style `@field_validator` validators,'
+ ' see the migration guide for more details',
+ DeprecationWarning,
+ stacklevel=2,
+ )
+
+
+def root_validator(
+ *__args,
+ pre: bool = False,
+ skip_on_failure: bool = False,
+ allow_reuse: bool = False,
+) -> Any:
+ warn(
+ 'Pydantic V1 style `@root_validator` validators are deprecated.'
+ ' You should migrate to Pydantic V2 style `@model_validator` validators,'
+ ' see the migration guide for more details',
+ DeprecationWarning,
+ stacklevel=2,
+ )
diff --git a/testSrc/com/koxudaxi/pydantic/PydanticInspectionV2Test.kt b/testSrc/com/koxudaxi/pydantic/PydanticInspectionV2Test.kt
index a5b286ac..4db438dc 100644
--- a/testSrc/com/koxudaxi/pydantic/PydanticInspectionV2Test.kt
+++ b/testSrc/com/koxudaxi/pydantic/PydanticInspectionV2Test.kt
@@ -25,4 +25,8 @@ open class PydanticInspectionV2Test : PydanticInspectionBase(version = "v2") {
fun testReadOnlyPropertyFrozenConfigDict() {
doTest()
}
+
+ fun testValidators() {
+ doTest()
+ }
}