pltr-cli 0.5.2__py3-none-any.whl → 0.7.0__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.
- pltr/__init__.py +1 -1
- pltr/commands/dataset.py +742 -1
- pltr/services/dataset.py +544 -1
- pltr/utils/formatting.py +170 -0
- {pltr_cli-0.5.2.dist-info → pltr_cli-0.7.0.dist-info}/METADATA +1 -1
- {pltr_cli-0.5.2.dist-info → pltr_cli-0.7.0.dist-info}/RECORD +9 -9
- {pltr_cli-0.5.2.dist-info → pltr_cli-0.7.0.dist-info}/WHEEL +0 -0
- {pltr_cli-0.5.2.dist-info → pltr_cli-0.7.0.dist-info}/entry_points.txt +0 -0
- {pltr_cli-0.5.2.dist-info → pltr_cli-0.7.0.dist-info}/licenses/LICENSE +0 -0
pltr/commands/dataset.py
CHANGED
|
@@ -22,6 +22,9 @@ branches_app = typer.Typer()
|
|
|
22
22
|
files_app = typer.Typer()
|
|
23
23
|
transactions_app = typer.Typer()
|
|
24
24
|
views_app = typer.Typer()
|
|
25
|
+
schema_app = typer.Typer()
|
|
26
|
+
schedules_app = typer.Typer()
|
|
27
|
+
jobs_app = typer.Typer()
|
|
25
28
|
console = Console()
|
|
26
29
|
formatter = OutputFormatter(console)
|
|
27
30
|
|
|
@@ -70,7 +73,175 @@ def get_dataset(
|
|
|
70
73
|
raise typer.Exit(1)
|
|
71
74
|
|
|
72
75
|
|
|
73
|
-
#
|
|
76
|
+
# Schema commands
|
|
77
|
+
@schema_app.command("get")
|
|
78
|
+
def get_schema(
|
|
79
|
+
dataset_rid: str = typer.Argument(
|
|
80
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
81
|
+
),
|
|
82
|
+
profile: Optional[str] = typer.Option(
|
|
83
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
84
|
+
),
|
|
85
|
+
format: str = typer.Option(
|
|
86
|
+
"table",
|
|
87
|
+
"--format",
|
|
88
|
+
"-f",
|
|
89
|
+
help="Output format (table, json, csv)",
|
|
90
|
+
autocompletion=complete_output_format,
|
|
91
|
+
),
|
|
92
|
+
output: Optional[str] = typer.Option(
|
|
93
|
+
None, "--output", "-o", help="Output file path"
|
|
94
|
+
),
|
|
95
|
+
):
|
|
96
|
+
"""Get the schema of a dataset."""
|
|
97
|
+
try:
|
|
98
|
+
cache_rid(dataset_rid)
|
|
99
|
+
service = DatasetService(profile=profile)
|
|
100
|
+
|
|
101
|
+
with SpinnerProgressTracker().track_spinner(
|
|
102
|
+
f"Fetching schema for {dataset_rid}..."
|
|
103
|
+
):
|
|
104
|
+
schema = service.get_schema(dataset_rid)
|
|
105
|
+
|
|
106
|
+
# Format schema for display
|
|
107
|
+
if format == "json":
|
|
108
|
+
formatter._format_json(schema, output)
|
|
109
|
+
else:
|
|
110
|
+
formatter.print_info(f"Dataset: {dataset_rid}")
|
|
111
|
+
formatter.print_info(f"Status: {schema.get('status', 'Unknown')}")
|
|
112
|
+
if schema.get("schema"):
|
|
113
|
+
formatter.print_info("\nSchema:")
|
|
114
|
+
formatter._format_json(schema.get("schema"))
|
|
115
|
+
|
|
116
|
+
if output:
|
|
117
|
+
formatter.print_success(f"Schema saved to {output}")
|
|
118
|
+
|
|
119
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
120
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
121
|
+
raise typer.Exit(1)
|
|
122
|
+
except Exception as e:
|
|
123
|
+
formatter.print_error(f"Failed to get schema: {e}")
|
|
124
|
+
raise typer.Exit(1)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@schema_app.command("set")
|
|
128
|
+
def set_schema(
|
|
129
|
+
dataset_rid: str = typer.Argument(
|
|
130
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
131
|
+
),
|
|
132
|
+
from_csv: Optional[str] = typer.Option(
|
|
133
|
+
None, "--from-csv", help="Infer schema from CSV file"
|
|
134
|
+
),
|
|
135
|
+
json_schema: Optional[str] = typer.Option(
|
|
136
|
+
None, "--json", help="JSON string defining the schema"
|
|
137
|
+
),
|
|
138
|
+
json_file: Optional[str] = typer.Option(
|
|
139
|
+
None, "--json-file", help="Path to JSON file containing schema definition"
|
|
140
|
+
),
|
|
141
|
+
branch: str = typer.Option("master", "--branch", help="Dataset branch"),
|
|
142
|
+
transaction_rid: Optional[str] = typer.Option(
|
|
143
|
+
None, "--transaction-rid", help="Transaction RID to use"
|
|
144
|
+
),
|
|
145
|
+
profile: Optional[str] = typer.Option(
|
|
146
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
147
|
+
),
|
|
148
|
+
):
|
|
149
|
+
"""Set or update the schema of a dataset."""
|
|
150
|
+
try:
|
|
151
|
+
cache_rid(dataset_rid)
|
|
152
|
+
service = DatasetService(profile=profile)
|
|
153
|
+
|
|
154
|
+
# Validate that exactly one input method is provided
|
|
155
|
+
input_methods = [from_csv, json_schema, json_file]
|
|
156
|
+
if sum(x is not None for x in input_methods) != 1:
|
|
157
|
+
formatter.print_error(
|
|
158
|
+
"Exactly one of --from-csv, --json, or --json-file must be provided"
|
|
159
|
+
)
|
|
160
|
+
raise typer.Exit(1)
|
|
161
|
+
|
|
162
|
+
schema = None
|
|
163
|
+
|
|
164
|
+
# Infer schema from CSV
|
|
165
|
+
if from_csv:
|
|
166
|
+
with SpinnerProgressTracker().track_spinner(
|
|
167
|
+
f"Inferring schema from {from_csv}..."
|
|
168
|
+
):
|
|
169
|
+
schema = service.infer_schema_from_csv(from_csv)
|
|
170
|
+
formatter.print_info(
|
|
171
|
+
f"Inferred schema from CSV with {len(schema.field_schema_list)} fields"
|
|
172
|
+
)
|
|
173
|
+
for field in schema.field_schema_list:
|
|
174
|
+
formatter.print_info(
|
|
175
|
+
f" - {field.name}: {field.type} (nullable={field.nullable})"
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# Parse schema from JSON string
|
|
179
|
+
elif json_schema:
|
|
180
|
+
import json
|
|
181
|
+
from foundry_sdk.v2.core.models import DatasetSchema, DatasetFieldSchema
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
schema_data = json.loads(json_schema)
|
|
185
|
+
fields = []
|
|
186
|
+
for field_data in schema_data.get("fields", []):
|
|
187
|
+
fields.append(
|
|
188
|
+
DatasetFieldSchema(
|
|
189
|
+
name=field_data["name"],
|
|
190
|
+
type=field_data["type"],
|
|
191
|
+
nullable=field_data.get("nullable", True),
|
|
192
|
+
)
|
|
193
|
+
)
|
|
194
|
+
schema = DatasetSchema(field_schema_list=fields)
|
|
195
|
+
except (json.JSONDecodeError, KeyError) as e:
|
|
196
|
+
formatter.print_error(f"Invalid JSON schema: {e}")
|
|
197
|
+
raise typer.Exit(1)
|
|
198
|
+
|
|
199
|
+
# Load schema from JSON file
|
|
200
|
+
elif json_file:
|
|
201
|
+
import json
|
|
202
|
+
from foundry_sdk.v2.core.models import DatasetSchema, DatasetFieldSchema
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
with open(json_file, "r") as f:
|
|
206
|
+
schema_data = json.load(f)
|
|
207
|
+
fields = []
|
|
208
|
+
for field_data in schema_data.get("fields", []):
|
|
209
|
+
fields.append(
|
|
210
|
+
DatasetFieldSchema(
|
|
211
|
+
name=field_data["name"],
|
|
212
|
+
type=field_data["type"],
|
|
213
|
+
nullable=field_data.get("nullable", True),
|
|
214
|
+
)
|
|
215
|
+
)
|
|
216
|
+
schema = DatasetSchema(field_schema_list=fields)
|
|
217
|
+
except (FileNotFoundError, json.JSONDecodeError, KeyError) as e:
|
|
218
|
+
formatter.print_error(f"Failed to load schema from file: {e}")
|
|
219
|
+
raise typer.Exit(1)
|
|
220
|
+
|
|
221
|
+
# Apply the schema
|
|
222
|
+
with SpinnerProgressTracker().track_spinner(
|
|
223
|
+
f"Setting schema on dataset {dataset_rid}..."
|
|
224
|
+
):
|
|
225
|
+
service.put_schema(
|
|
226
|
+
dataset_rid=dataset_rid,
|
|
227
|
+
schema=schema,
|
|
228
|
+
branch=branch,
|
|
229
|
+
transaction_rid=transaction_rid,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
formatter.print_success(f"Successfully set schema on dataset {dataset_rid}")
|
|
233
|
+
if transaction_rid:
|
|
234
|
+
formatter.print_info(f"Transaction RID: {transaction_rid}")
|
|
235
|
+
|
|
236
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
237
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
238
|
+
raise typer.Exit(1)
|
|
239
|
+
except FileNotFoundError as e:
|
|
240
|
+
formatter.print_error(f"File not found: {e}")
|
|
241
|
+
raise typer.Exit(1)
|
|
242
|
+
except Exception as e:
|
|
243
|
+
formatter.print_error(f"Failed to set schema: {e}")
|
|
244
|
+
raise typer.Exit(1)
|
|
74
245
|
|
|
75
246
|
|
|
76
247
|
@app.command("create")
|
|
@@ -189,6 +360,139 @@ def create_branch(
|
|
|
189
360
|
raise typer.Exit(1)
|
|
190
361
|
|
|
191
362
|
|
|
363
|
+
@branches_app.command("delete")
|
|
364
|
+
def delete_branch(
|
|
365
|
+
dataset_rid: str = typer.Argument(
|
|
366
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
367
|
+
),
|
|
368
|
+
branch_name: str = typer.Argument(..., help="Branch name to delete"),
|
|
369
|
+
confirm: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
370
|
+
profile: Optional[str] = typer.Option(
|
|
371
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
372
|
+
),
|
|
373
|
+
):
|
|
374
|
+
"""Delete a branch from a dataset."""
|
|
375
|
+
try:
|
|
376
|
+
cache_rid(dataset_rid)
|
|
377
|
+
service = DatasetService(profile=profile)
|
|
378
|
+
|
|
379
|
+
# Prevent deleting master branch
|
|
380
|
+
if branch_name.lower() == "master":
|
|
381
|
+
formatter.print_error("Cannot delete the master branch")
|
|
382
|
+
raise typer.Exit(1)
|
|
383
|
+
|
|
384
|
+
# Confirmation prompt
|
|
385
|
+
if not confirm:
|
|
386
|
+
confirmed = typer.confirm(
|
|
387
|
+
f"Are you sure you want to delete branch '{branch_name}' from dataset {dataset_rid}? "
|
|
388
|
+
f"This action cannot be undone."
|
|
389
|
+
)
|
|
390
|
+
if not confirmed:
|
|
391
|
+
formatter.print_info("Branch deletion cancelled")
|
|
392
|
+
raise typer.Exit(0)
|
|
393
|
+
|
|
394
|
+
with SpinnerProgressTracker().track_spinner(
|
|
395
|
+
f"Deleting branch '{branch_name}' from {dataset_rid}..."
|
|
396
|
+
):
|
|
397
|
+
service.delete_branch(dataset_rid, branch_name)
|
|
398
|
+
|
|
399
|
+
formatter.print_success(f"Branch '{branch_name}' deleted successfully")
|
|
400
|
+
formatter.print_info(f"Dataset: {dataset_rid}")
|
|
401
|
+
|
|
402
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
403
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
404
|
+
raise typer.Exit(1)
|
|
405
|
+
except Exception as e:
|
|
406
|
+
formatter.print_error(f"Failed to delete branch: {e}")
|
|
407
|
+
raise typer.Exit(1)
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
@branches_app.command("get")
|
|
411
|
+
def get_branch(
|
|
412
|
+
dataset_rid: str = typer.Argument(
|
|
413
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
414
|
+
),
|
|
415
|
+
branch_name: str = typer.Argument(..., help="Branch name"),
|
|
416
|
+
profile: Optional[str] = typer.Option(
|
|
417
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
418
|
+
),
|
|
419
|
+
format: str = typer.Option(
|
|
420
|
+
"table",
|
|
421
|
+
"--format",
|
|
422
|
+
"-f",
|
|
423
|
+
help="Output format (table, json, csv)",
|
|
424
|
+
autocompletion=complete_output_format,
|
|
425
|
+
),
|
|
426
|
+
output: Optional[str] = typer.Option(
|
|
427
|
+
None, "--output", "-o", help="Output file path"
|
|
428
|
+
),
|
|
429
|
+
):
|
|
430
|
+
"""Get detailed information about a specific branch."""
|
|
431
|
+
try:
|
|
432
|
+
cache_rid(dataset_rid)
|
|
433
|
+
service = DatasetService(profile=profile)
|
|
434
|
+
|
|
435
|
+
with SpinnerProgressTracker().track_spinner(
|
|
436
|
+
f"Fetching branch '{branch_name}' from {dataset_rid}..."
|
|
437
|
+
):
|
|
438
|
+
branch = service.get_branch(dataset_rid, branch_name)
|
|
439
|
+
|
|
440
|
+
formatter.format_branch_detail(branch, format, output)
|
|
441
|
+
|
|
442
|
+
if output:
|
|
443
|
+
formatter.print_success(f"Branch information saved to {output}")
|
|
444
|
+
|
|
445
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
446
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
447
|
+
raise typer.Exit(1)
|
|
448
|
+
except Exception as e:
|
|
449
|
+
formatter.print_error(f"Failed to get branch: {e}")
|
|
450
|
+
raise typer.Exit(1)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
@branches_app.command("transactions")
|
|
454
|
+
def list_branch_transactions(
|
|
455
|
+
dataset_rid: str = typer.Argument(
|
|
456
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
457
|
+
),
|
|
458
|
+
branch_name: str = typer.Argument(..., help="Branch name"),
|
|
459
|
+
profile: Optional[str] = typer.Option(
|
|
460
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
461
|
+
),
|
|
462
|
+
format: str = typer.Option(
|
|
463
|
+
"table",
|
|
464
|
+
"--format",
|
|
465
|
+
"-f",
|
|
466
|
+
help="Output format (table, json, csv)",
|
|
467
|
+
autocompletion=complete_output_format,
|
|
468
|
+
),
|
|
469
|
+
output: Optional[str] = typer.Option(
|
|
470
|
+
None, "--output", "-o", help="Output file path"
|
|
471
|
+
),
|
|
472
|
+
):
|
|
473
|
+
"""Get transaction history for a specific branch."""
|
|
474
|
+
try:
|
|
475
|
+
cache_rid(dataset_rid)
|
|
476
|
+
service = DatasetService(profile=profile)
|
|
477
|
+
|
|
478
|
+
with SpinnerProgressTracker().track_spinner(
|
|
479
|
+
f"Fetching transaction history for branch '{branch_name}' in {dataset_rid}..."
|
|
480
|
+
):
|
|
481
|
+
transactions = service.get_branch_transactions(dataset_rid, branch_name)
|
|
482
|
+
|
|
483
|
+
formatter.format_transactions(transactions, format, output)
|
|
484
|
+
|
|
485
|
+
if output:
|
|
486
|
+
formatter.print_success(f"Branch transactions saved to {output}")
|
|
487
|
+
|
|
488
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
489
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
490
|
+
raise typer.Exit(1)
|
|
491
|
+
except Exception as e:
|
|
492
|
+
formatter.print_error(f"Failed to get branch transactions: {e}")
|
|
493
|
+
raise typer.Exit(1)
|
|
494
|
+
|
|
495
|
+
|
|
192
496
|
# Files commands
|
|
193
497
|
@files_app.command("list")
|
|
194
498
|
def list_files(
|
|
@@ -320,6 +624,93 @@ def get_file(
|
|
|
320
624
|
raise typer.Exit(1)
|
|
321
625
|
|
|
322
626
|
|
|
627
|
+
@files_app.command("delete")
|
|
628
|
+
def delete_file(
|
|
629
|
+
dataset_rid: str = typer.Argument(
|
|
630
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
631
|
+
),
|
|
632
|
+
file_path: str = typer.Argument(..., help="Path of file within dataset to delete"),
|
|
633
|
+
branch: str = typer.Option("master", "--branch", help="Dataset branch"),
|
|
634
|
+
confirm: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
635
|
+
profile: Optional[str] = typer.Option(
|
|
636
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
637
|
+
),
|
|
638
|
+
):
|
|
639
|
+
"""Delete a file from a dataset."""
|
|
640
|
+
try:
|
|
641
|
+
cache_rid(dataset_rid)
|
|
642
|
+
service = DatasetService(profile=profile)
|
|
643
|
+
|
|
644
|
+
# Confirmation prompt
|
|
645
|
+
if not confirm:
|
|
646
|
+
confirmed = typer.confirm(
|
|
647
|
+
f"Are you sure you want to delete '{file_path}' from dataset {dataset_rid}?"
|
|
648
|
+
)
|
|
649
|
+
if not confirmed:
|
|
650
|
+
formatter.print_info("File deletion cancelled")
|
|
651
|
+
raise typer.Exit(0)
|
|
652
|
+
|
|
653
|
+
with SpinnerProgressTracker().track_spinner(
|
|
654
|
+
f"Deleting {file_path} from {dataset_rid}..."
|
|
655
|
+
):
|
|
656
|
+
service.delete_file(dataset_rid, file_path, branch)
|
|
657
|
+
|
|
658
|
+
formatter.print_success(f"File '{file_path}' deleted successfully")
|
|
659
|
+
formatter.print_info(f"Dataset: {dataset_rid}")
|
|
660
|
+
formatter.print_info(f"Branch: {branch}")
|
|
661
|
+
|
|
662
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
663
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
664
|
+
raise typer.Exit(1)
|
|
665
|
+
except Exception as e:
|
|
666
|
+
formatter.print_error(f"Failed to delete file: {e}")
|
|
667
|
+
raise typer.Exit(1)
|
|
668
|
+
|
|
669
|
+
|
|
670
|
+
@files_app.command("info")
|
|
671
|
+
def get_file_info(
|
|
672
|
+
dataset_rid: str = typer.Argument(
|
|
673
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
674
|
+
),
|
|
675
|
+
file_path: str = typer.Argument(..., help="Path of file within dataset"),
|
|
676
|
+
branch: str = typer.Option("master", "--branch", help="Dataset branch"),
|
|
677
|
+
profile: Optional[str] = typer.Option(
|
|
678
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
679
|
+
),
|
|
680
|
+
format: str = typer.Option(
|
|
681
|
+
"table",
|
|
682
|
+
"--format",
|
|
683
|
+
"-f",
|
|
684
|
+
help="Output format (table, json, csv)",
|
|
685
|
+
autocompletion=complete_output_format,
|
|
686
|
+
),
|
|
687
|
+
output: Optional[str] = typer.Option(
|
|
688
|
+
None, "--output", "-o", help="Output file path"
|
|
689
|
+
),
|
|
690
|
+
):
|
|
691
|
+
"""Get metadata information about a file in a dataset."""
|
|
692
|
+
try:
|
|
693
|
+
cache_rid(dataset_rid)
|
|
694
|
+
service = DatasetService(profile=profile)
|
|
695
|
+
|
|
696
|
+
with SpinnerProgressTracker().track_spinner(
|
|
697
|
+
f"Getting file info for {file_path} in {dataset_rid}..."
|
|
698
|
+
):
|
|
699
|
+
file_info = service.get_file_info(dataset_rid, file_path, branch)
|
|
700
|
+
|
|
701
|
+
formatter.format_file_info(file_info, format, output)
|
|
702
|
+
|
|
703
|
+
if output:
|
|
704
|
+
formatter.print_success(f"File information saved to {output}")
|
|
705
|
+
|
|
706
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
707
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
708
|
+
raise typer.Exit(1)
|
|
709
|
+
except Exception as e:
|
|
710
|
+
formatter.print_error(f"Failed to get file info: {e}")
|
|
711
|
+
raise typer.Exit(1)
|
|
712
|
+
|
|
713
|
+
|
|
323
714
|
# Transaction commands
|
|
324
715
|
@transactions_app.command("start")
|
|
325
716
|
def start_transaction(
|
|
@@ -581,6 +972,49 @@ def list_transactions(
|
|
|
581
972
|
raise typer.Exit(1)
|
|
582
973
|
|
|
583
974
|
|
|
975
|
+
@transactions_app.command("build")
|
|
976
|
+
def get_transaction_build(
|
|
977
|
+
dataset_rid: str = typer.Argument(
|
|
978
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
979
|
+
),
|
|
980
|
+
transaction_rid: str = typer.Argument(..., help="Transaction Resource Identifier"),
|
|
981
|
+
profile: Optional[str] = typer.Option(
|
|
982
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
983
|
+
),
|
|
984
|
+
format: str = typer.Option(
|
|
985
|
+
"table",
|
|
986
|
+
"--format",
|
|
987
|
+
"-f",
|
|
988
|
+
help="Output format (table, json, csv)",
|
|
989
|
+
autocompletion=complete_output_format,
|
|
990
|
+
),
|
|
991
|
+
output: Optional[str] = typer.Option(
|
|
992
|
+
None, "--output", "-o", help="Output file path"
|
|
993
|
+
),
|
|
994
|
+
):
|
|
995
|
+
"""Get build information for a transaction."""
|
|
996
|
+
try:
|
|
997
|
+
cache_rid(dataset_rid)
|
|
998
|
+
service = DatasetService(profile=profile)
|
|
999
|
+
|
|
1000
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1001
|
+
f"Fetching build information for transaction {transaction_rid}..."
|
|
1002
|
+
):
|
|
1003
|
+
build_info = service.get_transaction_build(dataset_rid, transaction_rid)
|
|
1004
|
+
|
|
1005
|
+
formatter.format_transaction_build(build_info, format, output)
|
|
1006
|
+
|
|
1007
|
+
if output:
|
|
1008
|
+
formatter.print_success(f"Build information saved to {output}")
|
|
1009
|
+
|
|
1010
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1011
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1012
|
+
raise typer.Exit(1)
|
|
1013
|
+
except Exception as e:
|
|
1014
|
+
formatter.print_error(f"Failed to get transaction build: {e}")
|
|
1015
|
+
raise typer.Exit(1)
|
|
1016
|
+
|
|
1017
|
+
|
|
584
1018
|
# Views commands
|
|
585
1019
|
@views_app.command("list")
|
|
586
1020
|
def list_views(
|
|
@@ -627,6 +1061,223 @@ def list_views(
|
|
|
627
1061
|
raise typer.Exit(1)
|
|
628
1062
|
|
|
629
1063
|
|
|
1064
|
+
@views_app.command("get")
|
|
1065
|
+
def get_view(
|
|
1066
|
+
view_rid: str = typer.Argument(
|
|
1067
|
+
..., help="View Resource Identifier", autocompletion=complete_rid
|
|
1068
|
+
),
|
|
1069
|
+
branch: str = typer.Option("master", "--branch", help="Branch name"),
|
|
1070
|
+
profile: Optional[str] = typer.Option(
|
|
1071
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1072
|
+
),
|
|
1073
|
+
format: str = typer.Option(
|
|
1074
|
+
"table",
|
|
1075
|
+
"--format",
|
|
1076
|
+
"-f",
|
|
1077
|
+
help="Output format (table, json, csv)",
|
|
1078
|
+
autocompletion=complete_output_format,
|
|
1079
|
+
),
|
|
1080
|
+
output: Optional[str] = typer.Option(
|
|
1081
|
+
None, "--output", "-o", help="Output file path"
|
|
1082
|
+
),
|
|
1083
|
+
):
|
|
1084
|
+
"""Get detailed information about a view."""
|
|
1085
|
+
try:
|
|
1086
|
+
cache_rid(view_rid)
|
|
1087
|
+
service = DatasetService(profile=profile)
|
|
1088
|
+
|
|
1089
|
+
with SpinnerProgressTracker().track_spinner(f"Fetching view {view_rid}..."):
|
|
1090
|
+
view = service.get_view(view_rid, branch)
|
|
1091
|
+
|
|
1092
|
+
formatter.format_view_detail(view, format, output)
|
|
1093
|
+
|
|
1094
|
+
if output:
|
|
1095
|
+
formatter.print_success(f"View information saved to {output}")
|
|
1096
|
+
|
|
1097
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1098
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1099
|
+
raise typer.Exit(1)
|
|
1100
|
+
except Exception as e:
|
|
1101
|
+
formatter.print_error(f"Failed to get view: {e}")
|
|
1102
|
+
raise typer.Exit(1)
|
|
1103
|
+
|
|
1104
|
+
|
|
1105
|
+
@views_app.command("add-datasets")
|
|
1106
|
+
def add_backing_datasets(
|
|
1107
|
+
view_rid: str = typer.Argument(
|
|
1108
|
+
..., help="View Resource Identifier", autocompletion=complete_rid
|
|
1109
|
+
),
|
|
1110
|
+
dataset_rids: list[str] = typer.Argument(
|
|
1111
|
+
..., help="Dataset RIDs to add as backing datasets"
|
|
1112
|
+
),
|
|
1113
|
+
profile: Optional[str] = typer.Option(
|
|
1114
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1115
|
+
),
|
|
1116
|
+
format: str = typer.Option(
|
|
1117
|
+
"table",
|
|
1118
|
+
"--format",
|
|
1119
|
+
"-f",
|
|
1120
|
+
help="Output format (table, json, csv)",
|
|
1121
|
+
autocompletion=complete_output_format,
|
|
1122
|
+
),
|
|
1123
|
+
):
|
|
1124
|
+
"""Add backing datasets to a view."""
|
|
1125
|
+
try:
|
|
1126
|
+
cache_rid(view_rid)
|
|
1127
|
+
service = DatasetService(profile=profile)
|
|
1128
|
+
|
|
1129
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1130
|
+
f"Adding {len(dataset_rids)} backing datasets to view {view_rid}..."
|
|
1131
|
+
):
|
|
1132
|
+
result = service.add_backing_datasets(view_rid, dataset_rids)
|
|
1133
|
+
|
|
1134
|
+
formatter.print_success("Successfully added backing datasets to view")
|
|
1135
|
+
formatter.print_info(f"View RID: {view_rid}")
|
|
1136
|
+
formatter.print_info(f"Added datasets: {', '.join(dataset_rids)}")
|
|
1137
|
+
|
|
1138
|
+
if format == "json":
|
|
1139
|
+
formatter._format_json(result)
|
|
1140
|
+
|
|
1141
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1142
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1143
|
+
raise typer.Exit(1)
|
|
1144
|
+
except Exception as e:
|
|
1145
|
+
formatter.print_error(f"Failed to add backing datasets: {e}")
|
|
1146
|
+
raise typer.Exit(1)
|
|
1147
|
+
|
|
1148
|
+
|
|
1149
|
+
@views_app.command("remove-datasets")
|
|
1150
|
+
def remove_backing_datasets(
|
|
1151
|
+
view_rid: str = typer.Argument(
|
|
1152
|
+
..., help="View Resource Identifier", autocompletion=complete_rid
|
|
1153
|
+
),
|
|
1154
|
+
dataset_rids: list[str] = typer.Argument(
|
|
1155
|
+
..., help="Dataset RIDs to remove as backing datasets"
|
|
1156
|
+
),
|
|
1157
|
+
profile: Optional[str] = typer.Option(
|
|
1158
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1159
|
+
),
|
|
1160
|
+
format: str = typer.Option(
|
|
1161
|
+
"table",
|
|
1162
|
+
"--format",
|
|
1163
|
+
"-f",
|
|
1164
|
+
help="Output format (table, json, csv)",
|
|
1165
|
+
autocompletion=complete_output_format,
|
|
1166
|
+
),
|
|
1167
|
+
):
|
|
1168
|
+
"""Remove backing datasets from a view."""
|
|
1169
|
+
try:
|
|
1170
|
+
cache_rid(view_rid)
|
|
1171
|
+
service = DatasetService(profile=profile)
|
|
1172
|
+
|
|
1173
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1174
|
+
f"Removing {len(dataset_rids)} backing datasets from view {view_rid}..."
|
|
1175
|
+
):
|
|
1176
|
+
result = service.remove_backing_datasets(view_rid, dataset_rids)
|
|
1177
|
+
|
|
1178
|
+
formatter.print_success("Successfully removed backing datasets from view")
|
|
1179
|
+
formatter.print_info(f"View RID: {view_rid}")
|
|
1180
|
+
formatter.print_info(f"Removed datasets: {', '.join(dataset_rids)}")
|
|
1181
|
+
|
|
1182
|
+
if format == "json":
|
|
1183
|
+
formatter._format_json(result)
|
|
1184
|
+
|
|
1185
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1186
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1187
|
+
raise typer.Exit(1)
|
|
1188
|
+
except Exception as e:
|
|
1189
|
+
formatter.print_error(f"Failed to remove backing datasets: {e}")
|
|
1190
|
+
raise typer.Exit(1)
|
|
1191
|
+
|
|
1192
|
+
|
|
1193
|
+
@views_app.command("replace-datasets")
|
|
1194
|
+
def replace_backing_datasets(
|
|
1195
|
+
view_rid: str = typer.Argument(
|
|
1196
|
+
..., help="View Resource Identifier", autocompletion=complete_rid
|
|
1197
|
+
),
|
|
1198
|
+
dataset_rids: list[str] = typer.Argument(
|
|
1199
|
+
..., help="Dataset RIDs to set as backing datasets"
|
|
1200
|
+
),
|
|
1201
|
+
profile: Optional[str] = typer.Option(
|
|
1202
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1203
|
+
),
|
|
1204
|
+
format: str = typer.Option(
|
|
1205
|
+
"table",
|
|
1206
|
+
"--format",
|
|
1207
|
+
"-f",
|
|
1208
|
+
help="Output format (table, json, csv)",
|
|
1209
|
+
autocompletion=complete_output_format,
|
|
1210
|
+
),
|
|
1211
|
+
):
|
|
1212
|
+
"""Replace all backing datasets in a view."""
|
|
1213
|
+
try:
|
|
1214
|
+
cache_rid(view_rid)
|
|
1215
|
+
service = DatasetService(profile=profile)
|
|
1216
|
+
|
|
1217
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1218
|
+
f"Replacing backing datasets in view {view_rid} with {len(dataset_rids)} new datasets..."
|
|
1219
|
+
):
|
|
1220
|
+
result = service.replace_backing_datasets(view_rid, dataset_rids)
|
|
1221
|
+
|
|
1222
|
+
formatter.print_success("Successfully replaced backing datasets in view")
|
|
1223
|
+
formatter.print_info(f"View RID: {view_rid}")
|
|
1224
|
+
formatter.print_info(f"New datasets: {', '.join(dataset_rids)}")
|
|
1225
|
+
|
|
1226
|
+
if format == "json":
|
|
1227
|
+
formatter._format_json(result)
|
|
1228
|
+
|
|
1229
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1230
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1231
|
+
raise typer.Exit(1)
|
|
1232
|
+
except Exception as e:
|
|
1233
|
+
formatter.print_error(f"Failed to replace backing datasets: {e}")
|
|
1234
|
+
raise typer.Exit(1)
|
|
1235
|
+
|
|
1236
|
+
|
|
1237
|
+
@views_app.command("add-primary-key")
|
|
1238
|
+
def add_primary_key(
|
|
1239
|
+
view_rid: str = typer.Argument(
|
|
1240
|
+
..., help="View Resource Identifier", autocompletion=complete_rid
|
|
1241
|
+
),
|
|
1242
|
+
key_fields: list[str] = typer.Argument(
|
|
1243
|
+
..., help="Field names to use as primary key"
|
|
1244
|
+
),
|
|
1245
|
+
profile: Optional[str] = typer.Option(
|
|
1246
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1247
|
+
),
|
|
1248
|
+
format: str = typer.Option(
|
|
1249
|
+
"table",
|
|
1250
|
+
"--format",
|
|
1251
|
+
"-f",
|
|
1252
|
+
help="Output format (table, json, csv)",
|
|
1253
|
+
autocompletion=complete_output_format,
|
|
1254
|
+
),
|
|
1255
|
+
):
|
|
1256
|
+
"""Add a primary key to a view."""
|
|
1257
|
+
try:
|
|
1258
|
+
cache_rid(view_rid)
|
|
1259
|
+
service = DatasetService(profile=profile)
|
|
1260
|
+
|
|
1261
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1262
|
+
f"Adding primary key to view {view_rid}..."
|
|
1263
|
+
):
|
|
1264
|
+
result = service.add_primary_key(view_rid, key_fields)
|
|
1265
|
+
|
|
1266
|
+
formatter.print_success("Successfully added primary key to view")
|
|
1267
|
+
formatter.print_info(f"View RID: {view_rid}")
|
|
1268
|
+
formatter.print_info(f"Primary key fields: {', '.join(key_fields)}")
|
|
1269
|
+
|
|
1270
|
+
if format == "json":
|
|
1271
|
+
formatter._format_json(result)
|
|
1272
|
+
|
|
1273
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1274
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1275
|
+
raise typer.Exit(1)
|
|
1276
|
+
except Exception as e:
|
|
1277
|
+
formatter.print_error(f"Failed to add primary key: {e}")
|
|
1278
|
+
raise typer.Exit(1)
|
|
1279
|
+
|
|
1280
|
+
|
|
630
1281
|
@views_app.command("create")
|
|
631
1282
|
def create_view(
|
|
632
1283
|
dataset_rid: str = typer.Argument(
|
|
@@ -671,11 +1322,101 @@ def create_view(
|
|
|
671
1322
|
raise typer.Exit(1)
|
|
672
1323
|
|
|
673
1324
|
|
|
1325
|
+
# Schedules commands
|
|
1326
|
+
@schedules_app.command("list")
|
|
1327
|
+
def list_schedules(
|
|
1328
|
+
dataset_rid: str = typer.Argument(
|
|
1329
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
1330
|
+
),
|
|
1331
|
+
profile: Optional[str] = typer.Option(
|
|
1332
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1333
|
+
),
|
|
1334
|
+
format: str = typer.Option(
|
|
1335
|
+
"table",
|
|
1336
|
+
"--format",
|
|
1337
|
+
"-f",
|
|
1338
|
+
help="Output format (table, json, csv)",
|
|
1339
|
+
autocompletion=complete_output_format,
|
|
1340
|
+
),
|
|
1341
|
+
output: Optional[str] = typer.Option(
|
|
1342
|
+
None, "--output", "-o", help="Output file path"
|
|
1343
|
+
),
|
|
1344
|
+
):
|
|
1345
|
+
"""List schedules that target a specific dataset."""
|
|
1346
|
+
try:
|
|
1347
|
+
cache_rid(dataset_rid)
|
|
1348
|
+
service = DatasetService(profile=profile)
|
|
1349
|
+
|
|
1350
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1351
|
+
f"Fetching schedules for dataset {dataset_rid}..."
|
|
1352
|
+
):
|
|
1353
|
+
schedules = service.get_schedules(dataset_rid)
|
|
1354
|
+
|
|
1355
|
+
formatter.format_schedules(schedules, format, output)
|
|
1356
|
+
|
|
1357
|
+
if output:
|
|
1358
|
+
formatter.print_success(f"Schedules information saved to {output}")
|
|
1359
|
+
|
|
1360
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1361
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1362
|
+
raise typer.Exit(1)
|
|
1363
|
+
except Exception as e:
|
|
1364
|
+
formatter.print_error(f"Failed to get schedules: {e}")
|
|
1365
|
+
raise typer.Exit(1)
|
|
1366
|
+
|
|
1367
|
+
|
|
1368
|
+
# Jobs commands
|
|
1369
|
+
@jobs_app.command("list")
|
|
1370
|
+
def list_jobs(
|
|
1371
|
+
dataset_rid: str = typer.Argument(
|
|
1372
|
+
..., help="Dataset Resource Identifier", autocompletion=complete_rid
|
|
1373
|
+
),
|
|
1374
|
+
branch: str = typer.Option("master", "--branch", help="Dataset branch"),
|
|
1375
|
+
profile: Optional[str] = typer.Option(
|
|
1376
|
+
None, "--profile", "-p", help="Profile name", autocompletion=complete_profile
|
|
1377
|
+
),
|
|
1378
|
+
format: str = typer.Option(
|
|
1379
|
+
"table",
|
|
1380
|
+
"--format",
|
|
1381
|
+
"-f",
|
|
1382
|
+
help="Output format (table, json, csv)",
|
|
1383
|
+
autocompletion=complete_output_format,
|
|
1384
|
+
),
|
|
1385
|
+
output: Optional[str] = typer.Option(
|
|
1386
|
+
None, "--output", "-o", help="Output file path"
|
|
1387
|
+
),
|
|
1388
|
+
):
|
|
1389
|
+
"""List jobs for a specific dataset."""
|
|
1390
|
+
try:
|
|
1391
|
+
cache_rid(dataset_rid)
|
|
1392
|
+
service = DatasetService(profile=profile)
|
|
1393
|
+
|
|
1394
|
+
with SpinnerProgressTracker().track_spinner(
|
|
1395
|
+
f"Fetching jobs for dataset {dataset_rid} (branch: {branch})..."
|
|
1396
|
+
):
|
|
1397
|
+
jobs = service.get_jobs(dataset_rid, branch)
|
|
1398
|
+
|
|
1399
|
+
formatter.format_jobs(jobs, format, output)
|
|
1400
|
+
|
|
1401
|
+
if output:
|
|
1402
|
+
formatter.print_success(f"Jobs information saved to {output}")
|
|
1403
|
+
|
|
1404
|
+
except (ProfileNotFoundError, MissingCredentialsError) as e:
|
|
1405
|
+
formatter.print_error(f"Authentication error: {e}")
|
|
1406
|
+
raise typer.Exit(1)
|
|
1407
|
+
except Exception as e:
|
|
1408
|
+
formatter.print_error(f"Failed to get jobs: {e}")
|
|
1409
|
+
raise typer.Exit(1)
|
|
1410
|
+
|
|
1411
|
+
|
|
674
1412
|
# Add subcommands to main app
|
|
675
1413
|
app.add_typer(branches_app, name="branches")
|
|
676
1414
|
app.add_typer(files_app, name="files")
|
|
677
1415
|
app.add_typer(transactions_app, name="transactions")
|
|
678
1416
|
app.add_typer(views_app, name="views")
|
|
1417
|
+
app.add_typer(schema_app, name="schema")
|
|
1418
|
+
app.add_typer(schedules_app, name="schedules")
|
|
1419
|
+
app.add_typer(jobs_app, name="jobs")
|
|
679
1420
|
|
|
680
1421
|
|
|
681
1422
|
@app.callback()
|