From 5adba7fcd52a2e90fba07ce62f7d2e31cc09b184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 31 May 2026 11:22:26 +0200 Subject: [PATCH] perf(load): use libyaml CLoader when available Base the TUM loaders (and the param-file load) on yaml.CLoader when PyYAML is built with libyaml, falling back to the pure-Python Loader otherwise. Same ParserError/ScannerError, same custom !include constructors. YAML parse time ~8x lower; validation suite identical (same verdicts, same 8 expected-fail tracebacks, post-exec SUCCESS). Co-Authored-By: Claude Opus 4.8 --- src/testium/interpreter/utils/include.py | 4 ++-- src/testium/interpreter/utils/test_init.py | 4 ++-- src/testium/interpreter/utils/yaml_load.py | 7 +++++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/testium/interpreter/utils/include.py b/src/testium/interpreter/utils/include.py index 0fd3d3e..19bd0c6 100644 --- a/src/testium/interpreter/utils/include.py +++ b/src/testium/interpreter/utils/include.py @@ -6,10 +6,10 @@ 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 -from interpreter.utils.yaml_load import yaml_load +from interpreter.utils.yaml_load import yaml_load, YAML_BASE_LOADER -class TUMLoaderNoIncludes(yaml.Loader): +class TUMLoaderNoIncludes(YAML_BASE_LOADER): def __init__(self, stream): diff --git a/src/testium/interpreter/utils/test_init.py b/src/testium/interpreter/utils/test_init.py index e8d4d87..8c0d483 100644 --- a/src/testium/interpreter/utils/test_init.py +++ b/src/testium/interpreter/utils/test_init.py @@ -11,7 +11,7 @@ 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.yaml_load import yaml_load, YAML_BASE_LOADER from interpreter.utils import clear_recursively from runtime.tum_except import ETUMSyntaxError from interpreter.utils.params import expanse, eval_func_init @@ -89,7 +89,7 @@ def locate_report_file(rep_file): def yamltodict(param_file, silent=True): # load of the file with open(param_file, "r") as fd: - dp = yaml_load(fd, param_file, yaml.Loader) + dp = yaml_load(fd, param_file, YAML_BASE_LOADER) if dp is None: tm.print_info(f"The YAML file '{param_file}' is empty.") diff --git a/src/testium/interpreter/utils/yaml_load.py b/src/testium/interpreter/utils/yaml_load.py index df6b82f..5f6e477 100644 --- a/src/testium/interpreter/utils/yaml_load.py +++ b/src/testium/interpreter/utils/yaml_load.py @@ -1,3 +1,4 @@ +import yaml from yaml.parser import ParserError from yaml import load, Loader from yaml.scanner import ScannerError @@ -5,6 +6,12 @@ from api.testium import print_debug from runtime.tum_except import ETUMSyntaxError import io +# Use the libyaml-backed loader (much faster parsing) when PyYAML was built +# with it, falling back to the pure-Python loader otherwise. The C loader +# raises the same ParserError/ScannerError and supports the same custom +# constructors (!include) and construct_* helpers the TUM loaders rely on. +YAML_BASE_LOADER = yaml.CLoader if getattr(yaml, "__with_libyaml__", False) else yaml.Loader + def print_yaml(file: io.TextIOWrapper, file_name): """ Prints YAML file if debug mode is activated.