Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-mashumaro for 
openSUSE:Factory checked in at 2026-02-05 18:00:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-mashumaro (Old)
 and      /work/SRC/openSUSE:Factory/.python-mashumaro.new.1670 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-mashumaro"

Thu Feb  5 18:00:32 2026 rev:7 rq:1331141 version:3.19

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-mashumaro/python-mashumaro.changes        
2026-02-03 21:32:04.906123437 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-mashumaro.new.1670/python-mashumaro.changes  
    2026-02-05 18:05:51.129329167 +0100
@@ -1,0 +2,7 @@
+Wed Feb  4 07:55:29 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- update to 3.19:
+  * Added support for recursive types in JSON Schema (#303)
+  * Added "Trusted Publishing" workflow (#304)
+
+-------------------------------------------------------------------

Old:
----
  mashumaro-3.18.tar.gz

New:
----
  mashumaro-3.19.tar.gz

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

Other differences:
------------------
++++++ python-mashumaro.spec ++++++
--- /var/tmp/diff_new_pack.t8dCYU/_old  2026-02-05 18:05:52.169372795 +0100
+++ /var/tmp/diff_new_pack.t8dCYU/_new  2026-02-05 18:05:52.185373466 +0100
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-mashumaro
-Version:        3.18
+Version:        3.19
 Release:        0
 Summary:        Fast and well tested serialization library
 License:        Apache-2.0

++++++ mashumaro-3.18.tar.gz -> mashumaro-3.19.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mashumaro-3.18/.github/workflows/publish.yml 
new/mashumaro-3.19/.github/workflows/publish.yml
--- old/mashumaro-3.18/.github/workflows/publish.yml    1970-01-01 
01:00:00.000000000 +0100
+++ new/mashumaro-3.19/.github/workflows/publish.yml    2026-02-03 
20:07:21.000000000 +0100
@@ -0,0 +1,38 @@
+name: publish.yml
+on:
+  release:
+    types:
+      - published
+
+jobs:
+  pypi-publish:
+    name: Upload release to PyPI
+    runs-on: ubuntu-latest
+    permissions:
+      contents: read
+      id-token: write
+    environment:
+      name: pypi
+      url: https://pypi.org/project/mashumaro/
+
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v6
+
+      - name: Set up Python 3.14
+        uses: actions/setup-python@v6
+        with:
+          python-version: "3.14"
+
+      - name: Install Poetry
+        run: |
+          curl -sSL https://install.python-poetry.org | python - -y
+
+      - name: Install dependencies
+        run: poetry install --no-interaction --no-root
+
+      - name: Build
+        run: poetry build
+
+      - name: Publish to PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mashumaro-3.18/mashumaro/jsonschema/models.py 
new/mashumaro-3.19/mashumaro/jsonschema/models.py
--- old/mashumaro-3.18/mashumaro/jsonschema/models.py   2026-01-30 
19:30:35.000000000 +0100
+++ new/mashumaro-3.19/mashumaro/jsonschema/models.py   2026-02-03 
20:07:21.000000000 +0100
@@ -210,3 +210,5 @@
     all_refs: Optional[bool] = None
     ref_prefix: Optional[str] = None
     plugins: Sequence[BasePlugin] = ()
+    # PEP 695 TypeAliasType recursion guard
+    _building_type_aliases: set[int] = field(default_factory=set, repr=False)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mashumaro-3.18/mashumaro/jsonschema/schema.py 
new/mashumaro-3.19/mashumaro/jsonschema/schema.py
--- old/mashumaro-3.18/mashumaro/jsonschema/schema.py   2026-01-30 
19:30:35.000000000 +0100
+++ new/mashumaro-3.19/mashumaro/jsonschema/schema.py   2026-02-03 
20:07:21.000000000 +0100
@@ -317,6 +317,15 @@
 register = Registry.register
 
 
+def _type_alias_definition_name(alias_type: Any) -> str:
+    """Return a stable $defs key for PEP 695 TypeAliasType."""
+
+    name = getattr(alias_type, "__name__", None)
+    if isinstance(name, str) and name:
+        return name
+    return clean_id(str(id(alias_type)))
+
+
 BASIC_TYPES = {str, int, float, bool}
 
 
@@ -474,7 +483,36 @@
         if evaluated is not None:
             return get_schema(instance.derive(type=evaluated), ctx)
     elif is_type_alias_type(instance.type):
-        return get_schema(instance.derive(type=instance.type.__value__), ctx)
+        alias_type = instance.type
+        def_name = _type_alias_definition_name(alias_type)
+        alias_id = id(alias_type)
+        ref_prefix = ctx.ref_prefix or ctx.dialect.definitions_root_pointer
+
+        # If we're already building this alias, it's recursion.
+        # In that case, force using $ref/$defs.
+        if alias_id in ctx._building_type_aliases:
+            # The $defs placeholder may not exist yet (mutual recursion).
+            ctx.definitions.setdefault(def_name, EmptyJSONSchema())
+            return JSONSchema(reference=f"{ref_prefix}/{def_name}")
+
+        ctx._building_type_aliases.add(alias_id)
+        try:
+            value_schema = get_schema(
+                instance.derive(type=alias_type.__value__), ctx
+            )
+        finally:
+            ctx._building_type_aliases.discard(alias_id)
+
+        # If the alias is marked as recursive (direct or mutual),
+        # store its definition in $defs and return a $ref.
+        if def_name in ctx.definitions or ctx.all_refs:
+            existing = ctx.definitions.get(def_name)
+            if existing is None or isinstance(existing, EmptyJSONSchema):
+                ctx.definitions[def_name] = value_schema
+            return JSONSchema(reference=f"{ref_prefix}/{def_name}")
+
+        # Non-recursive alias: return the schema directly, without $defs.
+        return value_schema
 
 
 @register
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/mashumaro-3.18/pyproject.toml 
new/mashumaro-3.19/pyproject.toml
--- old/mashumaro-3.18/pyproject.toml   2026-01-30 19:30:35.000000000 +0100
+++ new/mashumaro-3.19/pyproject.toml   2026-02-03 20:07:21.000000000 +0100
@@ -4,7 +4,7 @@
 
 [project]
 name = "mashumaro"
-version = "3.18"
+version = "3.19"
 license = "Apache-2.0"
 description = "Fast and well tested serialization library"
 readme = "README.md"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/mashumaro-3.18/tests/test_jsonschema/test_jsonschema_pep_695.py 
new/mashumaro-3.19/tests/test_jsonschema/test_jsonschema_pep_695.py
--- old/mashumaro-3.18/tests/test_jsonschema/test_jsonschema_pep_695.py 
2026-01-30 19:30:35.000000000 +0100
+++ new/mashumaro-3.19/tests/test_jsonschema/test_jsonschema_pep_695.py 
2026-02-03 20:07:21.000000000 +0100
@@ -1,9 +1,137 @@
-type MyTypeAliasType = int | str
+from mashumaro.core.meta.types.common import clean_id
 from mashumaro.jsonschema import build_json_schema
+from mashumaro.jsonschema.models import Context
+from mashumaro.jsonschema.schema import _type_alias_definition_name
+
+type JSON = int | str | float | bool | None | list[JSON] | dict[str, JSON]
+type X = int | str
+type A = int | list[B]
+type B = str | list[A]
 
 
 def test_type_alias_type_with_jsonschema():
-    schema = build_json_schema(MyTypeAliasType)
+    schema = build_json_schema(X)
     assert schema.to_dict() == {
         "anyOf": [{"type": "integer"}, {"type": "string"}]
     }
+
+
+def test_jsonschema_for_recursive_union() -> None:
+    schema = build_json_schema(JSON)
+    assert schema.to_dict() == {
+        "$ref": "#/$defs/JSON",
+        "$defs": {
+            "JSON": {
+                "anyOf": [
+                    {"type": "integer"},
+                    {"type": "string"},
+                    {"type": "number"},
+                    {"type": "boolean"},
+                    {"type": "null"},
+                    {"type": "array", "items": {"$ref": "#/$defs/JSON"}},
+                    {
+                        "type": "object",
+                        "additionalProperties": {"$ref": "#/$defs/JSON"},
+                        "propertyNames": {"type": "string"},
+                    },
+                ]
+            }
+        },
+    }
+
+
+def test_jsonschema_for_mutual_recursive_type_aliases_without_refs() -> None:
+    schema = build_json_schema(A)
+    assert schema.to_dict() == {
+        "$ref": "#/$defs/A",
+        "$defs": {
+            "A": {
+                "anyOf": [
+                    {"type": "integer"},
+                    {
+                        "type": "array",
+                        "items": {
+                            "anyOf": [
+                                {"type": "string"},
+                                {
+                                    "type": "array",
+                                    "items": {"$ref": "#/$defs/A"},
+                                },
+                            ]
+                        },
+                    },
+                ]
+            }
+        },
+    }
+
+
+def test_jsonschema_for_mutual_recursive_type_aliases_with_refs() -> None:
+    schema = build_json_schema(A, all_refs=True)
+    assert schema.to_dict() == {
+        "$ref": "#/$defs/A",
+        "$defs": {
+            "A": {
+                "anyOf": [
+                    {"type": "integer"},
+                    {"type": "array", "items": {"$ref": "#/$defs/B"}},
+                ]
+            },
+            "B": {
+                "anyOf": [
+                    {"type": "string"},
+                    {"type": "array", "items": {"$ref": "#/$defs/A"}},
+                ]
+            },
+        },
+    }
+
+
+def test_type_alias_non_recursive_inlines_when_all_refs_false() -> None:
+    schema = build_json_schema(X, all_refs=False)
+    assert schema.to_dict() == {
+        "anyOf": [
+            {"type": "integer"},
+            {"type": "string"},
+        ]
+    }
+
+
+def test_type_alias_non_recursive_uses_defs_when_all_refs_true() -> None:
+    schema = build_json_schema(X, all_refs=True)
+    assert schema.to_dict() == {
+        "$ref": "#/$defs/X",
+        "$defs": {
+            "X": {
+                "anyOf": [
+                    {"type": "integer"},
+                    {"type": "string"},
+                ]
+            }
+        },
+    }
+
+
+def test_type_alias_placeholder_not_leaking_into_context_defs() -> None:
+    # Ensure that for non-recursive aliases with all_refs=False we don't leave
+    # unused entries in Context.definitions.
+    ctx = Context()
+    schema = build_json_schema(X, context=ctx, all_refs=False)
+    assert schema.to_dict() == {
+        "anyOf": [
+            {"type": "integer"},
+            {"type": "string"},
+        ]
+    }
+    assert ctx.definitions == {}
+
+
+def test_type_alias_definition_name_falls_back_to_clean_id_when_name_empty() 
-> (
+    None
+):
+    class NamelessAlias:
+        __name__ = ""
+
+    alias = NamelessAlias()
+
+    assert _type_alias_definition_name(alias) == clean_id(str(id(alias)))

Reply via email to