Skip to content

Data Templates

albert.collections.data_templates.DataTemplateCollection

DataTemplateCollection(*, session: AlbertSession)

Bases: BaseCollection

DataTemplateCollection is a collection class for managing DataTemplate entities in the Albert platform.

Methods:

Name Description
create

Creates a new data template.

get_by_id

Get a data template by its ID.

get_by_ids

Get a list of data templates by their IDs.

get_by_name

Get a data template by its name.

add_data_columns

Adds data columns to a data template.

add_parameters

Adds parameters to a data template.

list

Lists data template entities with optional filters.

update

Updates a data template.

delete

Deletes a data template by its ID.

Attributes:

Name Type Description
base_path
Source code in src/albert/collections/data_templates.py
def __init__(self, *, session: AlbertSession):
    super().__init__(session=session)
    self.base_path = f"/api/{DataTemplateCollection._api_version}/datatemplates"

base_path

base_path = f'/api/{_api_version}/datatemplates'

create

create(*, data_template: DataTemplate) -> DataTemplate

Creates a new data template.

Parameters:

Name Type Description Default
data_template DataTemplate

The DataTemplate object to create.

required

Returns:

Type Description
DataTemplate

The registered DataTemplate object with an ID.

Source code in src/albert/collections/data_templates.py
def create(self, *, data_template: DataTemplate) -> DataTemplate:
    """Creates a new data template.

    Parameters
    ----------
    data_template : DataTemplate
        The DataTemplate object to create.

    Returns
    -------
    DataTemplate
        The registered DataTemplate object with an ID.
    """
    # Preprocess data_column_values to set validation to None if it is an empty list
    # Handle a bug in the API where validation is an empty list
    # https://support.albertinvent.com/hc/en-us/requests/9177
    if (
        isinstance(data_template.data_column_values, list)
        and len(data_template.data_column_values) == 0
    ):
        data_template.data_column_values = None
    if data_template.data_column_values is not None:
        for column_value in data_template.data_column_values:
            if isinstance(column_value.validation, list) and len(column_value.validation) == 0:
                column_value.validation = None
    # remove them on the initial post
    parameter_values = data_template.parameter_values
    data_template.parameter_values = None
    response = self.session.post(
        self.base_path,
        json=data_template.model_dump(mode="json", by_alias=True, exclude_none=True),
    )
    dt = DataTemplate(**response.json())
    dt.parameter_values = parameter_values
    if data_template.parameter_values is None or len(data_template.parameter_values) == 0:
        return dt
    else:
        return self.add_parameters(
            data_template_id=dt.id, parameters=data_template.parameter_values
        )

get_by_id

get_by_id(*, id: DataTemplateId) -> DataTemplate

Get a data template by its ID.

Parameters:

Name Type Description Default
id DataTemplateId

The ID of the data template to get.

required

Returns:

Type Description
DataTemplate

The data template object on match or None

Source code in src/albert/collections/data_templates.py
def get_by_id(self, *, id: DataTemplateId) -> DataTemplate:
    """Get a data template by its ID.

    Parameters
    ----------
    id : DataTemplateId
        The ID of the data template to get.

    Returns
    -------
    DataTemplate
        The data template object on match or None
    """
    response = self.session.get(f"{self.base_path}/{id}")
    return DataTemplate(**response.json())

get_by_ids

get_by_ids(
    *, ids: list[DataTemplateId]
) -> list[DataTemplate]

Get a list of data templates by their IDs.

Parameters:

Name Type Description Default
ids list[DataTemplateId]

The list of DataTemplate IDs to get.

required

Returns:

Type Description
list[DataTemplate]

A list of DataTemplate objects with the provided IDs.

Source code in src/albert/collections/data_templates.py
def get_by_ids(self, *, ids: list[DataTemplateId]) -> list[DataTemplate]:
    """Get a list of data templates by their IDs.

    Parameters
    ----------
    ids : list[DataTemplateId]
        The list of DataTemplate IDs to get.

    Returns
    -------
    list[DataTemplate]
        A list of DataTemplate objects with the provided IDs.
    """
    url = f"{self.base_path}/ids"
    batches = [ids[i : i + 250] for i in range(0, len(ids), 250)]
    return [
        DataTemplate(**item)
        for batch in batches
        for item in self.session.get(url, params={"id": batch}).json()["Items"]
    ]

get_by_name

get_by_name(*, name: str) -> DataTemplate | None

Get a data template by its name.

Parameters:

Name Type Description Default
name str

The name of the data template to get.

required

Returns:

Type Description
DataTemplate | None

The matching data template object or None if not found.

Source code in src/albert/collections/data_templates.py
def get_by_name(self, *, name: str) -> DataTemplate | None:
    """Get a data template by its name.

    Parameters
    ----------
    name : str
        The name of the data template to get.

    Returns
    -------
    DataTemplate | None
        The matching data template object or None if not found.
    """
    hits = list(self.list(name=name))
    for h in hits:
        if h.name.lower() == name.lower():
            return h
    return None

