Skip to content

aliases

VALUE_ALIAS_SEPARATOR

logger

Classes

AliasValueMap (ValueMap) pydantic-model

A model class that holds a tree of values and their schemas.

Source code in kiara/models/aliases/__init__.py
class AliasValueMap(ValueMap):
    """A model class that holds a tree of values and their schemas."""

    _kiara_model_id = "instance.value_map.aliases"

    alias: Union[str, None] = Field(description="This maps own (full) alias.")
    version: int = Field(description="The version of this map (in this maps parent).")
    created: Union[datetime.datetime, None] = Field(
        description="The time this map was created."
    )
    assoc_schema: Union[ValueSchema, None] = Field(
        description="The schema for this maps associated value."
    )
    assoc_value: Union[uuid.UUID, None] = Field(
        description="The value that is associated with this map."
    )

    value_items: Dict[str, Dict[int, "AliasValueMap"]] = Field(
        description="The values contained in this set.", default_factory=dict
    )

    _data_registry: "DataRegistry" = PrivateAttr(default=None)
    _schema_locked: bool = PrivateAttr(default=False)
    _auto_schema: bool = PrivateAttr(default=True)
    _is_stored: bool = PrivateAttr(default=False)

    def _retrieve_data_to_hash(self) -> Any:
        raise NotImplementedError()

    @property
    def is_stored(self) -> bool:
        return self._is_stored

    def get_child_map(
        self, field_name: str, version: Union[str, None] = None
    ) -> Union["AliasValueMap", None]:
        """Get the child map for the specified field / version combination.

        Raises an error if the child field does not exist. Returns 'None' if not value is set yet (but schema is).
        """

        if version is not None:
            raise NotImplementedError()

        if VALUE_ALIAS_SEPARATOR not in field_name:

            if self.values_schema.get(field_name, None) is None:
                if not self.values_schema:
                    msg = "No available fields"
                else:
                    msg = "Available fields: " + ", ".join(self.values_schema.keys())
                raise KeyError(f"No field name '{field_name}'. {msg}")

            field_items = self.value_items[field_name]
            if not field_items:
                return None

            max_version = max(field_items.keys())

            item = field_items[max_version]
            return item

        else:
            child, rest = field_name.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)
            if child not in self.values_schema.keys():
                raise Exception(
                    f"No field name '{child}'. Available fields: {', '.join(self.values_schema.keys())}"
                )
            child_map = self.get_child_map(child)
            assert child_map is not None
            return child_map.get_child_map(rest)

    def get_value_obj(self, field_name: str) -> Value:

        item = self.get_child_map(field_name=field_name)
        if item is None:
            return self._data_registry.NONE_VALUE
        if item.assoc_value is None:
            raise Exception(f"No value associated for field '{field_name}'.")

        return self._data_registry.get_value(value_id=item.assoc_value)

    def get_value_id(self, field_name: str) -> uuid.UUID:

        item = self.get_child_map(field_name=field_name)
        if item is None:
            result = NONE_VALUE_ID
        else:
            result = item.assoc_value if item.assoc_value is not None else NONE_VALUE_ID

        return result

    def get_all_value_ids(
        self,
    ) -> Dict[str, uuid.UUID]:

        result: Dict[str, uuid.UUID] = {}
        for k in self.values_schema.keys():
            v_id = self.get_value_id(field_name=k)
            if v_id is None:
                v_id = NONE_VALUE_ID
            result[k] = v_id
        return result

    def set_alias_schema(self, alias: str, schema: ValueSchema):

        if self._schema_locked:
            raise Exception(f"Can't add schema for alias '{alias}': schema locked.")

        if VALUE_ALIAS_SEPARATOR not in alias:

            self._set_local_field_schema(field_name=alias, schema=schema)
        else:
            child, rest = alias.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)

            if child in self.values_schema.keys():
                child_map = self.get_child_map(child)
            else:
                self._set_local_field_schema(
                    field_name=child, schema=ValueSchema(type="none")
                )
                child_map = self._set_alias(alias=child, data=None)

            assert child_map is not None

            child_map.set_alias_schema(alias=rest, schema=schema)

    def _set_local_field_schema(self, field_name: str, schema: ValueSchema):

        assert field_name is not None
        if VALUE_ALIAS_SEPARATOR in field_name:
            raise Exception(
                f"Can't add schema, field name has alias separator in name: {field_name}. This is most likely a bug."
            )

        if field_name in self.values_schema.keys():
            raise Exception(
                f"Can't set alias schema for '{field_name}' to map: schema already set."
            )

        try:
            items = self.get_child_map(field_name)
            if items is not None:
                raise Exception(
                    f"Can't set schema for field '{field_name}': already at least one child set for this field."
                )
        except KeyError:
            pass

        self.values_schema[field_name] = schema
        self.value_items[field_name] = {}

    def get_alias(self, alias: str) -> Union["AliasValueMap", None]:

        if VALUE_ALIAS_SEPARATOR not in alias:
            if "@" in alias:
                raise NotImplementedError()

            child_map = self.get_child_map(alias)
            if child_map is None:
                return None

            return child_map

        else:
            child, rest = alias.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)
            if "@" in child:
                raise NotImplementedError()

            child_map = self.get_child_map(field_name=child)

            if child_map is None:
                return None

            return child_map.get_alias(rest)

    def set_value(self, field_name: str, data: Any) -> None:

        assert VALUE_ALIAS_SEPARATOR not in field_name

        self._set_alias(alias=field_name, data=data)

    def _set_aliases(self, **aliases: Any) -> Mapping[str, "AliasValueMap"]:

        result = {}
        for k, v in aliases.items():
            r = self._set_alias(alias=k, data=v)
            result[k] = r

        return result

    def _set_alias(self, alias: str, data: Any) -> "AliasValueMap":

        if VALUE_ALIAS_SEPARATOR not in alias:
            field_name: Union[str, None] = alias

            # means we are setting the alias in this map
            assert field_name is not None

            vs = self.values_schema[alias]
            if vs.type == "none":
                assert data is None
                value_id = None
            else:

                if data in [None, SpecialValue.NO_VALUE, SpecialValue.NOT_SET]:
                    if vs.default:
                        if callable(vs.default):
                            data = vs.default()
                        else:
                            data = copy.deepcopy(vs.default)

                value = self._data_registry.register_data(data=data, schema=vs)
                value_id = value.value_id

            new_map = self._set_local_value_item(
                field_name=field_name, value_id=value_id
            )
            return new_map

        else:
            child, rest = alias.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)
            field_name = None

            # means we are dealing with an intermediate alias map
            assert rest is not None
            assert child is not None
            assert field_name is None
            if child not in self.value_items.keys():
                if not self._auto_schema:
                    raise Exception(
                        f"Can't set alias '{alias}', no schema set for field: '{child}'."
                    )
                else:
                    self.set_alias_schema(alias=child, schema=ValueSchema(type="any"))

            field_item: Union[AliasValueMap, None] = None
            try:
                field_item = self.get_child_map(field_name=child)
            except KeyError:
                pass

            if self.alias:
                new_alias = f"{self.alias}.{child}"
            else:
                new_alias = child

            if field_item is None:
                new_version = 0
                schemas = {}
                self.value_items[child] = {}
            else:
                max_version = len(field_item.keys())
                new_version = max_version + 1
                assert field_item.alias == new_alias
                assert field_item.version == max_version
                schemas = field_item.values_schema

            new_map = AliasValueMap(
                alias=new_alias,
                version=new_version,
                assoc_schema=self.values_schema[child],
                assoc_value=None,
                values_schema=schemas,
            )
            new_map._data_registry = self._data_registry
            self.value_items[child][new_version] = new_map

            new_map._set_alias(alias=rest, data=data)

        return new_map

    def _set_local_value_item(
        self, field_name: str, value_id: Union[uuid.UUID, None] = None
    ) -> "AliasValueMap":

        assert VALUE_ALIAS_SEPARATOR not in field_name

        value: Union[Value, None] = None
        if value_id is not None:
            value = self._data_registry.get_value(value_id=value_id)
            assert value is not None
            assert value.value_id == value_id

        if field_name not in self.values_schema.keys():
            if not self._auto_schema:
                raise Exception(
                    f"Can't add value for field '{field_name}': field not in schema."
                )
            else:
                if value_id is None:
                    value_schema = ValueSchema(type="none")
                else:
                    value_schema = value.value_schema  # type: ignore
                self.set_alias_schema(alias=field_name, schema=value_schema)

        field_items = self.value_items.get(field_name, None)
        if not field_items:
            assert field_items is not None
            new_version = 0
            values_schema = {}
        else:
            max_version = max(field_items.keys())
            current_map = field_items[max_version]

            if value_id == current_map.assoc_value:
                logger.debug(
                    "set_field.skip",
                    value_id=None,
                    reason=f"Same value id: {value_id}",
                )
                return current_map

            # TODO: check schema
            new_version = max(field_items.keys()) + 1
            values_schema = current_map.values_schema

        if self.alias:
            new_alias = f"{self.alias}.{field_name}"
        else:
            new_alias = field_name
        new_map = AliasValueMap(
            alias=new_alias,
            version=new_version,
            assoc_schema=self.values_schema[field_name],
            assoc_value=value_id,
            values_schema=values_schema,
        )
        new_map._data_registry = self._data_registry
        self.value_items[field_name][new_version] = new_map
        return new_map

    def print_tree(self):

        t = self.get_tree("base")
        terminal_print(t)

    def get_tree(self, base_name: str) -> Tree:

        if self.assoc_schema:
            type_name = self.assoc_schema.type
        else:
            type_name = "none"

        if type_name == "none":
            type_str = ""
        else:
            type_str = f" ({type_name})"

        tree = Tree(f"{base_name}{type_str}")
        if self.assoc_value:
            data = tree.add("__data__")
            value = self._data_registry.get_value(self.assoc_value)
            data.add(str(value.data))

        for field_name, schema in self.values_schema.items():

            alias = self.get_alias(alias=field_name)
            if alias is not None:
                tree.add(alias.get_tree(base_name=field_name))
            else:
                if schema.type == "none":
                    type_str = ""
                else:
                    type_str = f" ({schema.type})"

                tree.add(f"{field_name}{type_str}")

        return tree

    def __repr__(self):

        return f"AliasMap(assoc_value={self.assoc_value}, field_names={self.value_items.keys()})"

    def __str__(self):
        return self.__repr__()

