tangle-cli 0.1.0__tar.gz → 0.1.2__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.0 → tangle_cli-0.1.2}/PKG-INFO +2 -2
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/__init__.py +1 -1
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/openapi/codegen.py +10 -2
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_manager.py +36 -6
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_runner.py +2 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_runs_cli.py +17 -1
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/pyproject.toml +2 -2
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/README.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/api_cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/api_schema.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/api_transport.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/args_container.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/artifacts.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/artifacts_cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/cli_helpers.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/cli_options.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/client.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_from_func.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_generator.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_inspector.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_publisher.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/components_cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/dynamic_discovery_client.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/generated_model_extensions.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/handler.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/hydration_trust.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/logger.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/models.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/module_bundler.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/openapi/__init__.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/openapi/parser.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_dehydrator.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_hydrator.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_annotations.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_details.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_search.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipelines.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipelines_cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/published_components_cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/py.typed +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/quickstart.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/secrets.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/secrets_cli.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/utils.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/version_manager.py +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/OSS-CONVENTIONS.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/PORT-README.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/SKILL.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/auth-wizard.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/builder.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/debugger.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/reporter.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/researcher.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/reviewer.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/agents/scenario-builder.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/data-sources.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/event-log.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/example-scenarios/01-mslr-ranking.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/example-scenarios/02-text-classification.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/example-scenarios/INDEX.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/iterating-on-runs.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/knowledge-corpus.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/secrets.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/setup.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-0-initialize.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-1-analyze.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-2-hypothesize.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-3-submit.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-4-monitor.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-5-evaluate.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-6-synthesize.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/step-7-decide.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/skills/tangent/references/tangle-tools.md +0 -0
- {tangle_cli-0.1.0 → tangle_cli-0.1.2}/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.2
|
|
4
4
|
Summary: CLI for Tangle, the open-source ML pipeline orchestration platform
|
|
5
5
|
Author: Alexey Volkov, Tangle authors
|
|
6
6
|
Author-email: Alexey Volkov <alexey.volkov@ark-kun.com>
|
|
@@ -13,7 +13,7 @@ Requires-Dist: platformdirs>=4.10.0
|
|
|
13
13
|
Requires-Dist: pydantic>=2.0
|
|
14
14
|
Requires-Dist: pyyaml>=6.0
|
|
15
15
|
Requires-Dist: requests>=2.32.0
|
|
16
|
-
Requires-Dist: tangle-api==0.1.
|
|
16
|
+
Requires-Dist: tangle-api==0.1.1
|
|
17
17
|
Requires-Dist: tomli>=2.0 ; python_full_version < '3.11'
|
|
18
18
|
Requires-Python: >=3.10
|
|
19
19
|
Project-URL: Homepage, https://tangleml.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.1"
|
|
18
18
|
|
|
19
19
|
__all__ = ["TangleDynamicDiscoveryClient", "__version__"]
|
|
@@ -510,7 +510,7 @@ def _param_signature(
|
|
|
510
510
|
body_names.append(name)
|
|
511
511
|
if parameter.required:
|
|
512
512
|
required_body_names.add(name)
|
|
513
|
-
include_body = has_request_body
|
|
513
|
+
include_body = has_request_body
|
|
514
514
|
if include_body:
|
|
515
515
|
body_annotation = "dict[str, Any] | None" if raw_body_override else "Any"
|
|
516
516
|
signature_parts.append(f"body: {body_annotation} = None")
|
|
@@ -537,6 +537,12 @@ def _body_dict_literal(names: list[str], required_names: set[str]) -> str:
|
|
|
537
537
|
return "{" + f"**{required_literal}, **{{{optional_expr}}}" + "}"
|
|
538
538
|
|
|
539
539
|
|
|
540
|
+
def _merged_body_dict_literal(names: list[str], required_names: set[str]) -> str:
|
|
541
|
+
"""Return request JSON with generic body fields overridden by named fields."""
|
|
542
|
+
|
|
543
|
+
return f"{{**(body or {{}}), **{_body_dict_literal(names, required_names)}}}"
|
|
544
|
+
|
|
545
|
+
|
|
540
546
|
def _validate_operation_path(path: str) -> None:
|
|
541
547
|
"""Reject OpenAPI operation paths that could override the configured origin."""
|
|
542
548
|
|
|
@@ -625,7 +631,9 @@ def generate_operations(
|
|
|
625
631
|
f" path_params={_dict_literal(path_names)},",
|
|
626
632
|
f" params={_dict_literal(query_names)},",
|
|
627
633
|
])
|
|
628
|
-
if body_names:
|
|
634
|
+
if body_names and include_body:
|
|
635
|
+
lines.append(f" json_data={_merged_body_dict_literal(body_names, required_body_names)},")
|
|
636
|
+
elif body_names:
|
|
629
637
|
lines.append(f" json_data={_body_dict_literal(body_names, required_body_names)},")
|
|
630
638
|
elif include_body:
|
|
631
639
|
lines.append(" json_data=body,")
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_manager.py
RENAMED
|
@@ -37,8 +37,8 @@ _FAILURE_EARLY_EXIT_STATUSES = ("FAILED", "SYSTEM_ERROR")
|
|
|
37
37
|
_EXECUTION_STATE_TIMINGS_METADATA_KEY = "execution_state_timings"
|
|
38
38
|
_EXECUTION_STATE_TIMING_MONOTONIC_METADATA_KEY = "_execution_state_timing_monotonic"
|
|
39
39
|
_SUBMISSION_ID_ANNOTATION_KEY = "tangle-cli/submission-id"
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
_SUBMIT_RECOVERY_BACKOFF_SECONDS = (0.5, 1.0, 2.0, 4.0, 8.0, 16.0)
|
|
41
|
+
_DEFAULT_SUBMIT_RECOVERY_ATTEMPTS = 2
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
class PipelineRunError(RuntimeError):
|
|
@@ -1529,6 +1529,11 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1529
1529
|
submission_id = annotations.get(_SUBMISSION_ID_ANNOTATION_KEY)
|
|
1530
1530
|
return str(submission_id) if submission_id else None
|
|
1531
1531
|
|
|
1532
|
+
@staticmethod
|
|
1533
|
+
def _submit_recovery_backoff_seconds(submit_recovery_attempts: int) -> tuple[float, ...]:
|
|
1534
|
+
attempt_count = max(0, min(int(submit_recovery_attempts), len(_SUBMIT_RECOVERY_BACKOFF_SECONDS)))
|
|
1535
|
+
return _SUBMIT_RECOVERY_BACKOFF_SECONDS[:attempt_count]
|
|
1536
|
+
|
|
1532
1537
|
def _submitted_runs_for_submission_id(self, submission_id: str) -> list[dict[str, Any]]:
|
|
1533
1538
|
query = {
|
|
1534
1539
|
"and": [
|
|
@@ -1554,14 +1559,32 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1554
1559
|
self,
|
|
1555
1560
|
*,
|
|
1556
1561
|
submission_id: str | None,
|
|
1562
|
+
submit_recovery_attempts: int = _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
1557
1563
|
) -> dict[str, Any] | None:
|
|
1558
1564
|
if not submission_id:
|
|
1559
1565
|
return None
|
|
1560
|
-
|
|
1566
|
+
backoff_seconds = self._submit_recovery_backoff_seconds(submit_recovery_attempts)
|
|
1567
|
+
total_lookup_attempts = len(backoff_seconds)
|
|
1568
|
+
if total_lookup_attempts == 0:
|
|
1569
|
+
self.logger.warn(
|
|
1570
|
+
"Submit recovery lookup disabled "
|
|
1571
|
+
f"({_SUBMISSION_ID_ANNOTATION_KEY}={submission_id}, "
|
|
1572
|
+
f"submit_recovery_attempts={submit_recovery_attempts}); "
|
|
1573
|
+
"resubmitting the same frozen body with preserved inputs."
|
|
1574
|
+
)
|
|
1575
|
+
return None
|
|
1576
|
+
for lookup_attempt, delay_seconds in enumerate(backoff_seconds, start=1):
|
|
1577
|
+
self.logger.info(
|
|
1578
|
+
"Waiting "
|
|
1579
|
+
f"{delay_seconds:g}s before checking whether failed submit already created a pipeline run "
|
|
1580
|
+
f"({_SUBMISSION_ID_ANNOTATION_KEY}={submission_id}, "
|
|
1581
|
+
f"lookup_attempt={lookup_attempt}/{total_lookup_attempts})"
|
|
1582
|
+
)
|
|
1583
|
+
time.sleep(delay_seconds)
|
|
1561
1584
|
self.logger.info(
|
|
1562
1585
|
"Checking whether failed submit already created a pipeline run "
|
|
1563
1586
|
f"({_SUBMISSION_ID_ANNOTATION_KEY}={submission_id}, "
|
|
1564
|
-
f"lookup_attempt={lookup_attempt}/{
|
|
1587
|
+
f"lookup_attempt={lookup_attempt}/{total_lookup_attempts})"
|
|
1565
1588
|
)
|
|
1566
1589
|
try:
|
|
1567
1590
|
matches = self._submitted_runs_for_submission_id(submission_id)
|
|
@@ -1598,8 +1621,6 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1598
1621
|
f"{_SUBMISSION_ID_ANNOTATION_KEY}={submission_id}: {', '.join(run_ids) or matches!r}. "
|
|
1599
1622
|
"Refusing to submit a duplicate."
|
|
1600
1623
|
)
|
|
1601
|
-
if lookup_attempt < _SUBMIT_RECOVERY_LOOKUP_ATTEMPTS:
|
|
1602
|
-
time.sleep(_SUBMIT_RECOVERY_LOOKUP_DELAY_SECONDS)
|
|
1603
1624
|
self.logger.warn(
|
|
1604
1625
|
"No existing pipeline run found after submit failure "
|
|
1605
1626
|
f"({_SUBMISSION_ID_ANNOTATION_KEY}={submission_id}); "
|
|
@@ -1647,6 +1668,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1647
1668
|
timeout_clock: str = "monotonic",
|
|
1648
1669
|
exit_on_first_failure: bool = False,
|
|
1649
1670
|
metadata: dict[str, Any] | None = None,
|
|
1671
|
+
submit_recovery_attempts: int = _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
1650
1672
|
metadata_factory: Callable[
|
|
1651
1673
|
[int, PipelineRunContext | None, Exception | None], dict[str, Any]
|
|
1652
1674
|
] | None = None,
|
|
@@ -1723,6 +1745,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1723
1745
|
if reused_after_submit_failure:
|
|
1724
1746
|
recovered_response = self._recover_submitted_run_after_submit_error(
|
|
1725
1747
|
submission_id=self._submission_id_from_body(body),
|
|
1748
|
+
submit_recovery_attempts=submit_recovery_attempts,
|
|
1726
1749
|
)
|
|
1727
1750
|
if recovered_response is not None:
|
|
1728
1751
|
response = self._adopt_submitted_run(
|
|
@@ -1754,6 +1777,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1754
1777
|
)
|
|
1755
1778
|
recovered_response = self._recover_submitted_run_after_submit_error(
|
|
1756
1779
|
submission_id=submission_id_for_recovery,
|
|
1780
|
+
submit_recovery_attempts=submit_recovery_attempts,
|
|
1757
1781
|
)
|
|
1758
1782
|
if recovered_response is None:
|
|
1759
1783
|
self.hooks.on_submit_error(submit_exc, context=context)
|
|
@@ -1834,6 +1858,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1834
1858
|
timeout_clock: str = "monotonic",
|
|
1835
1859
|
exit_on_first_failure: bool = False,
|
|
1836
1860
|
metadata: dict[str, Any] | None = None,
|
|
1861
|
+
submit_recovery_attempts: int = _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
1837
1862
|
) -> dict[str, Any]:
|
|
1838
1863
|
"""Submit/wait/retry an already prepared submit body.
|
|
1839
1864
|
|
|
@@ -1862,6 +1887,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1862
1887
|
timeout_clock=timeout_clock,
|
|
1863
1888
|
exit_on_first_failure=exit_on_first_failure,
|
|
1864
1889
|
metadata=metadata,
|
|
1890
|
+
submit_recovery_attempts=submit_recovery_attempts,
|
|
1865
1891
|
)
|
|
1866
1892
|
|
|
1867
1893
|
def run_pipeline_spec(
|
|
@@ -1882,6 +1908,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1882
1908
|
timeout_clock: str = "monotonic",
|
|
1883
1909
|
exit_on_first_failure: bool = False,
|
|
1884
1910
|
metadata: dict[str, Any] | None = None,
|
|
1911
|
+
submit_recovery_attempts: int = _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
1885
1912
|
) -> dict[str, Any]:
|
|
1886
1913
|
"""Submit/wait/retry an already hydrated/validated in-memory spec."""
|
|
1887
1914
|
|
|
@@ -1911,6 +1938,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1911
1938
|
timeout_clock=timeout_clock,
|
|
1912
1939
|
exit_on_first_failure=exit_on_first_failure,
|
|
1913
1940
|
metadata=metadata,
|
|
1941
|
+
submit_recovery_attempts=submit_recovery_attempts,
|
|
1914
1942
|
)
|
|
1915
1943
|
|
|
1916
1944
|
def run_pipeline(
|
|
@@ -1931,6 +1959,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1931
1959
|
timeout_clock: str = "monotonic",
|
|
1932
1960
|
exit_on_first_failure: bool = False,
|
|
1933
1961
|
metadata: dict[str, Any] | None = None,
|
|
1962
|
+
submit_recovery_attempts: int = _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
1934
1963
|
) -> dict[str, Any]:
|
|
1935
1964
|
"""Submit (and optionally wait for) a pipeline with lifecycle hooks.
|
|
1936
1965
|
|
|
@@ -1965,6 +1994,7 @@ class PipelineRunManager(TangleCliHandler):
|
|
|
1965
1994
|
timeout_clock=timeout_clock,
|
|
1966
1995
|
exit_on_first_failure=exit_on_first_failure,
|
|
1967
1996
|
metadata=metadata,
|
|
1997
|
+
submit_recovery_attempts=submit_recovery_attempts,
|
|
1968
1998
|
)
|
|
1969
1999
|
|
|
1970
2000
|
|
|
@@ -507,6 +507,7 @@ class PipelineRunner(PipelineRunnerHooks, PipelineRunManager):
|
|
|
507
507
|
open_browser: bool = False,
|
|
508
508
|
include_next_steps: bool = False,
|
|
509
509
|
metadata: dict[str, Any] | None = None,
|
|
510
|
+
submit_recovery_attempts: int = 2,
|
|
510
511
|
) -> dict[str, Any]:
|
|
511
512
|
"""Run a pipeline path through generic preparation + lifecycle hooks.
|
|
512
513
|
|
|
@@ -603,6 +604,7 @@ class PipelineRunner(PipelineRunnerHooks, PipelineRunManager):
|
|
|
603
604
|
timeout_clock=timeout_clock,
|
|
604
605
|
exit_on_first_failure=exit_on_first_failure,
|
|
605
606
|
metadata_factory=metadata_factory,
|
|
607
|
+
submit_recovery_attempts=submit_recovery_attempts,
|
|
606
608
|
)
|
|
607
609
|
context = result.get("context")
|
|
608
610
|
attempt = context.attempt if isinstance(context, PipelineRunContext) else max(preparations)
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_runs_cli.py
RENAMED
|
@@ -28,6 +28,7 @@ from .cli_options import (
|
|
|
28
28
|
from .logger import Logger, logger_for_log_type
|
|
29
29
|
from .pipeline_run_annotations import AnnotationManager
|
|
30
30
|
from .pipeline_run_manager import (
|
|
31
|
+
_DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
31
32
|
PipelineRunError,
|
|
32
33
|
PipelineRunHooks,
|
|
33
34
|
PipelineRunManager,
|
|
@@ -166,6 +167,15 @@ def pipeline_runs_submit(
|
|
|
166
167
|
auth_header: AuthHeaderOption = None,
|
|
167
168
|
header: HeaderOption = None,
|
|
168
169
|
config: ConfigOption = None,
|
|
170
|
+
submit_recovery_attempts: Annotated[
|
|
171
|
+
int,
|
|
172
|
+
Parameter(
|
|
173
|
+
help=(
|
|
174
|
+
"Number of post-failed-submit recovery lookups before resubmitting; "
|
|
175
|
+
"higher values wait longer for delayed run registration."
|
|
176
|
+
)
|
|
177
|
+
),
|
|
178
|
+
] = _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS,
|
|
169
179
|
log_type: LogTypeOption = "console",
|
|
170
180
|
) -> None:
|
|
171
181
|
"""Hydrate and submit a local pipeline YAML file as a run."""
|
|
@@ -181,6 +191,7 @@ def pipeline_runs_submit(
|
|
|
181
191
|
"run_as": (run_as, None),
|
|
182
192
|
"trusted_source": (trusted_source, None),
|
|
183
193
|
"trusted_hydration_cli": ("trusted_hydration_cli", trusted_hydration, None, False),
|
|
194
|
+
"submit_recovery_attempts": (submit_recovery_attempts, _DEFAULT_SUBMIT_RECOVERY_ATTEMPTS),
|
|
184
195
|
"log_type": (log_type, "console"),
|
|
185
196
|
**api_arg_specs(base_url=base_url, token=token, auth_header=auth_header, header=header),
|
|
186
197
|
}
|
|
@@ -194,7 +205,12 @@ def pipeline_runs_submit(
|
|
|
194
205
|
}
|
|
195
206
|
if args.dry_run:
|
|
196
207
|
return manager.build_submit_body(args.pipeline_path, **kwargs)
|
|
197
|
-
|
|
208
|
+
result = manager.run_pipeline(
|
|
209
|
+
args.pipeline_path,
|
|
210
|
+
**kwargs,
|
|
211
|
+
submit_recovery_attempts=args.submit_recovery_attempts,
|
|
212
|
+
)
|
|
213
|
+
return result["response"]
|
|
198
214
|
|
|
199
215
|
_run_manager_action(config, base_url, specs, action)
|
|
200
216
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "tangle-cli"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.2"
|
|
4
4
|
description = "CLI for Tangle, the open-source ML pipeline orchestration platform"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -18,7 +18,7 @@ dependencies = [
|
|
|
18
18
|
"pydantic>=2.0",
|
|
19
19
|
"pyyaml>=6.0",
|
|
20
20
|
"requests>=2.32.0",
|
|
21
|
-
"tangle-api==0.1.
|
|
21
|
+
"tangle-api==0.1.1",
|
|
22
22
|
"tomli>=2.0; python_version < '3.11'",
|
|
23
23
|
]
|
|
24
24
|
|
|
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.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_from_func.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_generator.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_inspector.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/component_publisher.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/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.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/openapi/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_dehydrator.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_hydrator.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_annotations.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_details.py
RENAMED
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/pipeline_run_search.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tangle_cli-0.1.0 → tangle_cli-0.1.2}/packages/tangle-cli/src/tangle_cli/published_components_cli.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.0 → tangle_cli-0.1.2}/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
|