Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pydantic for openSUSE:Factory 
checked in at 2026-05-12 19:26:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pydantic (Old)
 and      /work/SRC/openSUSE:Factory/.python-pydantic.new.1966 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pydantic"

Tue May 12 19:26:11 2026 rev:40 rq:1352320 version:2.13.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pydantic/python-pydantic.changes  
2026-04-18 21:32:20.475715056 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pydantic.new.1966/python-pydantic.changes    
    2026-05-12 19:26:31.690738734 +0200
@@ -1,0 +2,13 @@
+Sun May 10 19:57:53 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 2.13.4:
+  * Bump libc from 0.2.155 to 0.2.185 by @Viicos in #13109
+  * Adapt `pydantic-core` linker flags on macOS by @washingtoneg
+    and @Viicos in #13147
+  * Preserve `RootModel` core metadata by @Viicos in #13129
+  * Handle `AttributeError` subclasses with `from_attributes` by
+    @Viicos in #13096
+  * Fix `ValidationInfo.field_name` missing with
+    `model_validate_json()` by @Viicos in #13084
+
+-------------------------------------------------------------------

Old:
----
  pydantic-2.13.1.tar.gz

New:
----
  pydantic-2.13.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pydantic.spec ++++++
--- /var/tmp/diff_new_pack.AER21n/_old  2026-05-12 19:26:32.270762773 +0200
+++ /var/tmp/diff_new_pack.AER21n/_new  2026-05-12 19:26:32.274762938 +0200
@@ -27,7 +27,7 @@
 %endif
 %{?sle15_python_module_pythons}
 Name:           python-pydantic%{psuffix}
-Version:        2.13.1
+Version:        2.13.4
 Release:        0
 Summary:        Data validation and settings management using python type 
hinting
 License:        MIT
@@ -38,7 +38,7 @@
 BuildRequires:  %{python_module hatchling}
 BuildRequires:  %{python_module packaging}
 BuildRequires:  %{python_module pip}
-BuildRequires:  %{python_module pydantic-core = 2.46.1}
+BuildRequires:  %{python_module pydantic-core = 2.46.4}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 %if %{with test}
@@ -61,7 +61,7 @@
 BuildRequires:  %{python_module rich}
 %endif
 Requires:       python-annotated-types >= 0.6.0
-Requires:       python-pydantic-core = 2.46.1
+Requires:       python-pydantic-core = 2.46.4
 Requires:       python-typing-extensions >= 4.14.1
 Requires:       python-typing-inspection >= 0.4.2
 Recommends:     python-email-validator >= 2.0

++++++ pydantic-2.13.1.tar.gz -> pydantic-2.13.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/.github/workflows/ci.yml 
new/pydantic-2.13.4/.github/workflows/ci.yml
--- old/pydantic-2.13.1/.github/workflows/ci.yml        2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/.github/workflows/ci.yml        2026-05-06 
10:27:14.000000000 +0200
@@ -70,7 +70,7 @@
   core-build:
     name: core / Build on ${{ matrix.os }} (${{ matrix.target }} - ${{ 
matrix.interpreter || 'all' }}${{ matrix.os == 'linux' && format(' - {0}', 
matrix.manylinux == 'auto' && 'manylinux' || matrix.manylinux) || '' }})
     # only run on push to main, if a full build was requested or on release:
-    if: startsWith(github.ref, 'refs/tags/') || github.ref == 
'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'full 
build')
+    if: startsWith(github.ref, 'refs/tags/v') || github.ref == 
'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'full 
build')
     strategy:
       fail-fast: false
       matrix:
@@ -187,7 +187,7 @@
   core-build-pgo:
     name: core / Build PGO-optimized on ${{ matrix.platform.os }} / ${{ 
matrix.interpreter }}
     # only run on push to main, if a full build was requested or on release:
-    if: startsWith(github.ref, 'refs/tags/') || github.ref == 
'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'full 
build')
+    if: startsWith(github.ref, 'refs/tags/v') || github.ref == 
'refs/heads/main' || contains(github.event.pull_request.labels.*.name, 'full 
build')
     strategy:
       fail-fast: false
       matrix:
@@ -525,8 +525,7 @@
       matrix:
         python-version:
           - '3.13'
-          # Segmentation fault on pypy3.11.15 (latest), see 
https://github.com/pypy/pypy/issues/5400
-          - 'pypy3.11.13'
+          - 'pypy3.11'
 
     steps:
       - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 
v6.0.2
@@ -560,7 +559,7 @@
 
   build-pydantic:
     runs-on: ubuntu-latest
-    if: startsWith(github.ref, 'refs/tags/')
+    if: startsWith(github.ref, 'refs/tags/v')
     outputs:
       pydantic-version: ${{ steps.check-tag.outputs.VERSION }}
 
@@ -645,8 +644,7 @@
       fail-fast: false
       matrix:
         os: [ubuntu-latest, macos-latest, windows-latest]
-        # Segmentation fault on pypy3.11.15 (latest), see 
https://github.com/pypy/pypy/issues/5400
-        python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14', 
'3.14t', 'pypy3.11.13']
+        python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14', 
'3.14t', 'pypy3.11']
         include:
           # test macos intel just with latest python version
           - os: macos-15-intel
