ursa.store.uri

URI → (role, key) resolution for the M2 read path (ENG-890).

func:

parse_storage_uri splits an r2://bucket/key URI into the role name a caller passes to :func:ursa.get_store plus the prefix-relative key. M2 is read-only; write callers compose their own role names because the bucket → role mapping has four entries (RW and RO variants) and write-side semantics live in

func:

ursa.register.modality.

The bucket constants come from :mod:ursa.layout so a future bucket rename touches one module. The role names match the literals in

data:

ursa.store.config.R2Creds.

Reused by :func:ursa.get (this ticket) and :func:ursa.download (ENG-1091).

Module Contents

Functions

parse_storage_uri

Split an r2://bucket/key URI into (role, key) for read.

Data

API

ursa.store.uri.__all__

[‘parse_storage_uri’]

ursa.store.uri._READ_ROLE_BY_BUCKET: dict[str, str]

None

ursa.store.uri.parse_storage_uri(uri: str) tuple[str, str][source]

Split an r2://bucket/key URI into (role, key) for read.

Mapping (M2):

  • bucket :data:ursa.layout.RAW_BUCKET (constellation-data) → role "raw_ro"

  • bucket :data:ursa.layout.ASSETS_BUCKET (constellation-assets) → role "assets_ro"

Parameters

uri A storage URI that conforms to :data:ursa.catalog.schemas.StorageURI (Pydantic validates that upstream — this helper trusts shape and only checks semantics). Trailing slashes are preserved in the returned key so callers can pass it to store.list(prefix=key) without re-appending the delimiter.

Returns

(role, key) role is one of the literals in :data:ursa.store.config.R2Creds. key is the URI’s path with the leading / stripped so it composes cleanly with :class:ursa.store.ObjectStore keys (which are prefix-relative).

Raises

NotImplementedError For non-r2:// schemes. s3, gcs, and file are valid per the :data:ursa.catalog.schemas.URI_PATTERN regex but have no read-store mapping in M2. ValueError For r2:// URIs whose bucket is not in the M2 mapping.