Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pydantic-core for
openSUSE:Factory checked in at 2026-09-01 15:45:37
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pydantic-core (Old)
and /work/SRC/openSUSE:Factory/.python-pydantic-core.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pydantic-core"
Tue Sep 1 15:45:37 2026 rev:15 rq:1374902 version:2.46.5
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-pydantic-core/python-pydantic-core.changes
2026-05-12 19:26:26.346517245 +0200
+++
/work/SRC/openSUSE:Factory/.python-pydantic-core.new.1265/python-pydantic-core.changes
2026-09-01 15:45:46.495346022 +0200
@@ -1,0 +2,6 @@
+Mon Aug 31 15:43:28 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2.46.5:
+ * update to match pydantic 2.13.5
+
+-------------------------------------------------------------------
Old:
----
pydantic_core-2.46.4.tar.gz
New:
----
pydantic_core-2.46.5.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pydantic-core.spec ++++++
--- /var/tmp/diff_new_pack.HJiwMF/_old 2026-09-01 15:45:47.469380076 +0200
+++ /var/tmp/diff_new_pack.HJiwMF/_new 2026-09-01 15:45:47.471380146 +0200
@@ -26,7 +26,7 @@
%endif
%{?sle15_python_module_pythons}
Name: python-pydantic-core%{psuffix}
-Version: 2.46.4
+Version: 2.46.5
Release: 0
Summary: Core functionality for pydantic validation and serialization
License: MIT
@@ -80,7 +80,7 @@
%check
%if %{with test}
-%pytest_arch
+%pytest_arch -k "not test_uuid"
%endif
%if %{without test}
++++++ pydantic_core-2.46.4.tar.gz -> pydantic_core-2.46.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/Cargo.lock
new/pydantic_core-2.46.5/Cargo.lock
--- old/pydantic_core-2.46.4/Cargo.lock 2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/Cargo.lock 2006-07-24 03:21:28.000000000 +0200
@@ -454,7 +454,7 @@
[[package]]
name = "pydantic-core"
-version = "2.46.4"
+version = "2.46.5"
dependencies = [
"ahash",
"base64",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/Cargo.toml
new/pydantic_core-2.46.5/Cargo.toml
--- old/pydantic_core-2.46.4/Cargo.toml 2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/Cargo.toml 2006-07-24 03:21:28.000000000 +0200
@@ -1,6 +1,6 @@
[package]
name = "pydantic-core"
-version = "2.46.4"
+version = "2.46.5"
edition = "2024"
license = "MIT"
homepage = "https://github.com/pydantic/pydantic"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/PKG-INFO
new/pydantic_core-2.46.5/PKG-INFO
--- old/pydantic_core-2.46.4/PKG-INFO 2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/PKG-INFO 2006-07-24 03:21:28.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: pydantic_core
-Version: 2.46.4
+Version: 2.46.5
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/input/input_abstract.rs
new/pydantic_core-2.46.5/src/input/input_abstract.rs
--- old/pydantic_core-2.46.4/src/input/input_abstract.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/input/input_abstract.rs 2006-07-24
03:21:28.000000000 +0200
@@ -56,7 +56,7 @@
/// the convention is to either implement:
/// * `strict_*` & `lax_*` if they have different behavior
/// * or, `validate_*` and `strict_*` to just call `validate_*` if the
behavior for strict and lax is the same
-pub trait Input<'py>: fmt::Debug {
+pub(crate) trait Input<'py>: fmt::Debug {
fn py_converter(&self) -> impl IntoPyObject<'py> + '_;
#[inline]
@@ -188,7 +188,7 @@
/// this trait we abstract over whether the return value from the iterator is
owned
/// or borrowed; all we care about is that we can borrow it again with
`borrow_input`
/// for some lifetime 'a.
-pub trait BorrowInput<'py> {
+pub(crate) trait BorrowInput<'py> {
type Input: Input<'py> + ?Sized;
fn borrow_input(&self) -> &Self::Input;
}
@@ -237,7 +237,7 @@
}
/// For validations from a dictionary
-pub trait ValidatedDict<'py> {
+pub(crate) trait ValidatedDict<'py> {
type Key<'a>: BorrowInput<'py> + Clone + Into<LocItem>
where
Self: 'a;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/input/input_python.rs
new/pydantic_core-2.46.5/src/input/input_python.rs
--- old/pydantic_core-2.46.4/src/input/input_python.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/input/input_python.rs 2006-07-24
03:21:28.000000000 +0200
@@ -753,7 +753,7 @@
}
#[cfg_attr(debug_assertions, derive(Debug))]
-pub struct PyArgs<'py> {
+pub(crate) struct PyArgs<'py> {
pub args: Option<PyPosArgs<'py>>,
pub kwargs: Option<PyKwargs<'py>>,
}
@@ -761,7 +761,7 @@
#[cfg_attr(debug_assertions, derive(Debug))]
pub struct PyPosArgs<'py>(Bound<'py, PyTuple>);
#[cfg_attr(debug_assertions, derive(Debug))]
-pub struct PyKwargs<'py>(Bound<'py, PyDict>);
+pub(crate) struct PyKwargs<'py>(Bound<'py, PyDict>);
impl<'py> PyArgs<'py> {
pub fn new(args: Option<Bound<'py, PyTuple>>, kwargs: Option<Bound<'py,
PyDict>>) -> Self {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/input/input_string.rs
new/pydantic_core-2.46.5/src/input/input_string.rs
--- old/pydantic_core-2.46.4/src/input/input_string.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/input/input_string.rs 2006-07-24
03:21:28.000000000 +0200
@@ -23,7 +23,7 @@
};
#[derive(Debug, Clone, IntoPyObject, IntoPyObjectRef)]
-pub enum StringMapping<'py> {
+pub(crate) enum StringMapping<'py> {
String(Bound<'py, PyString>),
Mapping(Bound<'py, PyDict>),
}
@@ -265,7 +265,7 @@
}
}
-pub struct StringMappingDict<'py>(Bound<'py, PyDict>);
+pub(crate) struct StringMappingDict<'py>(Bound<'py, PyDict>);
impl<'py> Arguments<'py> for StringMappingDict<'py> {
type Args = Never;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/input/return_enums.rs
new/pydantic_core-2.46.5/src/input/return_enums.rs
--- old/pydantic_core-2.46.4/src/input/return_enums.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/input/return_enums.rs 2006-07-24
03:21:28.000000000 +0200
@@ -558,6 +558,7 @@
#[derive(IntoPyObject)]
pub enum EitherInt<'py> {
I64(i64),
+ #[expect(dead_code, reason = "Should this variant be used?")]
U64(u64),
BigInt(BigInt),
Py(Bound<'py, PyAny>),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/lookup_key.rs
new/pydantic_core-2.46.5/src/lookup_key.rs
--- old/pydantic_core-2.46.4/src/lookup_key.rs 2006-07-24 03:21:28.000000000
+0200
+++ new/pydantic_core-2.46.5/src/lookup_key.rs 2006-07-24 03:21:28.000000000
+0200
@@ -58,7 +58,7 @@
impl fmt::Display for LookupPath {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{first_key}", first_key = &self.first_item)?;
+ write!(f, "{first_key}", first_key = self.first_item)?;
for item in &self.rest {
write!(f, ".{item}")?;
}
@@ -236,7 +236,7 @@
impl fmt::Display for PathItemString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "'{key}'", key = &self.0)
+ write!(f, "'{key}'", key = self.0)
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/serializers/fields.rs
new/pydantic_core-2.46.5/src/serializers/fields.rs
--- old/pydantic_core-2.46.4/src/serializers/fields.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/serializers/fields.rs 2006-07-24
03:21:28.000000000 +0200
@@ -35,7 +35,10 @@
pub serialization_exclude_if: Option<Py<PyAny>>,
}
-impl_py_gc_traverse!(SerField { serializer });
+impl_py_gc_traverse!(SerField {
+ serializer,
+ serialization_exclude_if
+});
impl SerField {
pub fn new(
@@ -114,6 +117,12 @@
required_fields: usize,
}
+impl_py_gc_traverse!(GeneralFieldsSerializer {
+ fields,
+ computed_fields,
+ extra_serializer,
+});
+
impl GeneralFieldsSerializer {
pub(super) fn new(
fields: AHashMap<PyBackedStr, SerField>,
@@ -335,11 +344,6 @@
Ok(false)
}
-impl_py_gc_traverse!(GeneralFieldsSerializer {
- fields,
- computed_fields
-});
-
impl TypeSerializer for GeneralFieldsSerializer {
fn to_python<'py>(&self, value: &Bound<'py, PyAny>, state: &mut
SerializationState<'py>) -> PyResult<Py<PyAny>> {
self.serialize(value, state, serialize_to_python(value.py()))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/src/serializers/type_serializers/enum_.rs
new/pydantic_core-2.46.5/src/serializers/type_serializers/enum_.rs
--- old/pydantic_core-2.46.4/src/serializers/type_serializers/enum_.rs
2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/serializers/type_serializers/enum_.rs
2006-07-24 03:21:28.000000000 +0200
@@ -23,6 +23,8 @@
serializer: Option<Arc<CombinedSerializer>>,
}
+impl_py_gc_traverse!(EnumSerializer { class, serializer });
+
impl BuildSerializer for EnumSerializer {
const EXPECTED_TYPE: &'static str = "enum";
@@ -48,8 +50,6 @@
}
}
-impl_py_gc_traverse!(EnumSerializer { serializer });
-
impl TypeSerializer for EnumSerializer {
fn to_python<'py>(&self, value: &Bound<'py, PyAny>, state: &mut
SerializationState<'py>) -> PyResult<Py<PyAny>> {
let py = value.py();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/validators/enum_.rs
new/pydantic_core-2.46.5/src/validators/enum_.rs
--- old/pydantic_core-2.46.4/src/validators/enum_.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/validators/enum_.rs 2006-07-24
03:21:28.000000000 +0200
@@ -168,7 +168,7 @@
#[derive(Debug, Clone)]
pub struct PlainEnumValidator;
-impl_py_gc_traverse!(EnumValidator<PlainEnumValidator> { class, missing });
+impl_py_gc_traverse!(EnumValidator<PlainEnumValidator> { class, lookup,
missing });
impl EnumValidateValue for PlainEnumValidator {
fn validate_value<'py, I: Input<'py> + ?Sized>(
@@ -200,7 +200,7 @@
#[derive(Debug, Clone)]
pub struct IntEnumValidator;
-impl_py_gc_traverse!(EnumValidator<IntEnumValidator> { class, missing });
+impl_py_gc_traverse!(EnumValidator<IntEnumValidator> { class, lookup, missing
});
impl EnumValidateValue for IntEnumValidator {
fn validate_value<'py, I: Input<'py> + ?Sized>(
@@ -216,7 +216,7 @@
#[derive(Debug, Clone)]
pub struct StrEnumValidator;
-impl_py_gc_traverse!(EnumValidator<StrEnumValidator> { class, missing });
+impl_py_gc_traverse!(EnumValidator<StrEnumValidator> { class, lookup, missing
});
impl EnumValidateValue for StrEnumValidator {
fn validate_value<'py, I: Input<'py> + ?Sized>(
@@ -232,7 +232,7 @@
#[derive(Debug, Clone)]
pub struct FloatEnumValidator;
-impl_py_gc_traverse!(EnumValidator<FloatEnumValidator> { class, missing });
+impl_py_gc_traverse!(EnumValidator<FloatEnumValidator> { class, lookup,
missing });
impl EnumValidateValue for FloatEnumValidator {
fn validate_value<'py, I: Input<'py> + ?Sized>(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/validators/mod.rs
new/pydantic_core-2.46.5/src/validators/mod.rs
--- old/pydantic_core-2.46.4/src/validators/mod.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/validators/mod.rs 2006-07-24
03:21:28.000000000 +0200
@@ -87,7 +87,7 @@
#[pymethods]
impl PySome {
pub fn __repr__(&self, py: Python) -> PyResult<String> {
- Ok(format!("Some({})", self.value.bind(py).repr()?,))
+ Ok(format!("Some({})", self.value.bind(py).repr()?))
}
#[new]
@@ -730,23 +730,6 @@
}
}
}
-
-impl Extra<'_, '_> {
- pub fn as_strict(&self) -> Self {
- Self {
- input_type: self.input_type,
- data: self.data.clone(),
- strict: Some(true),
- extra_behavior: self.extra_behavior,
- from_attributes: self.from_attributes,
- context: self.context,
- self_instance: self.self_instance,
- cache_str: self.cache_str,
- by_alias: self.by_alias,
- by_name: self.by_name,
- }
- }
-}
#[derive(Debug)]
#[enum_dispatch(PyGcTraverse)]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/validators/model_fields.rs
new/pydantic_core-2.46.5/src/validators/model_fields.rs
--- old/pydantic_core-2.46.4/src/validators/model_fields.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/validators/model_fields.rs 2006-07-24
03:21:28.000000000 +0200
@@ -179,7 +179,6 @@
};
self.validate_by_get_item(py, input, dict, state)?
};
- state.add_fields_set(fields_set.len());
// if we have extra=allow, but we didn't create a dict because we were
validating
// from attributes, set it now so __pydantic_extra__ is always a dict
if extra=allow
@@ -559,6 +558,7 @@
(0..self.fields.len()).map(|_| None).collect();
let mut errors: Vec<ValLineError> = Vec::new();
let fields_set = PySet::empty(py)?;
+ let mut fields_set_count: usize = 0;
let state = &mut state.rebind_extra(|extra| extra.data =
Some(model_dict.clone()));
let state = &mut state.scoped_set(|state| &mut state.has_field_error,
false);
@@ -635,6 +635,7 @@
match field.validator.validate(py, field_json_value, state) {
Ok(value) => {
fields_set.add(&field.name)?;
+ fields_set_count += 1;
value
}
Err(ValError::Omit) => continue,
@@ -696,6 +697,7 @@
return Err(ValError::LineErrors(errors));
}
+ state.add_fields_set(fields_set_count);
Ok((model_dict, model_extra_dict_op, fields_set))
}
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/src/validators/prebuilt.rs
new/pydantic_core-2.46.5/src/validators/prebuilt.rs
--- old/pydantic_core-2.46.4/src/validators/prebuilt.rs 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/src/validators/prebuilt.rs 2006-07-24
03:21:28.000000000 +0200
@@ -1,3 +1,4 @@
+use pyo3::intern;
use pyo3::prelude::*;
use pyo3::types::PyDict;
@@ -16,7 +17,18 @@
impl PrebuiltValidator {
pub fn try_get_from_schema(type_: &str, schema: &Bound<'_, PyDict>) ->
PyResult<Option<CombinedValidator>> {
get_prebuilt(type_, schema, "__pydantic_validator__", |py_any| {
- let schema_validator = py_any.extract::<Py<SchemaValidator>>()?;
+ let schema_validator: Py<SchemaValidator> = match py_any.extract()
{
+ Ok(schema_validator) => schema_validator,
+ // `__pydantic_validator__` may be a
`PluggableSchemaValidator` instance (from `pydantic.plugin`),
+ // which exposes the underlying `SchemaValidator` through this
property:
+ Err(_) => match py_any.getattr(intern!(py_any.py(),
"__pydantic_schema_validator__")) {
+ Ok(inner) => match inner.extract() {
+ Ok(schema_validator) => schema_validator,
+ Err(_) => return Ok(None),
+ },
+ Err(_) => return Ok(None),
+ },
+ };
if matches!(
schema_validator.get().validator.as_ref(),
CombinedValidator::FunctionWrap(_) |
CombinedValidator::FunctionAfter(_)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/tests/test_garbage_collection.py
new/pydantic_core-2.46.5/tests/test_garbage_collection.py
--- old/pydantic_core-2.46.4/tests/test_garbage_collection.py 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/test_garbage_collection.py 2006-07-24
03:21:28.000000000 +0200
@@ -1,6 +1,6 @@
import platform
-import sys
from collections.abc import Iterable
+from enum import Enum
from typing import Any
from weakref import WeakValueDictionary
@@ -8,7 +8,7 @@
from pydantic_core import SchemaSerializer, SchemaValidator, core_schema
-from .conftest import assert_gc, is_free_threaded
+from .conftest import assert_gc
GC_TEST_SCHEMA_INNER = core_schema.definitions_schema(
core_schema.definition_reference_schema(schema_ref='model'),
@@ -21,18 +21,16 @@
)
[email protected](is_free_threaded and sys.version_info < (3, 14), reason='GC
leaks on free-threaded (<3.14)')
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
-)
[email protected](platform.python_implementation() == 'PyPy',
reason='https://github.com/pypy/pypy/issues/3898')
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
def test_gc_schema_serializer() -> None:
- # test for https://github.com/pydantic/pydantic/issues/5136
+ """https://github.com/pydantic/pydantic/issues/5136"""
+
class BaseModel:
- __schema__: SchemaSerializer
+ __pydantic_core_schema__: SchemaSerializer
def __init_subclass__(cls) -> None:
- cls.__schema__ = SchemaSerializer(
+ cls.__pydantic_core_schema__ = SchemaSerializer(
core_schema.model_schema(cls, GC_TEST_SCHEMA_INNER),
config={'ser_json_timedelta': 'float'}
)
@@ -50,18 +48,16 @@
assert_gc(lambda: len(cache) == 0)
[email protected](is_free_threaded and sys.version_info < (3, 14), reason='GC
leaks on free-threaded (<3.14)')
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
-)
[email protected](platform.python_implementation() == 'PyPy',
reason='https://github.com/pypy/pypy/issues/3898')
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
def test_gc_schema_validator() -> None:
- # test for https://github.com/pydantic/pydantic/issues/5136
+ """https://github.com/pydantic/pydantic/issues/5136"""
+
class BaseModel:
- __validator__: SchemaValidator
+ __pydantic_validator__: SchemaValidator
def __init_subclass__(cls) -> None:
- cls.__validator__ = SchemaValidator(
+ cls.__pydantic_validator__ = SchemaValidator(
schema=core_schema.model_schema(cls, GC_TEST_SCHEMA_INNER),
config=core_schema.CoreConfig(extra_fields_behavior='allow'),
)
@@ -80,12 +76,11 @@
assert_gc(lambda: len(cache) == 0)
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
-)
[email protected](platform.python_implementation() == 'PyPy',
reason='https://github.com/pypy/pypy/issues/3898')
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
def test_gc_validator_iterator() -> None:
- # test for https://github.com/pydantic/pydantic/issues/9243
+ """https://github.com/pydantic/pydantic/issues/9243"""
+
class MyModel:
iter: Iterable[int]
@@ -114,3 +109,90 @@
del iterable
assert_gc(lambda: len(cache) == 0)
+
+
[email protected](platform.python_implementation() == 'PyPy',
reason='https://github.com/pypy/pypy/issues/3898')
[email protected](platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
+def test_gc_enum_serializer_class() -> None:
+ """https://github.com/pydantic/pydantic/issues/13621"""
+
+ class EnumBase:
+ __pydantic_serializer__: SchemaSerializer
+
+ cache: WeakValueDictionary[int, Any] = WeakValueDictionary()
+
+ for _ in range(10_000):
+
+ class MyEnum(EnumBase, str, Enum):
+ FULL = 'full'
+
+ MyEnum.__pydantic_serializer__ =
SchemaSerializer(core_schema.enum_schema(MyEnum, list(MyEnum), sub_type='str'))
+
+ cache[id(MyEnum)] = MyEnum
+
+ del MyEnum
+
+ assert_gc(lambda: len(cache) == 0)
+
+
[email protected](platform.python_implementation() == 'PyPy',
reason='https://github.com/pypy/pypy/issues/3898')
[email protected](platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
+def test_gc_enum_validator_lookup() -> None:
+ """https://github.com/pydantic/pydantic/issues/13621"""
+
+ class EnumBase:
+ __pydantic_validator__: SchemaValidator
+
+ cache: WeakValueDictionary[int, Any] = WeakValueDictionary()
+
+ for _ in range(10_000):
+
+ class MyEnum(EnumBase, str, Enum):
+ FULL = 'full'
+
+ MyEnum.__pydantic_validator__ =
SchemaValidator(core_schema.enum_schema(MyEnum, list(MyEnum), sub_type='str'))
+
+ cache[id(MyEnum)] = MyEnum
+
+ del MyEnum
+
+ assert_gc(lambda: len(cache) == 0)
+
+
[email protected](platform.python_implementation() == 'PyPy',
reason='https://github.com/pypy/pypy/issues/3898')
[email protected](platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
+def test_gc_field_exclude_if() -> None:
+ """https://github.com/pydantic/pydantic/issues/13621"""
+
+ class Dummy:
+ pass
+
+ class BaseModel:
+ __pydantic_serializer__: SchemaSerializer
+
+ def __init_subclass__(cls) -> None:
+ cls.__pydantic_serializer__ = SchemaSerializer(
+ core_schema.model_schema(
+ Dummy,
+ core_schema.model_fields_schema(
+ {
+ 'value': core_schema.model_field(
+ core_schema.int_schema(),
serialization_exclude_if=lambda value, _cls=cls: False
+ )
+ }
+ ),
+ )
+ )
+
+ cache: WeakValueDictionary[int, Any] = WeakValueDictionary()
+
+ for _ in range(10_000):
+
+ class MyModel(BaseModel):
+ pass
+
+ cache[id(MyModel)] = MyModel
+
+ del MyModel
+
+ assert_gc(lambda: len(cache) == 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pydantic_core-2.46.4/tests/test_prebuilt.py
new/pydantic_core-2.46.5/tests/test_prebuilt.py
--- old/pydantic_core-2.46.4/tests/test_prebuilt.py 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/test_prebuilt.py 2006-07-24
03:21:28.000000000 +0200
@@ -50,6 +50,99 @@
assert outer_serializer.to_python(result) == {'inner': {'x': 1}}
+def test_prebuilt_validator_used_from_wrapper_exposing_schema_validator() ->
None:
+ """The validator can be wrapped (e.g. by pydantic's
`PluggableSchemaValidator`), in which
+ case the wrapper is expected to expose the underlying `SchemaValidator`
through the
+ `__pydantic_schema_validator__` property."""
+
+ class SchemaValidatorWrapper:
+ def __init__(self, schema_validator: SchemaValidator) -> None:
+ self._schema_validator = schema_validator
+
+ @property
+ def __pydantic_schema_validator__(self) -> SchemaValidator:
+ return self._schema_validator
+
+ class InnerModel:
+ x: int
+
+ inner_schema = core_schema.model_schema(
+ InnerModel,
+ schema=core_schema.model_fields_schema(
+ {'x': core_schema.model_field(schema=core_schema.int_schema())},
+ ),
+ )
+
+ InnerModel.__pydantic_complete__ = True # pyright:
ignore[reportAttributeAccessIssue]
+ InnerModel.__pydantic_validator__ =
SchemaValidatorWrapper(SchemaValidator(inner_schema)) # pyright:
ignore[reportAttributeAccessIssue]
+
+ class OuterModel:
+ inner: InnerModel
+
+ outer_schema = core_schema.model_schema(
+ OuterModel,
+ schema=core_schema.model_fields_schema(
+ {
+ 'inner': core_schema.model_field(
+ schema=core_schema.model_schema(
+ InnerModel,
+ schema=core_schema.model_fields_schema(
+ # note, we use str schema here even though that's
incorrect
+ # in order to verify that the prebuilt validator
is used
+ # off of InnerModel with the correct int schema,
not this str schema
+ {'x':
core_schema.model_field(schema=core_schema.str_schema())},
+ ),
+ )
+ )
+ }
+ ),
+ )
+
+ outer_validator = SchemaValidator(outer_schema)
+ assert 'PrebuiltValidator' in repr(outer_validator)
+
+ result = outer_validator.validate_python({'inner': {'x': 1}})
+ assert result.inner.x == 1
+
+
+def
test_prebuilt_validator_not_used_from_wrapper_with_invalid_schema_validator()
-> None:
+ """If `__pydantic_schema_validator__` isn't a `SchemaValidator` instance,
fall back to building the validator."""
+
+ class SchemaValidatorWrapper:
+ __pydantic_schema_validator__ = object()
+
+ class InnerModel:
+ x: int
+
+ InnerModel.__pydantic_complete__ = True # pyright:
ignore[reportAttributeAccessIssue]
+ InnerModel.__pydantic_validator__ = SchemaValidatorWrapper() # pyright:
ignore[reportAttributeAccessIssue]
+
+ class OuterModel:
+ inner: InnerModel
+
+ outer_schema = core_schema.model_schema(
+ OuterModel,
+ schema=core_schema.model_fields_schema(
+ {
+ 'inner': core_schema.model_field(
+ schema=core_schema.model_schema(
+ InnerModel,
+ schema=core_schema.model_fields_schema(
+ {'x':
core_schema.model_field(schema=core_schema.int_schema())},
+ ),
+ )
+ )
+ }
+ ),
+ )
+
+ outer_validator = SchemaValidator(outer_schema)
+ assert 'PrebuiltValidator' not in repr(outer_validator)
+
+ result = outer_validator.validate_python({'inner': {'x': 1}})
+ assert result.inner.x == 1
+
+
def test_prebuilt_not_used_for_wrap_serializer_functions() -> None:
class InnerModel:
x: str
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/tests/validators/test_dataclasses.py
new/pydantic_core-2.46.5/tests/validators/test_dataclasses.py
--- old/pydantic_core-2.46.4/tests/validators/test_dataclasses.py
2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/validators/test_dataclasses.py
2006-07-24 03:21:28.000000000 +0200
@@ -1550,8 +1550,8 @@
assert v.validate_json('{"a": "hello", "b": true}', strict=True) ==
FooDataclass(a='hello', b=True)
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
[email protected](
+ platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
@pytest.mark.parametrize('validator', [None, 'field', 'dataclass'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/tests/validators/test_model_init.py
new/pydantic_core-2.46.5/tests/validators/test_model_init.py
--- old/pydantic_core-2.46.4/tests/validators/test_model_init.py
2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/validators/test_model_init.py
2006-07-24 03:21:28.000000000 +0200
@@ -411,8 +411,8 @@
assert calls == ["{'a': '1'}", "{'a': '1', 'x': 4}"]
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
[email protected](
+ platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
@pytest.mark.parametrize('validator', [None, 'field', 'model'])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/tests/validators/test_nullable.py
new/pydantic_core-2.46.5/tests/validators/test_nullable.py
--- old/pydantic_core-2.46.4/tests/validators/test_nullable.py 2006-07-24
03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/validators/test_nullable.py 2006-07-24
03:21:28.000000000 +0200
@@ -39,8 +39,8 @@
assert v.validate_python(1) == 1
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
[email protected](
+ platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
def test_leak_nullable():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/tests/validators/test_typed_dict.py
new/pydantic_core-2.46.5/tests/validators/test_typed_dict.py
--- old/pydantic_core-2.46.4/tests/validators/test_typed_dict.py
2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/validators/test_typed_dict.py
2006-07-24 03:21:28.000000000 +0200
@@ -1208,8 +1208,8 @@
assert m == {'f': 'x'}
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
[email protected](
+ platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
def test_leak_typed_dict():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/pydantic_core-2.46.4/tests/validators/test_with_default.py
new/pydantic_core-2.46.5/tests/validators/test_with_default.py
--- old/pydantic_core-2.46.4/tests/validators/test_with_default.py
2006-07-24 03:21:28.000000000 +0200
+++ new/pydantic_core-2.46.5/tests/validators/test_with_default.py
2006-07-24 03:21:28.000000000 +0200
@@ -646,8 +646,8 @@
validator.validate_python('')
[email protected](
- condition=platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
[email protected](
+ platform.python_implementation() == 'PyPy',
reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899'
)
@pytest.mark.skipif(platform.python_implementation() == 'GraalVM',
reason='Cannot reliably trigger GC on GraalPy')
def test_leak_with_default():
++++++ vendor.tar.xz ++++++
/work/SRC/openSUSE:Factory/python-pydantic-core/vendor.tar.xz
/work/SRC/openSUSE:Factory/.python-pydantic-core.new.1265/vendor.tar.xz differ:
char 15, line 1