Unicat Python SDK

Up - Home


unicat.utils

from unicat.utils import *
def gid() -> str  # a uuid4

def maybe_gid(possible_gid: Any) -> bool

def test_true(data: Any) -> bool

def test_false(data: Any) -> bool

def make_bool(any: Any) -> bool

def make_bool_str(any: Any) -> str

def make_str(any: Any) -> str

def make_json_str(any: Any) -> str

def make_json(any: Any) -> Any

def make_json_list(any: Any) -> list[Any]

def make_int(any: Any) -> int

def make_float(any: Any) -> float

def noop(any: Any) -> Any

def make_str_list(any: Any) -> list[str]

def convert_value_to_fielddata(fieldtype: str, value: Any) -> bool | str | Any | int | float | list[str] | list[Any]
    """Return a value suitable for writing to Unicat, for list field types this
    means converting newline-separated entries to lists.
    For class or classlist fields, we produce a JSON data structure.

    This can raise exceptions when the value doesn't match the type, e.g. converting a
    string to a float.
    """

def convert_fielddata_to_value(fieldtype: str, fielddata: Any) -> str | int | float
    """Return a value suitable for writing in a cell, such as a text or a number.
    Lists will be flattened by stringifying each item and concatenating with \n.
    For class or classlist fields, we will have pretty-printed JSON.
    """

def merge_dicts(a: dict, b: dict) -> dict
    """Merge b into a, returning a.

    a is updated; if you don't want to mutate a, call it as `merge_dicts(dict(a), b)`.
    """

def diff_record_fields_data(unicat: Unicat, record: UnicatRecord, localizedfielddata: dict) -> dict  # dict format: d[language][fieldname] = value
    """Return a version of localizedfielddata that only has data that is different from
    the raw record data.
    """

def hash_text(text: str) -> str  # unicode ok

def hash_data(data: Any) -> str  # data must be json-serializable

class DuckObject  # quickly construct an object-like duck from a dict or kwargs, see below

class FieldColumns  # flatten a list of (class-)fields, see below

DuckObject

DuckObjects are used to quickly construct an object-like duck.

Uses keyword arguments to construct any duck-like object with those attributes.

ducklike = DuckObject(walk="waddle", talk="quack")
assert ducklike.walk == "waddle"
assert ducklike.talk == "quack"
assert not hasattr(ducklike, "bill")

duckquery = DuckObject(
    q="",
    filter=["value", "is", [base_artnr_field.gid, article.base_artnr]]
)
print(duckquery.q, duckquery.filter)

duckrecord = DuckObject(gid="<anything gid-like>")
print(duckrecord.gid)

FieldColumns

FieldColumns are needed for class fields, that have nested subfields.

With FieldColumns, we can flatten a list of fields to a list of columns, associated with those fields.

Each column has a fieldstack, that is a list of the field and nested subfields. For a regular field, the fieldstack is just that field. A classfield with three subfields will yield three columns, and each column has a fieldstack with the classfield first, and then the subfield for that column. If that subfield is another classfield, we'll get more columns and deeper stackfields.

For example, you have [image, dimensions] as fields, and dimensions is of type class, and has subfields width and length; FieldColumns will give you [image, dimensions.width, dimensions.length], useable for writing to tab-separated files or spreadsheets.

Client code can look something like this, for reading from Unicat:

columns = FieldColumns(fields, prefix_column_count=3)
for column in columns:
    column_name = column.name()  # e.g. 'image' or 'dimensions.width__mm'
    column_label = column.label()  # e.g. 'Image' or 'Dimensions\nWidth [mm]'
    column_value = None
    error = None
    try:
        record_field = column.extract_record_field(record.fields[language])
        column_value = record_field.value if record_field else None
    except KeyError:
        error = (
            "Field is not part of this definition. Do not enter data here."
        )

FieldColumns can also be used to write to Unicat, when we need a record's fields data structure:

recordfields_data = {}
for column in columns:
    fieldvalue = row[column.index].value
    column.update_fields_data(recordfields_data, fieldvalue)
unicat.mutate.update_record(record, {language: recordfields_data})