tangle-cli 0.1.5__tar.gz → 0.1.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/PKG-INFO +1 -1
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/__init__.py +1 -1
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_compiler.py +61 -2
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipelines.py +2 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipelines_cli.py +24 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/compiler_context.py +1 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/ref.py +1 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/task.py +11 -1
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/pyproject.toml +1 -1
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/README.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/api_cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/api_schema.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/api_transport.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/args_container.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/artifacts.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/artifacts_cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/cli_helpers.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/cli_options.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/client.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_from_func.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_generator.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_inspector.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_publisher.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/components_cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/dynamic_discovery_client.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/generated_model_extensions.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/handler.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/hydration_trust.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/logger.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/models.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/module_bundler.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/openapi/__init__.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/openapi/codegen.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/openapi/parser.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_dehydrator.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_hydrator.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_annotations.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_details.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_manager.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_search.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_runner.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_runs_cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_spec_utils.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_validation.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/published_components_cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/py.typed +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/__init__.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/cfg.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/dynamic_data.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/emit.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/errors.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/graph.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/ids.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/pipeline.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/placeholders.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/raw.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/registered.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/subpipeline.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/task_env.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/trace.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/types.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/quickstart.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/schema_validation.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/schemas/__init__.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/schemas/dehydrated_pipeline_schema.json +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/schemas/pipeline_schema.json +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/secrets.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/secrets_cli.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/utils.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/version_manager.py +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/OSS-CONVENTIONS.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/PORT-README.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/SKILL.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/auth-wizard.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/builder.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/debugger.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/reporter.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/researcher.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/reviewer.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/agents/scenario-builder.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/data-sources.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/event-log.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/example-scenarios/01-mslr-ranking.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/example-scenarios/02-text-classification.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/example-scenarios/INDEX.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/iterating-on-runs.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/knowledge-corpus.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/secrets.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/setup.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-0-initialize.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-1-analyze.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-2-hypothesize.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-3-submit.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-4-monitor.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-5-evaluate.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-6-synthesize.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/step-7-decide.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/tangle-tools.md +0 -0
- {tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/uploading-artifacts.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: tangle-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: CLI for Tangle, the open-source ML pipeline orchestration platform
|
|
5
5
|
Author: Alexey Volkov, Tangle authors, Volv Grebennikov
|
|
6
6
|
Author-email: Alexey Volkov <alexey.volkov@ark-kun.com>, Volv Grebennikov <volv.grebennikov@shopify.com>
|
|
@@ -14,6 +14,6 @@ from tangle_cli.dynamic_discovery_client import TangleDynamicDiscoveryClient
|
|
|
14
14
|
try:
|
|
15
15
|
__version__ = metadata_version("tangle-cli")
|
|
16
16
|
except PackageNotFoundError:
|
|
17
|
-
__version__ = "0.1.
|
|
17
|
+
__version__ = "0.1.6"
|
|
18
18
|
|
|
19
19
|
__all__ = ["TangleDynamicDiscoveryClient", "__version__"]
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_compiler.py
RENAMED
|
@@ -72,6 +72,40 @@ from .schema_validation import SchemaValidationError, validate_dehydrated_pipeli
|
|
|
72
72
|
from .utils import dump_yaml
|
|
73
73
|
|
|
74
74
|
|
|
75
|
+
IMAGE_IDS: dict[str, str] = {}
|
|
76
|
+
"""Logical image-id registry used by ``@task(image_id=...)``.
|
|
77
|
+
|
|
78
|
+
OSS ships this empty. Downstream distributions may register environment-specific
|
|
79
|
+
image defaults without hard-coding their image literals into the open-source
|
|
80
|
+
package; CLI ``--image ID=REF`` overrides still win over registered defaults.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def register_image_id(image_id: str, image: str) -> None:
|
|
85
|
+
"""Register a default image reference for ``@task(image_id=...)``."""
|
|
86
|
+
if not image_id:
|
|
87
|
+
raise ValueError("image_id must be a non-empty string")
|
|
88
|
+
if not image:
|
|
89
|
+
raise ValueError("image must be a non-empty string")
|
|
90
|
+
IMAGE_IDS[image_id] = image
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def get_image_id(image_id: str) -> str | None:
|
|
94
|
+
"""Return the registered default image for ``image_id``, if any."""
|
|
95
|
+
return IMAGE_IDS.get(image_id)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def resolve_image_id(
|
|
99
|
+
image_id: str,
|
|
100
|
+
image_overrides: Mapping[str, str] | None = None,
|
|
101
|
+
) -> str | None:
|
|
102
|
+
"""Resolve ``image_id`` using compile-time overrides, then registered defaults."""
|
|
103
|
+
overrides = image_overrides or {}
|
|
104
|
+
if image_id in overrides:
|
|
105
|
+
return overrides[image_id]
|
|
106
|
+
return get_image_id(image_id)
|
|
107
|
+
|
|
108
|
+
|
|
75
109
|
@dataclass
|
|
76
110
|
class CompileResult:
|
|
77
111
|
"""Outcome of a :func:`compile_pipeline` call.
|
|
@@ -102,6 +136,7 @@ def compile_pipeline(
|
|
|
102
136
|
*,
|
|
103
137
|
pipeline_name: str | None = None,
|
|
104
138
|
emit_components_sidecar: bool = True,
|
|
139
|
+
image_overrides: Mapping[str, str] | None = None,
|
|
105
140
|
) -> CompileResult:
|
|
106
141
|
"""Compile ``script`` to a single pipeline YAML at ``output``.
|
|
107
142
|
|
|
@@ -132,6 +167,9 @@ def compile_pipeline(
|
|
|
132
167
|
compilation fails with a :class:`CompileError` (a valid
|
|
133
168
|
dehydrated pipeline cannot be produced without the sidecar).
|
|
134
169
|
Pipelines that use only ``ref(url=...)`` are unaffected.
|
|
170
|
+
image_overrides: Compile-time image-id overrides from ``--image
|
|
171
|
+
ID=REF``. They apply only to ``@task(image_id=...)`` refs that do
|
|
172
|
+
not also set an explicit ``image=``.
|
|
135
173
|
|
|
136
174
|
Returns:
|
|
137
175
|
A :class:`CompileResult`. ``components_path`` is the sidecar path
|
|
@@ -143,6 +181,7 @@ def compile_pipeline(
|
|
|
143
181
|
unreachable ``@task`` source/dependency files).
|
|
144
182
|
"""
|
|
145
183
|
overrides = dict(overrides or {})
|
|
184
|
+
image_overrides = dict(image_overrides or {})
|
|
146
185
|
|
|
147
186
|
# 1. Validate the script path.
|
|
148
187
|
script_path = Path(script).resolve()
|
|
@@ -197,6 +236,7 @@ def compile_pipeline(
|
|
|
197
236
|
root_overrides=overrides,
|
|
198
237
|
emit_components_sidecar=emit_components_sidecar,
|
|
199
238
|
source_dirs=purge_dirs,
|
|
239
|
+
image_overrides=image_overrides,
|
|
200
240
|
)
|
|
201
241
|
|
|
202
242
|
# 5. Compile the root (and, recursively, all children) into in-memory
|
|
@@ -436,7 +476,11 @@ def _compile_pipeline_fn(
|
|
|
436
476
|
)
|
|
437
477
|
if task_refs:
|
|
438
478
|
components_path = output_path.with_name(output_path.stem + ".components.yaml")
|
|
439
|
-
components_entries = _build_local_from_python_components(
|
|
479
|
+
components_entries = _build_local_from_python_components(
|
|
480
|
+
task_refs,
|
|
481
|
+
components_yaml_dir=components_path.parent,
|
|
482
|
+
image_overrides=ctx.image_overrides,
|
|
483
|
+
)
|
|
440
484
|
_rewrite_task_componentref_urls(
|
|
441
485
|
body_dict=body_dict,
|
|
442
486
|
task_refs=task_refs,
|
|
@@ -1427,7 +1471,10 @@ def _relocate_relative_local_url(url: str, source_dir: Path, sidecar_dir: Path)
|
|
|
1427
1471
|
|
|
1428
1472
|
|
|
1429
1473
|
def _build_local_from_python_components(
|
|
1430
|
-
task_refs: list[tuple[str, CallableRef]],
|
|
1474
|
+
task_refs: list[tuple[str, CallableRef]],
|
|
1475
|
+
*,
|
|
1476
|
+
components_yaml_dir: Path,
|
|
1477
|
+
image_overrides: Mapping[str, str] | None = None,
|
|
1431
1478
|
) -> dict[str, Any]:
|
|
1432
1479
|
"""Build the ``<stem>.components.yaml`` content for @task refs.
|
|
1433
1480
|
|
|
@@ -1492,6 +1539,16 @@ def _build_local_from_python_components(
|
|
|
1492
1539
|
local_from_python: dict[str, Any] = {}
|
|
1493
1540
|
if ref._task_image is not None:
|
|
1494
1541
|
local_from_python["image"] = ref._task_image
|
|
1542
|
+
elif ref._task_image_id is not None:
|
|
1543
|
+
resolved_image = resolve_image_id(ref._task_image_id, image_overrides)
|
|
1544
|
+
if resolved_image is None:
|
|
1545
|
+
raise CompileError(
|
|
1546
|
+
f"@task image_id={ref._task_image_id!r} on function "
|
|
1547
|
+
f"{ref._task_function_name!r} did not resolve to an image. "
|
|
1548
|
+
f"Pass --image {ref._task_image_id}=IMAGE to `tangle sdk pipelines compile`, "
|
|
1549
|
+
f"or register a default with register_image_id({ref._task_image_id!r}, IMAGE)."
|
|
1550
|
+
)
|
|
1551
|
+
local_from_python["image"] = resolved_image
|
|
1495
1552
|
# Always pin the function name. Without it the hydrator defaults
|
|
1496
1553
|
# to the file stem and extracts the wrong symbol.
|
|
1497
1554
|
assert ref._task_function_name is not None
|
|
@@ -2233,6 +2290,7 @@ class PipelineCompiler(TangleCliHandler):
|
|
|
2233
2290
|
overrides: Mapping[str, str] | None = None,
|
|
2234
2291
|
pipeline_name: str | None = None,
|
|
2235
2292
|
emit_components_sidecar: bool = True,
|
|
2293
|
+
image_overrides: Mapping[str, str] | None = None,
|
|
2236
2294
|
) -> CompileResult:
|
|
2237
2295
|
"""Compile ``script`` to a single dehydrated pipeline YAML at ``output``.
|
|
2238
2296
|
|
|
@@ -2251,6 +2309,7 @@ class PipelineCompiler(TangleCliHandler):
|
|
|
2251
2309
|
overrides,
|
|
2252
2310
|
pipeline_name=pipeline_name,
|
|
2253
2311
|
emit_components_sidecar=emit_components_sidecar,
|
|
2312
|
+
image_overrides=image_overrides,
|
|
2254
2313
|
)
|
|
2255
2314
|
self.log.info(f"wrote {result.pipeline_path}")
|
|
2256
2315
|
if result.components_path is not None:
|
|
@@ -258,6 +258,7 @@ def compile_pipeline_file(
|
|
|
258
258
|
overrides: Mapping[str, str] | None = None,
|
|
259
259
|
pipeline_name: str | None = None,
|
|
260
260
|
emit_components_sidecar: bool = True,
|
|
261
|
+
image_overrides: Mapping[str, str] | None = None,
|
|
261
262
|
logger: Any | None = None,
|
|
262
263
|
) -> CompileResult:
|
|
263
264
|
"""Compile a Python-authored pipeline to a dehydrated YAML bundle.
|
|
@@ -284,6 +285,7 @@ def compile_pipeline_file(
|
|
|
284
285
|
overrides=dict(overrides) if overrides else None,
|
|
285
286
|
pipeline_name=pipeline_name,
|
|
286
287
|
emit_components_sidecar=emit_components_sidecar,
|
|
288
|
+
image_overrides=dict(image_overrides) if image_overrides else None,
|
|
287
289
|
)
|
|
288
290
|
except (CompileError, SchemaValidationError) as exc:
|
|
289
291
|
raise PipelineValidationError(str(exc)) from exc
|
|
@@ -138,6 +138,18 @@ def _parse_overrides(values: list[str] | None) -> dict[str, str]:
|
|
|
138
138
|
return parsed
|
|
139
139
|
|
|
140
140
|
|
|
141
|
+
def _parse_image_overrides(values: list[str] | None) -> dict[str, str]:
|
|
142
|
+
parsed: dict[str, str] = {}
|
|
143
|
+
for value in values or []:
|
|
144
|
+
if "=" not in value:
|
|
145
|
+
raise SystemExit("--image entries must use ID=REF syntax")
|
|
146
|
+
image_id, image_ref = value.split("=", 1)
|
|
147
|
+
if not image_id or not image_ref:
|
|
148
|
+
raise SystemExit("--image entries must use ID=REF syntax")
|
|
149
|
+
parsed[image_id] = image_ref
|
|
150
|
+
return parsed
|
|
151
|
+
|
|
152
|
+
|
|
141
153
|
@app.command(name="hydrate")
|
|
142
154
|
def pipelines_hydrate(
|
|
143
155
|
pipeline_path: pathlib.Path,
|
|
@@ -266,6 +278,17 @@ def pipelines_compile(
|
|
|
266
278
|
negative_iterable=(),
|
|
267
279
|
),
|
|
268
280
|
] = None,
|
|
281
|
+
image: Annotated[
|
|
282
|
+
list[str] | None,
|
|
283
|
+
Parameter(
|
|
284
|
+
name="--image",
|
|
285
|
+
help=(
|
|
286
|
+
"Compile-time image-id override as ID=REF for @task(image_id=ID). "
|
|
287
|
+
"Repeat for multiple IDs."
|
|
288
|
+
),
|
|
289
|
+
negative_iterable=(),
|
|
290
|
+
),
|
|
291
|
+
] = None,
|
|
269
292
|
log_type: LogTypeOption = "console",
|
|
270
293
|
) -> None:
|
|
271
294
|
"""Compile a Python-authored pipeline to a dehydrated YAML bundle."""
|
|
@@ -276,6 +299,7 @@ def pipelines_compile(
|
|
|
276
299
|
pipeline_path,
|
|
277
300
|
output,
|
|
278
301
|
overrides=_parse_overrides(override),
|
|
302
|
+
image_overrides=_parse_image_overrides(image),
|
|
279
303
|
pipeline_name=pipeline,
|
|
280
304
|
logger=logger,
|
|
281
305
|
)
|
|
@@ -252,6 +252,7 @@ class CompileContext:
|
|
|
252
252
|
subgraph_dir: Path
|
|
253
253
|
root_overrides: dict[str, str] = field(default_factory=dict)
|
|
254
254
|
emit_components_sidecar: bool = True
|
|
255
|
+
image_overrides: dict[str, str] = field(default_factory=dict)
|
|
255
256
|
max_depth: int = 32
|
|
256
257
|
# Compiled CHILD artifacts keyed by compile key (Decision M dedup).
|
|
257
258
|
# The root is NOT stored here; it is returned directly.
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/ref.py
RENAMED
|
@@ -49,6 +49,7 @@ class CallableRef:
|
|
|
49
49
|
_task_source_path: Path | None = None
|
|
50
50
|
_task_function_name: str | None = None
|
|
51
51
|
_task_image: str | None = None
|
|
52
|
+
_task_image_id: str | None = None
|
|
52
53
|
_task_dependencies_from: Path | None = None
|
|
53
54
|
_task_mode: str | None = None
|
|
54
55
|
_task_resolve_root: Path | None = None
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/task.py
RENAMED
|
@@ -65,6 +65,7 @@ def task(
|
|
|
65
65
|
*,
|
|
66
66
|
env: TaskEnv | None = None,
|
|
67
67
|
image: str | None = None,
|
|
68
|
+
image_id: str | None = None,
|
|
68
69
|
dependencies_from: str | Path | None = None,
|
|
69
70
|
mode: str | None = None,
|
|
70
71
|
resolve_root: str | Path | None = None,
|
|
@@ -95,6 +96,10 @@ def task(
|
|
|
95
96
|
written verbatim into the emitted
|
|
96
97
|
``components.yaml#local_from_python.image`` field. Overrides
|
|
97
98
|
``env.image`` when both are given.
|
|
99
|
+
image_id: Logical image identifier resolved at compile time via
|
|
100
|
+
registered defaults or ``tangle sdk pipelines compile --image
|
|
101
|
+
ID=REF`` overrides. Ignored when explicit ``image=`` supplies
|
|
102
|
+
an image; otherwise it also overrides ``env.image``.
|
|
98
103
|
dependencies_from: Path to a ``pyproject.toml`` (or any file
|
|
99
104
|
the hydrator understands) that declares pip
|
|
100
105
|
dependencies. Resolved relative to the caller's source
|
|
@@ -138,7 +143,11 @@ def task(
|
|
|
138
143
|
# overrides the corresponding ``env`` field; otherwise the env value
|
|
139
144
|
# (if any) is used. This mirrors YAML anchor semantics: start from the
|
|
140
145
|
# declared-once defaults, override locally where needed.
|
|
141
|
-
effective_image =
|
|
146
|
+
effective_image = (
|
|
147
|
+
image
|
|
148
|
+
if image is not None
|
|
149
|
+
else (None if image_id is not None else (env.image if env else None))
|
|
150
|
+
)
|
|
142
151
|
effective_deps_raw = (
|
|
143
152
|
dependencies_from
|
|
144
153
|
if dependencies_from is not None
|
|
@@ -202,6 +211,7 @@ def task(
|
|
|
202
211
|
_task_source_path=source_path,
|
|
203
212
|
_task_function_name=function_name,
|
|
204
213
|
_task_image=effective_image,
|
|
214
|
+
_task_image_id=image_id,
|
|
205
215
|
_task_dependencies_from=deps_path,
|
|
206
216
|
_task_mode=mode,
|
|
207
217
|
_task_resolve_root=resolve_root_path,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_from_func.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_generator.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_inspector.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/component_publisher.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/dynamic_discovery_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/openapi/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_dehydrator.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_hydrator.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_annotations.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_details.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_manager.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_run_search.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_runs_cli.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_spec_utils.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/pipeline_validation.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/published_components_cli.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/__init__.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/cfg.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/emit.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/errors.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/graph.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/ids.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/pipeline.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/raw.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/task_env.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/trace.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/python_pipeline/types.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/schema_validation.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/packages/tangle-cli/src/tangle_cli/schemas/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.5 → tangle_cli-0.1.6}/skills/tangent/references/example-scenarios/01-mslr-ranking.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|