Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/tangle-cli/src/tangle_cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
try:
__version__ = metadata_version("tangle-cli")
except PackageNotFoundError:
__version__ = "0.1.29"
__version__ = "0.1.30"

__all__ = ["TangleDynamicDiscoveryClient", "__version__"]
11 changes: 10 additions & 1 deletion packages/tangle-cli/src/tangle_cli/pipeline_dehydrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ def __init__(
*,
base_url: str | None = None,
client_factory: Callable[[], Any] | None = None,
extract_subgraphs: bool = True,
uri_readers: Mapping[str, UriReader] | None = None,
uri_writers: Mapping[str, UriWriter] | None = None,
) -> None:
Expand All @@ -148,6 +149,7 @@ def __init__(
base_url=base_url or DEFAULT_API_URL,
)
self.remembered_choices = dict(remembered_choices or {})
self.extract_subgraphs = extract_subgraphs
self.output_file = output_file
self.component_extension = component_extension or ".yaml"

Expand Down Expand Up @@ -756,7 +758,14 @@ def dehydrate(self, data: dict[str, Any]) -> dict[str, Any]:
# Every choice that promises a dehydrated document must replace nested
# graph boundaries too; otherwise they keep their inline spec. A nested
# graph has no canonical URL of its own, so URL extracts it to a file.
if default_choice in (DehydrateChoice.AUTO, DehydrateChoice.FILE, DehydrateChoice.URL):
#
# ``extract_subgraphs=False`` keeps every boundary inline and dehydrates
# only the leaf components inside it, in place. It is for callers that
# represent nested graphs themselves (the decompiler turns each into
# Python), so the output is deliberately not a fully dehydrated document.
if not self.extract_subgraphs:
pass
elif default_choice in (DehydrateChoice.AUTO, DehydrateChoice.FILE, DehydrateChoice.URL):
self._extract_subgraphs_to_files(working)
elif default_choice in (DehydrateChoice.DIGEST, DehydrateChoice.NAME):
self._extract_subgraphs_portable(working, default_choice)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "tangle-cli"
version = "0.1.29"
version = "0.1.30"
description = "CLI for Tangle, the open-source ML pipeline orchestration platform"
readme = "README.md"
authors = [
Expand Down
19 changes: 19 additions & 0 deletions tests/test_dehydrator_portable_refs.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,22 @@ def test_errors_still_propagate_outside_the_generated_fallback_contract(

with pytest.raises(ConnectionError):
PipelineHydrator(client=Library(error=ConnectionError("down"))).hydrate_file(pipeline)


@pytest.mark.parametrize("choice", [DehydrateChoice.DIGEST, DehydrateChoice.FILE, DehydrateChoice.AUTO])
def test_extract_subgraphs_false_dehydrates_only_the_leaves_in_place(tmp_path: Path, choice: str) -> None:
"""A caller that represents nested graphs itself keeps every boundary
inline; only the leaf components inside it are dehydrated, in place, with
no subgraph file written."""
document = _pipeline({"spec": INNER}, task="sub")

result = PipelineDehydrator(
{"": choice}, output_file=tmp_path / "out.yaml", client=Library({}), extract_subgraphs=False
).dehydrate(document)

boundary = result["implementation"]["graph"]["tasks"]["sub"]["componentRef"]
assert boundary["spec"]["name"] == "Inner", "the graph boundary stays inline"
leaf = boundary["spec"]["implementation"]["graph"]["tasks"]["leaf"]["componentRef"]
assert "spec" not in leaf and set(leaf) == {"url"}, "the leaf inside it is dehydrated"
assert not (tmp_path / "subgraphs").exists()
assert not [p for p in tmp_path.rglob("*.yaml") if "inner" in p.name.lower()]
2 changes: 1 addition & 1 deletion tests/test_packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def test_tangle_cli_wheel_supports_expert_no_deps_import_path_without_tangle_api
requires_dist = [line for line in metadata.splitlines() if line.startswith("Requires-Dist: ")]
assert not any(name.startswith("tangle_api/") for name in names)
assert "tangle_cli/openapi/openapi.json" not in names
assert "Version: 0.1.29" in metadata
assert "Version: 0.1.30" in metadata
assert "Requires-Dist: tangle-api==0.1.1" in requires_dist
assert not any("extra == 'native'" in line for line in requires_dist)
assert "Provides-Extra: native" in metadata
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading