diff --git a/cbrain_cli/data/projects.py b/cbrain_cli/data/projects.py index 58ff27b..de27047 100644 --- a/cbrain_cli/data/projects.py +++ b/cbrain_cli/data/projects.py @@ -27,9 +27,8 @@ def switch_project(args): return None # Handle the special case of "all" - if group_id == "all": - print("Project switch 'all' not yet implemented as of Aug 2025") - return None + if group_id.lower() == "all": + return _perform_project_unswitch() # Convert to integer for regular group IDs try: @@ -164,3 +163,38 @@ def list_projects(args): projects_data = json.loads(data) return projects_data + + +def _perform_project_unswitch(): + """Internal helper to clear project keys from the credentials file.""" + try: + from cbrain_cli.config import CREDENTIALS_FILE + + # 1. Check if the file even exists + if not CREDENTIALS_FILE.exists(): + print("No active session found. You are already viewing 'All Projects'.") + return {"name": "All Projects"} + + # 2. Read the file + with open(CREDENTIALS_FILE, "r") as f: + credentials = json.load(f) + + # 3. Clear the keys + credentials.pop("current_group_id", None) + credentials.pop("current_group_name", None) + credentials.pop("current_project_id", None) + + # 4. Save back to file + with open(CREDENTIALS_FILE, "w") as f: + json.dump(credentials, f, indent=2) + + print("Successfully unswitched. Now viewing 'All Projects'.") + return {"name": "All Projects"} + + except Exception as e: + print(f"Error during unswitch: {e}") + return None + +def unswitch_project(args): + """Handler for the 'cbrain project unswitch' command.""" + return _perform_project_unswitch() \ No newline at end of file diff --git a/cbrain_cli/handlers.py b/cbrain_cli/handlers.py index 83c0ccf..5aaa7a7 100644 --- a/cbrain_cli/handlers.py +++ b/cbrain_cli/handlers.py @@ -24,7 +24,7 @@ show_file, upload_file, ) -from cbrain_cli.data.projects import list_projects, show_project, switch_project +from cbrain_cli.data.projects import list_projects, show_project, switch_project, unswitch_project from cbrain_cli.data.remote_resources import list_remote_resources, show_remote_resource from cbrain_cli.data.tags import create_tag, delete_tag, list_tags, show_tag, update_tag from cbrain_cli.data.tasks import list_tasks, show_task @@ -174,8 +174,10 @@ def handle_project_show(args): def handle_project_unswitch(args): - """Unswitch from current project context.""" - print("Project Unswitch 'all' not yet implemented as of Aug 2025") + """Unswitch from current project context by reverting to 'All Projects'.""" + result = unswitch_project(args) + if result: + print_current_project(result) # Tool command handlers diff --git a/cbrain_cli/main.py b/cbrain_cli/main.py index 41e2d07..7850292 100644 --- a/cbrain_cli/main.py +++ b/cbrain_cli/main.py @@ -88,7 +88,7 @@ def main(): # file list file_list_parser = file_subparsers.add_parser("list", help="List files") - file_list_parser.add_argument("--group-id", type=int, help="Filter files by group ID") + file_list_parser.add_argument("--group-id", "--project-id", type=int, dest="group_id", help="Filter files by Group/Project ID") file_list_parser.add_argument("--dp-id", type=int, help="Filter files by data provider ID") file_list_parser.add_argument("--user-id", type=int, help="Filter files by user ID") file_list_parser.add_argument("--parent-id", type=int, help="Filter files by parent ID") @@ -110,7 +110,8 @@ def main(): file_upload_parser.add_argument( "--data-provider", type=int, required=True, help="Data provider ID" ) - file_upload_parser.add_argument("--group-id", type=int, help="Group ID") + file_upload_parser.add_argument("--group-id", "--project-id", type=int, dest="group_id", help="Group/Project ID") + file_upload_parser.add_argument("--file-type", type=str, default="SingleFile", help="File type (default: SingleFile)") file_upload_parser.set_defaults(func=handle_errors(handle_file_upload)) @@ -303,7 +304,7 @@ def main(): tag_create_parser = tag_subparsers.add_parser("create", help="Create a new tag") tag_create_parser.add_argument("--name", type=str, required=True, help="Tag name") tag_create_parser.add_argument("--user-id", type=int, required=True, help="User ID") - tag_create_parser.add_argument("--group-id", type=int, required=True, help="Group ID") + tag_create_parser.add_argument("--group-id", "--project-id", type=int, required=True, dest="group_id", help="Group/Project ID") tag_create_parser.set_defaults(func=handle_errors(handle_tag_create)) # tag update @@ -315,7 +316,7 @@ def main(): ) tag_update_parser.add_argument("--name", type=str, required=True, help="Tag name") tag_update_parser.add_argument("--user-id", type=int, required=True, help="User ID") - tag_update_parser.add_argument("--group-id", type=int, required=True, help="Group ID") + tag_update_parser.add_argument("--group-id", "--project-id", type=int, required=True, dest="group_id", help="Group/Project ID") tag_update_parser.set_defaults(func=handle_errors(handle_tag_update)) # tag delete @@ -399,23 +400,20 @@ def main(): # MARK: Setup CLI args = parser.parse_args() + if args.command == "version": + return handle_errors(version_info)(args) if not args.command: - parser.print_help() - return - + parser.print_help(file=sys.stderr) + return 1 + # Handle session commands (no authentication needed for login, version, and whoami). if args.command == "login": return handle_errors(create_session)(args) - elif args.command == "version": - return handle_errors(version_info)(args) + elif args.command == "whoami": return handle_errors(whoami_user)(args) - # All other commands require authentication. - if not is_authenticated(): - return 1 - # Handle authenticated commands. if args.command == "logout": return handle_errors(logout_session)(args) @@ -433,23 +431,23 @@ def main(): if not hasattr(args, "action") or not args.action: # Show help for the specific model command. if args.command == "file": - file_parser.print_help() + file_parser.print_help(file=sys.stderr) elif args.command == "dataprovider": - dataprovider_parser.print_help() + dataprovider_parser.print_help(file=sys.stderr) elif args.command == "project": - project_parser.print_help() + project_parser.print_help(file=sys.stderr) elif args.command == "tool": - tool_parser.print_help() + tool_parser.print_help(file=sys.stderr) elif args.command == "tool-config": - tool_configs_parser.print_help() + tool_configs_parser.print_help(file=sys.stderr) elif args.command == "tag": - tag_parser.print_help() + tag_parser.print_help(file=sys.stderr) elif args.command == "background": - background_parser.print_help() + background_parser.print_help(file=sys.stderr) elif args.command == "task": - task_parser.print_help() + task_parser.print_help(file=sys.stderr) elif args.command == "remote-resource": - remote_resource_parser.print_help() + remote_resource_parser.print_help(file=sys.stderr) return 1 else: # Execute the function associated with the command.