mirror of
https://github.com/microsoft/qlib.git
synced 2026-11-12 14:01:03 +08:00
* security: constrain config-driven code execution * fix: address security test and lint failures * ci: restore dependency and title lint compatibility * ci: handle current MLflow and Windows OSQP changes * ci: use lxml release with cross-platform wheels * fix: defer optional CVXPY solver imports * style: document intentional lazy import * ci: skip broken released OSQP on Windows Python 3.8 * test: make MLflow client timing check robust * ci: retry nondeterministic benchmark smoke test * fix: cap filelock before fork safety regression * fix: use filelock release compatible with multiprocessing * fix(security): restrict operator lookup and validate trusted roots * fix(security): preserve numeric expressions and legacy model imports * fix: preserve TRA initialization and document config migration Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: preserve safe expression syntax and cache semantics Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: use explicit scoped trust for file modules Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: satisfy CI lint without weakening trust checks Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: handle escaped file paths in module refusal errors Match the repr-formatted module path in refusal messages and cover Windows, UNC, quoted, and newline-containing paths on every platform. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix: preserve expression parser error logging Log ExpressionSyntaxError with its field and traceback before re-raising, while preserving custom operator NameError and SyntaxError handling. Add five regression cases covering logging, exception identity, and failed cache entries. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * test: isolate expression logger capture Capture parser logs directly on qlib.data without propagating to parent and root capture handlers. Restore logger state with monkeypatch and retain exact single-record, traceback, and exception-identity assertions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(security): preserve malformed feature boundaries and reject unsupported literals * test(security): cover malformed dollar-prefixed expressions --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Yang Liu <DG-git-dev@users.noreply.github.com>
52 lines
1.6 KiB
Python
52 lines
1.6 KiB
Python
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
from pathlib import Path
|
|
import runpy
|
|
from unittest.mock import Mock, call
|
|
|
|
import pytest
|
|
from ruamel.yaml import YAML
|
|
|
|
import qlib
|
|
|
|
|
|
TRA_DIR = Path(__file__).resolve().parents[1] / "examples" / "benchmarks" / "TRA"
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"config_name",
|
|
[
|
|
"config_alstm.yaml",
|
|
"config_alstm_tra.yaml",
|
|
"config_alstm_tra_init.yaml",
|
|
"config_transformer.yaml",
|
|
"config_transformer_tra.yaml",
|
|
"config_transformer_tra_init.yaml",
|
|
],
|
|
)
|
|
def test_tra_example_forwards_initialization_config(monkeypatch, config_name):
|
|
monkeypatch.chdir(TRA_DIR)
|
|
config_path = Path("configs") / config_name
|
|
with config_path.open() as stream:
|
|
config = YAML(typ="safe", pure=True).load(stream)
|
|
|
|
assert "trusted" not in config["qlib_init"]
|
|
assert "trusted_module_roots" not in config["qlib_init"]
|
|
for component in ("model", "dataset"):
|
|
assert config["task"][component]["trusted"] is True
|
|
|
|
main = runpy.run_path(str(TRA_DIR / "example.py"))["main"]
|
|
initialize = Mock()
|
|
dataset, model = Mock(), Mock()
|
|
factory = Mock(side_effect=[dataset, model])
|
|
monkeypatch.setattr(qlib, "init", initialize)
|
|
monkeypatch.setitem(main.__globals__, "init_instance_by_config", factory)
|
|
|
|
main(seed=42, config_file=str(config_path))
|
|
|
|
initialize.assert_called_once_with(**config["qlib_init"])
|
|
config["task"]["model"]["kwargs"]["seed"] = 42
|
|
assert factory.call_args_list == [call(config["task"]["dataset"]), call(config["task"]["model"])]
|
|
model.fit.assert_called_once_with(dataset)
|