Skip to content

Commit 4cf41ae

Browse files
committed
Revert "Add custom_init logic"
This reverts commit f2368a4.
1 parent 58afc54 commit 4cf41ae

File tree

6 files changed

+3
-231
lines changed

6 files changed

+3
-231
lines changed

pydantic_core/core_schema.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2845,7 +2845,6 @@ class ModelSchema(TypedDict, total=False):
28452845
revalidate_instances: Literal['always', 'never', 'subclass-instances'] # default: 'never'
28462846
strict: bool
28472847
frozen: bool
2848-
custom_init: bool
28492848
config: CoreConfig
28502849
ref: str
28512850
metadata: Any
@@ -2860,7 +2859,6 @@ def model_schema(
28602859
revalidate_instances: Literal['always', 'never', 'subclass-instances'] | None = None,
28612860
strict: bool | None = None,
28622861
frozen: bool | None = None,
2863-
custom_init: bool | None = None,
28642862
config: CoreConfig | None = None,
28652863
ref: str | None = None,
28662864
metadata: Any = None,
@@ -2900,7 +2898,6 @@ class MyModel:
29002898
should re-validate defaults to config.revalidate_instances, else 'never'
29012899
strict: Whether the model is strict
29022900
frozen: Whether the model is frozen
2903-
custom_init: Whether the model has a custom init method
29042901
config: The config to use for the model
29052902
ref: optional unique identifier of the schema, used to reference the schema in other places
29062903
metadata: Any other information you want to include with the schema, not used by pydantic-core
@@ -2914,7 +2911,6 @@ class MyModel:
29142911
revalidate_instances=revalidate_instances,
29152912
strict=strict,
29162913
frozen=frozen,
2917-
custom_init=custom_init,
29182914
config=config,
29192915
ref=ref,
29202916
metadata=metadata,

src/argument_markers.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,3 @@ impl ArgsKwargs {
6060
}
6161
}
6262
}
63-
64-
pub(crate) const VALIDATED_DATA_KEY: &str = "validated_data";
65-
66-
#[pyclass(module = "pydantic_core._pydantic_core", frozen, get_all, freelist = 100)]
67-
#[derive(Debug, Clone)]
68-
pub struct ValidatedData {
69-
pub model_dict: PyObject,
70-
pub model_extra: PyObject,
71-
pub fields_set: PyObject,
72-
}
73-
74-
impl ValidatedData {
75-
pub(crate) fn new(model_dict: &PyAny, model_extra: &PyAny, fields_set: &PyAny) -> Self {
76-
Self {
77-
model_dict: model_dict.to_object(model_dict.py()),
78-
model_extra: model_extra.to_object(model_dict.py()),
79-
fields_set: fields_set.to_object(model_dict.py()),
80-
}
81-
}
82-
}
83-
84-
#[pymethods]
85-
impl ValidatedData {
86-
fn __repr__(&self, py: Python) -> String {
87-
let model_dict = safe_repr(self.model_dict.as_ref(py));
88-
let model_extra = safe_repr(self.model_extra.as_ref(py));
89-
let fields_set = safe_repr(self.fields_set.as_ref(py));
90-
format!("ValidatedData(model_dict={model_dict}, model_extra={model_extra}, fields_set={fields_set})")
91-
}
92-
}

src/input/input_abstract.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use std::fmt;
33
use pyo3::prelude::*;
44
use pyo3::types::{PyString, PyType};
55

6-
use crate::argument_markers::ValidatedData;
76
use crate::errors::{InputValue, LocItem, ValResult};
87
use crate::{PyMultiHostUrl, PyUrl};
98

@@ -45,11 +44,6 @@ pub trait Input<'a>: fmt::Debug + ToPyObject {
4544
None
4645
}
4746

48-
#[cfg_attr(has_no_coverage, no_coverage)]
49-
fn validated_data(&self) -> Option<ValidatedData> {
50-
None
51-
}
52-
5347
// input_ prefix to differentiate from the function on PyAny
5448
fn input_is_instance(&self, class: &PyAny, json_mask: u8) -> PyResult<bool>;
5549