@@ -884,7 +882,7 @@
 
   release-pydantic-core:
     needs: [core-test-builds-arch, core-test-builds-os, core-build-sdist, 
check]
-    if: needs.check.outputs.result == 'success' && startsWith(github.ref, 
'refs/tags/')
+    if: needs.check.outputs.result == 'success' && startsWith(github.ref, 
'refs/tags/v')
     runs-on: ubuntu-latest
     environment: release
 
@@ -943,7 +941,7 @@
 
   release-pydantic:
     needs: [build-pydantic, release-pydantic-core]
-    if: startsWith(github.ref, 'refs/tags/')
+    if: startsWith(github.ref, 'refs/tags/v')
     runs-on: ubuntu-latest
     environment: release
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/CITATION.cff 
new/pydantic-2.13.4/CITATION.cff
--- old/pydantic-2.13.1/CITATION.cff    2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/CITATION.cff    2026-05-06 10:27:14.000000000 +0200
@@ -44,5 +44,5 @@
   - hints
   - typing
 license: MIT
-version: v2.13.1
-date-released: 2026-04-15
+version: v2.13.4
+date-released: 2026-05-06
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/HISTORY.md 
new/pydantic-2.13.4/HISTORY.md
--- old/pydantic-2.13.1/HISTORY.md      2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/HISTORY.md      2026-05-06 10:27:14.000000000 +0200
@@ -2,6 +2,41 @@
 <!-- markdownlint-disable descriptive-link-text -->
 <!-- markdownlint-disable-next-line first-line-heading -->
 
