API

ZSets

ZSets can be added a + b, negated -a, ZSetPythons can be multiplied a * n

They also have the following methods:


def iter(
    self,
    match: frozenset[T] | MatchAll
) -> Iterator[tuple[T, int]]:
    ...

[src] Iterates over the value, count of the ZSet in no particular order. Optionally filter on a set of values.


def iter_by_index(
    self,
    index: Index[T, K],
    match_keys: frozenset[K] | MatchAll
) -> Iterator[tuple[K, T, int]]:
    ...

[src] Iterates over the key, value, count of the indexed ZSet in the order defined by the index. Optionally filter on a set of values.

Operators

Debugging

st.identity_print(
    a: T,
) -> T

[src] Prints a, then returns it.

Day to day

st.map(
    a: st.ZSet[T],
    *,
    f: Callable[[T], V],
) -> st.ZSet[V]

[src] Maps function f over all the values in a


st.map_many(
    a: st.ZSet[T],
    *,
    f: Callable[[T], frozenset[V]],
) -> st.ZSet[V]

[src] Maps function f over all the values in a. f returns many values in a frozenset, these are unioned together in the returned ZSet


st.filter(
    a: st.ZSet[T],
    *,
    f: Callable[[T], bool],
) -> st.ZSet[T]

[src] Equivalent to SQL’s WHERE


st.join(
    l: st.ZSet[T],
    r: st.ZSet[U],
    *,
    on_left: st.Index[T, K],
    on_right: st.Index[U, K],
) -> st.ZSet[st.Pair[T, U]]

[src] Equivalent to SQL’s JOIN


st.outer_join(
    l: st.ZSet[T],
    r: st.ZSet[U],
    *,
    on_left: st.Index[T, K],
    on_right: st.Index[U, K],
) -> st.ZSet[st.Pair[T, Union[U, st.Empty]]]

[src] Equivalent to SQL’s LEFT OUTER JOIN, with Empty() equivalent to NULL


st.distinct(
    a: st.ZSet[T],
) -> st.ZSet[T]

[src] Equivalent to SQL’s DISTINCT


st.add(
    a: TAddable,
    b: TAddable,
) -> TAddable

[src] Adds two values, equivalent to SQL’s UNION when applied to ZSets.


st.count(
    a: st.ZSet[T],
) -> st.ZSet[int]

[src] Counts the number of values (effectively sum(count for _, count in a.iter())). Returns a ZSet containing a single int


st.first_n(
    a: st.ZSet[T],
    *,
    index: st.Index[T, K],
    n: int,
) -> st.ZSet[T]

[src] Similar to SQL’s ORDER BY ... LIMIT n. The output is unordered (it’s still a ZSet), but calling:

for key, value, count in z.iter_by_index(index):
    ...

Will yield values ordered by the index.


st.transitive_closure(
    a: st.ZSet[st.Pair[TIndexable, TIndexable]],
) -> st.ZSet[st.Pair[TIndexable, TIndexable]]

[src] Given a set of edges left -> right, returns the transitive closure of all the edges.

Example – given:

left right
 0    1
 1    2
 2    3
 0    4
 1    5

Output:

left right
 0    1
 0    2
 0    3
 0    4
 0    5
 1    2
 1    3
 1    5
 2    3

Read the code for ideas implementing other recursive functions.

Group/Reduce

st.reduce(
    a: st.ZSet[T],
    *,
    zero: Callable[[], TReducable],
    pick_value: Callable[[T], TReducable],
) -> st.ZSet[TReducable]

[src] A more general version of st.count(...). In common usage zero and pick_value will be functions that either:

  • Return 0 and an int, thereby implementing SQL’s SUM.
  • Return an empty ZSetPython[SomeType] and a ZSetPython[SomeType] respectively, thereby (kinda) implementing SQL’s ARRAY_AGG

Note that to handle the removal of rows in the inputted changes, TReducable has to implement __mul__ (which luckily ZSetPythons do).


st.group_reduce_flatten(
    a: st.ZSet[T],
    *,
    by: st.Index[T, K],
    zero: Callable[[], TReducable],
    pick_value: Callable[[T], TReducable],
) -> st.ZSet[st.Pair[TReducable, K]]

[src] Equivalent to SQL’s SELECT reduce(...) FROM ... GROUP BY .... In common usage zero and pick_value will be functions that return a ZSetPython[SomeType]

The output is a ZSet of pairs of the reduced value and the key they were grouped by.


st.group(
    a: st.ZSet[T],
    *,
    by: st.Index[T, K],
) -> st.Grouped[st.ZSet[T], K]

[src] Groups a by a key.


st.flatten(
    a: st.Grouped[st.ZSet[T], K],
) -> st.ZSet[st.Pair[T, K]]

[src] Flattens a Group to a more useful ZSet

