Connecting and creating¶
Use connect to read a database that someone else runs. It takes the token you read with, which decides what you may see, though a server started with mosaica serve --open needs none. If the operator has not issued you a token, login makes one from your own password, API key or OIDC access token. A back end that signs in its own users calls authorise instead, which makes a token for any local principal, OIDC identity or set of access terms, or the operator's own token.
Use create or open when the database is your own. Each gives a Database kept in a directory, which starts its own server when a commit or a read first needs it.
connect
¶
connect(url: str, token: Optional[TokenSource] = None) -> Viewer
Connect to a Mosaica database someone else runs, returning a Viewer that reads what the
token's terms admit.
url: the address of the database's viewer plane.token: the token the database's operator issued you, in any of the formsTokenSourcedescribes. Leave it out for a server started withmosaica serve --open.
v = mosaica.connect("https://maps.example/viewer", token=my_token)
v.view("papers").count()
v = mosaica.connect(url, lambda: mosaica.login(url, api_key=my_key))
create
¶
create(
path: str | PathLike | None = None,
replace: bool = False,
port: int | None = None,
) -> Database
Make a new, empty database in a directory, and return it as a Database.
path: the directory, which must be empty or not yet exist. Without it the database goes in a temporary directory, in memory where the system offers one (/dev/shmon Linux), which is deleted asclose()describes.replace:Truedeletes a Mosaica database already atpathfirst. A non-empty directory that is not a Mosaica database is refused either way.port: the port its server listens on, on this machine only, and the database keeps it. A taken port is refused when the server starts, and0lets the system choose a free one.None, the default, serves on 9141, or on the next free port above it when 9141 is taken. The server prints the address it serves at when it starts.
db = mosaica.create()
db = mosaica.create("~/maps/papers", replace=True, port=9200)
open
¶
open(path: str | PathLike, port: int | None = None) -> Database
Reopen a database kept in a directory, and return it as a Database.
A committed database reopens ready to read, and its next commit adds to it. A database saved before its first commit reopens with its declarations and inserts as they were left.
path: the database's directory, which holds itsmosaica.toml, or before its first commit the package's own record of it.port: the port its server listens on from now on, ascreate()describes.None, the default, keeps the one the database was served on.
A temporary directory that a crashed process left behind opens too, unless another live
process has it open. The next create() removes it once you close it, so call save(path)
on it to keep a copy.
db = mosaica.open("~/maps/papers")
db.view("papers").count()
Database
¶
A Mosaica database kept in a directory, which you fill from data frames and then read.
Make one with create(), or reopen one with open(). You describe what the database holds
with the declare_* methods before handing each declared thing a table with insert, which
names the columns to read from it. Nothing reaches the database until commit, which builds
it and starts its server the first time.
Reads go through that server with the operator's own token, which authorise describes under
read_all. To read as someone who holds only some access terms, call viewer(terms).
db = mosaica.create()
db.declare_view("papers")
db.insert("papers", frame, x="x", y="y", access="labels")
db.commit()
db.view("papers").count()
Its attributes:
path: the directory the database is kept in.temporary:Truewhencreate()made the database in a temporary directory, whichclose()deletes.built:Trueonce the first commit has built the database.inserts: theInsertrecords made before the first commit, which that commit builds from.pending: theInsertrecords made since the last commit, which the next commit sends.listening: the addresses the server listens on, asserve()returns them, orNonewhile the server is not running.port: the port stated atcreate()oropen(), orNonewhen none was.
binary
property
¶
binary: str
The path of the mosaica program that checks, builds and serves this database.
The program is the one MOSAICA_BIN names, then the one the mosaica-native wheel
installed, then a build in a Mosaica checkout, whichever is found first. A mosaica on
PATH is used only when MOSAICA_BIN names it. Reading this raises Refusal when none is
found.
save
¶
save(path: str | PathLike) -> Path
Copy the database's directory to path, and return that path.
Because a temporary database is deleted when it is closed, saving it is how you keep one.
The copy is an ordinary database, which open(path) reopens and
mosaica serve --deployment <path>/mosaica.toml serves. A Parquet file inserted from
outside the database's directory stays where it is, and the copy reads it from there.
path: the directory to copy into, outside the database's own, which must be empty or not yet exist.
close
¶
close() -> None
Stop the database's server, and delete its directory if the database is temporary.
After close() a temporary database refuses every call, because its directory is gone,
while any other database starts its server again when a call needs it.
The server also stops when nothing refers to the database any more, and when Python exits,
however it exits. A temporary database's directory is deleted then too, except after a
process that ended without running its exit handlers, such as a killed one, when a later
create() removes it. A Map or a Selection refers to the database it reads, which keeps
the server running while you hold one. Tokens the database made stay valid until they
expire, within the hour, unless revoke ends them sooner.
token
¶
token(terms: Sequence[str] | None = None) -> Token
Make a token that reads this database with the access terms given.
Pass the token to connect or Map to read as someone who holds it.
terms: the access terms the token holds, as a list or as one term in a string. Without them the token is the operator's own, whichauthorisedescribes underread_all.
token = db.token(["cs.LG"])
revoke
¶
revoke(token) -> None
End a token this database made, so that it can no longer read.
token: theToken, or itstoken_id.
An id that names no live token is accepted. A reader holding the Token can still get
another with its renew(), as mosaica.revoke describes.
viewer_url
property
¶
viewer_url: str | None
The address that readers read the database from, or None while the server is not
running.
session_url
property
¶
session_url: str | None
The address that tokens for the database are made at, or None while the server is not
running.
operator_credential
property
¶
operator_credential: str
The secret that gives full control of this database's server.
control, token and viewer use it. The secret is kept in the database's directory,
and the package sends it only to the database's own server on this machine.
Token
dataclass
¶
A token that lets its holder read a Mosaica database until its session ends.
login and authorise return one, and connect, Map and logout take one or its token
string. Printing a token shows its expiry, its principal and how many terms it holds, and
leaves the token string out, so that the secret does not end up in a saved notebook or a log.
token: the secret string a reader sends with each request. Anyone who holds it reads as the token's principal.expires_at: when the token's session ends, in seconds since 1970, orNonewhen that is not known. A catalogue change, such as a grant to its principal, can end it sooner.token_id: the idrevoketakes to end the token without sending the token again. Only a tokenauthorisemade has one, and it isNoneotherwise.renew: a function that makes a fresh token from the credential that made this one, which therefore stays in this process. It is set whenloginorauthorisemade the token and isNoneotherwise. A reader fromconnectand aMapcall it when the token is about to expire, or when a403 expired-tokenanswer says that its session has ended.principal: the local principal the token reads as, whenauthorisemade it for one orloginwas given a password, andNoneotherwise.terms: the access terms the token holds, whenauthorisemade it for a set of terms, andNoneotherwise.
seconds_left
property
¶
seconds_left: Optional[float]
Seconds until the token expires, or None if its expiry is not known.
TokenSource
module-attribute
¶
TokenSource = Union[str, Token, Callable[[], Union[str, 'Token']]]
The forms in which connect, Viewer and Map take a token: the token string, a Token, or a
function that returns either.
A reader gets a fresh token when the one it holds is about to expire, or when a 403
expired-token answer says that its session has ended. It renews a Token with the token's own
renew and calls a function again, while it sends a plain string unchanged until the server
refuses it. A function is therefore the way to hand a reader tokens that your own code makes.
login
¶
login(
viewer_url: str,
*,
principal: Optional[str] = None,
password: Optional[str] = None,
api_key: Optional[str] = None,
access_token: Optional[str] = None,
timeout: float = 10.0,
) -> Token
Log in to a Mosaica database and return a token that reads as the principal the credential belongs to.
viewer_url: the address of the database's viewer plane, where readers read.principal,password: a local principal's name and password, given together.api_key: an API key the database's operator issued.access_token: an OIDC access token from a provider the database accepts.timeout: how long to wait for the server, in seconds. The default is 10.
Any combination but exactly one of the three credentials raises ValueError, as a missing
viewer_url does. The principal must hold the read permission. The server answers
every credential it does not accept with the same refusal, which raises PermissionError, so
the error does not reveal whether a principal exists.
token = mosaica.login(viewer_url, principal="ann", password=password)
mosaica.connect(viewer_url, token).view("papers").count()
logout
¶
logout(
viewer_url: str, token: Union[str, Token], *, timeout: float = 10.0
) -> None
End a token's session, so that the token can no longer read.
viewer_url: the address of the database's viewer plane.token: the token to end, as a string or aToken.timeout: how long to wait for the server, in seconds. The default is 10.
A token the server does not recognise, or whose session has already ended, raises
PermissionError.
authorise
¶
authorise(
session_url: str,
credential: str,
*,
principal: Optional[str] = None,
access_token: Optional[str] = None,
terms: Optional[Sequence[str]] = None,
read_all: bool = False,
timeout: float = 10.0,
) -> Token
Make a token on the session plane that reads as a local principal, an OIDC identity, a set of access terms or the operator.
An application that signs its own users in calls this from its back end, with an API key, to give each user a token that reads as them.
session_url: the address of the database's session plane, where tokens are made.credential: an API key whose principal holdsauthorise-as, or the operator credential. Either one can make a token that reads as anyone.principal: the name of a local principal to read as. The token carries the principal's terms and itsreadandwritepermissions, and none of its others, such asread-all. The principal must holdread.access_token: the OIDC access token of an identity to read as, which the server checks aslogindoes. The token carries the identity's terms and permissions as forprincipal.terms: the access terms the token holds, as a list or one term as a string, for a reader the catalogue does not name. The token holds them andread. Only the operator credential may sendterms.read_all:Truemakes the operator's own token, which holdsread-alland so reads every item that is not deleted or suppressed, including items committed after the token was made. Only the operator credential may send it.timeout: how long to wait for the server, in seconds. The default is 10.
Name exactly one of principal, access_token, terms and read_all. Anything else, or an
empty session_url or credential, raises ValueError, and a request the server refuses
raises PermissionError, whose message holds the server's status and answer. A Database
makes these tokens with its own operator credential through db.token(terms) and
db.viewer(terms).
token = mosaica.authorise(session_url, api_key, principal="ann")
token = mosaica.authorise(session_url, operator_credential, terms=["cs.LG"])
mosaica.connect(viewer_url, token).view("papers").count()
revoke
¶
revoke(
session_url: str,
credential: str,
token_id: Union[int, Token],
*,
timeout: float = 10.0,
) -> None
End a token that authorise made, so that it can no longer read.
session_url: the address of the database's session plane.credential: the operator credential, which ends any token, or an API key, which ends only the tokens made with a key of its own principal.token_id: theToken, or itstoken_id. Only the id is sent.timeout: how long to wait for the server, in seconds. The default is 10.
The server accepts an id that names no live token without saying so, because any other
answer would tell a caller which tokens exist. An empty session_url or credential, or a
Token without a token_id, raises ValueError, and a request the server refuses raises
PermissionError. A reader holding the Token can make another with its renew(), because
the credential that made it keeps working.
mosaica.revoke(session_url, credential, token)
Refusal
¶
Bases: ValueError
The exception the package raises when it will not make a call, or when the server refuses a request, with a message that says what was wrong and what to write instead.
Catching Refusal handles every refusal from a Database or a reader in one place. Code that
catches ValueError catches it too, because Refusal is a ValueError. The token functions
login, logout, authorise and revoke raise PermissionError for a request the server
refuses, and Control returns each refusal in its Answer without raising.
status: the HTTP status of a read the server refused, andNonefor every other refusal.retry_after_s: how many seconds to wait before sending the request again, set when the server answers429or names a wait, andNoneotherwise.report: the report of acommit,remove,suppress,unsuppressorleavethat applied nothing, which says what was refused and why, the dictionaryDatabase.compact(wait=True)would have returned where the compaction did not succeed, andNoneotherwise.
try:
db.commit()
except mosaica.Refusal as refused:
print(refused.report)