+## v2.13.4 (2026-05-06)
+
+[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.4)
+
+### What's Changed
+
+#### Packaging
+
+* Bump libc from 0.2.155 to 0.2.185 by @Viicos in 
[#13109](https://github.com/pydantic/pydantic/pull/13109)
+* Adapt `pydantic-core` linker flags on macOS by @washingtoneg and @Viicos in 
[#13147](https://github.com/pydantic/pydantic/pull/13147)
+
+#### Fixes
+
+* Preserve `RootModel` core metadata by @Viicos in 
[#13129](https://github.com/pydantic/pydantic/pull/13129)
+
+## v2.13.3 (2026-04-20)
+
+[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.3)
+
+### What's Changed
+
+#### Fixes
+
+* Handle `AttributeError` subclasses with `from_attributes` by @Viicos in 
[#13096](https://github.com/pydantic/pydantic/pull/13096)
+
+## v2.13.2 (2026-04-17)
+
+[GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.2)
+
+### What's Changed
+
+#### Fixes
+
+* Fix `ValidationInfo.field_name` missing with `model_validate_json()` by 
@Viicos in [#13084](https://github.com/pydantic/pydantic/pull/13084)
+
 ## v2.13.1 (2026-04-15)
 
 [GitHub release](https://github.com/pydantic/pydantic/releases/tag/v2.13.1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/docs/index.md 
new/pydantic-2.13.4/docs/index.md
--- old/pydantic-2.13.1/docs/index.md   2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/docs/index.md   2026-05-06 10:27:14.000000000 +0200
@@ -14,67 +14,25 @@
 
 Fast and extensible, Pydantic plays nicely with your linters/IDE/brain. Define 
how data should be in pure, canonical Python 3.9+; validate it with Pydantic.
 
-!!! logfire "Monitor Pydantic with Pydantic Logfire :fire:"
-    **[Pydantic Logfire](https://pydantic.dev/logfire)** is a production-grade 
observability platform for AI and general applications. See LLM interactions, 
agent behavior, API requests, and database queries in one unified trace. With 
SDKs for Python, JavaScript/TypeScript, and Rust, Logfire works with all 
OpenTelemetry-compatible languages.
+**Sign up for our newsletter, *The Pydantic Stack*, with updates & tutorials 
on Pydantic, Logfire, and Pydantic AI:**
 
-    Logfire integrates with many popular Python libraries including FastAPI, 
OpenAI and Pydantic itself, so you can use Logfire to monitor Pydantic 
validations and understand why some inputs fail validation:
-
-    ```python {title="Monitoring Pydantic with Logfire" test="skip"}
-    from datetime import datetime
-
-    import logfire
-
-    from pydantic import BaseModel
-
-    logfire.configure()
-    logfire.instrument_pydantic()  # (1)!
-
-
-    class Delivery(BaseModel):
-        timestamp: datetime
-        dimensions: tuple[int, int]
-
-
-    # this will record details of a successful validation to logfire
-    m = Delivery(timestamp='2020-01-02T03:04:05Z', dimensions=['10', '20'])
-    print(repr(m.timestamp))
-    #> datetime.datetime(2020, 1, 2, 3, 4, 5, tzinfo=TzInfo(UTC))
-    print(m.dimensions)
-    #> (10, 20)
-
-    Delivery(timestamp='2020-01-02T03:04:05Z', dimensions=['10'])  # (2)!
-    ```
-
-    1. Set logfire record all both successful and failed validations, use 
`record='failure'` to only record failed validations, [learn 
more](https://logfire.pydantic.dev/docs/integrations/pydantic/).
-    2. This will raise a `ValidationError` since there are too few 
`dimensions`, details of the input data and validation errors will be recorded 
in Logfire.
-
-    Would give you a view like this in the Logfire platform:
-
-    [![Logfire Pydantic 
Integration](img/logfire-pydantic-integration.png)](https://logfire.pydantic.dev/docs/guides/web-ui/live/)
-
-    This is just a toy example, but hopefully makes clear the potential value 
of instrumenting a more complex application.
-
-    **[Learn more about Pydantic Logfire](https://logfire.pydantic.dev/docs/)**
-
-    **Sign up for our newsletter, *The Pydantic Stack*, with updates & 
tutorials on Pydantic, Logfire, and Pydantic AI:**
-
-      <form method="POST" 
action="https://eu.customerioforms.com/forms/submit_action?site_id=53d2086c3c4214eaecaa&form_id=14b22611745b458&success_url=https://docs.pydantic.dev/";
 class="md-typeset" style="display: flex; align-items: center; gap: 0.5rem; 
max-width: 100%;">
-          <input
-          type="email"
-          id="email_input"
-          name="email"
-          class="md-input md-input--stretch"
-          style="flex: 1; background: var(--md-default-bg-color); color: 
var(--md-default-fg-color);"
-          required
-          placeholder="Email"
-          data-1p-ignore
-          data-lpignore="true"
-          data-protonpass-ignore="true"
-          data-bwignore="true"
-          />
-          <input type="hidden" id="source_input" name="source" 
value="pydantic" />
-          <button type="submit" class="md-button 
md-button--primary">Subscribe</button>
-      </form>
+<form method="POST" 
action="https://eu.customerioforms.com/forms/submit_action?site_id=53d2086c3c4214eaecaa&form_id=14b22611745b458&success_url=https://docs.pydantic.dev/";
 class="md-typeset" style="display: flex; align-items: center; gap: 0.5rem; 
max-width: 100%;">
+    <input
+    type="email"
+    id="email_input"
+    name="email"
+    class="md-input md-input--stretch"
+    style="flex: 1; background: var(--md-default-bg-color); color: 
var(--md-default-fg-color);"
+    required
+    placeholder="Email"
+    data-1p-ignore
+    data-lpignore="true"
+    data-protonpass-ignore="true"
+    data-bwignore="true"
+    />
+    <input type="hidden" id="source_input" name="source" value="pydantic" />
+    <button type="submit" class="md-button 
md-button--primary">Subscribe</button>
+</form>
 
 ## Why use Pydantic?
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/docs/version-policy.md 
new/pydantic-2.13.4/docs/version-policy.md
--- old/pydantic-2.13.1/docs/version-policy.md  2026-04-15 15:55:16.000000000 
+0200
+++ new/pydantic-2.13.4/docs/version-policy.md  2026-05-06 10:27:14.000000000 
+0200
@@ -34,7 +34,16 @@
 
 ## Pydantic V3 and beyond
 
-We expect to make new major releases roughly once a year going forward, 
although as mentioned above, any associated breaking changes should be trivial 
to fix compared to the V1-to-V2 transition.
+Any associated breaking changes in the V3 release will be introduced with 
care. This will include bug fixes that can't be solved in V2 without 
introducing a change in behavior
+(e.g. [fixing configuration not following the 
MRO](https://github.com/pydantic/pydantic/issues/9992)), or changes that don't 
remove existing functionality or doesn't provide
+proper alternatives.
+
+In V3, it is expected to merged `pydantic-core` as an internal sub-module of 
Pydantic, meaning it won't be published as a standalone library anymore.
+
+## Tagging conventions
+
+Pydantic uses Git tags to identify all published versions on PyPI (including 
alpha and beta releases), prefixed with the `v` character. Since v2.13, 
`pydantic-core`
+has been merged as a workspace member inside the `pydantic` repository, and 
subsequent `pydantic-core` releases are tagged as `core-vx.y.z`.
 
 ## Experimental Features
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pydantic-2.13.1/pydantic/_internal/_generate_schema.py 
new/pydantic-2.13.4/pydantic/_internal/_generate_schema.py
--- old/pydantic-2.13.1/pydantic/_internal/_generate_schema.py  2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic/_internal/_generate_schema.py  2026-05-06 
10:27:14.000000000 +0200
@@ -840,8 +840,17 @@
                 generic_origin: type[BaseModel] | None = getattr(cls, 
'__pydantic_generic_metadata__', {}).get('origin')
 
                 if cls.__pydantic_root_model__:
-                    # FIXME: should the common field metadata be used here?
-                    inner_schema, _ = self._common_field_schema('root', 
fields['root'], decorators)
+                    inner_schema, metadata = self._common_field_schema('root', 
fields['root'], decorators)
+                    if cls.__doc__ and metadata.get('pydantic_js_updates', 
{}).get('description'):
+                        # This is a bit of a leaky abstraction, but as the 
model docstring takes priority
+                        # over the root field's description, we need to 
override it here. This can't be done
+                        # in the JSON Schema generation logic because the 
metadata's `pydantic_js_updates` are
+                        # applied last, and overrides any value previously set 
(so the description set from the
+                        # docstring in 
`GenerateJsonSchema._update_class_schema()` is overridden):
+                        update_core_metadata(
+                            metadata, pydantic_js_updates={'description': 
inspect.cleandoc(cls.__doc__)}
+                        )
+
                     inner_schema = apply_model_validators(inner_schema, 
model_validators, 'inner')
                     model_schema = core_schema.model_schema(
                         cls,
@@ -852,6 +861,7 @@
                         post_init=getattr(cls, '__pydantic_post_init__', None),
                         config=core_config,
                         ref=model_ref,
+                        metadata=metadata,
                     )
                 else:
                     fields_schema: core_schema.CoreSchema = 
core_schema.model_fields_schema(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pydantic/json_schema.py 
new/pydantic-2.13.4/pydantic/json_schema.py
--- old/pydantic-2.13.1/pydantic/json_schema.py 2026-04-15 15:55:16.000000000 
+0200
+++ new/pydantic-2.13.4/pydantic/json_schema.py 2026-05-06 10:27:14.000000000 
+0200
@@ -1636,7 +1636,6 @@
         """
         from ._internal._dataclasses import is_stdlib_dataclass
         from .main import BaseModel
-        from .root_model import RootModel
 
         if (config_title := config.get('title')) is not None:
             json_schema.setdefault('title', config_title)
@@ -1664,8 +1663,6 @@
 
         if docstring:
             json_schema.setdefault('description', inspect.cleandoc(docstring))
-        elif issubclass(cls, RootModel) and (root_description := 
cls.__pydantic_fields__['root'].description):
-            json_schema.setdefault('description', root_description)
 
         extra = config.get('extra')
         if 'additionalProperties' not in json_schema:  # This check is 
particularly important for `typed_dict_schema()`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pydantic/version.py 
new/pydantic-2.13.4/pydantic/version.py
--- old/pydantic-2.13.1/pydantic/version.py     2026-04-15 15:55:16.000000000 
+0200
+++ new/pydantic-2.13.4/pydantic/version.py     2026-05-06 10:27:14.000000000 
+0200
@@ -8,7 +8,7 @@
 
 __all__ = 'VERSION', 'version_info'
 
-VERSION = '2.13.1'
+VERSION = '2.13.4'
 """The version of Pydantic.
 
 This version specifier is guaranteed to be compliant with the [specification],
@@ -19,7 +19,7 @@
 """
 
 # Keep this in sync with the version constraint in the `pyproject.toml` 
dependencies:
-_COMPATIBLE_PYDANTIC_CORE_VERSION = '2.46.1'
+_COMPATIBLE_PYDANTIC_CORE_VERSION = '2.46.4'
 
 
 def version_short() -> str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pydantic-core/Cargo.lock 
new/pydantic-2.13.4/pydantic-core/Cargo.lock
--- old/pydantic-2.13.1/pydantic-core/Cargo.lock        2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/Cargo.lock        2026-05-06 
10:27:14.000000000 +0200
@@ -366,9 +366,9 @@
 
 [[package]]
 name = "libc"
-version = "0.2.155"
+version = "0.2.185"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f"
 
 [[package]]
 name = "litemap"
@@ -454,7 +454,7 @@
 
 [[package]]
 name = "pydantic-core"
-version = "2.46.1"
+version = "2.46.4"
 dependencies = [
  "ahash",
  "base64",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pydantic-core/Cargo.toml 
new/pydantic-2.13.4/pydantic-core/Cargo.toml
--- old/pydantic-2.13.1/pydantic-core/Cargo.toml        2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/Cargo.toml        2026-05-06 
10:27:14.000000000 +0200
@@ -1,6 +1,6 @@
 [package]
 name = "pydantic-core"
-version = "2.46.1"
+version = "2.46.4"
 edition = "2024"
 license = "MIT"
 homepage = "https://github.com/pydantic/pydantic";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pydantic-core/build.rs 
new/pydantic-2.13.4/pydantic-core/build.rs
--- old/pydantic-2.13.1/pydantic-core/build.rs  2026-04-15 15:55:16.000000000 
+0200
+++ new/pydantic-2.13.4/pydantic-core/build.rs  2026-05-06 10:27:14.000000000 
+0200
@@ -13,4 +13,13 @@
     }
     println!("cargo:rustc-check-cfg=cfg(specified_profile_use)");
     println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap());
+
+    // The macOS `ld_prime` new Linker (used in macOS 15 GitHub CI runners),
+    // reserves significantly less Mach-O header padding than the old linker.
+    // Tools like Homebrew use install_name_tool to rewrite dylib paths 
post-install,
+    // and that requires spare space in the header. Without this flag the 
relink
+    // fails with "updated load commands do not fit in the header".
+    if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("macos") {
+        println!("cargo:rustc-link-arg=-Wl,-headerpad_max_install_names");
+    }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pydantic-core/src/lookup_key.rs 
new/pydantic-2.13.4/pydantic-core/src/lookup_key.rs
--- old/pydantic-2.13.1/pydantic-core/src/lookup_key.rs 2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/src/lookup_key.rs 2026-05-06 
10:27:14.000000000 +0200
@@ -3,7 +3,7 @@
 use std::fmt;
 
 use pyo3::IntoPyObjectExt;
-use pyo3::exceptions::{PyTypeError, PyValueError};
+use pyo3::exceptions::{PyAttributeError, PyTypeError, PyValueError};
 use pyo3::prelude::*;
 use pyo3::pybacked::PyBackedStr;
 use pyo3::types::{PyDict, PyList, PyMapping, PyString};
@@ -111,7 +111,7 @@
     }
 
     pub fn simple_py_get_attr<'py>(&self, obj: &Bound<'py, PyAny>) -> 
PyResult<Option<Bound<'py, PyAny>>> {
-        self.get_impl(obj, PyAnyMethods::getattr_opt, |d, loc| 
loc.py_get_attrs(&d))
+        self.get_impl(obj, py_get_attrs, |d, loc| loc.py_get_attrs(&d))
     }
 
     pub fn py_get_attr<'py>(
@@ -366,7 +366,7 @@
             // FIXME: should this instance check be for Mapping instead of 
Dict, and use `mapping_get`?
             Ok(obj.get_item(self).ok())
         } else {
-            obj.getattr_opt(self)
+            py_get_attrs(obj, self)
         }
     }
 }
@@ -454,3 +454,20 @@
         (self as u8 & other as u8) != 0
     }
 }
+
+// TODO replace with `PyAnyMethods::getattr_opt` once 
https://github.com/PyO3/pyo3/pull/5985 is merged:
+fn py_get_attrs<'py, N>(obj: &Bound<'py, PyAny>, attr_name: N) -> 
PyResult<Option<Bound<'py, PyAny>>>
+where
+    N: IntoPyObject<'py, Target = PyString>,
+{
+    match obj.getattr(attr_name) {
+        Ok(attr) => Ok(Some(attr)),
+        Err(err) => {
+            if err.get_type(obj.py()).is_subclass_of::<PyAttributeError>()? {
+                Ok(None)
+            } else {
+                Err(err)
+            }
+        }
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pydantic-2.13.1/pydantic-core/src/validators/model_fields.rs 
new/pydantic-2.13.4/pydantic-core/src/validators/model_fields.rs
--- old/pydantic-2.13.1/pydantic-core/src/validators/model_fields.rs    
2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/src/validators/model_fields.rs    
2026-05-06 10:27:14.000000000 +0200
@@ -629,6 +629,8 @@
         // dict, and try to set defaults for any missing fields
 
         for (field, field_result) in std::iter::zip(&self.fields, 
field_results) {
+            let state = &mut 
state.scoped_set_field_name(Some(field.name.as_py_str().bind(py).clone()));
+
             let field_value = if let Some((field_info, field_json_value)) = 
field_result {
                 match field.validator.validate(py, field_json_value, state) {
                     Ok(value) => {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pydantic-2.13.1/pydantic-core/tests/validators/test_arguments.py 
new/pydantic-2.13.4/pydantic-core/tests/validators/test_arguments.py
--- old/pydantic-2.13.1/pydantic-core/tests/validators/test_arguments.py        
2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/tests/validators/test_arguments.py        
2026-05-06 10:27:14.000000000 +0200
@@ -1,5 +1,4 @@
 import os
-import platform
 import re
 import sys
 from functools import wraps
@@ -1139,9 +1138,6 @@
         )
 
 
[email protected](
-    platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 
11), reason='pypy 3.11 type formatting'
-)
 def test_error_display(pydantic_version):
     v = SchemaValidator(
         core_schema.arguments_schema(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pydantic-2.13.1/pydantic-core/tests/validators/test_definitions_recursive.py
 
new/pydantic-2.13.4/pydantic-core/tests/validators/test_definitions_recursive.py
--- 
old/pydantic-2.13.1/pydantic-core/tests/validators/test_definitions_recursive.py
    2026-04-15 15:55:16.000000000 +0200
+++ 
new/pydantic-2.13.4/pydantic-core/tests/validators/test_definitions_recursive.py
    2026-05-06 10:27:14.000000000 +0200
@@ -1,6 +1,5 @@
 import datetime
 import platform
-import sys
 from dataclasses import dataclass
 from typing import Optional
 
@@ -753,9 +752,6 @@
     assert v.validate_python(long_input) == long_input
 
 
[email protected](
-    platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 
11), reason='pypy 3.11 type formatting'
-)
 def test_error_inside_definition_wrapper():
     with pytest.raises(SchemaError) as exc_info:
         SchemaValidator(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pydantic-2.13.1/pydantic-core/tests/validators/test_string.py 
new/pydantic-2.13.4/pydantic-core/tests/validators/test_string.py
--- old/pydantic-2.13.1/pydantic-core/tests/validators/test_string.py   
2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/tests/validators/test_string.py   
2026-05-06 10:27:14.000000000 +0200
@@ -348,9 +348,6 @@
 
 
 @pytest.mark.parametrize('mode', (None, 'schema', 'config'))
[email protected](
-    platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 
11), reason='pypy 3.11 type formatting'
-)
 def test_backtracking_regex_rust_unsupported(mode) -> None:
     pattern = r'r(#*)".*?"\1'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/pydantic-2.13.1/pydantic-core/tests/validators/test_union.py 
new/pydantic-2.13.4/pydantic-core/tests/validators/test_union.py
--- old/pydantic-2.13.1/pydantic-core/tests/validators/test_union.py    
2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pydantic-core/tests/validators/test_union.py    
2026-05-06 10:27:14.000000000 +0200
@@ -1,5 +1,3 @@
-import platform
-import sys
 from dataclasses import dataclass
 from datetime import date, time
 from enum import Enum, IntEnum
@@ -233,9 +231,6 @@
     ]
 
 
[email protected](
-    platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 
11), reason='pypy 3.11 type formatting'
-)
 def test_empty_choices():
     msg = r'Error building "union" validator:\s+SchemaError: One or more union 
choices required'
     with pytest.raises(SchemaError, match=msg):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/pyproject.toml 
new/pydantic-2.13.4/pyproject.toml
--- old/pydantic-2.13.1/pyproject.toml  2026-04-15 15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/pyproject.toml  2026-05-06 10:27:14.000000000 +0200
@@ -47,7 +47,7 @@
     'typing-extensions>=4.14.1',
     'annotated-types>=0.6.0',
     # Keep this in sync with the version in the 
`check_pydantic_core_version()` function:
-    'pydantic-core==2.46.1',
+    'pydantic-core==2.46.4',
     'typing-inspection>=0.4.2',
 ]
 dynamic = ['version', 'readme']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/tests/test_json_schema.py 
new/pydantic-2.13.4/tests/test_json_schema.py
--- old/pydantic-2.13.1/tests/test_json_schema.py       2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/tests/test_json_schema.py       2026-05-06 
10:27:14.000000000 +0200
@@ -5391,6 +5391,38 @@
     }
 
 
+def test_root_model_annotated_root_type_parameterized() -> None:
+    """https://github.com/pydantic/pydantic/issues/13123""";
+
+    MyType = Annotated[str, Field(examples=['hello'], description='desc', 
deprecated=True)]
+
+    class MyModel(RootModel[MyType]):
+        pass
+
+    assert MyModel.model_json_schema() == {
+        'deprecated': True,
+        'description': 'desc',
+        'examples': ['hello'],
+        'title': 'MyModel',
+        'type': 'string',
+    }
+
+
+def test_root_model_annotated_root_type() -> None:
+    """https://github.com/pydantic/pydantic/issues/13123""";
+
+    class MyModel(RootModel):
+        root: Annotated[str, Field(examples=['hello'], description='desc', 
deprecated=True)]
+
+    assert MyModel.model_json_schema() == {
+        'deprecated': True,
+        'description': 'desc',
+        'examples': ['hello'],
+        'title': 'MyModel',
+        'type': 'string',
+    }
+
+
 def test_type_adapter_json_schemas_title_description():
     class Model(BaseModel):
         a: str
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/tests/test_main.py 
new/pydantic-2.13.4/tests/test_main.py
--- old/pydantic-2.13.1/tests/test_main.py      2026-04-15 15:55:16.000000000 
+0200
+++ new/pydantic-2.13.4/tests/test_main.py      2026-05-06 10:27:14.000000000 
+0200
@@ -2010,11 +2010,7 @@
 
 
 def test_class_kwargs_custom_config():
-    if platform.python_implementation() == 'PyPy':
-        msg = r"__init_subclass__\(\) got an unexpected keyword argument 
'some_config'"
-    else:
-        msg = r'__init_subclass__\(\) takes no keyword arguments'
-    with pytest.raises(TypeError, match=msg):
+    with pytest.raises(TypeError, match=r'__init_subclass__\(\) takes no 
keyword arguments'):
 
         class Model(BaseModel, some_config='new_value'):
             a: int
@@ -3056,6 +3052,25 @@
     assert res == ModelFromAttributesFalse(x=1)
 
 
+def test_from_attributes_attributeerror_subclass() -> None:
+    """https://github.com/pydantic/pydantic/issues/13092""";
+
+    class SubAttributeError(AttributeError):
+        pass
+
+    class Model(BaseModel, from_attributes=True):
+        field: Union[int, None] = None
+
+    class Obj:
+        @property
+        def child(self):
+            raise SubAttributeError()
+
+    m = Model.model_validate(Obj())
+
+    assert m.field is None
+
+
 @pytest.mark.parametrize(
     'field_type,input_value,expected,raises_match,strict',
     [
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/tests/test_missing_sentinel.py 
new/pydantic-2.13.4/tests/test_missing_sentinel.py
--- old/pydantic-2.13.1/tests/test_missing_sentinel.py  2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/tests/test_missing_sentinel.py  2026-05-06 
10:27:14.000000000 +0200
@@ -2,6 +2,7 @@
 from typing import Annotated, Union
 
 import pytest
+import typing_extensions
 from annotated_types import Ge
 from pydantic_core import MISSING, PydanticSerializationUnexpectedValue
 
@@ -53,7 +54,11 @@
     f: Union[int, MISSING] = MISSING
 
 
[email protected](reason="PEP 661 sentinels aren't picklable yet in the 
experimental typing-extensions implementation")
[email protected](
+    # Unreleased typing-extensions has the final sentinel implementation with 
pickle support:
+    condition=not hasattr(typing_extensions, 'sentinel'),
+    reason="PEP 661 sentinels aren't picklable yet in the experimental 
typing-extensions implementation",
+)
 def test_missing_sentinel_pickle() -> None:
     m = ModelPickle()
     m_reconstructed = pickle.loads(pickle.dumps(m))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/tests/test_pickle.py 
new/pydantic-2.13.4/tests/test_pickle.py
--- old/pydantic-2.13.1/tests/test_pickle.py    2026-04-15 15:55:16.000000000 
+0200
+++ new/pydantic-2.13.4/tests/test_pickle.py    2026-05-06 10:27:14.000000000 
+0200
@@ -6,7 +6,7 @@
 import sys
 from pathlib import Path
 from textwrap import dedent
-from typing import Optional
+from typing import TYPE_CHECKING, Optional
 
 import pytest
 
@@ -15,17 +15,31 @@
 from pydantic._internal._model_construction import _PydanticWeakRef
 from pydantic.config import ConfigDict
 
-try:
+IS_PYPY = sys.implementation.name == 'pypy' and sys.version_info >= (3, 11)
+
+if TYPE_CHECKING:
     import cloudpickle
-except ImportError:
-    cloudpickle = None
+else:
+    if not IS_PYPY:
+        try:
+            import cloudpickle
+        except ImportError:
+            cloudpickle = None
+    else:
+        cloudpickle = None
 
 TEST_DATA_DIR = Path(__file__).parent / 'test_data'
 
-pytestmark = pytest.mark.skipif(cloudpickle is None, reason='cloudpickle is 
not installed')
+pytestmark = pytest.mark.skipif(
+    cloudpickle is None,
+    reason='cloudpickle is not installed, or tests are running with PyPy 
(https://github.com/cloudpipe/cloudpickle/issues/592).',
+)
 
+# Note: this xfail marker was used when cloudpickle was partially compatible 
with PyPy. Since PyPy 7.3.22, it isn't compatible
+# at all (importing it fails), so all tests are skipped as per the module's 
`pytestmark`. We keep the xfail marker if this ever
+# changes:
 cloudpickle_pypy_xfail = pytest.mark.xfail(
-    condition=sys.implementation.name == 'pypy' and sys.version_info >= (3, 
11),
+    condition=IS_PYPY,
     reason='Cloudpickle issue: - possibly 
https://github.com/cloudpipe/cloudpickle/issues/557',
 )
 
@@ -99,7 +113,10 @@
         # Importable model can be pickled with either pickle or cloudpickle.
         (ImportableModel, False),
         (ImportableModel, True),
-        # Locally-defined model can only be pickled with cloudpickle.
+        # Locally-defined model can only be pickle
+        # # Note: this xfail marker was used when cloudpickle was partially 
compatible with PyPy. Since PyPy 7.3.22, it is completelyisn't compatible
+        # # at all (importing it fails), so all tests are skipped as per the 
module's `pytestmark`. We keep the xfail marker if this ever
+        # # changes:d with cloudpickle.
         pytest.param(model_factory(), True, marks=cloudpickle_pypy_xfail),
     ],
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/tests/test_validators.py 
new/pydantic-2.13.4/tests/test_validators.py
--- old/pydantic-2.13.1/tests/test_validators.py        2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/tests/test_validators.py        2026-05-06 
10:27:14.000000000 +0200
@@ -3145,3 +3145,45 @@
     )  # Create a Sub instance without triggering validation (e.g., using 
model_construct)
     # Attempt to create Base with the Sub instance. This line should succeed 
if the bug is fixed, but currently raises ValidationError.
     Base(sub=sub)  # <-- This throws AssertionError because Sub's 'after' 
validator runs again.
+
+
+def test_model_validate_by_json_field_validator_with_validation_info() -> None:
+    """https://github.com/pydantic/pydantic/issues/13074""";
+
+    class Foo(BaseModel):
+        field1: int
+        field2: int
+
+        @field_validator('field2')
+        @classmethod
+        def _validate_field2(cls, v: int, info: ValidationInfo) -> int:
+            assert info.field_name in ('field1', 'field2')
+            assert info.context == 'context'
+
+            return v + info.data['field1']
+
+    f1 = Foo.model_validate({'field1': 1, 'field2': 2}, context='context')
+    f2 = Foo.model_validate_json('{"field1": 1, "field2": 2}', 
context='context')
+
+    assert f1.field1 == f2.field1 == 1
+    assert f1.field2 == f2.field2 == 3
+
+
+def test_model_validate_json_default_value_validator_with_validation_info() -> 
None:
+    """https://github.com/pydantic/pydantic/issues/13074""";
+
+    class Foo(BaseModel, validate_default=True):
+        field: int = 1
+
+        @field_validator('field')
+        @classmethod
+        def _validate_field(cls, v: int, info: ValidationInfo) -> int:
+            assert info.field_name == 'field'
+            assert info.context == 'context'
+
+            return v + 1
+
+    f1 = Foo.model_validate({'field': 1}, context='context')
+    f2 = Foo.model_validate_json('{"field1": 1}', context='context')
+
+    assert f1.field == f2.field == 2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pydantic-2.13.1/tests/types/test_model.py 
new/pydantic-2.13.4/tests/types/test_model.py
--- old/pydantic-2.13.1/tests/types/test_model.py       2026-04-15 
15:55:16.000000000 +0200
+++ new/pydantic-2.13.4/tests/types/test_model.py       2026-05-06 
10:27:14.000000000 +0200
@@ -7,8 +7,6 @@
     ConfigDict,
     SerializationInfo,
     TypeAdapter,
-    ValidationInfo,
-    field_validator,
     model_serializer,
 )
 
@@ -85,22 +83,3 @@
     else:
         assert serializer.to_python(ModelB(a=123, b='test'), **kwargs) == 
'ModelA'
         assert serializer.to_json(ModelB(a=123, b='test'), **kwargs) == 
b'"ModelA"'
-
-
-def test_model_validate_by_json_with_validation_info_data():
-    """https://github.com/pydantic/pydantic/issues/13074""";
-
-    class Foo(BaseModel):
-        field1: int
-        field2: int
-
-        @field_validator('field2')
-        @classmethod
-        def _validate_field2(cls, v: str, info: ValidationInfo) -> int:
-            return v + info.data['field1']
-
-    f1 = Foo.model_validate({'field1': 1, 'field2': 2})
-    f2 = Foo.model_validate_json('{"field1": 1, "field2": 2}')
-
-    assert f1.field1 == f2.field1 == 1
-    assert f1.field2 == f2.field2 == 3

Reply via email to