add_data_columns

add_data_columns(
    *,
    data_template_id: DataTemplateId,
    data_columns: list[DataColumnValue],
) -> DataTemplate

Adds data columns to a data template.

Parameters:

Name Type Description Default
data_template_id str

The ID of the data template to add the columns to.

required
data_columns list[DataColumnValue]

The list of DataColumnValue objects to add to the data template.

required

Returns:

Type Description
DataTemplate

The updated DataTemplate object.

Source code in src/albert/collections/data_templates.py
def add_data_columns(
    self, *, data_template_id: DataTemplateId, data_columns: list[DataColumnValue]
) -> DataTemplate:
    """Adds data columns to a data template.

    Parameters
    ----------
    data_template_id : str
        The ID of the data template to add the columns to.
    data_columns : list[DataColumnValue]
        The list of DataColumnValue objects to add to the data template.

    Returns
    -------
    DataTemplate
        The updated DataTemplate object.
    """
    # if there are enum values, we need to add them as an allowed enum
    for column in data_columns:
        if (
            column.validation
            and len(column.validation) > 0
            and isinstance(column.validation[0].value, list)
        ):
            for enum_value in column.validation[0].value:
                self.session.put(
                    f"{self.base_path}/{data_template_id}/datacolumns/{column.sequence}/enums",
                    json=[
                        enum_value.model_dump(mode="json", by_alias=True, exclude_none=True)
                    ],
                )

    payload = {
        "DataColumns": [
            x.model_dump(mode="json", by_alias=True, exclude_none=True) for x in data_columns
        ]
    }
    self.session.put(
        f"{self.base_path}/{data_template_id}/datacolumns",
        json=payload,
    )
    return self.get_by_id(id=data_template_id)

add_parameters

add_parameters(
    *,
    data_template_id: DataTemplateId,
    parameters: list[ParameterValue],
) -> DataTemplate

Adds parameters to a data template.

Parameters:

Name Type Description Default
data_template_id str

The ID of the data template to add the columns to.

required
parameters list[ParameterValue]

The list of ParameterValue objects to add to the data template.

required

Returns:

Type Description
DataTemplate

The updated DataTemplate object.

Source code in src/albert/collections/data_templates.py
def add_parameters(
    self, *, data_template_id: DataTemplateId, parameters: list[ParameterValue]
) -> DataTemplate:
    """Adds parameters to a data template.

    Parameters
    ----------
    data_template_id : str
        The ID of the data template to add the columns to.
    parameters : list[ParameterValue]
        The list of ParameterValue objects to add to the data template.

    Returns
    -------
    DataTemplate
        The updated DataTemplate object.
    """
    # make sure the parameter values have a default validaion of string type.
    initial_enum_values = {}  # use index to track the enum values
    if parameters is None or len(parameters) == 0:
        return self.get_by_id(id=data_template_id)
    for i, param in enumerate(parameters):
        if (
            param.validation
            and len(param.validation) > 0
            and param.validation[0].datatype == DataType.ENUM
        ):
            initial_enum_values[i] = param.validation[0].value
            param.validation[0].value = None
            param.validation[0].datatype = DataType.STRING

    payload = {
        "Parameters": [
            x.model_dump(mode="json", by_alias=True, exclude_none=True) for x in parameters
        ]
    }
    # if there are enum values, we need to add them as an allowed enum
    response = self.session.put(
        f"{self.base_path}/{data_template_id}/parameters",
        json=payload,
    )
    returned_parameters = [ParameterValue(**x) for x in response.json()["Parameters"]]
    for i, param in enumerate(returned_parameters):
        if i in initial_enum_values:
            param.validation[0].value = initial_enum_values[i]
            param.validation[0].datatype = DataType.ENUM
    self._add_param_enums(
        data_template_id=data_template_id,
        new_parameters=returned_parameters,
    )
    dt_with_params = self.get_by_id(id=data_template_id)
    for i, param in enumerate(dt_with_params.parameter_values):
        if i in initial_enum_values:
            param.validation[0].value = initial_enum_values[i]
            param.validation[0].datatype = DataType.ENUM

    return self.update(data_template=dt_with_params)

list

list(
    *,
    name: str | None = None,
    user_id: str | None = None,
    order_by: OrderBy = DESCENDING,
    limit: int = 100,
    offset: int = 0,
) -> Iterator[DataTemplate]

Lists data template entities with optional filters.

Parameters:

Name Type Description Default
name Union[str, None]

The name of the data template to filter by, by default None.

None
user_id str

user_id to filter by, by default None.

None
order_by OrderBy

The order by which to sort the results, by default OrderBy.DESCENDING.

DESCENDING

Returns:

Type Description
Iterator[DataTemplate]