Attributes

alias: str pydantic-field

This maps own (full) alias.

assoc_schema: ValueSchema pydantic-field

The schema for this maps associated value.

assoc_value: UUID pydantic-field

The value that is associated with this map.

created: datetime pydantic-field

The time this map was created.

is_stored: bool property readonly
value_items: Dict[str, Dict[int, AliasValueMap]] pydantic-field

The values contained in this set.

version: int pydantic-field required

The version of this map (in this maps parent).

Methods

get_alias(self, alias)
Source code in kiara/models/aliases/__init__.py
def get_alias(self, alias: str) -> Union["AliasValueMap", None]:

    if VALUE_ALIAS_SEPARATOR not in alias:
        if "@" in alias:
            raise NotImplementedError()

        child_map = self.get_child_map(alias)
        if child_map is None:
            return None

        return child_map

    else:
        child, rest = alias.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)
        if "@" in child:
            raise NotImplementedError()

        child_map = self.get_child_map(field_name=child)

        if child_map is None:
            return None

        return child_map.get_alias(rest)
get_all_value_ids(self)
Source code in kiara/models/aliases/__init__.py
def get_all_value_ids(
    self,
) -> Dict[str, uuid.UUID]:

    result: Dict[str, uuid.UUID] = {}
    for k in self.values_schema.keys():
        v_id = self.get_value_id(field_name=k)
        if v_id is None:
            v_id = NONE_VALUE_ID
        result[k] = v_id
    return result
