@@ -496,18 +496,10 @@ def _rollback_interactive(ctx: typer.Context) -> None:
496496 pass
497497
498498
499- @app .command ()
500- def delete (
501- ctx : typer .Context ,
502- name : str = typer .Argument (..., help = "The logical name of the dataset to delete." ),
503- ) -> None :
504- """
505- Marks a dataset for permanent deletion.
506- This action is finalized via a Pull Request and CI/CD pipeline.
507- """
499+ def _run_delete_logic (ctx : typer .Context , name : str ) -> None :
500+ """The core logic for marking a dataset for deletion."""
508501 console .print (f"🗑️ Preparing deletion for [bold red]{ name } [/]." )
509502
510- # Verify the dataset exists before proceeding
511503 if not manifest .get_dataset (name ):
512504 console .print (f"[red]Error: Dataset '{ name } ' not found.[/]" )
513505 raise typer .Exit (1 )
@@ -516,7 +508,6 @@ def delete(
516508 "[bold yellow]WARNING:[/] This will propose the [underline]permanent deletion[/] of the dataset and all its version history from Cloudflare R2."
517509 )
518510
519- # Use a text prompt for strong confirmation
520511 confirmation = questionary .text (
521512 f"To confirm, please type the name of the dataset ({ name } ):"
522513 ).ask ()
@@ -525,7 +516,6 @@ def delete(
525516 console .print ("Confirmation failed. Deletion cancelled." )
526517 return
527518
528- # Mark the dataset for deletion in the manifest
529519 if manifest .mark_for_deletion (name ):
530520 console .print (
531521 f"\n [bold green]✅ Dataset '{ name } ' has been marked for deletion.[/]"
@@ -538,20 +528,13 @@ def delete(
538528 " 4. Open a Pull Request to finalize the deletion."
539529 )
540530 else :
541- # This case should be caught by the check above, but is here for safety
542531 console .print (f"[red]Error: Could not mark '{ name } ' for deletion.[/]" )
543532 raise typer .Exit (1 )
544533
545534
546- @app .command ()
547- def prune_versions (
548- ctx : typer .Context ,
549- name : str = typer .Argument (..., help = "The logical name of the dataset to prune." ),
550- keep : int = typer .Option (
551- ..., "--keep" , "-k" , help = "The number of most recent versions to keep."
552- ),
553- ) -> None :
554- """Marks old versions of a dataset for permanent deletion."""
535+ # --- New Refactored Prune Logic ---
536+ def _run_prune_versions_logic (ctx : typer .Context , name : str , keep : int ) -> None :
537+ """The core logic for marking old versions for deletion."""
555538 console .print (f"🔪 Preparing to prune old versions of [cyan]{ name } [/]..." )
556539
557540 dataset = manifest .get_dataset (name )
@@ -586,7 +569,6 @@ def prune_versions(
586569 console .print ("Pruning cancelled." )
587570 return
588571
589- # Mark the versions for deletion in the manifest
590572 manifest .mark_versions_for_deletion (name , versions_to_delete )
591573 console .print (
592574 f"\n [bold green]✅ { len (versions_to_delete )} version(s) have been marked for deletion.[/]"
@@ -600,6 +582,87 @@ def prune_versions(
600582 )
601583
602584
585+ # --- Updated CLI Commands (now thin wrappers) ---
586+ @app .command ()
587+ def delete (
588+ ctx : typer .Context ,
589+ name : str = typer .Argument (..., help = "The logical name of the dataset to delete." ),
590+ ) -> None :
591+ """Marks a dataset for permanent deletion via a PR."""
592+ _run_delete_logic (ctx , name )
593+
594+
595+ @app .command ()
596+ def prune_versions (
597+ ctx : typer .Context ,
598+ name : str = typer .Argument (..., help = "The logical name of the dataset to prune." ),
599+ keep : int = typer .Option (
600+ ..., "--keep" , "-k" , help = "The number of most recent versions to keep."
601+ ),
602+ ) -> None :
603+ """Marks old versions of a dataset for permanent deletion via a PR."""
604+ _run_prune_versions_logic (ctx , name , keep )
605+
606+
607+ # --- New Interactive Functions for TUI ---
608+ def _delete_interactive (ctx : typer .Context ) -> None :
609+ """Guides the user through deleting a dataset interactively."""
610+ console .print ("\n [bold]Interactive Dataset Deletion[/]" )
611+ all_datasets = manifest .read_manifest ()
612+ if not all_datasets :
613+ console .print ("[yellow]No datasets found to delete.[/]" )
614+ return
615+
616+ dataset_names = [ds ["fileName" ] for ds in all_datasets ]
617+ selected_name = questionary .select (
618+ "Which dataset would you like to mark for deletion?" , choices = dataset_names
619+ ).ask ()
620+
621+ if selected_name is None :
622+ console .print ("Deletion cancelled." )
623+ return
624+
625+ try :
626+ _run_delete_logic (ctx , name = selected_name )
627+ except typer .Exit :
628+ pass
629+
630+
631+ def _prune_versions_interactive (ctx : typer .Context ) -> None :
632+ """Guides the user through pruning old versions interactively."""
633+ console .print ("\n [bold]Interactive Version Pruning[/]" )
634+ all_datasets = manifest .read_manifest ()
635+ if not all_datasets :
636+ console .print ("[yellow]No datasets found to prune.[/]" )
637+ return
638+
639+ dataset_names = [ds ["fileName" ] for ds in all_datasets ]
640+ selected_name = questionary .select (
641+ "Which dataset would you like to prune?" , choices = dataset_names
642+ ).ask ()
643+
644+ if selected_name is None :
645+ console .print ("Pruning cancelled." )
646+ return
647+
648+ keep_str = questionary .text (
649+ "How many of the most recent versions do you want to keep?" ,
650+ validate = lambda text : text .isdigit ()
651+ and int (text ) > 0
652+ or "Please enter a positive number." ,
653+ ).ask ()
654+
655+ if keep_str is None :
656+ console .print ("Pruning cancelled." )
657+ return
658+
659+ try :
660+ _run_prune_versions_logic (ctx , name = selected_name , keep = int (keep_str ))
661+ except typer .Exit :
662+ pass
663+
664+
665+ # --- Final, Corrected Main TUI Callback ---
603666@app .callback (invoke_without_command = True )
604667def main (ctx : typer .Context , no_prompt : bool = COMMON_OPTIONS ["no_prompt" ]) -> None :
605668 """
@@ -609,7 +672,6 @@ def main(ctx: typer.Context, no_prompt: bool = COMMON_OPTIONS["no_prompt"]) -> N
609672 ctx .ensure_object (dict )
610673 ctx .obj ["no_prompt" ] = no_prompt
611674
612- # If a sub-command was provided just return – ctx.obj is now populated.
613675 if ctx .invoked_subcommand :
614676 return
615677
@@ -620,13 +682,13 @@ def main(ctx: typer.Context, no_prompt: bool = COMMON_OPTIONS["no_prompt"]) -> N
620682 console .print ("[bold yellow]Welcome to the Data Manager TUI![/]" )
621683
622684 actions : dict [str , Callable [[typer .Context ], None ] | str ] = {
623- "Verify R2 configuration" : verify ,
624685 "List all datasets" : list_datasets ,
625686 "Prepare a dataset for release" : _prepare_interactive ,
626687 "Pull a dataset version" : _pull_interactive ,
627688 "Rollback a dataset to a previous version" : _rollback_interactive ,
628- "Delete a dataset" : delete ,
629- "Prune old dataset versions" : prune_versions ,
689+ "Delete a dataset" : _delete_interactive ,
690+ "Prune old dataset versions" : _prune_versions_interactive ,
691+ "Verify R2 configuration" : verify ,
630692 "Exit" : "exit" ,
631693 }
632694
@@ -640,9 +702,7 @@ def main(ctx: typer.Context, no_prompt: bool = COMMON_OPTIONS["no_prompt"]) -> N
640702
641703 action = actions [choice ]
642704 if callable (action ):
643- # Call the function directly
644705 action (ctx )
645-
646706 else :
647707 raise NotImplementedError (f"Action '{ choice } ' is not implemented yet." )
648708
0 commit comments