An iterator of DataTemplate objects matching the provided criteria.

Source code in src/albert/collections/data_templates.py
def list(
    self,
    *,
    name: str | None = None,
    user_id: str | None = None,
    order_by: OrderBy = OrderBy.DESCENDING,
    limit: int = 100,
    offset: int = 0,
) -> Iterator[DataTemplate]:
    """
    Lists data template entities with optional filters.

    Parameters
    ----------
    name : Union[str, None], optional
        The name of the data template to filter by, by default None.
    user_id : str, optional
        user_id to filter by, by default None.
    order_by : OrderBy, optional
        The order by which to sort the results, by default OrderBy.DESCENDING.

    Returns
    -------
    Iterator[DataTemplate]
        An iterator of DataTemplate objects matching the provided criteria.
    """

    def deserialize(items: list[dict]) -> Iterator[DataTemplate]:
        for item in items:
            id = item["albertId"]
            try:
                yield self.get_by_id(id=id)
            except AlbertHTTPError as e:
                logger.warning(f"Error fetching parameter group {id}: {e}")
        # get by ids is not currently returning metadata correctly, so temp fixing this
        # return self.get_by_ids(ids=[x["albertId"] for x in items])

    params = {
        "limit": limit,
        "offset": offset,
        "order": OrderBy(order_by).value if order_by else None,
        "text": name,
        "userId": user_id,
    }

    return AlbertPaginator(
        mode=PaginationMode.OFFSET,
        path=f"{self.base_path}/search",
        session=self.session,
        deserialize=deserialize,
        params=params,
    )

update

update(*, data_template: DataTemplate) -> DataTemplate

Updates a data template.

Parameters:

Name Type Description Default
data_template DataTemplate

The DataTemplate object to update. The ID must be set and matching the ID of the DataTemplate to update.

required

Returns:

Type Description
DataTemplate

The Updated DataTemplate object.

Source code in src/albert/collections/data_templates.py
def update(self, *, data_template: DataTemplate) -> DataTemplate:
    """Updates a data template.

    Parameters
    ----------
    data_template : DataTemplate
        The DataTemplate object to update. The ID must be set and matching the ID of the DataTemplate to update.

    Returns
    -------
    DataTemplate
        The Updated DataTemplate object.
    """

    existing = self.get_by_id(id=data_template.id)

    base_payload = self._generate_patch_payload(existing=existing, updated=data_template)

    path = f"{self.base_path}/{existing.id}"
    (
        general_patches,
        new_data_columns,
        data_column_enum_patches,
        new_parameters,
        parameter_enum_patches,
        parameter_patches,
    ) = generate_data_template_patches(
        initial_patches=base_payload,
        updated_data_template=data_template,
        existing_data_template=existing,
    )

    if len(new_data_columns) > 0:
        self.session.put(
            f"{self.base_path}/{existing.id}/datacolumns",
            json={
                "DataColumns": [
                    x.model_dump(mode="json", by_alias=True, exclude_none=True)
                    for x in new_data_columns
                ],
            },
        )
    if len(data_column_enum_patches) > 0:
        for sequence, enum_patches in data_column_enum_patches.items():
            if len(enum_patches) == 0:
                continue
            self.session.put(
                f"{self.base_path}/{existing.id}/datacolumns/{sequence}/enums",
                json=enum_patches,  # these are simple dicts for now
            )
    if len(new_parameters) > 0:
        self.session.put(
            f"{self.base_path}/{existing.id}/parameters",
            json={
                "Parameters": [
                    x.model_dump(mode="json", by_alias=True, exclude_none=True)
                    for x in new_parameters
                ],
            },
        )
    if len(parameter_enum_patches) > 0:
        for sequence, enum_patches in parameter_enum_patches.items():
            if len(enum_patches) == 0:
                continue
            self.session.put(
                f"{self.base_path}/{existing.id}/parameters/{sequence}/enums",
                json=enum_patches,  # these are simple dicts for now
            )
    if len(parameter_patches) > 0:
        payload = PGPatchPayload(data=parameter_patches)
        self.session.patch(
            path + "/parameters",
            json=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
        )
    if len(general_patches.data) > 0:
        payload = GeneralPatchPayload(data=general_patches.data)
        self.session.patch(
            path,
            json=payload.model_dump(mode="json", by_alias=True, exclude_none=True),
        )
    return self.get_by_id(id=data_template.id)

delete

delete(*, id: DataTemplateId) -> None

Deletes a data template by its ID.

Parameters:

Name Type Description Default
id str

The ID of the data template to delete.

required
Source code in src/albert/collections/data_templates.py
def delete(self, *, id: DataTemplateId) -> None:
    """Deletes a data template by its ID.

    Parameters
    ----------
    id : str
        The ID of the data template to delete.
    """
    self.session.delete(f"{self.base_path}/{id}")