diff --git a/dbzero/dbzero/enum.py b/dbzero/dbzero/enum.py index efd12b62..2a150c06 100644 --- a/dbzero/dbzero/enum.py +++ b/dbzero/dbzero/enum.py @@ -7,10 +7,10 @@ @overload -def enum(cls: str, values: List[str], *, prefix: Optional[str] = None) -> EnumType: ... +def enum(cls: str, values: List[str]) -> EnumType: ... @overload -def enum(*, values: List[str], prefix: Optional[str] = None) -> EnumType: ... +def enum(*, values: List[str]) -> EnumType: ... @overload def enum(cls: type) -> EnumType: ... @@ -30,10 +30,6 @@ def enum(cls: Optional[Union[str, type]] = None, *args: Any, **kwargs: Any) -> E values : list of str A list of unique string names for the enum members. The order of values is preserved. - prefix : str, optional - Scopes the enum definition to a specific data prefix. If None (default), - the enum is defined in the prefix that is active at the time of creation. - This allows for creating data-model-specific enums. Returns ------- diff --git a/src/dbzero/bindings/python/Memo.cpp b/src/dbzero/bindings/python/Memo.cpp index 7e063870..b81c79e9 100644 --- a/src/dbzero/bindings/python/Memo.cpp +++ b/src/dbzero/bindings/python/Memo.cpp @@ -206,7 +206,12 @@ namespace db0::python PY_API_FUNC // destroy associated db0 Object instance memo_obj->destroy(); - Py_TYPE(memo_obj)->tp_free((PyObject*)memo_obj); + if (Py_IsInitialized()) + { + // Skip deallocation during/after Python finalization + // Python Garbage Collector might be finalized (i.e. destroyed) at this point + Py_TYPE(memo_obj)->tp_free((PyObject*)memo_obj); + } } template diff --git a/src/dbzero/bindings/python/PyToolkit.cpp b/src/dbzero/bindings/python/PyToolkit.cpp index f24a9966..c25db036 100644 --- a/src/dbzero/bindings/python/PyToolkit.cpp +++ b/src/dbzero/bindings/python/PyToolkit.cpp @@ -740,6 +740,12 @@ namespace db0::python return {}; } + if (!Py_IsInitialized()) { + // Simply return the lock after python instance was finalized + // This is safe because fixture threads should be stopped at this point + return SafeRLock(m_api_mutex); + } + // unlock GIL while waiting for the API mutex PyThreadState *__save = PyEval_SaveThread(); auto result = SafeRLock(m_api_mutex); diff --git a/src/dbzero/object_model/value/Member.hpp b/src/dbzero/object_model/value/Member.hpp index 1db72582..f865c165 100644 --- a/src/dbzero/object_model/value/Member.hpp +++ b/src/dbzero/object_model/value/Member.hpp @@ -78,7 +78,8 @@ namespace db0::object_model { // create member function pointer using UnloadMemberFunc = typename LangToolkit::ObjectSharedPtr (*)(db0::swine_ptr &, Value, unsigned int, AccessFlags); - static std::vector unload_member_functions; + static auto *unload_member_functions_ptr = new std::vector(); + auto &unload_member_functions = *unload_member_functions_ptr; if (unload_member_functions.empty()) { registerUnloadMemberFunctions(unload_member_functions); } @@ -101,7 +102,8 @@ namespace db0::object_model { // create member function pointer using UnrefMemberFunc = void (*)(db0::swine_ptr &, Value); - static std::vector unref_member_functions; + static auto *unref_member_functions_ptr = new std::vector(); + auto &unref_member_functions = *unref_member_functions_ptr; if (unref_member_functions.empty()) { registerUnrefMemberFunctions(unref_member_functions); } diff --git a/src/dbzero/workspace/FixtureThreads.cpp b/src/dbzero/workspace/FixtureThreads.cpp index 3b2b121a..c5aba1b5 100644 --- a/src/dbzero/workspace/FixtureThreads.cpp +++ b/src/dbzero/workspace/FixtureThreads.cpp @@ -210,7 +210,7 @@ namespace db0 // otherwise it may deadlock on trying to invoke API calls from auto-commit // (e.g. instance destruction triggered by LangCache::clear) auto __api_lock = LangToolkit::lockApi(); - // // NOTE: since this a separate thread, we must acuire the language interpreter's lock (where required) + // NOTE: since this a separate thread, we must acquire the language interpreter's lock (where required) auto lang_lock = LangToolkit::ensureLocked(); auto callbacks = fixture.onAutoCommit(); if (!callbacks.empty()) {