Adds some type hints to improve developer experience.
Adds a utility maybe_dotted_gid to check whether a string may be a chain of gids, separated by dots. Also works for a single gid, but if you need only a single gid, keep using maybe_gid.
Unicat v2025.07.001 adds module information for Unicat Connect modules, allowing the modules to read and write module-related information. Multiple users can now read and write shared settings and configurations. The modules can add log entries.
We have three new classes, UnicatModule, UnicatModuleAction, and UnicatModuleLog.
To support these, there are four new reading methods and nine new mutating functions.
unicat.get_all_module_names() -> list[str]
unicat.get_module(name: str, *, force: bool) -> UnicatModule | None
unicat.get_modules(names: list[str], *, force: bool) -> list[UnicatModule]
unicat.walk_modules() -> Iterator[UnicatModule]
mutate.register_module(name: str, version: str) -> UnicatModule
mutate.unregister_module(module: UnicatModule) -> bool
mutate.set_module_key(module: UnicatModule, key: str, value: Any) -> UnicatModule
mutate.set_module_keys(module: UnicatModule, keyvalues: dict(str, Any)) -> UnicatModule
mutate.clear_module_key(module: UnicatModule, key: str) -> UnicatModule
mutate.clear_module_keys(module: UnicatModule, keys: list(str)) -> UnicatModule
mutate.publish_module_action(module: UnicatModule, action: str, configuration: dict(str, Any)) -> UnicatModule
mutate.unpublish_module_action(module: UnicatModule, action: str) -> UnicatModule
mutate.add_module_log(module: UnicatModule, version: str, action: str, configuration: dict(str, Any), command: str, started_at: timestamp, ended_at: timestamp, status: str, output: str) -> UnicatModule
Another change is that a definitions all_fields and all_base_fields now first return the fields, and then the fields from all the classes, instead of the other way around.
Unicat v2025.04.002 adds metadata to schema definitions, classes, and fields.
On these classes, there's a new metadata property, that is a dict of UnicatMetadataField items.
For mutating, the create and modify functions for definitions, classes, and fields accept a metadata argument. In addition, there are six new mutating functions.
mutate.modify_definition_set_metadata(definition: UnicatDefinition, name: str, *, type: str, is_localized: bool, value: Any) -> UnicatDefinition
mutate.modify_definition_clear_metadata(definition: UnicatDefinition, name: str) -> UnicatDefinition
mutate.modify_class_set_metadata(class_: UnicatClass, name: str, *, type: str, is_localized: bool, value: Any) -> UnicatClass
mutate.modify_class_clear_metadata(class_: UnicatClass, name: str) -> UnicatClass
mutate.modify_field_set_metadata(field: UnicatField, name: str, *, type: str, is_localized: bool, value: Any) -> UnicatField
mutate.modify_field_clear_metadata(field: UnicatField, name: str) -> UnicatField
Unicat v2025.01.001 adds keys to the field 'values' option, so each value has a key and a localized label. This version of the Unicat Python library fully supports that, and adds a .key property to a RecordField (if applicable).
The walk_* functions now throw on error, for example when the API returns an unexpected 500 error.
The retry mechanism will now also retry on status 500, 502, 503, and 504 (with exponential backoff and max # of tries)
Optional limit argument for walk_*_query methodes now uses that exact value, within a range of 1 to 1000, and it has a default of 100.
Fix error when accessing .original on a new definition, class, or field.
mutate.extend_record_definition_remove_class(record: UnicatRecord, class_: UnicatClass) -> UnicatRecord
mutate.extend_record_definition_remove_field(record: UnicatRecord, field: UnicatField) -> UnicatRecord
mutate.extend_record_definition_remove_fieldlist_field(record: UnicatRecord, fieldlist: gid, field: UnicatField) -> UnicatRecord
Specifically, 'nee' (Dutch), 'nein' (German), and 'non' (French) are now interpreted as false. Also, 'nil' is interpreted as false.
This affects test_true as well, since it is implemented as not test_false.
In rare cases an assetlist or recordlist field can have references to assets or records that no longer exist. This used to throw a UnicatError for the entire list, but now it returns None for that specific item, so you can still use the rest of the items.
A new sync() method that brings the local storage in sync with the server. Raises UnicatError on error.
unicat.sync() -> True
Internally, the return value for api.sync() changed from None to a tuple (bool, result). The boolean indicates failure or success. On failure, result holds a standard Unicat error response . On success, the result is a boolean that indicates if we're in sync (True), or if there's more data to be synced (False).
If pathname is given for a (transformed) download, updated_on is checked earlier, so a transform call (which is fairly expensive) can be skipped.
Renamed get_assets_by_pathnames to get_assets_by_pathname, and changed the return
value to a dict keyed by pathname, for consistency with other by_name functions.
unicat.get_assets_by_pathname(pathnames: list[str], *, force: bool) -> dict[str, UnicatAsset]
Fixed docs for by_name functions that fetch multiple items - they return dicts keyed by name. Fixed returned values for those to return empty dicts when the names list is empty.
unicat.get_definitions_by_name(names: list[str]) -> dict[str, UnicatDefinition]
unicat.get_classes_by_name(names: list[str]) -> dict[str, UnicatClass]
unicat.get_fields_by_name(names: list[str]) -> dict[str, UnicatField]
unicat.get_record_queries_by_name(names: list[str]) -> dict[str, UnicatQuery]
unicat.get_asset_queries_by_name(names: list[str]) -> dict[str, UnicatQuery]
unicat.get_schema_queries_by_name(names: list[str]) -> dict[str, UnicatQuery]
Fixed walk_schema_query crash.
Fixed error-reporting from a UnicatJob gone wrong.
New project properties and methods
project.backups: list[UnicatProjectBackup]
project.get_backup(version: int) -> UnicatProjectBackup | None
New UnicatProjectBackup class
backup.version: int
backup.name: str
backup.created_by: str
backup.timestamp: timestamp # 1610635123.351925
New mutation methods
mutate.create_backup(created_by: str, name: str, return_job: Bool = False) -> UnicatProjectBackup | UnicatJob
mutate.update_backup(backup: UnicatProjectBackup, name: str) -> UnicatProjectBackup
mutate.restore_backup(backup: UnicatProjectBackup, return_job: Bool = False) -> UnicatProject | UnicatJob
mutate.delete_backup(backup: UnicatProjectBackup) -> UnicatProject
mutate.delete_backups(backups: list[UnicatProjectBackup]) -> UnicatProject
All the things that came before