Databasing

class dsviper.Databasing

Bases: object

Abstracts the persistence layer behind a CRUD like database.

Reads need no transaction. Every WRITE requires one already open - set, delete and the blob operations raise without writing anything when there is none. extend_definitions is the exception in both directions: it opens an exclusive transaction of its own, so it raises when one is already open.

Note: Not directly instantiable.

TRANSACTION_DEFERRED = 'Deferred'
TRANSACTION_EXCLUSIVE = 'Exclusive'
TRANSACTION_IMMEDIATE = 'Immediate'
begin_transaction(mode: str | None = None) → None

Begin a transaction in mode ‘Deferred’ (the default), ‘Immediate’ or ‘Exclusive’.

Another spelling raises.

Transactions do not nest: calling this while in_transaction() is True raises, and the transaction already open is untouched.

blob(blob_id: ValueBlobId) → ValueBlob | None

Return the bytes of the blob blob_id names, or None if it is not held here.

Raises past 2 GB, where the bytes cannot be handed over in one piece. Ask blob_info(blob_id).chunked() first, and read such a blob with read_blob.

A blob reserved by create_zero_blob raises until freeze_blob seals it; blob_info answers None for it meanwhile.

blob_ids() → set[ValueBlobId]

Return the set of blob_id of every sealed blob.

A blob create_zero_blob reserved joins it once freeze_blob seals it.

blob_info(blob_id: ValueBlobId) → BlobInfo | None

Return the BlobInfo for blob_id, or None if this source does not hold it.

It gives the layout, the size and whether the blob is chunked. A blob create_zero_blob reserved answers None until freeze_blob seals it.

blob_infos(blob_ids: set[ValueBlobId]) → list[BlobInfo]

Return one BlobInfo per blob_id of blob_ids this source holds.

An unknown blob_id is left out, so the list may be shorter than blob_ids.

blob_statistics() → BlobStatistics

Return the statistics for blobs.

blob_stream_close(stream_id: ValueUUId, blob_id: ValueBlobId) → None

Close the stream stream_id names.

What it collected is stored under blob_id. Requires an open transaction, and raises without writing when there is none.

blob_stream_create(blob_layout: BlobLayout, size: int) → ValueUUId

Open a stream for a blob of size bytes laid out by blob_layout.

Returns the uuid naming it. Requires an open transaction, and raises without writing when there is none.

blob_stream_delete(stream_id: ValueUUId) → None

Drop the stream stream_id names, discarding what it collected.

Requires an open transaction, and raises without writing when there is none.

blob_stream_write(stream_id: ValueUUId, blob: ValueBlob, offset: int) → None

Write blob into the stream stream_id names, at offset.

Requires an open transaction, and raises without writing when there is none.

close() → None

Close the database.

codec_name() → str

Return the name of the codec.

commit() → None

Commit the transaction, so what it wrote stays.

Raises when no transaction is open.

create_blob(blob_id: ValueBlobId, blob_layout: BlobLayout, blob: ValueBlob) → bool

Store blob under blob_id and blob_layout.

Returns True if it was not already there. Requires an open transaction, and raises without writing when there is none.

create_zero_blob(blob_id: ValueBlobId, blob_layout: BlobLayout, size: int) → bool

Reserve size zeroed bytes under blob_id and blob_layout.

The blob is filled later. Returns True if it was created. Requires an open transaction, and raises without writing when there is none.

Until freeze_blob seals it, blob_ids leaves it out, blob_info answers None, and blob and read_blob raise.

data_version() → int

Return the counter another connection’s commit bumps.

An unchanged value means nothing was committed elsewhere since the last read.

definitions() → DefinitionsConst

Return the Definitions every value in this source is typed by.

It is a SNAPSHOT: extending the source afterwards does not show through the handle you hold, so ask again. A view obtained from Definitions.const() is live instead - same class, opposite liveness.

definitions_hexdigest() → str

Return the SHA1 of the definitions, as a hex string.

del_blob(blob_id: ValueBlobId) → bool

Delete the blob blob_id names, and return True if it was there.

Requires an open transaction, and raises without writing when there is none.

delete(attachment: Attachment, key: ValueKey) → bool

Delete the document attachment holds at key.

Returns True if it was there. Requires an open transaction, and raises without writing when there is none.

documentation() → str

Return the free text stored with the database at create(). One made without any answers ‘not documented.’, one made in memory answers ‘In Memory’ - both are placeholders written in at create(), not substituted on read.

extend_definitions(other: DefinitionsConst) → DefinitionsExtendInfo

Add every type and attachment of other this source does not hold yet.

It opens an exclusive transaction of its own, so it raises when one is already open - the reverse of every other write here.

freeze_blob(blob_id: ValueBlobId) → bool

Seal the blob blob_id names against further writes.

Returns True if it was still open. Requires an open transaction, and raises without writing when there is none.

get(attachment: Attachment, key: ValueKey) → ValueOptional

Return a ValueOptional over the document attachment holds at key.

Always a ValueOptional, never None: ask is_nil() whether it holds anything, and unwrap() for the document itself.

An absent document answers a nil ValueOptional; a key of another concept than the one attachment files raises, so is_nil() reports absence and never a mismatched key.

The document comes back as a copy; mutating it does not reach what is stored.

has(attachment: Attachment, key: ValueKey) → bool

Return True if attachment holds a document at key.

in_transaction() → bool

Return True if a transaction is running.

is_closed() → bool

Return True if the database is closed.

keys(attachment: Attachment) → ValueSet

Return every key attachment holds a document for.

The set is taken now: a later write does not reach it.

path() → str

Return the file path behind this source.

A database made in memory answers ‘InMemory’ rather than a path, and that exact string is how the runtime recognises one, so no file may take it: creating or opening a file of that path raises. Over a socket the answer is whatever the server answers for its own database.

read_blob(blob_id: ValueBlobId, size: int, offset: int) → ValueBlob

Return size bytes of the blob blob_id names, starting at offset.

The read side of blob_stream_create, blob_stream_write and blob_stream_close, and the only way to read a blob past 2 GB, which blob() refuses.

rollback() → None

Roll back the transaction, so what it wrote is dropped.

Raises when no transaction is open.

set(attachment: Attachment, key: ValueKey, value: _InputValues) → bool

Write value into attachment at key, replacing what was there.

The value is copied in: mutating it afterwards does not reach what was written, and writing the same object under two keys stores two independent documents.

Returns True when the document was written; a check that refuses raises instead of answering. It needs an attachment extend_definitions has registered - an unregistered one raises whatever the transaction - and an open transaction, without which it raises and writes nothing.

uuid() → ValueUUId

Return the uuid identifying the database behind this source.

write_blob(blob_id: ValueBlobId, blob: ValueBlob, offset: int) → None

Write the bytes of blob into the stored blob blob_id names, at offset.

Requires an open transaction, and raises without writing when there is none.