Skip to content

Commit 08c934e

Browse files
committed
Refactor client: device auth, CLI, pagination
Replace password auth with a browser-based device authorization flow and persistent token caching (~/.config/brainstem/token). Export AuthenticationError and modernize BrainstemClient: session-backed requests, unified load/save/delete methods, auto-pagination (load_all), query param handling (filters/sort/include/limit/offset), model→app routing table, and many convenience loaders (load_project/subject/session/... ). Add a command-line interface (brainstem entrypoint), update README and tutorial for new usage, add pyproject.toml (remove setup.py), and include comprehensive unit tests for client behavior and auth flow.
1 parent bc595e3 commit 08c934e

File tree

10 files changed

+1617
-484
lines changed

10 files changed

+1617
-484
lines changed

README.md

Lines changed: 135 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,157 @@ You can install the package using `pip`:
88
pip install brainstem_python_api_tools
99
```
1010

11+
## Authentication
12+
13+
Authentication uses a **browser-based device authorization flow** that supports two-factor authentication (2FA). No credentials are entered into the tool itself.
14+
15+
```python
16+
from brainstem_api_tools import BrainstemClient
17+
18+
# First run: opens a browser window for secure login.
19+
# The token is cached at ~/.config/brainstem/token and reused automatically.
20+
client = BrainstemClient()
21+
```
22+
23+
To skip the browser flow, pass a token directly:
24+
```python
25+
client = BrainstemClient(token="YOUR_TOKEN")
26+
```
27+
28+
For headless environments (no browser available):
29+
```python
30+
client = BrainstemClient(headless=True) # prints a URL + code to enter manually
31+
```
32+
33+
To connect to a different server (e.g. a local development instance):
34+
```python
35+
client = BrainstemClient(url="http://127.0.0.1:8000/")
36+
```
37+
38+
> **Security note:** The cached token file is stored with owner-read-only permissions (`0600`). Treat it like a password and do not commit it to version control.
39+
1140
## Getting Started
1241
To get started with the BrainSTEM API tools, please refer to the tutorial script provided:
1342

1443
- **Tutorial:** `brainstem_api_tutorial.py`
1544

1645
The tutorial demonstrates how to:
1746

18-
- **Authenticate:** Load the client and authenticate using your credentials.
19-
- **Loading Data:** Load sessions and filter data using flexible options.
20-
- **Updating Entries:** Modify existing models and update them in the database.
21-
- **Creating Entries:** Submit new data entries with required fields.
22-
- **Loading Public Data:** Access public projects and data using the public portal.
47+
- **Authenticate:** Load the client and authenticate via your browser.
48+
- **Load Data:** Load sessions and filter data using flexible options.
49+
- **Paginate:** Retrieve large datasets using `limit` / `offset` or `load_all=True`.
50+
- **Convenience Loaders:** Use `load_session()`, `load_subject()`, etc. for common queries.
51+
- **Update Entries:** Modify existing records and update them in the database.
52+
- **Create Entries:** Submit new data entries with required fields.
53+
- **Delete Entries:** Remove records by ID.
54+
- **Load Public Data:** Access public projects and data using the public portal.
2355

2456
## Example Usage
2557
```python
2658
from brainstem_api_tools import BrainstemClient
2759

2860
client = BrainstemClient()
29-
response = client.load_model('session', sort=['name'])
61+
62+
# Load sessions sorted by name
63+
response = client.load('session', sort=['name'])
3064
print(response.json())
65+
66+
# Filter and include related data
67+
response = client.load(
68+
'session',
69+
filters={'name.icontains': 'Rat'},
70+
sort=['-name'],
71+
include=['projects'],
72+
)
73+
74+
# Paginate results (manual)
75+
page2 = client.load('session', limit=20, offset=20).json()
76+
77+
# Auto-paginate — fetches every page and returns a merged dict
78+
all_sessions = client.load('session', load_all=True)
79+
80+
# Convenience loaders — sensible defaults with named filter kwargs
81+
# load_session embeds dataacquisition, behaviors, manipulations, epochs
82+
sessions = client.load_session(name='Rat', load_all=True)
83+
84+
# load_subject embeds procedures and subjectlogs
85+
subjects = client.load_subject(sex='M', projects='<project-uuid>', load_all=True)
86+
87+
# load_project embeds sessions, subjects, collections, cohorts
88+
projects = client.load_project(name='MyProject')
89+
90+
# load_behavior / load_dataacquisition / load_manipulation scope by session UUID
91+
behaviors = client.load_behavior(session='<session-uuid>', load_all=True)
92+
93+
# load_procedure scopes by subject UUID
94+
procedures = client.load_procedure(subject='<subject-uuid>', load_all=True)
95+
96+
# Create a record
97+
client.save('session', data={'name': 'New session', 'projects': ['<project-uuid>']})
98+
99+
# Update a record
100+
client.save('session', id='<session-uuid>', data={'description': 'updated'})
101+
102+
# Delete a record
103+
client.delete('session', id='<session-uuid>')
104+
```
105+
106+
## Contributing
107+
Contributions are welcome! Feel free to open issues or submit pull requests on GitHub.
108+
109+
## Command-line Interface
110+
111+
After installation a `brainstem` command is available in your shell.
112+
113+
### Authentication
114+
```bash
115+
# Authenticate (opens browser) and cache token
116+
brainstem login
117+
118+
# Headless — prints URL + code instead of opening browser
119+
brainstem login --headless
120+
121+
# Connect to a local dev server
122+
brainstem login --url http://127.0.0.1:8000/
123+
124+
# Remove cached token
125+
brainstem logout
126+
```
127+
128+
### Loading data
129+
```bash
130+
# Load all sessions (private portal)
131+
brainstem load session
132+
133+
# Filter, sort and embed related data
134+
brainstem load session --filters name.icontains=Rat --sort -name --include projects
135+
136+
# Load a single record by UUID
137+
brainstem load session --id <uuid>
138+
139+
# Manual pagination
140+
brainstem load session --limit 20 --offset 20
141+
142+
# Public portal
143+
brainstem load project --portal public
144+
```
145+
146+
### Creating and updating records
147+
```bash
148+
# Create a new session
149+
brainstem save session --data '{"name":"New session","projects":["<uuid>"]}'
150+
151+
# Update an existing record
152+
brainstem save session --id <uuid> --data '{"description":"updated"}'
31153
```
32154

155+
### Deleting records
156+
```bash
157+
brainstem delete session --id <uuid>
158+
```
159+
160+
All subcommands accept `--token`, `--headless`, and `--url` to override defaults.
161+
33162
## Contributing
34163
Contributions are welcome! Feel free to open issues or submit pull requests on GitHub.
35164

brainstem_api_tools/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .brainstem_api_client import BrainstemClient, ModelType, PortalType
1+
from .brainstem_api_client import BrainstemClient, ModelType, PortalType, AuthenticationError

0 commit comments

Comments
 (0)