Internal

st.neg(
    a: TNegable,
) -> TNegable

[src] Returns -a (remember, applicable to ZSets).


st.make_scalar(
    a: st.ZSet[T],
    *,
    zero: Callable[[], T],
) -> T

[src] Turn a ZSet of count = 1 to a scalar value.


st.make_set(
    a: T,
) -> st.ZSet[T]

[src] Turn a scalar into a ZSet of count = 1. SQL implicitly does this if you do SELECT 1


st.add3(
    a: TAddable,
    b: TAddable,
    c: TAddable,
) -> TAddable

[src] Add three things.


st.haitch(
    a: st.ZSet[T],
    b: st.ZSet[T],
) -> st.ZSet[T]

[src] Used internally by st.distinct(...), efficiently watches for change of sign in counts.

Delay/Differentiate/Integrate

st.delay(
    a: T,
) -> T

[src] Returns the previous value it was called with, see reference page.


st.delay_indexed(
    a: st.ZSet[T],
    *,
    indexes: tuple[st.Index[T, K]], ...],
) -> st.ZSet[T]

[src] Returns the previous value it was called with, with indexes.


st.differentiate(
    a: TAddAndNegable,
) -> TAddAndNegable

[src] Differentiates input values over time. See reference page.


st.integrate(
    a: TAddable,
) -> TAddable

[src] Integrates input values over time. See reference page.


st.integrate_indexed(
    a: st.ZSet[T],
    *,
    indexes: tuple[st.Index[T, K]], ...],
) -> st.ZSet[T]

[src] Integrates input values over time, adds indexes to the delay node. See reference page.


st.integrate_delay(
    a: TAddable,
) -> TAddable

[src] Integrates input values over time, returns the previous value. See reference page.

Compile


st.compile(
    func: Callable[..., Any],
) -> st.Graph[Any, Any]

[src] Compile a query function to a graph.


st.compile_lazy(
    func: Callable[..., Any],
) -> Callable[[], st.Graph[Any, Any]]

[src] Returns a function with no arguments that compiles the graph, caches it and returns it.


st.compile_typeof(
    t: T,
) -> type[T]

[src] Get the resolved type of t at query compile time.


with st.at_compile_time:
    ...

[src] Run this code block at query compile time.


Run

st.iteration(
    store: st.Store,
    g: st.Graph[Any, Any],
    inputs: tuple[Any, ...],
    flush: bool,
) -> tuple[Any, ...]

[src] Run a single iteration of a graph, returning resultant changes.


st.actions(
    store: st.Store,
    g: st.Graph[Any, Any],
) -> Any

[src] Return a tuple of helpers to insert, remove, replace. Examples dotted around the docs.


Indexes

Indexes pick a key of type K from a value of type T. The index key should be indexable:

IndexableAtom = str | int | float | bool | None | date | datetime | UUID
Indexable = IndexableAtom | tuple[IndexableAtom, ...]

For each of the constructor methods, an optional boolean ascending can be passed in, this is equivalent to SQL’s ASC/DESC. If the key is tuple[IndexableAtom, ...], ascending must be a tuple of bools of the same length.


st.Index.atom(
    name: str,
    t: type[T],
    k: type[KAtom],
    f: Callable[[T], KAtom],
    ascending: bool = True,
) -> Index[T, KAtom]:

[src] Pick an index of t using an f that returns an IndexableAtom.


st.Index.composite(
    names: tuple[str, ...],
    t: type[T],
    k: type[KTuple],
    f: Callable[[T], KTuple],
    ascendings: tuple[bool, ...] | None = None,
) -> Index[T, KTuple]:

[src] Pick an index of t using an f that returns a composite value, i.e. a tuple[IndexableAtom, IndexableAtom, ...].


st.Index.identity(
    t: type[KAtom],
    ascending: bool = True,
) -> Index[KAtom, KAtom]:

[src] Use a value that is already an IndexableAtom as an index.


st.Index.pick(
    t: type[T],
    f: Callable[[T], K],
    ascending: bool | tuple[bool, ...] = True,
) -> st.Index[T, K]

[src] Pick an index of t using a lambda function. The lambda function gets immediately called to determine the names and types of the index, so is somewhat restricted.


Database Connections

with st.connection_postgres(db_url: str) as conn:
    ...

[src] Context manager for a Postgres connection.


with st.connection_sqlite(db_url: pathlib.Path) as conn:
    ...

[src] Context manager for a SQLite connection.


Helpers

st.batched(
    iterable: list[T],
    n: int,
) -> Iterator[list[T]]

[src] See itertools docs.


st.write_png(
    graph: st.Graph[Any, Any],
    path: str,
    simplify_labels: bool,
    level: int,
) -> NoneType

[src] Write a graph to a .png file using dot