Metadata-Version: 2.4
Name: turoeducate-cli
Version: 0.1.0
Summary: CLI to programmatically upload WSI cases to TuroEducate
Author-email: Turocrates AI <founders@turocrates.ai>
License: Proprietary
Project-URL: Homepage, https://turoeducate.turocrates.ai
Keywords: wsi,pathology,turoeducate,upload,cli
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Healthcare Industry
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.31
Requires-Dist: click>=8.1

# turoeducate-cli

Command-line tool for uploading WSI files to [TuroEducate](https://turoeducate.turocrates.ai) and creating cases programmatically. Each file's basename becomes the case title.

## Install

```bash
pip install -e tools/turoeducate-cli
```

Requires Python 3.10+. The entry point `turoeducate` is registered as a console script.

## Usage

### Single file

```bash
turoeducate upload /path/to/case1.svs
```

You will be prompted for your email and password. The password is read via `getpass` (not echoed and not stored in shell history). The file is streamed directly to S3 via a presigned URL; the CLI never writes credentials to disk.

### Bulk directory

```bash
turoeducate upload-dir /path/to/slides/
turoeducate upload-dir /path/to/slides/ --recursive
turoeducate upload-dir /path/to/slides/ --folder-id <existing-folder-uuid>
```

One login, N uploads. Non-WSI files in the directory are skipped automatically.

### Common options

- `--email EMAIL` — skip the email prompt (still prompts for password)
- `--title TEXT` — (single-file only) override the case title
- `--folder-id UUID` — drop the case(s) into an existing folder
- `--difficulty {easy,medium,hard}` — default `medium`
- `--status {draft,published}` — default `draft`
- `--visibility {private,institution,public}` — default `private`
- `--base-url URL` — default `https://turoeducate.turocrates.ai`

Supported WSI formats: `.svs .tif .tiff .ndpi .scn .mrxs .bif`

## Behaviour

The CLI is **fire-and-forget**: it confirms the upload, creates the case, prints the URL, and exits. The server's DSA sync worker processes the tile pyramid asynchronously — the case will show "Processing" in the web UI until that completes (seconds to a few minutes depending on file size).

If a file fails during bulk upload, the error is printed and the remaining files still upload.

The file is streamed to S3 with a real `Content-Length` header (not chunked transfer encoding), so the upload matches the presigned URL's `content-type;host` signature.

## Security

- **HTTPS is enforced.** `--base-url` must start with `https://`. `http://` is only permitted for `localhost` / `127.0.0.1` during local development.
- **No credentials persisted.** Password is entered via `getpass` each run. The JWT is held in memory only, never written to disk or an environment variable.
- **Public API only.** The CLI talks exclusively to the same HTTPS endpoints the web UI uses — no backend internals, no direct database or storage access.
- **Server-enforced limits apply.** Login is rate-limited to 20/minute per IP; uploads respect your account's storage quota (413 Payload Too Large).

## Exit codes

| Code | Meaning |
| :--: | :--     |
| 0    | Success |
| 1    | Runtime error (login failed, upload failed, case creation failed) |
| 2    | Usage error (bad arguments, non-WSI file, invalid base URL) |
