Skip to content

Install and set up

Use the CANFAR Python package to automate work on a Science Platform Server: launch Sessions, list Container Images, fetch logs, inspect state, and clean up resources.

Install

Client version

These examples use the released v1.5.2 client. Unreleased additions are marked on their own pages. Read What's new and the upgrade guide before upgrading from v1.4.1.

CANFAR Data's CLI and Python storage tools have been in beta since v1.5.0. See the Data guide and community feedback routes.

Use the published release

Install the released package for regular use, and use the documentation that matches that release:

pip install --upgrade canfar

With uv:

uv add canfar

Install on an Intel Mac

cryptography 49.0.0 and later publish no Intel macOS wheels, so a plain install on an Intel Mac tries to compile it and fails with Failed to build cryptography. Install canfar as a uv tool from wheels only. You get cryptography 48.0.1, the last Intel release, in an environment of its own, without Homebrew or a compiler:

uv tool install canfar --no-build-package cryptography

uv remembers the option, so later upgrades need no extra flags:

uv tool upgrade canfar

Do not run uv run pip install …: uv-managed Python rejects it with error: externally-managed-environment.

cryptography 48.0.1 has known vulnerabilities

Advisory Severity Fixed in
GHSA-g6cj-pr64-35w5: PKCS#7 decryption oracle High 50.0.0
GHSA-jwv3-5hgf-82ww: X.509 path-building denial of service High 49.0.0
GHSA-m2h6-j472-rp4c: X.509 name-constraint bypass Moderate 49.0.0

canfar uses neither PKCS#7 nor X.509 path verification, and no unrelated packages share the tool environment.

If sysctl -n machdep.cpu.brand_string prints Apple M…, your Mac is Apple Silicon running an Intel Python under Rosetta. Use a native Python instead; it gets current releases.

Try this development branch

To test the development examples on main, use a separate checkout and Python environment. With Git and uv installed, run:

git clone --branch main https://github.com/opencadc/canfar.git canfar-preview
cd canfar-preview
uv sync
source .venv/bin/activate
canfar --help
canfar ps --help

The activation command above is for a macOS or Linux shell. In another shell, use uv run canfar … from the checkout instead. A development checkout can share the last release's version string. Read command help to verify each unreleased feature, such as CLI extensions.

The Python environment is separate, but the client still uses your normal ~/.canfar/config.yaml. Review the migration guide before changing saved configuration.

Authenticate

The simplest path is to authenticate with the CLI. Python then uses the saved Authentication Record and Server Selection:

canfar login cadc

Use canfar login srcnet if your account belongs to an SRCNet identity provider (IDP), the service that manages your login. It uses OpenID Connect (OIDC) device authorization: follow the displayed link to approve the login.

Log in directly from Python

The following alternatives perform the same OpenID Connect (OIDC) device login. Open the displayed verification URL and enter the user-facing code when prompted by your identity provider.

login.py
import canfar

assert canfar.login("srcnet") is True
login.py
import asyncio
import canfar

async def main() -> None:
    assert await canfar.alogin("srcnet") is True

if __name__ == "__main__":
    asyncio.run(main())

In Jupyter, define main() without the script entrypoint and run await main() in another cell. The async login performs native asynchronous network requests.

Python prints the verification URL, the user-facing device code, and Waiting for approval. It does not open a browser or render the CLI's QR code. The private OAuth device token is never printed.

Both functions save the Authentication Record and discovered Science Platform Servers but do not change the active Authentication or Server Selection. They return True when that Identity Provider has a saved Authentication Record, including when an existing record is kept because force is false. A reused record prints Already authenticated for '<idp>'. A new login prints Discovering servers for '<idp>'. and then Authenticated for '<idp>'. An unknown Identity Provider raises KeyError, and credential or discovery failures raise canfar.authentication.AuthenticationError.

Select the identity and server in Python

After either Python login function completes, select the saved identity and list its compatible servers:

from canfar import authentication, server

authentication.use("srcnet")
for candidate in server.list_servers():
    print(candidate.name, candidate.url)

Choose a name from that output, replace SERVER_NAME below, and select it before you construct a Session client:

server.use("SERVER_NAME")

These selection functions are synchronous and save the defaults used by new clients. In a notebook or another running event loop, run selection and discovery in a worker thread because they can start their own event loop:

import asyncio
import canfar
from canfar import authentication, server

assert await canfar.alogin("srcnet") is True
await asyncio.to_thread(authentication.use, "srcnet")
candidates = await asyncio.to_thread(server.list_servers)
for candidate in candidates:
    print(candidate.name, candidate.url)

After choosing a name from that output, run this in the next notebook cell:

await asyncio.to_thread(server.use, "SERVER_NAME")

The CLI canfar login flow includes selection, so you can use that route instead.

Storage and compute can use different accounts

The default arc and vault services use your saved CADC Authentication Record, even when compute uses SRCNet. Run canfar login cadc for those services. Then select SRCNet again for compute with canfar auth use srcnet and canfar server use SERVER_NAME if needed.

Create a Session

from canfar.sessions import Session

with Session() as session:
    ids = session.create(
        kind="notebook",
        image="images.canfar.net/skaha/astroml:latest",
        name="my-analysis",
    )
    print(ids)

Choose an image available on your selected server using canfar image ls --kind notebook; the image above is an example. Keep the returned IDs to inspect and clean up this specific run, as shown in the Python tutorial.

create() returns list[str]. A failed replica is omitted and a total HTTP or network failure returns []; request validation errors still raise.

Edit and save Configuration

Configuration is the persisted data shape. Its top-level fields are version, active, authentication, servers, registry, and console. Authentication Records are keyed by Identity Provider, Science Platform Servers by Server Name, and active stores the selected references. Use the bound config.editor to read, validate, and save changes:

from canfar.models.config import Configuration

config = Configuration()
width = config.editor.get("console.width")
config.editor.set("console.width", 132)
config.editor.save()

get() can return a scalar, mapping, or whole list through a dotted path. List indices are not supported. set() validates before mutating the bound model; invalid updates leave it unchanged. save() persists the validated Configuration atomically. The editor itself is not part of the serialized Configuration shape.

Private Container Images

Pass a ContainerRegistry in the Configuration when creating a Session from a private image:

from canfar.models.config import Configuration
from canfar.models.registry import ContainerRegistry
from canfar.sessions import Session

config = Configuration(
    registry=ContainerRegistry(username="username", secret="CLI_SECRET")
)
with Session(config=config) as session:
    ids = session.create(
        kind="notebook",
        image="images.canfar.net/my-project/private-image:latest",
        name="private-image-test",
    )