Skip to content

Commit 40af36d

Browse files
committed
Enhance project show command to support displaying specific project details by ID
1 parent ef63fa6 commit 40af36d

5 files changed

Lines changed: 140 additions & 45 deletions

File tree

capture_tests/expected_captures.txt

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ Stdout: 30 bytes
7575
Stderr: 0 bytes
7676

7777
Stdout:
78-
cbrain cli client version 0.9
78+
cbrain cli client version 1.0
7979
Stderr:
8080
(No output)
8181

@@ -418,33 +418,45 @@ Stderr:
418418
############################
419419
Command: cbrain project show 10
420420
Status: 0
421-
Stdout: TOFIX bytes
421+
Stdout: 198 bytes
422422
Stderr: 0 bytes
423423

424424
Stdout:
425-
TOFIX
425+
PROJECT DETAILS
426+
------------------------------
427+
Field Value
428+
--------- ---------
429+
ID 10
430+
Name NormTest1
431+
Type WorkGroup
432+
Site ID N/A
433+
Invisible N/A
426434
Stderr:
427435
(No output)
428436

429437
############################
430438
Command: cbrain --json project show 10
431439
Status: 0
432-
Stdout: TOFIX bytes
440+
Stdout: 85 bytes
433441
Stderr: 0 bytes
434442

435443
Stdout:
436-
TOFIX
444+
{
445+
"id": 10,
446+
"name": "NormTest1",
447+
"type": "WorkGroup"
448+
}
437449
Stderr:
438450
(No output)
439451

440452
############################
441453
Command: cbrain --jsonl project show 10
442454
Status: 0
443-
Stdout: TOFIX bytes
455+
Stdout: 48 bytes
444456
Stderr: 0 bytes
445457

446458
Stdout:
447-
TOFIX
459+
{"id":10,"name":"NormTest1","type":"WorkGroup"}
448460
Stderr:
449461
(No output)
450462

@@ -495,7 +507,7 @@ Stderr:
495507
############################
496508
Command: cbrain --json project switch all
497509
Status: 0
498-
Stdout: 40 bytes
510+
Stdout: 56 bytes
499511
Stderr: 0 bytes
500512

501513
Stdout:
@@ -506,7 +518,7 @@ Stderr:
506518
############################
507519
Command: cbrain --jsonl project switch all
508520
Status: 0
509-
Stdout: 40 bytes
521+
Stdout: 56 bytes
510522
Stderr: 0 bytes
511523

512524
Stdout:
@@ -644,7 +656,7 @@ Stderr:
644656

645657
############################
646658
Command: cbrain tag update 99 --name Renamed --user-id 2 --group-id 3
647-
Status: 0
659+
Status: 1
648660
Stdout: 37 bytes
649661
Stderr: 0 bytes
650662

@@ -1117,6 +1129,7 @@ Stderr: 0 bytes
11171129
Stdout:
11181130
Authentication error (401): Unauthorized
11191131
Error: Access denied. Please log in using authorized credentials.
1132+
Stderr:
11201133
(No output)
11211134

11221135
############################

cbrain_cli/data/projects.py

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -71,48 +71,70 @@ def switch_project(args):
7171

7272
def show_project(args):
7373
"""
74-
Get the current project/group from credentials.
74+
Get the current project/group from credentials or show a specific project by ID.
7575
7676
Parameters
7777
----------
7878
args : argparse.Namespace
79-
Command line arguments
79+
Command line arguments, may include project_id
8080
8181
Returns
8282
-------
8383
dict or None
8484
Dictionary containing project details if successful, None if no project set
8585
"""
86-
with open(CREDENTIALS_FILE) as f:
87-
credentials = json.load(f)
88-
89-
current_group_id = credentials.get("current_group_id")
90-
if not current_group_id:
91-
return None
92-
93-
# Get fresh group details from server
94-
group_endpoint = f"{cbrain_url}/groups/{current_group_id}"
95-
headers = auth_headers(api_token)
96-
97-
request = urllib.request.Request(group_endpoint, data=None, headers=headers, method="GET")
98-
99-
try:
100-
with urllib.request.urlopen(request) as response:
101-
data = response.read().decode("utf-8")
102-
group_data = json.loads(data)
103-
return group_data
104-
105-
except urllib.error.HTTPError as e:
106-
if e.code == 404:
107-
print(f"Error: Current project (ID {current_group_id}) no longer exists")
108-
# Clear the invalid group_id from credentials
109-
credentials.pop("current_group_id", None)
110-
credentials.pop("current_group_name", None)
111-
with open(CREDENTIALS_FILE, "w") as f:
112-
json.dump(credentials, f, indent=2)
86+
# Check if a specific project ID was provided
87+
project_id = getattr(args, "project_id", None)
88+
89+
if project_id:
90+
# Show specific project by ID
91+
group_endpoint = f"{cbrain_url}/groups/{project_id}"
92+
headers = auth_headers(api_token)
93+
request = urllib.request.Request(group_endpoint, data=None, headers=headers, method="GET")
94+
95+
try:
96+
with urllib.request.urlopen(request) as response:
97+
data = response.read().decode("utf-8")
98+
group_data = json.loads(data)
99+
return group_data
100+
except urllib.error.HTTPError as e:
101+
if e.code == 404:
102+
print(f"Error: Project with ID {project_id} not found")
103+
return None
104+
else:
105+
raise
106+
else:
107+
# Show current project from credentials
108+
with open(CREDENTIALS_FILE) as f:
109+
credentials = json.load(f)
110+
111+
current_group_id = credentials.get("current_group_id")
112+
if not current_group_id:
113113
return None
114-
else:
115-
raise
114+
115+
# Get fresh group details from server
116+
group_endpoint = f"{cbrain_url}/groups/{current_group_id}"
117+
headers = auth_headers(api_token)
118+
119+
request = urllib.request.Request(group_endpoint, data=None, headers=headers, method="GET")
120+
121+
try:
122+
with urllib.request.urlopen(request) as response:
123+
data = response.read().decode("utf-8")
124+
group_data = json.loads(data)
125+
return group_data
126+
127+
except urllib.error.HTTPError as e:
128+
if e.code == 404:
129+
print(f"Error: Current project (ID {current_group_id}) no longer exists")
130+
# Clear the invalid group_id from credentials
131+
credentials.pop("current_group_id", None)
132+
credentials.pop("current_group_name", None)
133+
with open(CREDENTIALS_FILE, "w") as f:
134+
json.dump(credentials, f, indent=2)
135+
return None
136+
else:
137+
raise
116138

