From c7c15098e6a280ef616a31ce767a76191253ff2e Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 16 Jul 2026 12:22:56 +0200 Subject: [PATCH 1/2] crash fix --- python_tests/test_tag_fields.py | 73 ++++++++++++++++++++ src/dbzero/bindings/python/PyInternalAPI.cpp | 2 +- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/python_tests/test_tag_fields.py b/python_tests/test_tag_fields.py index f259d8b7..250a2616 100755 --- a/python_tests/test_tag_fields.py +++ b/python_tests/test_tag_fields.py @@ -1,6 +1,11 @@ # SPDX-License-Identifier: LGPL-2.1-or-later # Copyright (c) 2025 DBZero Software sp. z o.o. +import os +import subprocess +import sys +import textwrap + import pytest import dbzero as db0 from dataclasses import dataclass @@ -173,6 +178,74 @@ def test_dataclass_enum_default_is_valid_initial_tag(db0_fixture): assert list(db0.find(DataclassEnumDefaultTag, TagFieldDataclassDefaultStatus.lead)) == [obj] +@pytest.mark.parametrize( + "manual_tag_operation", + [ + "db0.tags(self).add(db0.as_tag(self.agent))", + 'db0.tags(self).add("TAG_X")', + ], +) +def test_manual_tag_during_dataclass_tag_field_post_init_does_not_crash(tmp_path, manual_tag_operation): + script = textwrap.dedent( + f""" + from dataclasses import dataclass + import os + + import dbzero as db0 + + @db0.memo + class Agent: + def __init__(self, role): + self.role = role + + @db0.memo + @db0.tag_fields("agent") + @dataclass + class JobDef: + agent: Agent + + def __post_init__(self): + {manual_tag_operation} + + db_path = {str(tmp_path / "db0")!r} + os.mkdir(db_path) + db0.init(db_path, read_write=True) + db0.open("test", "rw") + + agent = Agent("test-agent") + job_def = JobDef(agent=agent) + assert job_def.agent.role == "test-agent" + db0.close() + """ + ) + + env = os.environ.copy() + env["PYTHONDONTWRITEBYTECODE"] = "1" + env["PYTHONFAULTHANDLER"] = "1" + try: + result = subprocess.run( + [sys.executable, "-c", script], + check=False, + env=env, + text=True, + capture_output=True, + timeout=10, + ) + except subprocess.TimeoutExpired as exc: + pytest.fail( + f"manual tag during tag_fields post-init timed out for {manual_tag_operation!r}\n" + f"stdout:\n{exc.stdout or ''}\n" + f"stderr:\n{exc.stderr or ''}" + ) + + assert result.returncode == 0, ( + f"manual tag during tag_fields post-init failed for {manual_tag_operation!r} " + f"with code {result.returncode}\n" + f"stdout:\n{result.stdout}\n" + f"stderr:\n{result.stderr}" + ) + + def test_initial_tags_use_final_values_and_flush_together(db0_fixture): @db0.memo @db0.tag_fields("status", "owner") diff --git a/src/dbzero/bindings/python/PyInternalAPI.cpp b/src/dbzero/bindings/python/PyInternalAPI.cpp index dd0bd161..48169da8 100755 --- a/src/dbzero/bindings/python/PyInternalAPI.cpp +++ b/src/dbzero/bindings/python/PyInternalAPI.cpp @@ -969,7 +969,7 @@ namespace db0::python db0::FixtureLock lock(memo_obj->ext().getFixture()); // materialize by calling postInit - memo_obj->modifyExt().postInit(lock); + memo_obj->modifyExt().postInit(lock, reinterpret_cast(memo_obj)); if (!memo_obj->ext().getType().isNoCache()) { memo_obj->ext().getFixture()->getLangCache().add(memo_obj->ext().getAddress(), memo_obj); } From d403581732bbe5c68e649f9f3949cff74f0048ea Mon Sep 17 00:00:00 2001 From: Wojtek Date: Thu, 16 Jul 2026 12:25:11 +0200 Subject: [PATCH 2/2] version update --- dbzero/setup.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dbzero/setup.py b/dbzero/setup.py index a36a94d3..e609ad91 100755 --- a/dbzero/setup.py +++ b/dbzero/setup.py @@ -10,7 +10,7 @@ setup( name='dbzero', - version='0.5.1', + version='0.5.2', description='DBZero community edition', packages=['dbzero'], python_requires='>=3.9', diff --git a/pyproject.toml b/pyproject.toml index b1a4fa20..f440af47 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ requires = ['meson-python'] [project] name = 'dbzero' -version = '0.5.1' +version = '0.5.2' description = 'A state management system for Python 3.x that unifies your applications business logic, data persistence, and caching into a single, efficient layer.' readme = 'README.md' requires-python = '>=3.9'