yamlgraph 0.3.9__py3-none-any.whl
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.
- examples/__init__.py +1 -0
- examples/codegen/__init__.py +5 -0
- examples/codegen/models/__init__.py +13 -0
- examples/codegen/models/schemas.py +76 -0
- examples/codegen/tests/__init__.py +1 -0
- examples/codegen/tests/test_ai_helpers.py +235 -0
- examples/codegen/tests/test_ast_analysis.py +174 -0
- examples/codegen/tests/test_code_analysis.py +134 -0
- examples/codegen/tests/test_code_context.py +301 -0
- examples/codegen/tests/test_code_nav.py +89 -0
- examples/codegen/tests/test_dependency_tools.py +119 -0
- examples/codegen/tests/test_example_tools.py +185 -0
- examples/codegen/tests/test_git_tools.py +112 -0
- examples/codegen/tests/test_impl_agent_schemas.py +193 -0
- examples/codegen/tests/test_impl_agent_v4_graph.py +94 -0
- examples/codegen/tests/test_jedi_analysis.py +226 -0
- examples/codegen/tests/test_meta_tools.py +250 -0
- examples/codegen/tests/test_plan_discovery_prompt.py +98 -0
- examples/codegen/tests/test_syntax_tools.py +85 -0
- examples/codegen/tests/test_synthesize_prompt.py +94 -0
- examples/codegen/tests/test_template_tools.py +244 -0
- examples/codegen/tools/__init__.py +80 -0
- examples/codegen/tools/ai_helpers.py +420 -0
- examples/codegen/tools/ast_analysis.py +92 -0
- examples/codegen/tools/code_context.py +180 -0
- examples/codegen/tools/code_nav.py +52 -0
- examples/codegen/tools/dependency_tools.py +120 -0
- examples/codegen/tools/example_tools.py +188 -0
- examples/codegen/tools/git_tools.py +151 -0
- examples/codegen/tools/impl_executor.py +614 -0
- examples/codegen/tools/jedi_analysis.py +311 -0
- examples/codegen/tools/meta_tools.py +202 -0
- examples/codegen/tools/syntax_tools.py +26 -0
- examples/codegen/tools/template_tools.py +356 -0
- examples/fastapi_interview.py +167 -0
- examples/npc/api/__init__.py +1 -0
- examples/npc/api/app.py +100 -0
- examples/npc/api/routes/__init__.py +5 -0
- examples/npc/api/routes/encounter.py +182 -0
- examples/npc/api/session.py +330 -0
- examples/npc/demo.py +387 -0
- examples/npc/nodes/__init__.py +5 -0
- examples/npc/nodes/image_node.py +92 -0
- examples/npc/run_encounter.py +230 -0
- examples/shared/__init__.py +0 -0
- examples/shared/replicate_tool.py +238 -0
- examples/storyboard/__init__.py +1 -0
- examples/storyboard/generate_videos.py +335 -0
- examples/storyboard/nodes/__init__.py +12 -0
- examples/storyboard/nodes/animated_character_node.py +248 -0
- examples/storyboard/nodes/animated_image_node.py +138 -0
- examples/storyboard/nodes/character_node.py +162 -0
- examples/storyboard/nodes/image_node.py +118 -0
- examples/storyboard/nodes/replicate_tool.py +49 -0
- examples/storyboard/retry_images.py +118 -0
- scripts/demo_async_executor.py +212 -0
- scripts/demo_interview_e2e.py +200 -0
- scripts/demo_streaming.py +140 -0
- scripts/run_interview_demo.py +94 -0
- scripts/test_interrupt_fix.py +26 -0
- tests/__init__.py +1 -0
- tests/conftest.py +178 -0
- tests/integration/__init__.py +1 -0
- tests/integration/test_animated_storyboard.py +63 -0
- tests/integration/test_cli_commands.py +242 -0
- tests/integration/test_colocated_prompts.py +139 -0
- tests/integration/test_map_demo.py +50 -0
- tests/integration/test_memory_demo.py +283 -0
- tests/integration/test_npc_api/__init__.py +1 -0
- tests/integration/test_npc_api/test_routes.py +357 -0
- tests/integration/test_npc_api/test_session.py +216 -0
- tests/integration/test_pipeline_flow.py +105 -0
- tests/integration/test_providers.py +163 -0
- tests/integration/test_resume.py +75 -0
- tests/integration/test_subgraph_integration.py +295 -0
- tests/integration/test_subgraph_interrupt.py +106 -0
- tests/unit/__init__.py +1 -0
- tests/unit/test_agent_nodes.py +355 -0
- tests/unit/test_async_executor.py +346 -0
- tests/unit/test_checkpointer.py +212 -0
- tests/unit/test_checkpointer_factory.py +212 -0
- tests/unit/test_cli.py +121 -0
- tests/unit/test_cli_package.py +81 -0
- tests/unit/test_compile_graph_map.py +132 -0
- tests/unit/test_conditions_routing.py +253 -0
- tests/unit/test_config.py +93 -0
- tests/unit/test_conversation_memory.py +276 -0
- tests/unit/test_database.py +145 -0
- tests/unit/test_deprecation.py +104 -0
- tests/unit/test_executor.py +172 -0
- tests/unit/test_executor_async.py +179 -0
- tests/unit/test_export.py +149 -0
- tests/unit/test_expressions.py +178 -0
- tests/unit/test_feature_brainstorm.py +194 -0
- tests/unit/test_format_prompt.py +145 -0
- tests/unit/test_generic_report.py +200 -0
- tests/unit/test_graph_commands.py +327 -0
- tests/unit/test_graph_linter.py +627 -0
- tests/unit/test_graph_loader.py +357 -0
- tests/unit/test_graph_schema.py +193 -0
- tests/unit/test_inline_schema.py +151 -0
- tests/unit/test_interrupt_node.py +182 -0
- tests/unit/test_issues.py +164 -0
- tests/unit/test_jinja2_prompts.py +85 -0
- tests/unit/test_json_extract.py +134 -0
- tests/unit/test_langsmith.py +600 -0
- tests/unit/test_langsmith_tools.py +204 -0
- tests/unit/test_llm_factory.py +109 -0
- tests/unit/test_llm_factory_async.py +118 -0
- tests/unit/test_loops.py +403 -0
- tests/unit/test_map_node.py +144 -0
- tests/unit/test_no_backward_compat.py +56 -0
- tests/unit/test_node_factory.py +348 -0
- tests/unit/test_passthrough_node.py +126 -0
- tests/unit/test_prompts.py +324 -0
- tests/unit/test_python_nodes.py +198 -0
- tests/unit/test_reliability.py +298 -0
- tests/unit/test_result_export.py +234 -0
- tests/unit/test_router.py +296 -0
- tests/unit/test_sanitize.py +99 -0
- tests/unit/test_schema_loader.py +295 -0
- tests/unit/test_shell_tools.py +229 -0
- tests/unit/test_state_builder.py +331 -0
- tests/unit/test_state_builder_map.py +104 -0
- tests/unit/test_state_config.py +197 -0
- tests/unit/test_streaming.py +307 -0
- tests/unit/test_subgraph.py +596 -0
- tests/unit/test_template.py +190 -0
- tests/unit/test_tool_call_integration.py +164 -0
- tests/unit/test_tool_call_node.py +178 -0
- tests/unit/test_tool_nodes.py +129 -0
- tests/unit/test_websearch.py +234 -0
- yamlgraph/__init__.py +35 -0
- yamlgraph/builder.py +110 -0
- yamlgraph/cli/__init__.py +159 -0
- yamlgraph/cli/__main__.py +6 -0
- yamlgraph/cli/commands.py +231 -0
- yamlgraph/cli/deprecation.py +92 -0
- yamlgraph/cli/graph_commands.py +541 -0
- yamlgraph/cli/validators.py +37 -0
- yamlgraph/config.py +67 -0
- yamlgraph/constants.py +70 -0
- yamlgraph/error_handlers.py +227 -0
- yamlgraph/executor.py +290 -0
- yamlgraph/executor_async.py +288 -0
- yamlgraph/graph_loader.py +451 -0
- yamlgraph/map_compiler.py +150 -0
- yamlgraph/models/__init__.py +36 -0
- yamlgraph/models/graph_schema.py +181 -0
- yamlgraph/models/schemas.py +124 -0
- yamlgraph/models/state_builder.py +236 -0
- yamlgraph/node_factory.py +768 -0
- yamlgraph/routing.py +87 -0
- yamlgraph/schema_loader.py +240 -0
- yamlgraph/storage/__init__.py +20 -0
- yamlgraph/storage/checkpointer.py +72 -0
- yamlgraph/storage/checkpointer_factory.py +123 -0
- yamlgraph/storage/database.py +320 -0
- yamlgraph/storage/export.py +269 -0
- yamlgraph/tools/__init__.py +1 -0
- yamlgraph/tools/agent.py +320 -0
- yamlgraph/tools/graph_linter.py +388 -0
- yamlgraph/tools/langsmith_tools.py +125 -0
- yamlgraph/tools/nodes.py +126 -0
- yamlgraph/tools/python_tool.py +179 -0
- yamlgraph/tools/shell.py +205 -0
- yamlgraph/tools/websearch.py +242 -0
- yamlgraph/utils/__init__.py +48 -0
- yamlgraph/utils/conditions.py +157 -0
- yamlgraph/utils/expressions.py +245 -0
- yamlgraph/utils/json_extract.py +104 -0
- yamlgraph/utils/langsmith.py +416 -0
- yamlgraph/utils/llm_factory.py +118 -0
- yamlgraph/utils/llm_factory_async.py +105 -0
- yamlgraph/utils/logging.py +104 -0
- yamlgraph/utils/prompts.py +171 -0
- yamlgraph/utils/sanitize.py +98 -0
- yamlgraph/utils/template.py +102 -0
- yamlgraph/utils/validators.py +181 -0
- yamlgraph-0.3.9.dist-info/METADATA +1105 -0
- yamlgraph-0.3.9.dist-info/RECORD +185 -0
- yamlgraph-0.3.9.dist-info/WHEEL +5 -0
- yamlgraph-0.3.9.dist-info/entry_points.txt +2 -0
- yamlgraph-0.3.9.dist-info/licenses/LICENSE +33 -0
- yamlgraph-0.3.9.dist-info/top_level.txt +4 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""CLI command implementations.
|
|
2
|
+
|
|
3
|
+
Contains all cmd_* functions for CLI subcommands.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
from argparse import Namespace
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from yamlgraph.cli.validators import validate_run_args
|
|
13
|
+
|
|
14
|
+
# Internal keys to skip when formatting results
|
|
15
|
+
_INTERNAL_KEYS = frozenset(
|
|
16
|
+
{
|
|
17
|
+
"_route",
|
|
18
|
+
"_loop_counts",
|
|
19
|
+
"thread_id",
|
|
20
|
+
"current_step",
|
|
21
|
+
"errors",
|
|
22
|
+
"topic",
|
|
23
|
+
"style",
|
|
24
|
+
"word_count",
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _format_value(value: Any, max_length: int = 200) -> str:
|
|
30
|
+
"""Format a single value for display.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
value: The value to format (str, list, Pydantic model, etc.)
|
|
34
|
+
max_length: Maximum length before truncation
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Formatted string representation
|
|
38
|
+
"""
|
|
39
|
+
if isinstance(value, BaseModel):
|
|
40
|
+
# Format Pydantic model as key: value pairs
|
|
41
|
+
lines = []
|
|
42
|
+
for field_name, field_value in value.model_dump().items():
|
|
43
|
+
formatted = _format_value(field_value, max_length)
|
|
44
|
+
lines.append(f" {field_name}: {formatted}")
|
|
45
|
+
return "\n" + "\n".join(lines)
|
|
46
|
+
|
|
47
|
+
if isinstance(value, list):
|
|
48
|
+
# Format list items
|
|
49
|
+
if not value:
|
|
50
|
+
return "[]"
|
|
51
|
+
if len(value) <= 3:
|
|
52
|
+
return str(value)
|
|
53
|
+
return f"[{len(value)} items]"
|
|
54
|
+
|
|
55
|
+
if isinstance(value, str):
|
|
56
|
+
if len(value) > max_length:
|
|
57
|
+
return value[:max_length] + "..."
|
|
58
|
+
return value
|
|
59
|
+
|
|
60
|
+
return str(value)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _format_result(result: dict[str, Any]) -> None:
|
|
64
|
+
"""Format and print pipeline result generically.
|
|
65
|
+
|
|
66
|
+
Iterates over all non-internal keys in the result dict
|
|
67
|
+
and prints their values. Works with any Pydantic model.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
result: Pipeline result dict with arbitrary Pydantic models
|
|
71
|
+
"""
|
|
72
|
+
for key, value in result.items():
|
|
73
|
+
if key in _INTERNAL_KEYS or value is None:
|
|
74
|
+
continue
|
|
75
|
+
|
|
76
|
+
print(f"\nš {key}:")
|
|
77
|
+
formatted = _format_value(value)
|
|
78
|
+
if formatted.startswith("\n"):
|
|
79
|
+
print(formatted)
|
|
80
|
+
else:
|
|
81
|
+
print(f" {formatted}")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def cmd_run(args: Namespace) -> None:
|
|
85
|
+
"""Run the yamlgraph pipeline."""
|
|
86
|
+
if not validate_run_args(args):
|
|
87
|
+
sys.exit(1)
|
|
88
|
+
|
|
89
|
+
from yamlgraph.builder import run_pipeline
|
|
90
|
+
from yamlgraph.storage import YamlGraphDB, export_state
|
|
91
|
+
from yamlgraph.utils import get_run_url, is_tracing_enabled
|
|
92
|
+
|
|
93
|
+
print("\nš Running yamlgraph pipeline")
|
|
94
|
+
print(f" Topic: {args.topic}")
|
|
95
|
+
print(f" Style: {args.style}")
|
|
96
|
+
print(f" Words: {args.word_count}")
|
|
97
|
+
print()
|
|
98
|
+
|
|
99
|
+
# Run pipeline
|
|
100
|
+
result = run_pipeline(
|
|
101
|
+
topic=args.topic,
|
|
102
|
+
style=args.style,
|
|
103
|
+
word_count=args.word_count,
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Save to database
|
|
107
|
+
db = YamlGraphDB()
|
|
108
|
+
db.save_state(result["thread_id"], result, status="completed")
|
|
109
|
+
print(f"\nš¾ Saved to database: thread_id={result['thread_id']}")
|
|
110
|
+
|
|
111
|
+
# Export to JSON
|
|
112
|
+
if args.export:
|
|
113
|
+
filepath = export_state(result)
|
|
114
|
+
print(f"š Exported to: {filepath}")
|
|
115
|
+
|
|
116
|
+
# Show results
|
|
117
|
+
print("\n" + "=" * 60)
|
|
118
|
+
print("RESULTS")
|
|
119
|
+
print("=" * 60)
|
|
120
|
+
|
|
121
|
+
_format_result(result)
|
|
122
|
+
|
|
123
|
+
# Show LangSmith link
|
|
124
|
+
if is_tracing_enabled() and (url := get_run_url()):
|
|
125
|
+
print(f"\nš LangSmith: {url}")
|
|
126
|
+
|
|
127
|
+
print()
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def cmd_list_runs(args: Namespace) -> None:
|
|
131
|
+
"""List recent pipeline runs."""
|
|
132
|
+
from yamlgraph.storage import YamlGraphDB
|
|
133
|
+
|
|
134
|
+
db = YamlGraphDB()
|
|
135
|
+
runs = db.list_runs(limit=args.limit)
|
|
136
|
+
|
|
137
|
+
if not runs:
|
|
138
|
+
print("No runs found.")
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
print(f"\nš Recent runs ({len(runs)}):\n")
|
|
142
|
+
print(f"{'Thread ID':<12} {'Status':<12} {'Updated':<20}")
|
|
143
|
+
print("-" * 50)
|
|
144
|
+
|
|
145
|
+
for run in runs:
|
|
146
|
+
print(f"{run['thread_id']:<12} {run['status']:<12} {run['updated_at'][:19]}")
|
|
147
|
+
|
|
148
|
+
print()
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def cmd_resume(args: Namespace) -> None:
|
|
152
|
+
"""Resume a pipeline from saved state."""
|
|
153
|
+
from yamlgraph.builder import build_resume_graph
|
|
154
|
+
from yamlgraph.storage import YamlGraphDB
|
|
155
|
+
|
|
156
|
+
db = YamlGraphDB()
|
|
157
|
+
state = db.load_state(args.thread_id)
|
|
158
|
+
|
|
159
|
+
if not state:
|
|
160
|
+
print(f"ā No run found with thread_id: {args.thread_id}")
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
print(f"\nš Resuming from: {state.get('current_step', 'unknown')}")
|
|
164
|
+
|
|
165
|
+
# Check what's already completed
|
|
166
|
+
if state.get("final_summary"):
|
|
167
|
+
print("ā
Pipeline already complete!")
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
# Show what will be skipped vs run
|
|
171
|
+
skipping = []
|
|
172
|
+
running = []
|
|
173
|
+
if state.get("generated"):
|
|
174
|
+
skipping.append("generate")
|
|
175
|
+
else:
|
|
176
|
+
running.append("generate")
|
|
177
|
+
if state.get("analysis"):
|
|
178
|
+
skipping.append("analyze")
|
|
179
|
+
else:
|
|
180
|
+
running.append("analyze")
|
|
181
|
+
running.append("summarize") # Always runs if we get here
|
|
182
|
+
|
|
183
|
+
if skipping:
|
|
184
|
+
print(f" Skipping: {', '.join(skipping)} (already in state)")
|
|
185
|
+
print(f" Running: {', '.join(running)}")
|
|
186
|
+
|
|
187
|
+
graph = build_resume_graph().compile()
|
|
188
|
+
result = graph.invoke(state)
|
|
189
|
+
|
|
190
|
+
# Save updated state
|
|
191
|
+
db.save_state(args.thread_id, result, status="completed")
|
|
192
|
+
print("\nā
Pipeline completed!")
|
|
193
|
+
|
|
194
|
+
if summary := result.get("final_summary"):
|
|
195
|
+
print(f"\nš Summary: {summary[:200]}...")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def cmd_trace(args: Namespace) -> None:
|
|
199
|
+
"""Show execution trace for a run."""
|
|
200
|
+
from yamlgraph.utils import get_latest_run_id, get_run_url, print_run_tree
|
|
201
|
+
|
|
202
|
+
run_id = args.run_id or get_latest_run_id()
|
|
203
|
+
|
|
204
|
+
if not run_id:
|
|
205
|
+
print("ā No run ID provided and could not find latest run.")
|
|
206
|
+
return
|
|
207
|
+
|
|
208
|
+
print(f"\nš Execution trace for: {run_id}")
|
|
209
|
+
print("ā" * 50)
|
|
210
|
+
print()
|
|
211
|
+
print_run_tree(run_id, verbose=args.verbose)
|
|
212
|
+
|
|
213
|
+
if url := get_run_url(run_id):
|
|
214
|
+
print(f"\nš View in LangSmith: {url}")
|
|
215
|
+
|
|
216
|
+
print()
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def cmd_export(args: Namespace) -> None:
|
|
220
|
+
"""Export a run to JSON."""
|
|
221
|
+
from yamlgraph.storage import YamlGraphDB, export_state
|
|
222
|
+
|
|
223
|
+
db = YamlGraphDB()
|
|
224
|
+
state = db.load_state(args.thread_id)
|
|
225
|
+
|
|
226
|
+
if not state:
|
|
227
|
+
print(f"ā No run found with thread_id: {args.thread_id}")
|
|
228
|
+
return
|
|
229
|
+
|
|
230
|
+
filepath = export_state(state)
|
|
231
|
+
print(f"ā
Exported to: {filepath}")
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Deprecation utilities for CLI commands.
|
|
2
|
+
|
|
3
|
+
Provides DeprecationError exception and helpers for migrating
|
|
4
|
+
old commands to the universal graph runner.
|
|
5
|
+
|
|
6
|
+
Term 'backward compatibility' signals refactoring need per project guidelines.
|
|
7
|
+
|
|
8
|
+
Example:
|
|
9
|
+
>>> from yamlgraph.cli.deprecation import DeprecationError, deprecated_command
|
|
10
|
+
>>>
|
|
11
|
+
>>> def cmd_old_command(args):
|
|
12
|
+
... # Signal this command needs refactoring
|
|
13
|
+
... deprecated_command("old", "graph run graphs/new.yaml --var x=y")
|
|
14
|
+
...
|
|
15
|
+
>>> # Running raises:
|
|
16
|
+
>>> # DeprecationError: DEPRECATED: 'old' is deprecated.
|
|
17
|
+
>>> # Use 'graph run graphs/new.yaml --var x=y' instead.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DeprecationError(Exception):
|
|
22
|
+
"""Raised when a deprecated command is used.
|
|
23
|
+
|
|
24
|
+
Signals "Refactor me" - deprecated commands should be removed.
|
|
25
|
+
|
|
26
|
+
Attributes:
|
|
27
|
+
old_command: The deprecated command being used
|
|
28
|
+
new_command: The replacement command to use instead
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
def __init__(self, old_command: str, new_command: str):
|
|
32
|
+
self.old_command = old_command
|
|
33
|
+
self.new_command = new_command
|
|
34
|
+
message = (
|
|
35
|
+
f"DEPRECATED: '{old_command}' is deprecated. Use '{new_command}' instead."
|
|
36
|
+
)
|
|
37
|
+
super().__init__(message)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Command mappings: old command -> graph path
|
|
41
|
+
COMMAND_MAPPINGS = {
|
|
42
|
+
"route": "graphs/router-demo.yaml",
|
|
43
|
+
"refine": "graphs/reflexion-demo.yaml",
|
|
44
|
+
"git-report": "graphs/git-report.yaml",
|
|
45
|
+
"memory-demo": "graphs/memory-demo.yaml",
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
# Variable mappings: old command -> arg name -> var name
|
|
49
|
+
ARG_MAPPINGS = {
|
|
50
|
+
"route": {"message": "message"},
|
|
51
|
+
"refine": {"topic": "topic"},
|
|
52
|
+
"git-report": {"query": "input"},
|
|
53
|
+
"memory-demo": {"input": "input"},
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_replacement_command(old_command: str, args: dict[str, str]) -> str | None:
|
|
58
|
+
"""Get the replacement graph run command.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
old_command: The deprecated command name
|
|
62
|
+
args: Dict of argument values
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Replacement command string, or None if unknown command
|
|
66
|
+
"""
|
|
67
|
+
graph_path = COMMAND_MAPPINGS.get(old_command)
|
|
68
|
+
if not graph_path:
|
|
69
|
+
return None
|
|
70
|
+
|
|
71
|
+
# Build --var arguments
|
|
72
|
+
var_args = []
|
|
73
|
+
arg_mapping = ARG_MAPPINGS.get(old_command, {})
|
|
74
|
+
for arg_name, var_name in arg_mapping.items():
|
|
75
|
+
if arg_name in args:
|
|
76
|
+
var_args.append(f"--var {var_name}={args[arg_name]}")
|
|
77
|
+
|
|
78
|
+
var_str = " ".join(var_args)
|
|
79
|
+
return f"graph run {graph_path} {var_str}".strip()
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def deprecated_command(old_command: str, new_command: str) -> None:
|
|
83
|
+
"""Raise DeprecationError for a deprecated command.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
old_command: The deprecated command being used
|
|
87
|
+
new_command: The replacement command suggestion
|
|
88
|
+
|
|
89
|
+
Raises:
|
|
90
|
+
DeprecationError: Always raised to signal deprecation
|
|
91
|
+
"""
|
|
92
|
+
raise DeprecationError(old_command, new_command)
|