From b364452ba505d028767e7610eb707cc7b712f489 Mon Sep 17 00:00:00 2001 From: mickaelbegon Date: Wed, 22 Jul 2026 09:33:49 -0400 Subject: [PATCH 1/3] Fix example content search paths --- bioptim/examples/__main__.py | 30 +++++++++++++----------------- tests/shard1/test__run_examples.py | 12 ++++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/bioptim/examples/__main__.py b/bioptim/examples/__main__.py index 4edfb5b6f..2219d0528 100644 --- a/bioptim/examples/__main__.py +++ b/bioptim/examples/__main__.py @@ -490,14 +490,14 @@ def applySearchHighlight(self, text): self.setFormat(start, length, style) -def unnestedDict(exDict): - """Converts a dict-of-dicts to a singly nested dict for non-recursive parsing""" +def unnestedDict(exDict, root_dir=""): + """Convert an example tree to a title-to-relative-path dictionary.""" out = {} for kk, vv in exDict.items(): if isinstance(vv, dict): - out.update(unnestedDict(vv)) + out.update(unnestedDict(vv, os.path.join(root_dir, kk))) else: - out[kk] = vv + out[kk] = os.path.join(root_dir, vv) return out @@ -575,19 +575,15 @@ def filterByContent(self, text=None): self.hl.setDocument(self.ui.codeView.document()) text = text.lower() titles = [] - for key, val in examples_.items(): - if isinstance(val, OrderedDict): - root_dir = key - checkDict = unnestedDict(val) - for kk, vv in checkDict.items(): - path = os.getcwd() + "/" + root_dir - filename = os.path.join(path, vv) - contents = self.getExampleContent(filename).lower() - if text in contents: - titles.append(kk) - else: - pass - self.showExamplesByTitle(titles) + for root_dir, examples in examples_.items(): + if not isinstance(examples, dict): + continue + for title, relative_filename in unnestedDict(examples, root_dir).items(): + filename = os.path.join(path, relative_filename) + contents = self.getExampleContent(filename).lower() + if text in contents: + titles.append(title) + self.showExamplesByTitle(titles) def getMatchingTitles(self, text, exDict=None, acceptAll=False): if exDict is None: diff --git a/tests/shard1/test__run_examples.py b/tests/shard1/test__run_examples.py index 6b4a9f917..7b22288ac 100644 --- a/tests/shard1/test__run_examples.py +++ b/tests/shard1/test__run_examples.py @@ -2,9 +2,21 @@ Test for file IO """ +import os from sys import platform +def test_example_paths_are_preserved_when_flattening(): + from bioptim.examples.__main__ import examples_, path, unnestedDict + + example_paths = unnestedDict(examples_["toy_examples/acados"], "toy_examples/acados") + + assert example_paths["Static arm"] == "toy_examples/acados/static_arm.py" + for root_dir, examples in examples_.items(): + for relative_path in unnestedDict(examples, root_dir).values(): + assert os.path.isfile(os.path.join(path, relative_path)) + + def test_run_examples(): if platform == "linux": # AppVeyor and GitHub action cannot work with graphic interface on Linux return From 69400b0169b1a85a733d52ef6b90869e8cf210a2 Mon Sep 17 00:00:00 2001 From: mickaelbegon Date: Wed, 22 Jul 2026 11:50:25 -0400 Subject: [PATCH 2/3] Run example path test headlessly on Linux --- tests/shard1/test__run_examples.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/shard1/test__run_examples.py b/tests/shard1/test__run_examples.py index 7b22288ac..d309762a4 100644 --- a/tests/shard1/test__run_examples.py +++ b/tests/shard1/test__run_examples.py @@ -6,7 +6,10 @@ from sys import platform -def test_example_paths_are_preserved_when_flattening(): +def test_example_paths_are_preserved_when_flattening(monkeypatch): + if platform == "linux": + monkeypatch.setenv("QT_QPA_PLATFORM", "offscreen") + from bioptim.examples.__main__ import examples_, path, unnestedDict example_paths = unnestedDict(examples_["toy_examples/acados"], "toy_examples/acados") From 66ad492c90e6e13479b2cc2d2d625cbfedb66c54 Mon Sep 17 00:00:00 2001 From: mickaelbegon Date: Sun, 26 Jul 2026 16:34:05 -0400 Subject: [PATCH 3/3] Fix cross-platform example search tests --- tests/shard1/test__run_examples.py | 58 +++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/tests/shard1/test__run_examples.py b/tests/shard1/test__run_examples.py index d309762a4..46f206b49 100644 --- a/tests/shard1/test__run_examples.py +++ b/tests/shard1/test__run_examples.py @@ -14,12 +14,68 @@ def test_example_paths_are_preserved_when_flattening(monkeypatch): example_paths = unnestedDict(examples_["toy_examples/acados"], "toy_examples/acados") - assert example_paths["Static arm"] == "toy_examples/acados/static_arm.py" + assert os.path.normpath(example_paths["Static arm"]) == os.path.normpath("toy_examples/acados/static_arm.py") for root_dir, examples in examples_.items(): for relative_path in unnestedDict(examples, root_dir).values(): assert os.path.isfile(os.path.join(path, relative_path)) +def test_filter_by_content_uses_example_package_path(monkeypatch, tmp_path): + if platform == "linux": + monkeypatch.setenv("QT_QPA_PLATFORM", "offscreen") + + import bioptim.examples.__main__ as examples_module + + example_directory = tmp_path / "nested" + example_directory.mkdir() + (example_directory / "matching.py").write_text("the content needle is here") + (example_directory / "other.py").write_text("unrelated content") + + monkeypatch.setattr( + examples_module, + "examples_", + { + "nested": { + "Matching example": "matching.py", + "Other example": "other.py", + }, + "metadata": "ignored", + }, + ) + monkeypatch.setattr(examples_module, "path", str(tmp_path)) + + class Highlighter: + searchText = None + + @staticmethod + def setDocument(_): + pass + + class CodeView: + @staticmethod + def document(): + return None + + class Loader: + hl = Highlighter() + ui = type("Ui", (), {"codeView": CodeView()})() + matching_titles = None + + @staticmethod + def getExampleContent(filename): + with open(filename) as example_file: + return example_file.read() + + def showExamplesByTitle(self, titles): + self.matching_titles = titles + + loader = Loader() + examples_module.ExampleLoader.filterByContent(loader, "NEEDLE") + + assert loader.hl.searchText == "NEEDLE" + assert loader.matching_titles == ["Matching example"] + + def test_run_examples(): if platform == "linux": # AppVeyor and GitHub action cannot work with graphic interface on Linux return