Files
testium/src/testium/interpreter/utils/eval.py
François 4529da7aee Restructure: consolidate everything inside testium/ package
Move src/lib/ → src/testium/runtime/ (internal plumbing)
Move src/testium/libs/ → src/testium/api/ (public SDK for test scripts)
Move src/py_func/ → src/testium/py_func/ (Python subprocess)
Move src/lua_func/ → src/testium/lua_func/ (Lua subprocess data)

The package now ships as a single coherent unit instead of four sibling
top-level packages (testium, lib, py_func, lua_func) — pip install
gives a clean site-packages/testium/ with no namespace pollution; .lua
files travel with the wheel via package_data; the wheel installs
cleanly and `testium -b` runs end-to-end including py_func subprocesses
and entry-point exporter plugins.

Naming:
- runtime/ (internal, no API guarantees) clearer than lib/
- api/ (public SDK consumed as `import api.testium as tm`) clearer than libs/

Imports updated en masse: from lib. → from runtime. and from libs. →
from api., plus the importlib.import_module("libs.*") strings in
test_item_console.py and test_item_runtime_plot.py. Test/example
scripts (helper_lib.py, parallel.py, post_execution.py) and the
fake_exporter test suite migrated too.

paths.py: subproc_path() now returns testium_path() — both point at
the testium package directory since the subprocesses live inside.

pyproject.toml: removed exclude=["lua_func", "py_func"] (no longer
needed), added package-data for testium.lua_func/*.lua, removed the
license classifier (PEP 639 conflict with license expression).

Subprocess isolation contract: py_func/ and lua_func/ may only import
runtime/ and their own modules — never interpreter/, main_win/, api/,
or testium/. Enforced by test/validation/items/isolation/ which runs a
py_func that statically scans subprocess source files for forbidden
imports. The contract holds today; the test prevents future drift.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-02 09:28:40 +02:00

76 lines
2.2 KiB
Python

import api.testium as tm
from interpreter.utils.py_eval import eval_exec
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError
def evaluate(val, **replacement_dict):
v2 = val
evaluated = False
if isinstance(val, str):
for key, replacement in replacement_dict.items():
val = val.replace(f"$({key})", str(replacement))
try:
v2 = eval_exec(val)
except Exception as e:
# eval can crash
if tm.debug_enabled():
s = f"Evaluation of '{val}' failed with message:\n " + str(e)
tm.print_debug(s)
v2 = val
evaluated = val != v2
return evaluated, v2
def eval_to_boolean(c):
if isinstance(c, bool):
condition = c
elif isinstance(c, (str, bytes)):
if c.lower() in [
"true",
"t",
"y",
"yes",
"ok",
]:
condition = True
elif c.lower() in [
"f",
"n",
"nok",
"ko",
"false",
"no",
]:
condition = False
else:
try:
cond = eval_exec(c)
condition = eval_to_boolean(cond)
except Exception as e:
print("eval with c: {}".format(c))
raise e
elif type(c) is int:
condition = c > 0
else:
raise ETUMSyntaxError("c : {} not string, int or bool".format(c))
return condition
def post_evaluate(post_eval, res):
"""This function is evaluating the result of a test,
therefore it may include a $(result) parameter.
"""
if (not post_eval is None) and (post_eval != ""):
if (not isinstance(post_eval, str)) or (not ("$(result)" in post_eval)):
raise ETUMRuntimeError(
f"'eval' ({post_eval}) must be a string and have the '$(result)' substitution keyword."
)
is_evaluated, res = evaluate(post_eval, result=res)
if not is_evaluated:
raise ETUMRuntimeError(
f"Function result evaluation fails: '{post_eval}' syntax error."
)
return res