src/input/input_python.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ use pyo3::types::{
1111
use pyo3::types::{PyDictItems, PyDictKeys, PyDictValues};
1212
use pyo3::{ffi, intern, AsPyPointer, PyTypeInfo};
1313

14-
use crate::argument_markers::{ValidatedData, VALIDATED_DATA_KEY};
1514
use crate::build_tools::safe_repr;
1615
use crate::errors::{ErrorType, InputValue, LocItem, ValError, ValResult};
1716
use crate::{ArgsKwargs, PyMultiHostUrl, PyUrl};
@@ -103,16 +102,6 @@ impl<'a> Input<'a> for PyAny {
103102
Some(self.getattr(name))
104103
}
105104

106-
#[cfg_attr(has_no_coverage, no_coverage)]
107-
fn validated_data(&self) -> Option<ValidatedData> {
108-
if let Ok(v) = self.get_item(intern!(self.py(), VALIDATED_DATA_KEY)) {
109-
if let Ok(validated_data) = v.extract::<ValidatedData>() {
110-
return Some(validated_data);
111-
}
112-
}
113-
None
114-
}
115-
116105
fn input_is_instance(&self, class: &PyAny, _json_mask: u8) -> PyResult<bool> {
117106
// See PyO3/pyo3#2694 - we can't use `is_instance` here since it requires PyType,
118107
// and some check objects are not types, this logic is lifted from `is_instance` in PyO3

src/validators/model.rs

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use pyo3::prelude::*;
77
use pyo3::types::{PyDict, PySet, PyString, PyTuple, PyType};
88
use pyo3::{ffi, intern};
99

10-
use crate::argument_markers::{ValidatedData, VALIDATED_DATA_KEY};
1110
use crate::build_tools::{py_err, schema_or_config_same, SchemaDict};
1211
use crate::errors::{ErrorType, ValError, ValResult};
1312
use crate::input::{py_error_on_minusone, Input};
@@ -56,7 +55,6 @@ pub struct ModelValidator {
5655
post_init: Option<Py<PyString>>,
5756
name: String,
5857
frozen: bool,
59-
custom_init: bool,
6058
}
6159

6260
impl BuildValidator for ModelValidator {
@@ -93,7 +91,6 @@ impl BuildValidator for ModelValidator {
9391
// which is not what we want here
9492
name: class.getattr(intern!(py, "__name__"))?.extract()?,
9593
frozen: schema.get_as(intern!(py, "frozen"))?.unwrap_or(false),
96-
custom_init: schema.get_as(intern!(py, "custom_init"))?.unwrap_or(false),
9794
}
9895
.into())
9996
}
@@ -243,19 +240,6 @@ impl ModelValidator {
243240
..*extra
244241
};
245242

246-
if self.custom_init {
247-
if let Some(validated_data) = input.validated_data() {
248-
set_model_attrs(
249-
self_instance,
250-
validated_data.model_dict.as_ref(py),
251-
validated_data.model_extra.as_ref(py),
252-
validated_data.fields_set.as_ref(py),
253-
)?;
254-
// we don't call post_init here, it'll be called by the original validator
255-
return Ok(self_instance.into_py(py));
256-
}
257-
}
258-
259243
let output = self.validator.validate(py, input, &new_extra, slots, recursion_guard)?;
260244
let (model_dict, model_extra, fields_set): (&PyAny, &PyAny, &PyAny) = output.extract(py)?;
261245
set_model_attrs(self_instance, model_dict, model_extra, fields_set)?;
@@ -279,16 +263,9 @@ impl ModelValidator {
279263

280264
fn create_class(&self, model_dict: &PyAny, model_extra: &PyAny, fields_set: &PyAny) -> PyResult<PyObject> {
281265
let py = model_dict.py();
282-
if self.custom_init {
283-
let kwargs = PyDict::new(py);
284-
let vd = ValidatedData::new(model_dict, model_extra, fields_set);
285-
kwargs.set_item(intern!(py, VALIDATED_DATA_KEY), vd.into_py(py))?;
286-
self.class.call(py, (), Some(kwargs))
287-
} else {
288-
let instance = create_class(self.class.as_ref(py))?;
289-
set_model_attrs(instance.as_ref(py), model_dict, model_extra, fields_set)?;
290-
Ok(instance)
291-
}
266+
let instance = create_class(self.class.as_ref(py))?;
267+
set_model_attrs(instance.as_ref(py), model_dict, model_extra, fields_set)?;
268+
Ok(instance)
292269
}
293270
}
294271

tests/validators/test_model.py

Lines changed: 0 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,157 +1164,3 @@ def f(values_or_values_and_fields_set: Any, *args: Any) -> Any:
11641164
assert m.b == 2
11651165
assert m.__pydantic_fields_set__ == {'a', 'b'}
11661166
assert calls == [call1, call2]
1167-
1168-
1169-
def test_custom_init():
1170-
calls = []
1171-
1172-
class Model:
1173-
__slots__ = '__dict__', '__pydantic_extra__', '__pydantic_fields_set__'
1174-
1175-
def __init__(self, **kwargs):
1176-
validated_data = kwargs['validated_data']
1177-
self.a = validated_data.model_dict['a']
1178-
self.b = validated_data.model_dict['b']
1179-
self.__pydantic_fields_set__ = validated_data.fields_set
1180-
calls.append(repr(kwargs))
1181-
1182-
v = SchemaValidator(
1183-
core_schema.model_schema(
1184-
Model,
1185-
core_schema.model_fields_schema(
1186-
{
1187-
'a': core_schema.model_field(core_schema.with_default_schema(core_schema.int_schema(), default=1)),
1188-
'b': core_schema.model_field(core_schema.int_schema()),
1189-
}
1190-
),
1191-
custom_init=True,
1192-
)
1193-
)
1194-
1195-
m = v.validate_python({'b': 2})
1196-
assert m.a == 1
1197-
assert m.b == 2
1198-
assert m.__pydantic_fields_set__ == {'b'}
1199-
assert calls == [
1200-
"{'validated_data': ValidatedData(model_dict={'a': 1, 'b': 2}, model_extra=None, fields_set={'b'})}"
1201-
]
1202-
1203-
1204-
def test_custom_init_nested():
1205-
calls = []
1206-
1207-
class ModelInner:
1208-
__slots__ = '__dict__', '__pydantic_extra__', '__pydantic_fields_set__'
1209-
a: int
1210-
b: int
1211-
1212-
def __init__(self, **data):
1213-
calls.append(f'inner: {data!r}')
1214-
self.__pydantic_validator__.validate_python(data, self_instance=self)
1215-
1216-
inner_schema = core_schema.model_schema(
1217-
ModelInner,
1218-
core_schema.model_fields_schema(
1219-
{
1220-
'a': core_schema.model_field(core_schema.with_default_schema(core_schema.int_schema(), default=1)),
1221-
'b': core_schema.model_field(core_schema.int_schema()),
1222-
}
1223-
),
1224-
custom_init=True,
1225-
)
1226-
ModelInner.__pydantic_validator__ = SchemaValidator(inner_schema)
1227-
1228-
class ModelOuter:
1229-
__slots__ = '__dict__', '__pydantic_extra__', '__pydantic_fields_set__'
1230-
a: int
1231-
b: ModelInner
1232-
1233-
def __init__(self, **data):
1234-
calls.append(f'outer: {data!r}')
1235-
self.__pydantic_validator__.validate_python(data, self_instance=self)
1236-
1237-
ModelOuter.__pydantic_validator__ = SchemaValidator(
1238-
core_schema.model_schema(
1239-
ModelOuter,
1240-
core_schema.model_fields_schema(
1241-
{
1242-
'a': core_schema.model_field(core_schema.with_default_schema(core_schema.int_schema(), default=1)),
1243-
'b': core_schema.model_field(inner_schema),
1244-
}
1245-
),
1246-
custom_init=True,
1247-
)
1248-
)
1249-
1250-
m = ModelOuter(a=2, b={'b': 3})
1251-
assert m.__pydantic_fields_set__ == {'a', 'b'}
1252-
assert m.a == 2
1253-
assert isinstance(m.b, ModelInner)
1254-
assert m.b.a == 1
1255-
assert m.b.b == 3
1256-
# insert_assert(calls)
1257-
assert calls == [
1258-
"outer: {'a': 2, 'b': {'b': 3}}",
1259-
"inner: {'validated_data': ValidatedData(model_dict={'a': 1, 'b': 3}, model_extra=None, fields_set={'b'})}",
1260-
]
1261-
1262-
1263-
class BadValidatedData:
1264-
"""
1265-
Attempt to confuse validation with a mock of ValidatedData should fail
1266-
"""
1267-
1268-
def __init__(self, model_dict: Dict[str, Any], fields_set: Set[str]):
1269-
self.model_dict = model_dict
1270-
self.fields_set = fields_set
1271-
1272-
1273-
def test_custom_init_mock():
1274-
calls = []
1275-
1276-
class Model:
1277-
def __init__(self, **kwargs):
1278-
validated_data = kwargs['validated_data']
1279-
self.a = validated_data.model_dict['a']
1280-
calls.append(repr(validated_data))
1281-
1282-
v = SchemaValidator(
1283-
core_schema.model_schema(
1284-
Model,
1285-
core_schema.model_fields_schema({'a': core_schema.model_field(core_schema.int_schema())}),
1286-
custom_init=True,
1287-
)
1288-
)
1289-
1290-
m = v.validate_python({'a': 2})
1291-
assert m.a == 2
1292-
assert calls == ["ValidatedData(model_dict={'a': 2}, model_extra=None, fields_set={'a'})"]
1293-
1294-
with pytest.raises(ValidationError, match=r'Field required \[type=missing,'):
1295-
v.validate_python({'validated_data': BadValidatedData({'a': 2}, {'a'})})
1296-
1297-
1298-
def test_custom_init_validated_data_field():
1299-
calls = []
1300-
1301-
class Model:
1302-
def __init__(self, **kwargs):
1303-
validated_data = kwargs['validated_data']
1304-
self.validated_data = validated_data.model_dict['validated_data']
1305-
calls.append(repr(validated_data))
1306-
1307-
v = SchemaValidator(
1308-
core_schema.model_schema(
1309-
Model,
1310-
core_schema.model_fields_schema({'validated_data': core_schema.model_field(core_schema.int_schema())}),
1311-
custom_init=True,
1312-
)
1313-
)
1314-
1315-
m = v.validate_python({'validated_data': 2})
1316-
assert m.validated_data == 2
1317-
assert calls == ["ValidatedData(model_dict={'validated_data': 2}, model_extra=None, fields_set={'validated_data'})"]
1318-
1319-
with pytest.raises(ValidationError, match='Input should be a valid integer'):
1320-
v.validate_python({'validated_data': BadValidatedData({'a': 2}, {'a'})})

0 commit comments

Comments
 (0)