get_child_map(self, field_name, version=None)

Get the child map for the specified field / version combination.

Raises an error if the child field does not exist. Returns 'None' if not value is set yet (but schema is).

Source code in kiara/models/aliases/__init__.py
def get_child_map(
    self, field_name: str, version: Union[str, None] = None
) -> Union["AliasValueMap", None]:
    """Get the child map for the specified field / version combination.

    Raises an error if the child field does not exist. Returns 'None' if not value is set yet (but schema is).
    """

    if version is not None:
        raise NotImplementedError()

    if VALUE_ALIAS_SEPARATOR not in field_name:

        if self.values_schema.get(field_name, None) is None:
            if not self.values_schema:
                msg = "No available fields"
            else:
                msg = "Available fields: " + ", ".join(self.values_schema.keys())
            raise KeyError(f"No field name '{field_name}'. {msg}")

        field_items = self.value_items[field_name]
        if not field_items:
            return None

        max_version = max(field_items.keys())

        item = field_items[max_version]
        return item

    else:
        child, rest = field_name.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)
        if child not in self.values_schema.keys():
            raise Exception(
                f"No field name '{child}'. Available fields: {', '.join(self.values_schema.keys())}"
            )
        child_map = self.get_child_map(child)
        assert child_map is not None
        return child_map.get_child_map(rest)
