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>
This commit is contained in:
2026-05-02 09:28:40 +02:00
parent 8bd9b3e9d6
commit 4529da7aee
88 changed files with 230 additions and 139 deletions

View File

@@ -109,9 +109,28 @@ All dialog items (`dialog_image`, `dialog_question`, `dialog_references`, `dialo
| `src/testium/interpreter/test_items/test_item_parallel.py` | `parallel` and `parallel_branch` items |
| `src/testium/interpreter/utils/globdict.py` | Global variable dict |
| `src/testium/interpreter/utils/termlog.py` | Terminal color output |
| `src/lib/stdout_redirect.py` | `StdioRedirect` singleton (`stdio_redir`) |
| `src/lib/string_queue.py` | Thread-safe string buffer used for stdout redirection |
| `src/testium/libs/testium.py` | Public API for test scripts (`tm.*`) |
| `src/testium/runtime/stdout_redirect.py` | `StdioRedirect` singleton (`stdio_redir`) |
| `src/testium/runtime/string_queue.py` | Thread-safe string buffer used for stdout redirection |
| `src/testium/api/testium.py` | Public API for test scripts (`tm.*`) |
| `src/testium/py_func/` | Python subprocess for `py_func` items (sandboxed: imports only `runtime/` and `py_func/`) |
| `src/testium/lua_func/` | Lua subprocess scripts for `lua_func` items |
## Package layout
The whole project is a single Python package under `src/testium/`:
```
src/testium/
├── __init__.py / __main__.py
├── runtime/ internal plumbing (jrpc, stdout_redirect, string_queue, tum_except, api)
├── api/ public SDK exposed to test scripts (`import api.testium as tm`)
├── interpreter/ test execution engine (NOT visible to py_func/lua_func)
├── main_win/ GUI (NOT visible to py_func/lua_func)
├── py_func/ subprocess code for python_func items
└── lua_func/ subprocess scripts for lua_func items (data files)
```
`subproc_path()` and `testium_path()` both return the package directory. The py_func subprocess is launched with cwd=that directory and `python3 py_func`. The contract that `py_func/` and `lua_func/` only depend on `runtime/` (no `interpreter`, `main_win`, `api`, `testium`) is enforced by `test/validation/items/isolation/`.
## GUI icons (main_win)

View File

@@ -1,5 +1,5 @@
import libs.testium as tm
import api.testium as tm
def post_exec():
print('Success !!!!')

View File

@@ -13,7 +13,6 @@ license-files = ["../LICENSE"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Programming Language :: Python",
"License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)",
]
dependencies = [
"setuptools",
@@ -36,7 +35,9 @@ testium = "testium:main"
[tool.setuptools.packages.find]
where=["."]
exclude=["lua_func", "py_func"]
[tool.setuptools.package-data]
"testium.lua_func" = ["*.lua"]
[tool.setuptools.dynamic]
version = {file = ["VERSION"]}

View File

@@ -245,7 +245,7 @@ A {classname}.close() is missing somewhere in your code !'.format(classname=type
if not sys.platform.startswith('win'):
# import SshConsole if pexpect is installed
try:
from libs.console_ssh import SshConsole
from api.console_ssh import SshConsole
except ImportError:
pass

View File

@@ -8,7 +8,7 @@ import os
import pexpect
from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn
from libs.console import Console
from api.console import Console
# Exception classes used by this module.

View File

@@ -3,7 +3,7 @@ import sys
import socket
import traceback
from libs.console import *
from api.console import *
class RawTCPConsole(Console):
TYPE = 'rawtcp'

View File

@@ -16,9 +16,9 @@ import numpy as np
import matplotlib.dates as mdates
from datetime import datetime, timedelta, timezone
import libs.testium as tm
import api.testium as tm
from interpreter.test_items.test_result import TestValue
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
from interpreter.utils.py_func_exec import PyFuncExecEngine
from interpreter.utils.api_srv import api_request
from interpreter.utils.eval import post_evaluate

View File

@@ -10,7 +10,7 @@ import os
ourPath = os.path.dirname(__file__)
sys.path.append(ourPath)
from libs.console import (Console, BytesStore, TIMEOUT_NULL)
from api.console import (Console, BytesStore, TIMEOUT_NULL)
class TermConsole(Console):
TYPE = 'term'

View File

@@ -4,7 +4,7 @@ import sys
import textwrap
from time import monotonic
import interpreter.utils.globdict as globdict
from lib.tum_except import (ETUMSyntaxError)
from runtime.tum_except import (ETUMSyntaxError)
###############################################################################
# Console helper functions
@@ -14,7 +14,7 @@ def add_console(console):
''' Function which adds a ``Console`` class instance to *testium*
:param console: The ``Console`` instance.
:type console: ``libs.console.Console`` or child class instance
:type console: ``api.console.Console`` or child class instance
:return: No returned value
'''
@@ -48,7 +48,7 @@ def console(name):
:param name: The name of the ``Console`` instance.
:type name: str
:return: The ``Console`` or child class object
:rtype: ``libs.console.Console`` or child class instance
:rtype: ``api.console.Console`` or child class instance
"""
cons = None
for c in globdict.gd('console_instances', []):
@@ -65,7 +65,7 @@ def add_plot(plot: object) -> None:
''' Function which adds a ``RuntimePlot`` class instance to *testium*
:param plot: The ``RuntimePlot`` instance.
:type plot: ``libs.runtime_plot.RuntimePlot`` or child class instance
:type plot: ``api.runtime_plot.RuntimePlot`` or child class instance
:return: No returned value
'''
@@ -99,7 +99,7 @@ def plot(name: str) -> object:
:param name: The name of the ``RuntimePlot`` instance.
:type name: str
:return: The ``RuntimePlot`` or child class object
:rtype: ``libs.runtime_plot.RuntimePlot`` or child class instance
:rtype: ``api.runtime_plot.RuntimePlot`` or child class instance
"""
plot = None
for g in globdict.gd('plot_instances', []):

View File

@@ -9,8 +9,8 @@ from multiprocessing import Queue
from interpreter.process import TestProcess
from interpreter.utils.test_ctrl import TestSetController
from lib.tum_except import ETUMFileError, ETUMRuntimeError
from lib.stdout_redirect import stdio_redir
from runtime.tum_except import ETUMFileError, ETUMRuntimeError
from runtime.stdout_redirect import stdio_redir
class Batch:

View File

@@ -6,9 +6,9 @@ from threading import Thread
from time import sleep
import copy
from lib.string_queue import StringQueue
from lib.tum_except import print_exception, ETUMRuntimeError, ETUMSyntaxError
import libs.testium as tm
from runtime.string_queue import StringQueue
from runtime.tum_except import print_exception, ETUMRuntimeError, ETUMSyntaxError
import api.testium as tm
import interpreter.utils.globdict as globdict
from interpreter.utils.params import expanse
from interpreter.utils.test_ctrl import TestSetController
@@ -26,7 +26,7 @@ from interpreter.utils.test_init import (
from interpreter.utils.constants import TestItemType as cst_type
from interpreter.test_set import TestSet
from interpreter.utils.include import TUMLoader, TUMLoaderNoIncludes, TUMLoaderRawIncludes
from lib.stdout_redirect import stdio_redir
from runtime.stdout_redirect import stdio_redir
from interpreter.utils.template import template_to_test
from interpreter.utils.yaml_load import yaml_load
from interpreter.utils.py_eval import eval_process_init

View File

@@ -1,4 +1,4 @@
from lib.tum_except import ETUMSyntaxError
from runtime.tum_except import ETUMSyntaxError
from interpreter.test_items.test_item import TestItem, test_run, test_data
from interpreter.test_items.test_result import TestResult, TestValue
from interpreter.test_items.item_actions.action import TestItemAction

View File

@@ -3,11 +3,11 @@ from time import sleep
import yaml
from copy import deepcopy
from interpreter.test_items.test_result import TestResult, TestValue
import libs.testium as tm
import api.testium as tm
from interpreter.utils.params import TestItemParams
from interpreter.utils.constants import TestItemType as cst_type
from interpreter.utils.eval import eval_to_boolean, evaluate, post_evaluate
from lib.tum_except import ETUMSyntaxError, item_load_context
from runtime.tum_except import ETUMSyntaxError, item_load_context
LOG_TEST_STOP = '<----- step "{}" finished'
LOG_TEST_START = '-----> step "{}" started'

View File

@@ -1,8 +1,8 @@
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import TestValue
from lib.tum_except import ETUMSyntaxError, item_load_context
import libs.testium as tm
from runtime.tum_except import ETUMSyntaxError, item_load_context
import api.testium as tm
from interpreter.utils.constants import TestItemType as cst
from interpreter.utils.eval import evaluate

View File

@@ -2,8 +2,8 @@ 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 lib.tum_except import item_load_context
import libs.testium as tm
from runtime.tum_except import item_load_context
import api.testium as tm
class TestItemChoicesDialog(TestItemDialogBase):

View File

@@ -3,9 +3,9 @@ import os
import importlib
import traceback
import libs.testium as tm
from lib.tum_except import ETUMSyntaxError
from lib.stdout_redirect import stdio_redir
import api.testium as tm
from runtime.tum_except import ETUMSyntaxError
from runtime.stdout_redirect import stdio_redir
from interpreter.test_items.test_item import test_run
from interpreter.test_items.item_actions import TestItemActions
from interpreter.test_items.item_actions.action import TestItemAction
@@ -345,17 +345,17 @@ class TestItemConsole(TestItemActions):
self.actions_token = {}
global console
console = importlib.import_module("libs.console")
console = importlib.import_module("api.console")
if not sys.platform.startswith("win"):
global console_ssh
console_ssh = importlib.import_module("libs.console_ssh")
console_ssh = importlib.import_module("api.console_ssh")
global termconsole
termconsole = importlib.import_module("libs.termconsole")
termconsole = importlib.import_module("api.termconsole")
global raw_tcp_console
raw_tcp_console = importlib.import_module("libs.raw_tcp_console")
raw_tcp_console = importlib.import_module("api.raw_tcp_console")
self.actions_token["console_name"] = self._prms.getParam(
"console_name", required=True

View File

@@ -1,11 +1,11 @@
import traceback
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError
from interpreter.utils.py_func_exec import PyFuncExecEngine
from interpreter.utils.api_srv import api_request
from interpreter.test_items.test_item import TestItem, test_run
from interpreter.test_items.test_result import TestResult, TestValue
import libs.testium as tm
import api.testium as tm
from interpreter.utils.params import TestItemParams
from interpreter.utils.constants import TestItemType as cst

View File

@@ -1,6 +1,6 @@
import multiprocessing
import libs.testium as tm
import api.testium as tm
from interpreter.test_items.test_item import TestItem

View File

@@ -1,7 +1,7 @@
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import (TestValue)
from interpreter.utils.constants import TestItemType as cst
from lib.tum_except import ETUMParamError, ETUMSyntaxError
from runtime.tum_except import ETUMParamError, ETUMSyntaxError
import interpreter.utils.version as git
class TestItemGit(TestItem):

View File

@@ -1,8 +1,8 @@
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import (TestResult, TestValue)
from interpreter.utils.constants import TestItemType as cst
from lib.tum_except import ETUMSyntaxError
import libs.testium as tm
from runtime.tum_except import ETUMSyntaxError
import api.testium as tm
class TestItemGroup(TestItem):
def __init__(self, dict_cycle, parent = None, status_queue=None, filename=""):

View File

@@ -4,8 +4,8 @@ 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 lib.tum_except import item_load_context
import libs.testium as tm
from runtime.tum_except import item_load_context
import api.testium as tm
class TestItemImageDialog(TestItemDialogBase):

View File

@@ -2,7 +2,7 @@ import sys
import traceback
from random import randint
from lib.tum_except import ETUMSyntaxError
from runtime.tum_except import ETUMSyntaxError
from interpreter.test_items.test_item import TestItem, test_run
from interpreter.test_items.test_result import TestResult, TestValue

View File

@@ -3,9 +3,9 @@ import socket
import re
import struct
from lib.tum_except import ETUMRuntimeError
import libs.testium as tm
from libs.console import Console
from runtime.tum_except import ETUMRuntimeError
import api.testium as tm
from api.console import Console
def is_ip_address(address):

View File

@@ -5,8 +5,8 @@ import time
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import (TestResult, TestValue)
from lib.tum_except import ETUMSyntaxError, item_load_context
import libs.testium as tm
from runtime.tum_except import ETUMSyntaxError, item_load_context
import api.testium as tm
from interpreter.utils.constants import TestItemType as cst
class TestItemLet(TestItem):

View File

@@ -4,10 +4,10 @@ import traceback
import pprint
import textwrap
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
from interpreter.test_items.test_item import TestItem, test_run
from interpreter.test_items.test_result import TestValue
import libs.testium as tm
import api.testium as tm
from interpreter.utils.lua_func_exec import LuaFuncExecEngine
from interpreter.utils.api_srv import api_request
from interpreter.utils.constants import TestItemType as cst

View File

@@ -5,7 +5,7 @@ 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 lib.tum_except import item_load_context
from runtime.tum_except import item_load_context
class TestItemMsgDialog(TestItemDialogBase):

View File

@@ -2,8 +2,8 @@ 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 lib.tum_except import item_load_context
import libs.testium as tm
from runtime.tum_except import item_load_context
import api.testium as tm
class TestItemNoteDialog(TestItemDialogBase):

View File

@@ -6,9 +6,9 @@ from interpreter.test_items.test_item import test_run
from interpreter.test_items.test_result import TestResult, TestValue
from interpreter.utils.constants import TestItemType as cst
from interpreter.utils.eval import eval_to_boolean
from lib.tum_except import ETUMSyntaxError
from lib.string_queue import StringQueue
from lib.stdout_redirect import stdio_redir
from runtime.tum_except import ETUMSyntaxError
from runtime.string_queue import StringQueue
from runtime.stdout_redirect import stdio_redir
class TestItemParallelBranch(TestItemContainer):

View File

@@ -4,10 +4,10 @@ import time
import pprint
import textwrap
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
from interpreter.test_items.test_item import TestItem, test_run
from interpreter.test_items.test_result import TestValue
import libs.testium as tm
import api.testium as tm
from interpreter.utils.py_func_exec import PyFuncExecEngine
from interpreter.utils.api_srv import api_request
from interpreter.utils.constants import TestItemType as cst

View File

@@ -2,7 +2,7 @@ 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 lib.tum_except import item_load_context
from runtime.tum_except import item_load_context
class TestItemQuestionDialog(TestItemDialogBase):

View File

@@ -1,7 +1,7 @@
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import (TestValue)
from lib.tum_except import ETUMSyntaxError
from runtime.tum_except import ETUMSyntaxError
from interpreter.utils.constants import TestItemType as cst
from interpreter.test_report.test_report import Export

View File

@@ -8,9 +8,9 @@ import traceback
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import (TestValue)
import libs.testium as tm
import api.testium as tm
from interpreter.utils.constants import TestItemType as cst
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
def nowInBetween(start, end):

View File

@@ -3,8 +3,8 @@ import importlib
import traceback
from functools import wraps
import libs.testium as tm
from lib.tum_except import ETUMSyntaxError, item_load_context
import api.testium as tm
from runtime.tum_except import ETUMSyntaxError, item_load_context
from interpreter.test_items.test_item import TestItem, test_run
from interpreter.test_items.test_result import TestResult, TestValue
from interpreter.test_items.item_actions import TestItemActions
@@ -235,4 +235,4 @@ class TestItemPlot(TestItemActions):
self.actions_token = self._prms.getParam("plot_name", required=True)
global runtime_plot
runtime_plot = importlib.import_module("libs.runtime_plot")
runtime_plot = importlib.import_module("api.runtime_plot")

View File

@@ -3,11 +3,11 @@ from time import sleep
from datetime import timedelta
from multiprocessing import Process, Pipe
import libs.testium as tm
import api.testium as tm
from interpreter.test_items.test_item import (TestItem, test_run)
from interpreter.test_items.test_result import (TestValue)
from interpreter.utils.constants import TestItemType as cst
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError, item_load_context
class TestItemSleep(TestItem):
"""sleep item usage.

View File

@@ -2,8 +2,8 @@ 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 lib.tum_except import item_load_context
import libs.testium as tm
from runtime.tum_except import item_load_context
import api.testium as tm
class TestItemTestedRefsDialog(TestItemDialogBase):

View File

@@ -4,14 +4,14 @@ from unittest import (TestCase, TestSuite, TextTestRunner,
TextTestResult)
from unittest.loader import defaultTestLoader
import libs.testium as tm
from lib.tum_except import (ETUMFileError)
import api.testium as tm
from runtime.tum_except import (ETUMFileError)
from interpreter.utils.modules import load_source
from interpreter.test_items.test_item import (TestItem, test_run, LOG_TEST_STOP, LOG_TEST_START)
from interpreter.test_items.test_result import (TestResult, TestValue)
from interpreter.test_items.test_item import test_data
from interpreter.utils.constants import TestItemType as cst
from lib.stdout_redirect import stdio_redir
from runtime.stdout_redirect import stdio_redir
class UnittestResult(TextTestResult):
"""Test result adapted for unittest test"""

View File

@@ -2,8 +2,8 @@ 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 lib.tum_except import item_load_context
import libs.testium as tm
from runtime.tum_except import item_load_context
import api.testium as tm
class TestItemValueDialog(TestItemDialogBase):

View File

@@ -1,4 +1,4 @@
from lib.tum_except import (ETUMRuntimeError)
from runtime.tum_except import (ETUMRuntimeError)
from datetime import datetime
from enum import Enum

View File

@@ -3,7 +3,7 @@ import os
import interpreter.test_report.test_report as tr
from interpreter.utils.paths import prepare_file_to_save
import interpreter.utils.constants as cst
import libs.testium as tm
import api.testium as tm
class ReportExport:

View File

@@ -1,5 +1,5 @@
from junit_xml import (TestSuite, TestCase)
import libs.testium as tm
import api.testium as tm
from interpreter.test_items.test_result import (TestValue)
import interpreter.test_report.report_export as rpe
import interpreter.test_report.test_report as tr

View File

@@ -4,8 +4,8 @@ from functools import wraps
import sqlite3
from time import (time, sleep)
import traceback
from lib.tum_except import (ETUMRuntimeError, ETUMSyntaxError)
from lib.stdout_redirect import stdio_redir
from runtime.tum_except import (ETUMRuntimeError, ETUMSyntaxError)
from runtime.stdout_redirect import stdio_redir
from interpreter.utils.params import (expanse)
from interpreter.utils.paths import prepare_file_to_save
import interpreter.utils.constants as cst

View File

@@ -2,13 +2,13 @@ import os
import datetime
from queue import Queue
from interpreter.utils.params import expanse
import libs.testium as tm
from lib.tum_except import ETUMSyntaxError
import api.testium as tm
from runtime.tum_except import ETUMSyntaxError
import interpreter.utils.settings as prefs
from interpreter.test_report.test_report import TestReport
from interpreter.utils.py_func_exec import PyFuncExecEngine
from interpreter.utils.api_srv import api_request
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
from interpreter.utils.constants import TestItemType as cst_type
import interpreter.utils.constants as cst
from interpreter.utils.constants import TEST_TYPE_LIST

View File

@@ -1,6 +1,6 @@
from lib.api import SUPPORTED_API
from runtime.api import SUPPORTED_API
import libs.testium as tm
import api.testium as tm
# Fill the api_dict with the function of tm
api_dict = {k: getattr(tm, k) for k in SUPPORTED_API if hasattr(tm, k)}

View File

@@ -1,6 +1,6 @@
import libs.testium as tm
import api.testium as tm
from interpreter.utils.py_eval import eval_exec
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError
def evaluate(val, **replacement_dict):

View File

@@ -1,8 +1,8 @@
import yaml
import os.path
import libs.testium as tm
import api.testium as tm
from interpreter.utils.params import expanse
from lib.tum_except import ETUMFileError
from runtime.tum_except import ETUMFileError
from interpreter.utils.template import template_to_test
from copy import copy
from interpreter.utils.globdict import global_dict

View File

@@ -1,6 +1,6 @@
from interpreter.utils.lua_process import LuaProcessBase
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
from interpreter.test_items.test_result import TestValue

View File

@@ -4,10 +4,10 @@ import shutil
import subprocess
import socket
import libs.testium as tm
from lib.jrpc import JsonRpcClient
import api.testium as tm
from runtime.jrpc import JsonRpcClient
from interpreter.utils.paths import subproc_path
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
from interpreter.utils.paths import sys_app_path_lin, sys_app_path_win
def _lua_version(path: str):

View File

@@ -1,5 +1,5 @@
import interpreter.utils.globdict as globdict
from lib.tum_except import ETUMSyntaxError, ETUMRuntimeError
from runtime.tum_except import ETUMSyntaxError, ETUMRuntimeError
glob_eval_func = None

View File

@@ -5,7 +5,7 @@ from pathlib import Path
import testium
from interpreter.utils.params import expanse
import subprocess
import libs.testium as tm
import api.testium as tm
def testium_path():
@@ -18,12 +18,9 @@ def testium_path():
return str(Path(tp).parent.resolve())
def subproc_path():
if getattr(sys, 'frozen', False):
# Exécuté depuis le .exe
return sys._MEIPASS
tp = inspect.getfile(inspect.getmodule(testium))
return str(Path(tp).parent.parent.resolve())
# py_func and lua_func now live inside the testium package; their cwd
# is the testium package root, same as testium_path().
return testium_path()
def prepare_file_to_save(file_name, file_ext=""):
iname = file_name

View File

@@ -1,6 +1,6 @@
from interpreter.utils.py_process import PyProcessBase
from lib.tum_except import ETUMRuntimeError
import libs.testium as tm
from runtime.tum_except import ETUMRuntimeError
import api.testium as tm
eval_process = None

View File

@@ -1,6 +1,6 @@
from interpreter.utils.py_process import PyProcessBase
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
from interpreter.test_items.test_result import TestValue

View File

@@ -3,10 +3,10 @@ import shutil
import sys
import subprocess
import socket
from lib.jrpc import JsonRpcClient
import libs.testium as tm
from runtime.jrpc import JsonRpcClient
import api.testium as tm
from interpreter.utils.paths import sys_app_path_lin, sys_app_path_win
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
from interpreter.utils.paths import testium_path, subproc_path

View File

@@ -2,7 +2,7 @@ import os
import configparser
import json
import platform
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
SettingsCompany = 'Testium'
SettingsApplication = 'testium'

View File

@@ -4,7 +4,7 @@ from jinja2 import Template
from jinja2.exceptions import TemplateSyntaxError, TemplateError, UndefinedError
from tempfile import TemporaryFile
from interpreter.utils.yaml_load import print_yaml
from lib.tum_except import ETUMSyntaxError
from runtime.tum_except import ETUMSyntaxError
def template_to_test(filename: str, params: list):

View File

@@ -1,6 +1,6 @@
from multiprocessing import Queue
from queue import Empty
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
class TestSetController:

View File

@@ -7,13 +7,13 @@ import yaml
import copy
from interpreter.utils.constants import TestItemType as cst
import libs.testium as tm
import api.testium as tm
import interpreter.utils.globdict as globdict
import interpreter.utils.settings as prefs
from interpreter.utils.paths import testium_path
from interpreter.utils.yaml_load import yaml_load
from interpreter.utils import clear_recursively
from lib.tum_except import ETUMSyntaxError
from runtime.tum_except import ETUMSyntaxError
from interpreter.utils.params import expanse, eval_func_init
from interpreter.utils.eval import evaluate
from interpreter.utils.version import (

View File

@@ -3,7 +3,7 @@ import sys
from importlib import import_module
import interpreter.utils.settings as prefs
import libs.testium as tm
import api.testium as tm
_cached_versions = {}

View File

@@ -1,8 +1,8 @@
from yaml.parser import ParserError
from yaml import load, Loader
from yaml.scanner import ScannerError
from libs.testium import print_debug
from lib.tum_except import ETUMSyntaxError
from api.testium import print_debug
from runtime.tum_except import ETUMSyntaxError
import io

View File

@@ -10,7 +10,7 @@ from interpreter.process import TestProcess
from interpreter.utils.test_ctrl import TestSetController
from main_win.test_controller_service import TestControllerService
import interpreter.utils.settings as prefs
from lib.tum_except import ETUMFileError, ETUMRuntimeError
from runtime.tum_except import ETUMFileError, ETUMRuntimeError
class TestFileManager:

View File

@@ -10,12 +10,12 @@ from PySide6.QtGui import (QFont, QFontInfo)
from time import (time)
from main_win.test_tree_items.common import (TEST_COLS, TEST_COLS_WITH_TIME)
from lib.tum_except import (ETUMFileError, ETUMSyntaxError)
from runtime.tum_except import (ETUMFileError, ETUMSyntaxError)
from main_win.test_controller_service import TestControllerService
from main_win.test_tree_items.test_tree_item import make_tree_item
from interpreter.test_items.test_result import (TestValue)
import libs.testium as tm
import api.testium as tm
import interpreter.utils.settings as prefs
from interpreter.utils.constants import TestItemType as cst
from interpreter.utils.icons import icon_prefix

View File

@@ -5,7 +5,7 @@ from PySide6.QtGui import (QIcon, QPixmap, QBrush, QColor)
from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QTreeWidgetItem)
from interpreter.utils.icons import icon_prefix
from libs.testium import print_warn
from api.testium import print_warn
# Maps item_name (from TestItemType.item_name) to visual config.
# Keys: icon (required), icon_on (optional 2nd state), expanded, unfoldable, no_breakpoint

View File

@@ -30,7 +30,7 @@ from main_win.f1_win.d_f1_win import DialogF1
from main_win.test_tree import QTestTree
from main_win.test_run.thread_output import ThreadTestOutput
from lib.string_queue import StringQueue
from runtime.string_queue import StringQueue
from interpreter.process import TestProcess
from interpreter.utils.test_ctrl import TestSetController
from interpreter.utils.icons import icon_prefix
@@ -38,14 +38,14 @@ from interpreter.utils.icons import icon_prefix
from main_win.test_run.outlog import OutLog
from main_win.test_run.test_run import ThreadTestStatus
import interpreter.utils.settings as prefs
from lib.stdout_redirect import stdio_redir
import libs.testium as tm
from runtime.stdout_redirect import stdio_redir
import api.testium as tm
from interpreter.utils.test_init import (
env_init,
locate_report_file,
)
from interpreter.utils.version import get_testium_version
from lib.tum_except import ETUMFileError, ETUMRuntimeError
from runtime.tum_except import ETUMFileError, ETUMRuntimeError
from main_win.test_controller_service import TestControllerService
from main_win.test_runner import TestRunner, TestState
from main_win.test_file_manager import TestFileManager

View File

@@ -6,7 +6,7 @@ from PySide6.QtGui import QCursor, QDesktopServices, QFont
from main_win.text_log_highlighter import TextLogHighlighter
import libs.testium as tm
import api.testium as tm
class QTextLog(QPlainTextEdit):
def __init__(self, parent):

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
import multiprocessing
from py_func.tm import _init_api, _remote_print
from lib.stdout_redirect import stdio_redir
from runtime.stdout_redirect import stdio_redir
class TcpStdOut:

View File

@@ -5,7 +5,7 @@ from pathlib import Path
import importlib
import traceback
from lib.tum_except import ETUMRuntimeError, ETUMSyntaxError
from runtime.tum_except import ETUMRuntimeError, ETUMSyntaxError
from py_func import tm

View File

@@ -7,8 +7,8 @@ import math
import json
import traceback
from lib.jrpc import JsonRpcSrv
from lib.tum_except import ETUMRuntimeError, print_exception
from runtime.jrpc import JsonRpcSrv
from runtime.tum_except import ETUMRuntimeError, print_exception
import py_func.tm as tm
from py_func.func_call import func_exec

View File

@@ -2,8 +2,8 @@
import json
import sys
from py_func.handle import FuncHandler
from lib.tum_except import ETUMRuntimeError
from lib.api import SUPPORTED_API
from runtime.tum_except import ETUMRuntimeError
from runtime.api import SUPPORTED_API
thismodule = sys.modules[__name__]
_func_call_thread = None

View File

View File

@@ -6,11 +6,11 @@ import itertools
from time import sleep
from typing import Callable, Any
try:
import libs.testium as tm
import api.testium as tm
except:
import py_func.tm as tm
from lib.tum_except import ETUMRuntimeError
from runtime.tum_except import ETUMRuntimeError
"""Lightweight JSON-RPC 2.0 helpers over TCP sockets.

View File

@@ -1,7 +1,7 @@
import sys
import threading
from threading import (Thread, Event)
from lib.string_queue import StringQueue
from runtime.string_queue import StringQueue
from time import (sleep)

View File

@@ -1,4 +1,4 @@
import libs.testium as tm
import api.testium as tm
def RetreiveData(console_name):
print("--------------- retrieving data ---------------")

View File

@@ -1,4 +1,4 @@
import libs.testium as tm
import api.testium as tm
def RetreiveData(console_name):
print("--------------- retrieving data ---------------")

View File

@@ -1,4 +1,4 @@
import libs.testium as libtm
import api.testium as libtm
def check_os(expected_os):

View File

@@ -0,0 +1,65 @@
"""Static check that py_func/ and lua_func/ subprocess code does not depend
on testium internals. The contract is:
py_func/*.py may import: py_func.*, runtime.*, plus stdlib/3rd-party
lua_func/*.lua may require: lua_func/<own files>, plus lua stdlib
Forbidden top-level modules: interpreter, main_win, api, testium.
"""
import ast
import os
import re
FORBIDDEN_PY = {"interpreter", "main_win", "api", "testium"}
FORBIDDEN_LUA = {"interpreter", "main_win", "api", "testium"}
def _collect_py_imports(path):
with open(path, "r", encoding="utf-8") as f:
tree = ast.parse(f.read(), filename=path)
out = set()
for node in ast.walk(tree):
if isinstance(node, ast.Import):
for n in node.names:
out.add(n.name.split(".")[0])
elif isinstance(node, ast.ImportFrom):
if node.level == 0 and node.module:
out.add(node.module.split(".")[0])
return out
def _collect_lua_requires(path):
with open(path, "r", encoding="utf-8") as f:
text = f.read()
return {m.split(".")[0] for m in re.findall(r'require\s*\(?\s*["\']([^"\']+)["\']', text)}
def check_isolation(testium_dir):
failures = []
py_dir = os.path.join(testium_dir, "py_func")
for root, _, files in os.walk(py_dir):
for f in files:
if not f.endswith(".py"):
continue
p = os.path.join(root, f)
leaks = _collect_py_imports(p) & FORBIDDEN_PY
if leaks:
failures.append(f"py_func/{os.path.relpath(p, py_dir)} leaks: {sorted(leaks)}")
lua_dir = os.path.join(testium_dir, "lua_func")
for root, _, files in os.walk(lua_dir):
for f in files:
if not f.endswith(".lua"):
continue
p = os.path.join(root, f)
leaks = _collect_lua_requires(p) & FORBIDDEN_LUA
if leaks:
failures.append(f"lua_func/{os.path.relpath(p, lua_dir)} leaks: {sorted(leaks)}")
if failures:
for line in failures:
print(f" - {line}")
return False
return True

View File

@@ -0,0 +1 @@
no_param: Null

View File

@@ -0,0 +1,8 @@
- py_func:
name: py_func/lua_func do not depend on testium internals
file: $(test_path)$(psep)check_isolation.py
func_name: check_isolation
key: $(test)_PASS
param:
- $(testium_path)
expected_result: True

View File

@@ -1,5 +1,5 @@
import time
import libs.testium as tm
import api.testium as tm
def sleep_func(duration):