117139

118140
def list_projects(args):

cbrain_cli/formatter/projects_fmt.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,49 @@ def print_current_project(project_data):
4545
print(f'Current project is "{group_name}" ID={group_id}')
4646

4747

48+
def print_project_details(project_data, args):
49+
"""
50+
Print detailed information about a specific project.
51+
52+
Parameters
53+
----------
54+
project_data : dict
55+
Dictionary containing project details
56+
args : argparse.Namespace
57+
Command line arguments, including the --json flag
58+
"""
59+
if getattr(args, "json", False):
60+
json_printer(project_data)
61+
return
62+
elif getattr(args, "jsonl", False):
63+
jsonl_printer(project_data)
64+
return
65+
66+
print("PROJECT DETAILS")
67+
print("-" * 30)
68+
69+
# Basic project information
70+
basic_info = [
71+
{"field": "ID", "value": str(project_data.get("id", "N/A"))},
72+
{"field": "Name", "value": str(project_data.get("name", "N/A"))},
73+
{"field": "Type", "value": str(project_data.get("type", "N/A"))},
74+
{"field": "Site ID", "value": str(project_data.get("site_id", "N/A"))},
75+
{"field": "Invisible", "value": str(project_data.get("invisible", "N/A"))},
76+
]
77+
78+
dynamic_table_print(basic_info, ["field", "value"], ["Field", "Value"])
79+
80+
# Display description if available
81+
if project_data.get("description"):
82+
print()
83+
print("DESCRIPTION")
84+
print("-" * 30)
85+
description = project_data.get("description").strip()
86+
# Handle multi-line descriptions
87+
for line in description.split("\n"):
88+
print(f"{line}")
89+
90+
4891
def print_no_project():
4992
"""
5093
Print message when no current project is set.

cbrain_cli/handlers.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,24 @@ def handle_project_switch(args):
153153

154154

155155
def handle_project_show(args):
156-
"""Display information about the currently active project or indicate if none is set."""
156+
"""Display information about the currently active project or a specific project by ID."""
157157
result = show_project(args)
158158
if result:
159-
print_current_project(result)
159+
# Check if a specific project ID was requested
160+
project_id = getattr(args, "project_id", None)
161+
if project_id:
162+
# Show detailed project information for specific project
163+
from cbrain_cli.formatter.projects_fmt import print_project_details
164+
165+
print_project_details(result, args)
166+
else:
167+
# Show current project information
168+
print_current_project(result)
160169
else:
161-
print_no_project()
170+
# Only show "no project" message if no specific ID was requested
171+
project_id = getattr(args, "project_id", None)
172+
if not project_id:
173+
print_no_project()
162174

163175

164176
def handle_project_unswitch(args):

cbrain_cli/main.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,12 @@ def main():
212212
project_switch_parser.set_defaults(func=handle_errors(handle_project_switch))
213213

214214
# project show
215-
project_show_parser = project_subparsers.add_parser("show", help="Show current project")
215+
project_show_parser = project_subparsers.add_parser(
216+
"show", help="Show current project or specific project by ID"
217+
)
218+
project_show_parser.add_argument(
219+
"project_id", type=int, nargs="?", help="Project ID to show (optional)"
220+
)
216221
project_show_parser.set_defaults(func=handle_errors(handle_project_show))
217222

218223
# project unswitch

0 commit comments

Comments
 (0)