Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions cbrain_cli/data/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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()
8 changes: 5 additions & 3 deletions cbrain_cli/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
42 changes: 20 additions & 22 deletions cbrain_cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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))

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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.
Expand Down