get_tree(self, base_name)
Source code in kiara/models/aliases/__init__.py
def get_tree(self, base_name: str) -> Tree:

    if self.assoc_schema:
        type_name = self.assoc_schema.type
    else:
        type_name = "none"

    if type_name == "none":
        type_str = ""
    else:
        type_str = f" ({type_name})"

    tree = Tree(f"{base_name}{type_str}")
    if self.assoc_value:
        data = tree.add("__data__")
        value = self._data_registry.get_value(self.assoc_value)
        data.add(str(value.data))

    for field_name, schema in self.values_schema.items():

        alias = self.get_alias(alias=field_name)
        if alias is not None:
            tree.add(alias.get_tree(base_name=field_name))
        else:
            if schema.type == "none":
                type_str = ""
            else:
                type_str = f" ({schema.type})"

            tree.add(f"{field_name}{type_str}")

    return tree
get_value_id(self, field_name)
Source code in kiara/models/aliases/__init__.py
def get_value_id(self, field_name: str) -> uuid.UUID:

    item = self.get_child_map(field_name=field_name)
    if item is None:
        result = NONE_VALUE_ID
    else:
        result = item.assoc_value if item.assoc_value is not None else NONE_VALUE_ID

    return result
get_value_obj(self, field_name)
Source code in kiara/models/aliases/__init__.py
def get_value_obj(self, field_name: str) -> Value:

    item = self.get_child_map(field_name=field_name)
    if item is None:
        return self._data_registry.NONE_VALUE
    if item.assoc_value is None:
        raise Exception(f"No value associated for field '{field_name}'.")

    return self._data_registry.get_value(value_id=item.assoc_value)
print_tree(self)
Source code in kiara/models/aliases/__init__.py
def print_tree(self):

    t = self.get_tree("base")
    terminal_print(t)
set_alias_schema(self, alias, schema)
Source code in kiara/models/aliases/__init__.py
def set_alias_schema(self, alias: str, schema: ValueSchema):

    if self._schema_locked:
        raise Exception(f"Can't add schema for alias '{alias}': schema locked.")

    if VALUE_ALIAS_SEPARATOR not in alias:

        self._set_local_field_schema(field_name=alias, schema=schema)
    else:
        child, rest = alias.split(VALUE_ALIAS_SEPARATOR, maxsplit=1)

        if child in self.values_schema.keys():
            child_map = self.get_child_map(child)
        else:
            self._set_local_field_schema(
                field_name=child, schema=ValueSchema(type="none")
            )
            child_map = self._set_alias(alias=child, data=None)

        assert child_map is not None

        child_map.set_alias_schema(alias=rest, schema=schema)
set_value(self, field_name, data)
Source code in kiara/models/aliases/__init__.py
def set_value(self, field_name: str, data: Any) -> None:

    assert VALUE_ALIAS_SEPARATOR not in field_name

    self._set_alias(alias=field_name, data=data)