From 6e6955fbbfca1dddf21ccfbb6ed4eb08ad95009d Mon Sep 17 00:00:00 2001 From: Vlad Korolev Date: Thu, 31 Jul 2025 23:21:30 -0400 Subject: [PATCH 1/6] Convert test_loaders_pydantic.py to pytest format - Extract loader_test helper function from base class - Convert 4 test methods to standalone functions - Test both YAML and JSON loaders with different models --- .../test_loaders_pydantic.py | 72 +++++++++++++------ 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/tests/test_loaders_dumpers/test_loaders_pydantic.py b/tests/test_loaders_dumpers/test_loaders_pydantic.py index fda5fd9e..2963e559 100644 --- a/tests/test_loaders_dumpers/test_loaders_pydantic.py +++ b/tests/test_loaders_dumpers/test_loaders_pydantic.py @@ -1,29 +1,57 @@ -import unittest +import os +from typing import Union +import pytest +from hbreader import FileInfo +from pydantic import BaseModel + +import tests.environment as test_base +from linkml_runtime.dumpers import yaml_dumper from linkml_runtime.loaders import json_loader, yaml_loader +from linkml_runtime.loaders.loader_root import Loader +from linkml_runtime.utils.yamlutils import YAMLRoot from tests.test_loaders_dumpers.environment import env -from tests.test_loaders_dumpers.loaderdumpertestcase import LoaderDumperTestCase from tests.test_loaders_dumpers.models.books_normalized_pydantic import BookSeries from tests.test_loaders_dumpers.models.kitchen_sink_pydantic import Dataset -class PydanticLoadersUnitTest(LoaderDumperTestCase): - env = env - - def test_yaml_loader_single(self): - """Load obo_sample.yaml, emit obo_sample_yaml.yaml and compare to obo_sample_output.yaml""" - self.loader_test("book_series_lotr.yaml", BookSeries, yaml_loader) - - def test_json_loader(self): - """Load obo_sample.json, emit obo_sample_json.yaml and check the results""" - self.loader_test("book_series_lotr.json", BookSeries, json_loader) - - def test_yaml_loader_kitchen_sink(self): - self.loader_test("kitchen_sink_normalized_inst_01.yaml", Dataset, yaml_loader) - - def test_json_loader_kitchen_sink(self): - self.loader_test("kitchen_sink_normalized_inst_01.json", Dataset, json_loader) - - -if __name__ == "__main__": - unittest.main() +def loader_test(filename: str, model: Union[type[YAMLRoot], type[BaseModel]], loader: Loader) -> None: + """ + Test the various permutations of the supplied loader using the input file 'filename' -- both load and loads + + :param filename: un-pathed file name to load + :param model: model to load the file name into + :param loader: package that contains 'load' and 'loads' operations + """ + metadata = FileInfo() + name, typ = filename.rsplit(".", 1) + expected_yaml = env.expected_path("load", name + "_" + typ + ".yaml") + if issubclass(model, YAMLRoot): + python_obj: YAMLRoot = loader.load(filename, model, metadata=metadata, base_dir=env.indir) + elif issubclass(model, BaseModel): + python_obj: BaseModel = loader.load(filename, model, metadata=metadata, base_dir=env.indir) + else: + raise TypeError(f"Unknown target class: {model}") + env.eval_single_file(expected_yaml, yaml_dumper.dumps(python_obj)) + + # Make sure metadata gets filled out properly + rel_path = os.path.abspath(os.path.join(test_base.env.cwd, "..")) + assert os.path.normpath("tests/test_loaders_dumpers/input") == os.path.normpath( + os.path.relpath(metadata.base_path, rel_path) + ) + assert os.path.normpath(f"tests/test_loaders_dumpers/input/{filename}") == os.path.normpath( + os.path.relpath(metadata.source_file, rel_path) + ) + + +@pytest.mark.parametrize( + "filename,model,loader", + [ + ("book_series_lotr.yaml", BookSeries, yaml_loader), + ("book_series_lotr.json", BookSeries, json_loader), + ("kitchen_sink_normalized_inst_01.yaml", Dataset, yaml_loader), + ("kitchen_sink_normalized_inst_01.json", Dataset, json_loader), + ], +) +def test_loader(filename, model, loader): + loader_test(filename, model, loader) From 758fdfa5aa7e769a186bae5b9c54560e681a202e Mon Sep 17 00:00:00 2001 From: Vlad Korolev Date: Mon, 4 Aug 2025 18:08:02 -0400 Subject: [PATCH 2/6] Inline and simplify loader test --- .../test_loaders_pydantic.py | 53 +++++++------------ 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/tests/test_loaders_dumpers/test_loaders_pydantic.py b/tests/test_loaders_dumpers/test_loaders_pydantic.py index 2963e559..f2c9bb10 100644 --- a/tests/test_loaders_dumpers/test_loaders_pydantic.py +++ b/tests/test_loaders_dumpers/test_loaders_pydantic.py @@ -1,5 +1,4 @@ -import os -from typing import Union +from pathlib import Path import pytest from hbreader import FileInfo @@ -8,42 +7,11 @@ import tests.environment as test_base from linkml_runtime.dumpers import yaml_dumper from linkml_runtime.loaders import json_loader, yaml_loader -from linkml_runtime.loaders.loader_root import Loader -from linkml_runtime.utils.yamlutils import YAMLRoot from tests.test_loaders_dumpers.environment import env from tests.test_loaders_dumpers.models.books_normalized_pydantic import BookSeries from tests.test_loaders_dumpers.models.kitchen_sink_pydantic import Dataset -def loader_test(filename: str, model: Union[type[YAMLRoot], type[BaseModel]], loader: Loader) -> None: - """ - Test the various permutations of the supplied loader using the input file 'filename' -- both load and loads - - :param filename: un-pathed file name to load - :param model: model to load the file name into - :param loader: package that contains 'load' and 'loads' operations - """ - metadata = FileInfo() - name, typ = filename.rsplit(".", 1) - expected_yaml = env.expected_path("load", name + "_" + typ + ".yaml") - if issubclass(model, YAMLRoot): - python_obj: YAMLRoot = loader.load(filename, model, metadata=metadata, base_dir=env.indir) - elif issubclass(model, BaseModel): - python_obj: BaseModel = loader.load(filename, model, metadata=metadata, base_dir=env.indir) - else: - raise TypeError(f"Unknown target class: {model}") - env.eval_single_file(expected_yaml, yaml_dumper.dumps(python_obj)) - - # Make sure metadata gets filled out properly - rel_path = os.path.abspath(os.path.join(test_base.env.cwd, "..")) - assert os.path.normpath("tests/test_loaders_dumpers/input") == os.path.normpath( - os.path.relpath(metadata.base_path, rel_path) - ) - assert os.path.normpath(f"tests/test_loaders_dumpers/input/{filename}") == os.path.normpath( - os.path.relpath(metadata.source_file, rel_path) - ) - - @pytest.mark.parametrize( "filename,model,loader", [ @@ -53,5 +21,20 @@ def loader_test(filename: str, model: Union[type[YAMLRoot], type[BaseModel]], lo ("kitchen_sink_normalized_inst_01.json", Dataset, json_loader), ], ) -def test_loader(filename, model, loader): - loader_test(filename, model, loader) +def test_loader_basemodel(filename, model, loader): + name = Path(filename).stem + type = Path(filename).suffix.lstrip(".") + expected_yaml = env.expected_path("load", f"{name}_{type}.yaml") + + metadata = FileInfo() + + python_obj: BaseModel = loader.load(filename, model, metadata=metadata, base_dir=env.indir) + assert env.eval_single_file(expected_yaml, yaml_dumper.dumps(python_obj)) + + # Make sure metadata gets filled out properly using pathlib + rel_path = Path(test_base.env.cwd).resolve().parent + base_path = Path(metadata.base_path).resolve() + source_file = Path(metadata.source_file).resolve() + + assert Path("tests/test_loaders_dumpers/input") == base_path.relative_to(rel_path) + assert Path(f"tests/test_loaders_dumpers/input/{filename}") == source_file.relative_to(rel_path) From fef0609c905afcddef5aadc91cf9d9116c9cf3a2 Mon Sep 17 00:00:00 2001 From: i alarmed alien Date: Wed, 6 Aug 2025 07:22:18 -0700 Subject: [PATCH 3/6] Temporary insert for debugging purposes --- .../test_loaders_pydantic.py | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/tests/test_loaders_dumpers/test_loaders_pydantic.py b/tests/test_loaders_dumpers/test_loaders_pydantic.py index f2c9bb10..a47a434c 100644 --- a/tests/test_loaders_dumpers/test_loaders_pydantic.py +++ b/tests/test_loaders_dumpers/test_loaders_pydantic.py @@ -11,24 +11,30 @@ from tests.test_loaders_dumpers.models.books_normalized_pydantic import BookSeries from tests.test_loaders_dumpers.models.kitchen_sink_pydantic import Dataset - +@pytest.mark.parametrize("format", list(LOADER.keys())) @pytest.mark.parametrize( - "filename,model,loader", + ("filename", "model"), [ - ("book_series_lotr.yaml", BookSeries, yaml_loader), - ("book_series_lotr.json", BookSeries, json_loader), - ("kitchen_sink_normalized_inst_01.yaml", Dataset, yaml_loader), - ("kitchen_sink_normalized_inst_01.json", Dataset, json_loader), + ("book_series_lotr", BookSeries), + ("kitchen_sink_normalized_inst_01", Dataset), ], ) -def test_loader_basemodel(filename, model, loader): - name = Path(filename).stem - type = Path(filename).suffix.lstrip(".") - expected_yaml = env.expected_path("load", f"{name}_{type}.yaml") - +def test_loader_base_model(filename, model, format): + loader = LOADER[format] + expected_yaml = env.expected_path("load", f"{filename}_{format}.yaml") metadata = FileInfo() - python_obj: BaseModel = loader.load(filename, model, metadata=metadata, base_dir=env.indir) + python_obj: BaseModel = loader.load(f"{filename}.{format}", model, metadata=metadata, base_dir=env.indir) + + # temporary insert for debugging + with open(expected_yaml) as expf: + expected = expf.read() + got = yaml_dumper.dumps(python_obj) + expected_trimmed = expected.replace("\r\n", "\n").strip() + got_trimmed = got.replace("\r\n", "\n").strip() + assert expected_trimmed == got_trimmed + # end insert + assert env.eval_single_file(expected_yaml, yaml_dumper.dumps(python_obj)) # Make sure metadata gets filled out properly using pathlib @@ -37,4 +43,4 @@ def test_loader_basemodel(filename, model, loader): source_file = Path(metadata.source_file).resolve() assert Path("tests/test_loaders_dumpers/input") == base_path.relative_to(rel_path) - assert Path(f"tests/test_loaders_dumpers/input/{filename}") == source_file.relative_to(rel_path) + assert Path(f"tests/test_loaders_dumpers/input/{filename}.{format}") == source_file.relative_to(rel_path) From 3477a204de4abe18b155bce1b3a2bb29abb9347d Mon Sep 17 00:00:00 2001 From: i alarmed alien Date: Wed, 6 Aug 2025 07:26:28 -0700 Subject: [PATCH 4/6] missing expression --- tests/test_loaders_dumpers/test_loaders_pydantic.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test_loaders_dumpers/test_loaders_pydantic.py b/tests/test_loaders_dumpers/test_loaders_pydantic.py index a47a434c..3cd86848 100644 --- a/tests/test_loaders_dumpers/test_loaders_pydantic.py +++ b/tests/test_loaders_dumpers/test_loaders_pydantic.py @@ -11,6 +11,9 @@ from tests.test_loaders_dumpers.models.books_normalized_pydantic import BookSeries from tests.test_loaders_dumpers.models.kitchen_sink_pydantic import Dataset +LOADER = {"yaml": yaml_loader, "json": json_loader} + + @pytest.mark.parametrize("format", list(LOADER.keys())) @pytest.mark.parametrize( ("filename", "model"), From a183f16de1ed47cd36b915a5c728e0f65ba91a0b Mon Sep 17 00:00:00 2001 From: ialarmedalien Date: Wed, 6 Aug 2025 09:25:35 -0700 Subject: [PATCH 5/6] path debugging --- tests/test_loaders_dumpers/test_loaders_pydantic.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_loaders_dumpers/test_loaders_pydantic.py b/tests/test_loaders_dumpers/test_loaders_pydantic.py index 3cd86848..927daa3a 100644 --- a/tests/test_loaders_dumpers/test_loaders_pydantic.py +++ b/tests/test_loaders_dumpers/test_loaders_pydantic.py @@ -25,6 +25,12 @@ def test_loader_base_model(filename, model, format): loader = LOADER[format] expected_yaml = env.expected_path("load", f"{filename}_{format}.yaml") + exp_yaml_path = Path(expected_yaml) + exp_path = Path(env.outdir) / "load" / f"{filename}_{format}.yaml" + assert exp_path.as_posix() == exp_yaml_path.as_posix() + assert exp_path.exists() + assert exp_yaml_path.exists() + metadata = FileInfo() python_obj: BaseModel = loader.load(f"{filename}.{format}", model, metadata=metadata, base_dir=env.indir) From af32cedaa067b7586739f9faba37d9ee6f4ccce3 Mon Sep 17 00:00:00 2001 From: ialarmedalien Date: Wed, 6 Aug 2025 09:29:39 -0700 Subject: [PATCH 6/6] path debugging --- tests/test_loaders_dumpers/test_loaders_pydantic.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_loaders_dumpers/test_loaders_pydantic.py b/tests/test_loaders_dumpers/test_loaders_pydantic.py index 927daa3a..f5046b59 100644 --- a/tests/test_loaders_dumpers/test_loaders_pydantic.py +++ b/tests/test_loaders_dumpers/test_loaders_pydantic.py @@ -28,6 +28,10 @@ def test_loader_base_model(filename, model, format): exp_yaml_path = Path(expected_yaml) exp_path = Path(env.outdir) / "load" / f"{filename}_{format}.yaml" assert exp_path.as_posix() == exp_yaml_path.as_posix() + + assert Path(env.indir).exists() + assert Path(env.outdir).exists() + assert exp_path.exists() assert exp_yaml_path.exists()