Dataclasses#

Extensions for dataclasses.

This module offers

Index: an inverted index for dataclasses Builder: to iteratively build (immutable) data objects

class ktz.dataclasses.Builder(Klass, immutable=False)#

Simple builder to incrementally build a dataclass.

An instance of this class maintains a kwargs dictionary which can be incrementally popularized. Calling the instance attempts to build the provided dataclass object.

Methods

__call__:

Assemble the dataclass

get:

Obtain an already added value

add:

Add another property

add(**kwargs)#

Add properties to the dataclass.

Parameters:
**kwargsAny
Raises:
ktz.Error

If immutable=True, this is raised when a key is provided multiple times.

get(key)#

Get the value of the provided key.

Parameters:
keystr
class ktz.dataclasses.Index(Klass, includes=None, excludes=None)#

Maintain an inverted index for dataclasses.

Provided instances are saved to indexes based on their properties. They can then be retrieved fast by those properties.

Attributes:
flat

Return all indexed dataclasses.

Methods

get:

Retrieve an object by key

dis:

Retrieve the union result for multi-key queries

con:

Retrieve the intersection result for multi-key queries

add(ts)#

Add instances to index.

Parameters:
tsT | Iterable[T]

The dataclass instances to be indexed. You may provide both single instances or iterables over such instances.

Returns:
“Index”

self

con(**kwargs)#

∧ : Obtain intersection of queried dataclasses.

Each indexed field is searched for the associated dataclasses and the intersection of these results is returned.

Parameters:
**kwargskwargs

field-key pairs

Returns:
set[T]

Subset of indexed dataclasses

Examples

>>> from dataclasses import dataclass
>>> from ktz.dataclasses import Index
>>> @dataclass(frozen=True)
... class A:
...     x: int
...     y: int
...
>>> idx = Index(A).add([A(x=2, y=1), A(x=2, y=2), A(x=3, y=3)])
>>> idx.con(x=2, y=1)
{A(x=2, y=1)}
dis(**kwargs)#

∨ : Obtain unionized subset of queried dataclasses.

Each indexed field is searched for the associated dataclasses and the union of these results is returned.

Parameters:
**kwargskwargs

field-key pairs

Returns:
set[T]

Subset of indexed dataclasses

Examples

>>> from dataclasses import dataclass
>>> from ktz.dataclasses import Index
>>> @dataclass(frozen=True)
... class A:
...     x: int
...     y: int
...
>>> idx = Index(A).add([A(x=2, y=1), A(x=2, y=2), A(x=3, y=3)])
>>> idx.dis(x=2, y=3)
{A(x=2, y=1), A(x=3, y=3)}
property flat#

Return all indexed dataclasses.

Note that this does not return a copy. You must create a copy before modifying this datastructure, otherwise you can expect undefined behaviour.

Returns:
set[T]

Set of all indexed dataclasses

freeze()#

Do not allow changes to the Index.

This removes the ability to mutate the Index state by freezing the underlying data management.

Examples

>>> from ktz.dataclasses import Index
>>> from dataclasses import dataclass
>>> @dataclass(frozen=True)
... class A:
...     x: int
...
>>> idx = Index(A)
>>> idx.freeze()
>>> idx.add(A(x=0))
Traceback (most recent call last):
  Input In [11] in <cell line: 1>
    idx.add(A(x=0))
  File ~/Complex/scm/ktz/ktz/dataclasses.py:325 in add
    raise ktz.Error("Cannot mutate a frozen Index")
Error: Cannot mutate a frozen Index
>>> idx.unfreeze()
>>> idx.add(A(x=0))
get(**kwargs)#

Shortcut for single-field queries.

If a single field is given, no distinction between dis() and con() exists. So this is a nice shortcut for simple queries.

Parameters:
**kwargsfield-key pair
Returns:
set[T]

Subset of indexed dataclasses

Examples

>>> from dataclasses import dataclass
>>> from ktz.dataclasses import Index
>>> @dataclass(frozen=True)
... class A:
...     x: int
...
>>> idx = Index(A).add([A(x=1), A(x=2)])
>>> idx.get(x=2)
{A(x=2)}
gets(**kwargs)#

Shortcut for single-field, single-value queries.

If a single field is given, no distinction between dis() and con() exists. So this is a nice shortcut for simple queries where only one value is expected.

Parameters:
**kwargsfield-key pair
Returns:
set[T]

Subset of indexed dataclasses

Examples

>>> from dataclasses import dataclass
>>> from ktz.dataclasses import Index
>>> @dataclass(frozen=True)
... class A:
...     x: int
...
>>> idx = Index(A).add([A(x=1), A(x=2)])
>>> idx.get(x=2)
{A(x=2)}
has(**kwargs)#

Test whether a value is indexed for one or more instances.

This is basically a shortcut for single-key checks. If more kwargs are provided, use a len check on con or dis instead.

keys(field)#

Obtain indexed keys for the given field.

This enumerates the possible keys that can be used to retrieve indexed dataclasses

Parameters:
fieldstr

The field of interest

Returns:
set[Any]

All known keys

Examples

>>> from dataclasses import dataclass
>>> from ktz.dataclasses import Index
>>> @dataclass(frozen=True)
... class A:
...     x: int
...
>>> idx = Index(A).add([A(x=2), A(x=3), A(x=5)])
>>> idx.keys('x')
{2, 3, 5}
unfreeze()#

Allow changes to the Index (the default).

This adds the ability to mutate the Index state to allow adding and deleting objects. See Index.freeze for an usage example.