From b3349d9a39be59271d67ed3beeb8fd50c0080e82 Mon Sep 17 00:00:00 2001 From: Louis Mandel Date: Mon, 25 Nov 2024 12:12:58 -0500 Subject: [PATCH 1/2] Fixes in `pdl_dumper` --- src/pdl/pdl_dumper.py | 17 ++++++++++++++++- tests/test_dump.py | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 tests/test_dump.py diff --git a/src/pdl/pdl_dumper.py b/src/pdl/pdl_dumper.py index 4ea5d6f4a..3122268c0 100644 --- a/src/pdl/pdl_dumper.py +++ b/src/pdl/pdl_dumper.py @@ -12,6 +12,7 @@ CallBlock, CodeBlock, ContributeTarget, + ContributeValue, DataBlock, EmptyBlock, ErrorBlock, @@ -82,6 +83,8 @@ def block_to_dict(block: pdl_ast.BlockType, json_compatible: bool) -> DumpedBloc d["kind"] = str(block.kind) if block.description is not None: d["description"] = block.description + if block.role is not None: + d["role"] = block.role if block.spec is not None: d["spec"] = block.spec if block.defs is not None: @@ -205,7 +208,7 @@ def block_to_dict(block: pdl_ast.BlockType, json_compatible: bool) -> DumpedBloc if block.assign is not None: d["def"] = block.assign if set(block.contribute) != {ContributeTarget.RESULT, ContributeTarget.CONTEXT}: - d["contribute"] = block.contribute + d["contribute"] = contribute_to_list(block.contribute) if block.result is not None: if isinstance(block.result, FunctionBlock): d["result"] = "" @@ -266,6 +269,18 @@ def location_to_dict(location: LocationType) -> dict[str, Any]: return {"path": location.path, "file": location.file, "table": location.table} +def contribute_to_list( + contribute: Sequence[ContributeTarget | dict[str, ContributeValue]] +) -> list[str | dict[str, Any]]: + acc: list[str | dict[str, Any]] = [] + for contrib in contribute: + if isinstance(contrib, str): + acc.append(str(contrib)) + elif isinstance(contrib, dict): + acc.append({str(k): v.model_dump() for k, v in contrib.items()}) + return acc + + # def scope_to_dict(scope: ScopeType) -> dict[str, Any]: # d = {} # for x, v in scope.items(): diff --git a/tests/test_dump.py b/tests/test_dump.py new file mode 100644 index 000000000..ef6d243a8 --- /dev/null +++ b/tests/test_dump.py @@ -0,0 +1,35 @@ +import pathlib + +from pdl.pdl_ast_utils import iter_block_children +from pdl.pdl_dumper import dump_yaml, program_to_dict +from pdl.pdl_parser import PDLParseError, parse_file, parse_str +from pdl.pdl_ast import BlockType, IncludeBlock + +def has_include(block: BlockType) -> bool: + if isinstance(block, IncludeBlock): + return True + else: + b = False + def f(x): + nonlocal b + if has_include(x): + b = True + iter_block_children(f,block) + return b + +def test_ast_iterators() -> None: + for yaml_file_name in pathlib.Path(".").glob("**/*.pdl"): + try: + ast1, _ = parse_file(yaml_file_name) + if has_include(ast1.root): + continue + d = program_to_dict(ast1) + s = dump_yaml(d) + ast2, _ = parse_str(s) + json1 = ast1.model_dump_json() + json2 = ast2.model_dump_json() + if str(yaml_file_name) == "examples/talk/7-chatbot-roles.pdl": + pass + assert json1 == json2, yaml_file_name + except PDLParseError: + pass From 03fc8d2cd8de405eba824e92146b009d125f2526 Mon Sep 17 00:00:00 2001 From: Louis Mandel Date: Mon, 25 Nov 2024 12:51:54 -0500 Subject: [PATCH 2/2] Test dumper when running the examples --- tests/test_dump.py | 23 ++++++++++++----------- tests/test_examples_run.py | 5 ++++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/test_dump.py b/tests/test_dump.py index ef6d243a8..65561fea9 100644 --- a/tests/test_dump.py +++ b/tests/test_dump.py @@ -1,21 +1,24 @@ import pathlib +from pdl.pdl_ast import BlockType, IncludeBlock from pdl.pdl_ast_utils import iter_block_children from pdl.pdl_dumper import dump_yaml, program_to_dict from pdl.pdl_parser import PDLParseError, parse_file, parse_str -from pdl.pdl_ast import BlockType, IncludeBlock + def has_include(block: BlockType) -> bool: if isinstance(block, IncludeBlock): return True - else: - b = False - def f(x): - nonlocal b - if has_include(x): - b = True - iter_block_children(f,block) - return b + b = False + + def f(x): + nonlocal b + if has_include(x): + b = True + + iter_block_children(f, block) + return b + def test_ast_iterators() -> None: for yaml_file_name in pathlib.Path(".").glob("**/*.pdl"): @@ -28,8 +31,6 @@ def test_ast_iterators() -> None: ast2, _ = parse_str(s) json1 = ast1.model_dump_json() json2 = ast2.model_dump_json() - if str(yaml_file_name) == "examples/talk/7-chatbot-roles.pdl": - pass assert json1 == json2, yaml_file_name except PDLParseError: pass diff --git a/tests/test_examples_run.py b/tests/test_examples_run.py index 74da81533..89c2d756b 100644 --- a/tests/test_examples_run.py +++ b/tests/test_examples_run.py @@ -8,6 +8,7 @@ from pdl import pdl from pdl.pdl_ast import ScopeType +from pdl.pdl_dumper import block_to_dict from pdl.pdl_interpreter import PDLRuntimeError from pdl.pdl_parser import PDLParseError @@ -169,7 +170,9 @@ def test_valid_programs(capsys: CaptureFixture[str], monkeypatch: MonkeyPatch) - scope = inputs.scope try: random.seed(11) - result = pdl.exec_file(pdl_file_name, scope=scope) + output = pdl.exec_file(pdl_file_name, scope=scope, output="all") + result = output["result"] + block_to_dict(output["trace"], json_compatible=True) result_dir_name = ( pathlib.Path(".") / "tests" / "results" / pdl_file_name.parent )