Value

class dsviper.Value

Bases: object

Creates values, and converts between them and Python objects.

Value.create(type [, initial_value]) builds one of any type; the concrete classes - ValueInt64, ValueString and the rest - construct directly. It also encodes and decodes.

The word has two senses here. encode and decode go between a value and the bytes of a blob; the encoded argument of a read chooses between a Python native (True) and the Value itself (False).

==, <, sorted() and their kin work between any two values and never raise. A native operand is decoded to the value type first - for an any or a variant, to the type of the value it holds: == answers False when it cannot be, and an ordering - <, sorted() - raises.

The order is the runtime’s, total across types. Two values of different types order by the kind of type, then by the type: an int64 5 sorts after an int32 9. Within one type, a vector, a set and a map order by size first, then element by element, so [3, 1, 2] sorts after [4], unlike a Python list; a string and a tuple order element by element, and an empty optional sorts first. Sets and maps keep their elements in this order.

None decoded to a Value is read by the type in context: in a slot that can be empty - an optional, an any - it is empty; in a void slot it is the void value; where the type cannot hold it, an optional argument is absent. The void value inside an optional or an any is ValueVoid().

Ownership follows the reference semantics of the runtime: a container holds the object you give it, and a read hands back what it holds, so mutating either is visible through the other. Three things are copied instead. What has to stay sorted and unique - a set element and a map key. Anything crossing a store: set takes a copy and get hands one back, so a document is never shared with a Database or a CommitDatabase, and mutating it after writing does not reach what was written. And an element of a pack-sized vector, which at() decodes afresh on each read (ValueVector.is_pack_sized).

Note: Not directly instantiable.

static bson_decode(blob: ValueBlob, type_structure: TypeStructure, definitions: DefinitionsConst) → ValueStructure

Return the struct the BSON in blob holds, read as type_structure against definitions.

static bson_encode(value: ValueStructure) → ValueBlob

Return the bson encoded blob of the value.

BSON is written from the JSON form, so it refuses infinity and not-a-number for the same reason json_encode does. Its integers are signed 64-bit: a uint64 above that range is refused here and carried by json_encode.

static collect_blob_ids(object: Value | Path | ValueProgram | CommitState | CommitMutableState) → set[ValueBlobId]

Return the set of blob_id of all referenced blob_id by the object, where object must be a Value, a Path, a CommitState, a CommitMutableState or a ValueProgram.

static collect_commit_ids(object: Value | Path | ValueProgram | CommitState | CommitMutableState) → set[ValueCommitId]

Return the set of commit_id of all referenced commit_id by the object, where object must be a Value, a Path, a CommitState, a CommitMutableState or a ValueProgram.

static copy() → _ValueT

Return a DEEP copy of a value: the containers it holds are copied too, unlike the shallow copy a container constructor makes.

static create(type: Type, initial_value: _InputValues | None = None) → Value

Return a new value of type, holding initial_value when one is given.

It hands back the SAME container: a value passed as initial_value is not copied, so mutating either shows in the other. A container constructor builds a NEW container instead, over the same ELEMENTS - a shallow copy, where only a mutation inside an element shows through.

The two are interchangeable for the immutable scalars, and differ for every container.

One exception, and it is a rule: what orders a container is COPIED. A ValueSet copies each element, which is its own key; a ValueMap copies each key and shares the value. A key that could mutate underneath would leave the container out of order.

static decode(blob: ValueBlob, type: Type, definitions: DefinitionsConst, *, stream_codec_instancing: StreamCodecInstancing | None = None, pack_sized: bool = False, encoded: Literal[True] = True) → _OutputValues

Return the value blob holds, read as type against definitions.

The blob must hold that value and nothing more: bytes left past it mean it holds another type or another codec wrote it, and decode raises.

It carries neither the type nor the definitions: the reader needs them and the codec the writer used. Definitions travel as a blob of their own - DefinitionsConst.encode(), read back by Definitions.decode(), whose codec is Codec.STREAM_TOKEN_BINARY by default.

stream_codec_instancing chooses the codec; Codec.STREAM_BINARY is used when it is None.

If pack_sized is True, a vector<T> whose T is sized (Type.is_sized) keeps its elements encoded and decodes one only when ValueVector.at reads it: the decoding cost of a large immutable resource is paid on use. See ValueVector.is_pack_sized for what that changes.

encoded=False returns a Value rather than a native object.

static deduce(value: _PythonValues) → Value

Return a strong typed conversion of a Python object.

static dumps(value: Value, *, json: bool = False) → _PythonValues

Return a DEEP projection to Python objects of the strong typed value, recursing all the way to the leaves - the inverse of loads.

Unlike the encoded getters (unwrap, at, and the rest), which are shallow - scalar leaves only, containers stay handles - dumps materializes nested containers too; and unlike encode, a serialization codec to bytes, it produces live Python objects.

Shapes: vector to list; tuple and vec to tuple; mat to a tuple of columns; set to set; map and structure to dict; enumeration to str; key to (instance_id, concept_runtime_id); blob to bytes. If json is True then: - a set is converted to a list. - a map is converted to a list of (key, value). - a blob is converted to a base64 str.

static encode(value: Value, *, stream_codec_instancing: StreamCodecInstancing | None = None) → ValueBlob

Return a blob encoding value.

stream_codec_instancing chooses the codec; Codec.STREAM_BINARY is used when it is None.

static from_xml_string(string: str, type: Type, definitions: DefinitionsConst, *, encoded: Literal[True] = True) → _OutputValues

Return the value the XML in string holds, read as type against definitions.

encoded=False returns a Value rather than a native object.

static hexdigest(value: Value, *, hashing: Hashing | None = None) → str

Hash the value with the hashing interface if specified else use SHA1.

static json_decode(string: str, type: Type, definitions: DefinitionsConst, *, encoded: Literal[True] = True) → _OutputValues

Return the value the JSON in string holds, read as type against definitions.

encoded=False returns a Value rather than a native object.

static json_encode(value: Value, indent: int = -1) → str

Return value encoded as JSON.

indent gives the number of spaces per level; -1 keeps it on one line. JSON has no form for infinity or not-a-number, so a value holding one is refused here rather than written as something else; a binary codec or to_xml_string carries it. A uint64 is written as the bare number, which a reader holding numbers as doubles rounds past 2**53, and an enumeration as its case name after a dot: ‘.green’.

static loads(object: _PythonValues, type: Type, definitions: DefinitionsConst) → Value

Return a value by decoding the Python object.

static read(type: Type, stream_reading: StreamReading, definitions: DefinitionsConst, *, pack_sized: bool = False) → Value

Read a value of type from stream_reading, typed against definitions.

pack_sized keeps sized elements packed, decoding them only on access.

static succ(value: Value) → Value

Return the successor of a value.

static to_xml_string(value: Value, indent: int = -1) → str

Return value encoded as XML.

indent gives the number of spaces per level; -1 keeps it on one line.

XML carries every value - infinity, not-a-number and the whole uint64 range included - and from_xml_string reads back one equal to it. An enumeration is its case name, a blob its base64.

static write(value: Value, stream_writing: StreamWriting) → None

Write value into stream_writing.