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>
79 lines
3.7 KiB
Python
79 lines
3.7 KiB
Python
from interpreter.test_items.test_item import test_run
|
|
from interpreter.test_items.test_result import TestValue
|
|
from interpreter.test_items.test_item_dialog_base import TestItemDialogBase, _is_text_mode, _is_interactive
|
|
from interpreter.utils.constants import TestItemType as cst
|
|
from runtime.tum_except import item_load_context
|
|
import api.testium as tm
|
|
|
|
|
|
class TestItemTestedRefsDialog(TestItemDialogBase):
|
|
def __init__(self, dict_item, parent=None, status_queue=None, filename=""):
|
|
self._name = cst.TYPE_REFERENCE_DLG.item_name
|
|
super().__init__(dict_item, parent, status_queue, filename=filename)
|
|
self._type = cst.TYPE_REFERENCE_DLG
|
|
self.is_container = False
|
|
with item_load_context(self.cmd(), self.name(), self.seqFilename()):
|
|
self._question = self._prms.getParam('question', required=True)
|
|
self._init_values = self._prms.getParamAll('reference', required=False, processed=True)
|
|
self._auto_result = self._prms.getParam('auto_result', required=False, default=None)
|
|
|
|
@test_run
|
|
def execute(self):
|
|
q = self._prms.expanse(self._question)
|
|
init_values = ','.join(self._init_values)
|
|
if _is_text_mode():
|
|
print(f"References: {q}")
|
|
rows = init_values.split(',') if init_values else ['']
|
|
result_rows = []
|
|
for i, row in enumerate(rows):
|
|
parts = (row.split('/') + ['', '', ''])[:3]
|
|
if _is_interactive():
|
|
ref = input(f"Row {i+1} - Reference [{parts[0]}]: ").strip() or parts[0]
|
|
rev = input(f"Row {i+1} - Revision [{parts[1]}]: ").strip() or parts[1]
|
|
serial = input(f"Row {i+1} - Serial [{parts[2]}]: ").strip() or parts[2]
|
|
else:
|
|
ref, rev, serial = parts[0], parts[1], parts[2]
|
|
result_rows.append(f"{ref}/{rev}/{serial}")
|
|
val = ','.join(result_rows)
|
|
if _is_interactive():
|
|
succ = True
|
|
else:
|
|
ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
|
|
if ar is None:
|
|
self.result.set(TestValue.FAILURE, 'Dialog not supported in batch mode')
|
|
return
|
|
succ = ar != 'cancel'
|
|
result = [val, succ]
|
|
else:
|
|
from interpreter.test_items.tested_references_files import tested_refs_dialog
|
|
ar = self._prms.expanse(self._auto_result) if self._auto_result is not None else None
|
|
args = [self.name(), q, init_values] + ([ar] if ar is not None else [])
|
|
result = self._run_dialog_with_result(tested_refs_dialog.main, args)
|
|
if result is None:
|
|
self.result.set(TestValue.FAILURE, "Dialog subprocess exited without returning a result")
|
|
return
|
|
val, succ = result
|
|
|
|
titems = []
|
|
if len(val) > 0:
|
|
i = 0
|
|
for sitem in val.split(','):
|
|
titem = {}
|
|
telems = sitem.split('/')
|
|
titem['reference'] = telems[0]
|
|
titem['revision'] = telems[1]
|
|
titem['serial'] = telems[2]
|
|
print("Identification:\n" + str(titem))
|
|
titems.append(titem)
|
|
self.result.reported = {'reference_{}'.format(i): titem}
|
|
i += 1
|
|
self.result.value = titems
|
|
tm.setgd('tested_items', titems)
|
|
if len(val) > 0:
|
|
if succ:
|
|
self.result.set(TestValue.SUCCESS, val)
|
|
else:
|
|
self.result.set(TestValue.FAILURE, val)
|
|
else:
|
|
self.result.set(TestValue.FAILURE, 'The dialog did not return any value')
|