Fix context subprocess leak and document py_func.tm helpers
- process.py: stop context_id engines in the inner finally block, before restore_gd() wipes _py_func_contexts/_lua_func_contexts from the global dict — engines were previously orphaned after every test run - py_func/tm.py: add user-facing docstrings to gd/setgd/delgd; remove internal JSON-serialization details from the docs - helper_lib.rst: auto-generate global variable helpers from py_func.tm (the actual subprocess API) instead of globdict - conf.py: add src/ to Sphinx sys.path so py_func.tm is importable - py_func_test_item.rst: simplify context sharing section, remove JSON-serializable/non-serializable distinction for end users - Regenerated PDF manual Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -45,12 +45,21 @@ for k in SUPPORTED_API:
|
||||
###############################################################################
|
||||
# gd/setgd/delgd with local-dict fallback for non-serializable values
|
||||
|
||||
def gd(*params):
|
||||
key = params[0] if params else None
|
||||
if key is not None and key in _local_dict:
|
||||
return _local_dict[key]
|
||||
def gd(name, default=None):
|
||||
"""Return a value from the testium global dictionary.
|
||||
|
||||
The value is accessible from any test item and from any ``py_func``
|
||||
subprocess, regardless of the ``context_id`` used.
|
||||
|
||||
:param name: Name of the entry to retrieve.
|
||||
:type name: str
|
||||
:param default: Value returned when the key is absent. Defaults to ``None``.
|
||||
:return: The stored value, or *default* if not found.
|
||||
"""
|
||||
if name is not None and name in _local_dict:
|
||||
return _local_dict[name]
|
||||
if _func_call_thread is not None:
|
||||
res = _func_call_thread.call("gd", params)
|
||||
res = _func_call_thread.call("gd", (name, default))
|
||||
if "result" in res:
|
||||
return res["result"]
|
||||
elif "error" in res:
|
||||
@@ -60,14 +69,25 @@ def gd(*params):
|
||||
raise ETUMRuntimeError("api not initialized")
|
||||
|
||||
|
||||
def setgd(*params):
|
||||
key = params[0] if params else None
|
||||
value = params[1] if len(params) > 1 else None
|
||||
if key is not None and not _is_json_serializable(value):
|
||||
_local_dict[key] = value
|
||||
def setgd(name, value):
|
||||
"""Store a value in the testium global dictionary.
|
||||
|
||||
The stored value is accessible from any subsequent test item and from any
|
||||
``py_func`` subprocess via :func:`gd`.
|
||||
|
||||
When ``context_id`` is used on the ``py_func`` item, any Python object
|
||||
(including those that cannot be transmitted to other processes) can be
|
||||
stored and shared between calls running in the same subprocess.
|
||||
|
||||
:param name: Name of the entry to set.
|
||||
:type name: str
|
||||
:param value: Value to store.
|
||||
"""
|
||||
if name is not None and not _is_json_serializable(value):
|
||||
_local_dict[name] = value
|
||||
return None
|
||||
if _func_call_thread is not None:
|
||||
res = _func_call_thread.call("setgd", params)
|
||||
res = _func_call_thread.call("setgd", (name, value))
|
||||
if "result" in res:
|
||||
return res["result"]
|
||||
elif "error" in res:
|
||||
@@ -77,13 +97,17 @@ def setgd(*params):
|
||||
raise ETUMRuntimeError("api not initialized")
|
||||
|
||||
|
||||
def delgd(*params):
|
||||
key = params[0] if params else None
|
||||
if key is not None and key in _local_dict:
|
||||
del _local_dict[key]
|
||||
def delgd(name):
|
||||
"""Remove an entry from the testium global dictionary.
|
||||
|
||||
:param name: Name of the entry to remove.
|
||||
:type name: str
|
||||
"""
|
||||
if name is not None and name in _local_dict:
|
||||
del _local_dict[name]
|
||||
return None
|
||||
if _func_call_thread is not None:
|
||||
res = _func_call_thread.call("delgd", params)
|
||||
res = _func_call_thread.call("delgd", (name,))
|
||||
if "result" in res:
|
||||
return res["result"]
|
||||
elif "error" in res:
|
||||
|
||||
@@ -265,6 +265,13 @@ Is the python exec path correct ?"""
|
||||
test_set.run_post_exec()
|
||||
finally:
|
||||
self.__exec = False
|
||||
# Stop shared context engines before restore_gd wipes them
|
||||
for engine in tm.gd("_py_func_contexts", {}).values():
|
||||
engine.stop()
|
||||
engine.join()
|
||||
for engine in tm.gd("_lua_func_contexts", {}).values():
|
||||
engine.stop()
|
||||
engine.join()
|
||||
# Sends signal to the GUI
|
||||
self.send_finished()
|
||||
restore_gd(gdict)
|
||||
|
||||
Reference in New Issue
Block a user