Models
zenml.models
special
Pydantic models for the various concepts in ZenML.
v2
special
base
special
base
Base model definitions.
BaseDatedResponseBody (BaseResponseBody)
Base body model for entities that track a creation and update timestamp.
Used as a base class for all body models associated with responses. Features a creation and update timestamp.
Source code in zenml/models/v2/base/base.py
class BaseDatedResponseBody(BaseResponseBody):
"""Base body model for entities that track a creation and update timestamp.
Used as a base class for all body models associated with responses.
Features a creation and update timestamp.
"""
created: datetime = Field(
title="The timestamp when this resource was created."
)
updated: datetime = Field(
title="The timestamp when this resource was last updated."
)
BaseIdentifiedResponse (BaseResponse[~AnyDatedBody, ~AnyMetadata, ~AnyResources], Generic)
Base domain model for resources with DB representation.
Source code in zenml/models/v2/base/base.py
class BaseIdentifiedResponse(
BaseResponse[AnyDatedBody, AnyMetadata, AnyResources],
Generic[AnyDatedBody, AnyMetadata, AnyResources],
):
"""Base domain model for resources with DB representation."""
id: UUID = Field(title="The unique resource id.")
permission_denied: bool = False
# Helper functions
def __hash__(self) -> int:
"""Implementation of hash magic method.
Returns:
Hash of the UUID.
"""
return hash((type(self),) + tuple([self.id]))
def __eq__(self, other: Any) -> bool:
"""Implementation of equality magic method.
Args:
other: The other object to compare to.
Returns:
True if the other object is of the same type and has the same UUID.
"""
if isinstance(other, type(self)):
return self.id == other.id
else:
return False
def _validate_hydrated_version(
self,
hydrated_model: "BaseResponse[AnyDatedBody, AnyMetadata, AnyResources]",
) -> None:
"""Helper method to validate the values within the hydrated version.
Args:
hydrated_model: the hydrated version of the model.
Raises:
HydrationError: if the hydrated version has different values set
for either the name of the body fields and the
_method_body_mutation is set to ResponseBodyUpdate.DENY.
"""
super()._validate_hydrated_version(hydrated_model)
assert isinstance(hydrated_model, type(self))
# Check if the ID is the same
if self.id != hydrated_model.id:
raise HydrationError(
"The hydrated version of the model does not have the same id."
)
def get_hydrated_version(
self,
) -> "BaseIdentifiedResponse[AnyDatedBody, AnyMetadata, AnyResources]":
"""Abstract method to fetch the hydrated version of the model.
Raises:
NotImplementedError: in case the method is not implemented.
"""
raise NotImplementedError(
"Please implement a `get_hydrated_version` method before "
"using/hydrating the model."
)
def get_body(self) -> "AnyDatedBody":
"""Fetch the body of the entity.
Returns:
The body field of the response.
Raises:
IllegalOperationError: If the user lacks permission to access the
entity represented by this response.
"""
if self.permission_denied:
raise IllegalOperationError(
f"Missing permissions to access {type(self).__name__} with "
f"ID {self.id}."
)
return super().get_body()
def get_metadata(self) -> "AnyMetadata":
"""Fetch the metadata of the entity.
Returns:
The metadata field of the response.
Raises:
IllegalOperationError: If the user lacks permission to access this
entity represented by this response.
"""
if self.permission_denied:
raise IllegalOperationError(
f"Missing permissions to access {type(self).__name__} with "
f"ID {self.id}."
)
return super().get_metadata()
# Analytics
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for base response models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata["entity_id"] = self.id
return metadata
# Body and metadata properties
@property
def created(self) -> datetime:
"""The `created` property.
Returns:
the value of the property.
"""
return self.get_body().created
@property
def updated(self) -> datetime:
"""The `updated` property.
Returns:
the value of the property.
"""
return self.get_body().updated
created: datetime
property
readonly
The created
property.
Returns:
Type | Description |
---|---|
datetime |
the value of the property. |
updated: datetime
property
readonly
The updated
property.
Returns:
Type | Description |
---|---|
datetime |
the value of the property. |
__eq__(self, other)
special
Implementation of equality magic method.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
other |
Any |
The other object to compare to. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the other object is of the same type and has the same UUID. |
Source code in zenml/models/v2/base/base.py
def __eq__(self, other: Any) -> bool:
"""Implementation of equality magic method.
Args:
other: The other object to compare to.
Returns:
True if the other object is of the same type and has the same UUID.
"""
if isinstance(other, type(self)):
return self.id == other.id
else:
return False
__hash__(self)
special
Implementation of hash magic method.
Returns:
Type | Description |
---|---|
int |
Hash of the UUID. |
Source code in zenml/models/v2/base/base.py
def __hash__(self) -> int:
"""Implementation of hash magic method.
Returns:
Hash of the UUID.
"""
return hash((type(self),) + tuple([self.id]))
get_analytics_metadata(self)
Fetches the analytics metadata for base response models.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
The analytics metadata. |
Source code in zenml/models/v2/base/base.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for base response models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata["entity_id"] = self.id
return metadata
get_body(self)
Fetch the body of the entity.
Returns:
Type | Description |
---|---|
AnyDatedBody |
The body field of the response. |
Exceptions:
Type | Description |
---|---|
IllegalOperationError |
If the user lacks permission to access the entity represented by this response. |
Source code in zenml/models/v2/base/base.py
def get_body(self) -> "AnyDatedBody":
"""Fetch the body of the entity.
Returns:
The body field of the response.
Raises:
IllegalOperationError: If the user lacks permission to access the
entity represented by this response.
"""
if self.permission_denied:
raise IllegalOperationError(
f"Missing permissions to access {type(self).__name__} with "
f"ID {self.id}."
)
return super().get_body()
get_hydrated_version(self)
Abstract method to fetch the hydrated version of the model.
Exceptions:
Type | Description |
---|---|
NotImplementedError |
in case the method is not implemented. |
Source code in zenml/models/v2/base/base.py
def get_hydrated_version(
self,
) -> "BaseIdentifiedResponse[AnyDatedBody, AnyMetadata, AnyResources]":
"""Abstract method to fetch the hydrated version of the model.
Raises:
NotImplementedError: in case the method is not implemented.
"""
raise NotImplementedError(
"Please implement a `get_hydrated_version` method before "
"using/hydrating the model."
)
get_metadata(self)
Fetch the metadata of the entity.
Returns:
Type | Description |
---|---|
AnyMetadata |
The metadata field of the response. |
Exceptions:
Type | Description |
---|---|
IllegalOperationError |
If the user lacks permission to access this entity represented by this response. |
Source code in zenml/models/v2/base/base.py
def get_metadata(self) -> "AnyMetadata":
"""Fetch the metadata of the entity.
Returns:
The metadata field of the response.
Raises:
IllegalOperationError: If the user lacks permission to access this
entity represented by this response.
"""
if self.permission_denied:
raise IllegalOperationError(
f"Missing permissions to access {type(self).__name__} with "
f"ID {self.id}."
)
return super().get_metadata()
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[APIKeyResponseBody, APIKeyResponseMetadata, APIKeyResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[ArtifactResponseBody, ArtifactResponseMetadata, ArtifactResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[ArtifactVisualizationResponseBody, ArtifactVisualizationResponseMetadata, ArtifactVisualizationResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[CodeReferenceResponseBody, CodeReferenceResponseMetadata, CodeReferenceResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[LogsResponseBody, LogsResponseMetadata, LogsResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[ModelVersionArtifactResponseBody, BaseResponseMetadata, ModelVersionArtifactResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[ModelVersionPipelineRunResponseBody, BaseResponseMetadata, ModelVersionPipelineRunResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[ServiceAccountResponseBody, ServiceAccountResponseMetadata, ServiceAccountResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[TagResourceResponseBody, BaseResponseMetadata, TagResourceResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[TagResponseBody, BaseResponseMetadata, TagResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[TriggerExecutionResponseBody, TriggerExecutionResponseMetadata, TriggerExecutionResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[UserResponseBody, UserResponseMetadata, UserResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[WorkspaceResponseBody, WorkspaceResponseMetadata, WorkspaceResponseResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseIdentifiedResponse[~UserBody, ~UserMetadata, ~UserResources] (BaseIdentifiedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseRequest (BaseZenModel)
Base request model.
Used as a base class for all request models.
Source code in zenml/models/v2/base/base.py
class BaseRequest(BaseZenModel):
"""Base request model.
Used as a base class for all request models.
"""
BaseResponse (BaseZenModel, Generic)
Base domain model for all responses.
Source code in zenml/models/v2/base/base.py
class BaseResponse(BaseZenModel, Generic[AnyBody, AnyMetadata, AnyResources]):
"""Base domain model for all responses."""
# Body and metadata pair
body: Optional["AnyBody"] = Field(
default=None, title="The body of the resource."
)
metadata: Optional["AnyMetadata"] = Field(
default=None, title="The metadata related to this resource."
)
resources: Optional["AnyResources"] = Field(
default=None, title="The resources related to this resource."
)
_response_update_strategy: ResponseUpdateStrategy = (
ResponseUpdateStrategy.ALLOW
)
_warn_on_response_updates: bool = True
def _validate_hydrated_version(
self,
hydrated_model: "BaseResponse[AnyBody, AnyMetadata, AnyResources]",
) -> None:
"""Helper method to validate the values within the hydrated version.
Args:
hydrated_model: the hydrated version of the model.
Raises:
HydrationError: if the hydrated version has different values set
for either the name of the body fields and the
_method_body_mutation is set to ResponseBodyUpdate.DENY.
"""
# Check whether the metadata exists in the hydrated version
if hydrated_model.metadata is None:
raise HydrationError(
"The hydrated model does not have a metadata field."
)
# Check if the name has changed
if "name" in self.model_fields:
original_name = getattr(self, "name")
hydrated_name = getattr(hydrated_model, "name")
if original_name != hydrated_name:
if (
self._response_update_strategy
== ResponseUpdateStrategy.ALLOW
):
setattr(self, "name", hydrated_name)
if self._warn_on_response_updates:
logger.warning(
f"The name of the entity has changed from "
f"`{original_name}` to `{hydrated_name}`."
)
elif (
self._response_update_strategy
== ResponseUpdateStrategy.IGNORE
):
if self._warn_on_response_updates:
logger.warning(
f"Ignoring the name change in the hydrated version "
f"of the response: `{original_name}` to "
f"`{hydrated_name}`."
)
elif (
self._response_update_strategy
== ResponseUpdateStrategy.DENY
):
raise HydrationError(
f"Failing the hydration, because there is a change in "
f"the name of the entity: `{original_name}` to "
f"`{hydrated_name}`."
)
# Check all the fields in the body
for field in self.get_body().model_fields:
original_value = getattr(self.get_body(), field)
hydrated_value = getattr(hydrated_model.get_body(), field)
if original_value != hydrated_value:
if (
self._response_update_strategy
== ResponseUpdateStrategy.ALLOW
):
setattr(self.get_body(), field, hydrated_value)
if self._warn_on_response_updates:
logger.warning(
f"The field `{field}` in the body of the response "
f"has changed from `{original_value}` to "
f"`{hydrated_value}`."
)
elif (
self._response_update_strategy
== ResponseUpdateStrategy.IGNORE
):
if self._warn_on_response_updates:
logger.warning(
f"Ignoring the change in the hydrated version of "
f"the field `{field}`: `{original_value}` -> "
f"`{hydrated_value}`."
)
elif (
self._response_update_strategy
== ResponseUpdateStrategy.DENY
):
raise HydrationError(
f"Failing the hydration, because there is a change in "
f"the field `{field}`: `{original_value}` -> "
f"`{hydrated_value}`"
)
def get_hydrated_version(
self,
) -> "BaseResponse[AnyBody, AnyMetadata, AnyResources]":
"""Abstract method to fetch the hydrated version of the model.
Raises:
NotImplementedError: in case the method is not implemented.
"""
raise NotImplementedError(
"Please implement a `get_hydrated_version` method before "
"using/hydrating the model."
)
def get_body(self) -> "AnyBody":
"""Fetch the body of the entity.
Returns:
The body field of the response.
Raises:
RuntimeError: If the body was not included in the response.
"""
if not self.body:
raise RuntimeError(
f"Missing response body for {type(self).__name__}."
)
return self.body
def get_metadata(self) -> "AnyMetadata":
"""Fetch the metadata of the entity.
Returns:
The metadata field of the response.
"""
if self.metadata is None:
# If the metadata is not there, check the class first.
metadata_annotation = self.model_fields["metadata"].annotation
assert metadata_annotation is not None, (
"For each response model, an annotated metadata"
"field should exist."
)
# metadata is defined as:
# metadata: Optional[....ResponseMetadata] = Field(default=None)
# We need to find the actual class inside the Optional annotation.
from zenml.utils.typing_utils import get_args
metadata_type = get_args(metadata_annotation)[0]
assert issubclass(metadata_type, BaseResponseMetadata)
if len(metadata_type.model_fields):
# If the metadata class defines any fields, fetch the metadata
# through the hydrated version.
hydrated_version = self.get_hydrated_version()
self._validate_hydrated_version(hydrated_version)
self.metadata = hydrated_version.metadata
else:
# Otherwise, use the metadata class to create an empty metadata
# object.
self.metadata = metadata_type()
assert self.metadata is not None
return self.metadata
def get_resources(self) -> "AnyResources":
"""Fetch the resources related to this entity.
Returns:
The resources field of the response.
Raises:
RuntimeError: If the resources field was not included in the response.
"""
if self.resources is None:
# If the resources are not there, check the class first.
resources_annotation = self.model_fields["resources"].annotation
assert resources_annotation is not None, (
"For each response model, an annotated resources"
"field should exist."
)
# metadata is defined as:
# metadata: Optional[....ResponseMetadata] = Field(default=None)
# We need to find the actual class inside the Optional annotation.
from zenml.utils.typing_utils import get_args
resources_type = get_args(resources_annotation)[0]
assert issubclass(resources_type, BaseResponseResources)
if len(resources_type.model_fields):
# If the resources class defines any fields, fetch the resources
# through the hydrated version.
hydrated_version = self.get_hydrated_version()
self._validate_hydrated_version(hydrated_version)
self.resources = hydrated_version.resources
else:
# Otherwise, use the resources class to create an empty
# resources object.
self.resources = resources_type()
if self.resources is None:
raise RuntimeError(
f"Missing response resources for {type(self).__name__}."
)
return self.resources
get_body(self)
Fetch the body of the entity.
Returns:
Type | Description |
---|---|
AnyBody |
The body field of the response. |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If the body was not included in the response. |
Source code in zenml/models/v2/base/base.py
def get_body(self) -> "AnyBody":
"""Fetch the body of the entity.
Returns:
The body field of the response.
Raises:
RuntimeError: If the body was not included in the response.
"""
if not self.body:
raise RuntimeError(
f"Missing response body for {type(self).__name__}."
)
return self.body
get_hydrated_version(self)
Abstract method to fetch the hydrated version of the model.
Exceptions:
Type | Description |
---|---|
NotImplementedError |
in case the method is not implemented. |
Source code in zenml/models/v2/base/base.py
def get_hydrated_version(
self,
) -> "BaseResponse[AnyBody, AnyMetadata, AnyResources]":
"""Abstract method to fetch the hydrated version of the model.
Raises:
NotImplementedError: in case the method is not implemented.
"""
raise NotImplementedError(
"Please implement a `get_hydrated_version` method before "
"using/hydrating the model."
)
get_metadata(self)
Fetch the metadata of the entity.
Returns:
Type | Description |
---|---|
AnyMetadata |
The metadata field of the response. |
Source code in zenml/models/v2/base/base.py
def get_metadata(self) -> "AnyMetadata":
"""Fetch the metadata of the entity.
Returns:
The metadata field of the response.
"""
if self.metadata is None:
# If the metadata is not there, check the class first.
metadata_annotation = self.model_fields["metadata"].annotation
assert metadata_annotation is not None, (
"For each response model, an annotated metadata"
"field should exist."
)
# metadata is defined as:
# metadata: Optional[....ResponseMetadata] = Field(default=None)
# We need to find the actual class inside the Optional annotation.
from zenml.utils.typing_utils import get_args
metadata_type = get_args(metadata_annotation)[0]
assert issubclass(metadata_type, BaseResponseMetadata)
if len(metadata_type.model_fields):
# If the metadata class defines any fields, fetch the metadata
# through the hydrated version.
hydrated_version = self.get_hydrated_version()
self._validate_hydrated_version(hydrated_version)
self.metadata = hydrated_version.metadata
else:
# Otherwise, use the metadata class to create an empty metadata
# object.
self.metadata = metadata_type()
assert self.metadata is not None
return self.metadata
get_resources(self)
Fetch the resources related to this entity.
Returns:
Type | Description |
---|---|
AnyResources |
The resources field of the response. |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If the resources field was not included in the response. |
Source code in zenml/models/v2/base/base.py
def get_resources(self) -> "AnyResources":
"""Fetch the resources related to this entity.
Returns:
The resources field of the response.
Raises:
RuntimeError: If the resources field was not included in the response.
"""
if self.resources is None:
# If the resources are not there, check the class first.
resources_annotation = self.model_fields["resources"].annotation
assert resources_annotation is not None, (
"For each response model, an annotated resources"
"field should exist."
)
# metadata is defined as:
# metadata: Optional[....ResponseMetadata] = Field(default=None)
# We need to find the actual class inside the Optional annotation.
from zenml.utils.typing_utils import get_args
resources_type = get_args(resources_annotation)[0]
assert issubclass(resources_type, BaseResponseResources)
if len(resources_type.model_fields):
# If the resources class defines any fields, fetch the resources
# through the hydrated version.
hydrated_version = self.get_hydrated_version()
self._validate_hydrated_version(hydrated_version)
self.resources = hydrated_version.resources
else:
# Otherwise, use the resources class to create an empty
# resources object.
self.resources = resources_type()
if self.resources is None:
raise RuntimeError(
f"Missing response resources for {type(self).__name__}."
)
return self.resources
model_post_init(/, self, context)
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
self |
BaseModel |
The BaseModel instance. |
required |
context |
Any |
The context. |
required |
Source code in zenml/models/v2/base/base.py
def init_private_attributes(self: BaseModel, context: Any, /) -> None:
"""This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args:
self: The BaseModel instance.
context: The context.
"""
if getattr(self, '__pydantic_private__', None) is None:
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)
BaseResponseBody (BaseZenModel)
Base body model.
Source code in zenml/models/v2/base/base.py
class BaseResponseBody(BaseZenModel):
"""Base body model."""
BaseResponseMetadata (BaseZenModel)
Base metadata model.
Used as a base class for all metadata models associated with responses.
Source code in zenml/models/v2/base/base.py
class BaseResponseMetadata(BaseZenModel):
"""Base metadata model.
Used as a base class for all metadata models associated with responses.
"""
BaseResponseResources (BaseZenModel)
Base resources model.
Used as a base class for all resource models associated with responses.
Source code in zenml/models/v2/base/base.py
class BaseResponseResources(BaseZenModel):
"""Base resources model.
Used as a base class for all resource models associated with responses.
"""
model_config = ConfigDict(extra="allow")
BaseResponse[ServerSettingsResponseBody, ServerSettingsResponseMetadata, ServerSettingsResponseResources] (BaseResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseResponse[~AnyDatedBody, ~AnyMetadata, ~AnyResources] (BaseResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseResponse[~AnyPluginBody, ~AnyPluginMetadata, ~AnyPluginResources] (BaseResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BaseUpdate (BaseZenModel)
Base update model.
Used as a base class for all update models.
Source code in zenml/models/v2/base/base.py
class BaseUpdate(BaseZenModel):
"""Base update model.
Used as a base class for all update models.
"""
model_config = ConfigDict(
# Ignore extras on all update models.
extra="ignore",
)
BaseZenModel (YAMLSerializationMixin, AnalyticsTrackedModelMixin)
Base model class for all ZenML models.
This class is used as a base class for all ZenML models. It provides functionality for tracking analytics events.
Source code in zenml/models/v2/base/base.py
class BaseZenModel(YAMLSerializationMixin, AnalyticsTrackedModelMixin):
"""Base model class for all ZenML models.
This class is used as a base class for all ZenML models. It provides
functionality for tracking analytics events.
"""
model_config = ConfigDict(
# Ignore extras on all models to support forwards and backwards
# compatibility (e.g. new fields in newer versions of ZenML servers
# are allowed to be passed to older versions of ZenML clients and
# vice versa but will be ignored).
extra="ignore",
)
base_plugin_flavor
Plugin flavor model definitions.
BasePluginFlavorResponse (BaseResponse[~AnyPluginBody, ~AnyPluginMetadata, ~AnyPluginResources], Generic)
Base response for all Plugin Flavors.
Source code in zenml/models/v2/base/base_plugin_flavor.py
class BasePluginFlavorResponse(
BaseResponse[AnyPluginBody, AnyPluginMetadata, AnyPluginResources],
Generic[AnyPluginBody, AnyPluginMetadata, AnyPluginResources],
):
"""Base response for all Plugin Flavors."""
name: str = Field(title="Name of the flavor.")
type: PluginType = Field(title="Type of the plugin.")
subtype: PluginSubType = Field(title="Subtype of the plugin.")
model_config = ConfigDict(extra="ignore")
def get_hydrated_version(
self,
) -> "BasePluginFlavorResponse[AnyPluginBody, AnyPluginMetadata, AnyPluginResources]":
"""Abstract method to fetch the hydrated version of the model.
Returns:
Hydrated version of the PluginFlavorResponse
"""
# TODO: shouldn't this call the Zen store ? The client should not have
# to know about the plugin flavor registry
from zenml.zen_server.utils import plugin_flavor_registry
plugin_flavor = plugin_flavor_registry().get_flavor_class(
name=self.name, _type=self.type, subtype=self.subtype
)
return plugin_flavor.get_flavor_response_model(hydrate=True)
get_hydrated_version(self)
Abstract method to fetch the hydrated version of the model.
Returns:
Type | Description |
---|---|
BasePluginFlavorResponse[AnyPluginBody, AnyPluginMetadata, AnyPluginResources] |
Hydrated version of the PluginFlavorResponse |
Source code in zenml/models/v2/base/base_plugin_flavor.py
def get_hydrated_version(
self,
) -> "BasePluginFlavorResponse[AnyPluginBody, AnyPluginMetadata, AnyPluginResources]":
"""Abstract method to fetch the hydrated version of the model.
Returns:
Hydrated version of the PluginFlavorResponse
"""
# TODO: shouldn't this call the Zen store ? The client should not have
# to know about the plugin flavor registry
from zenml.zen_server.utils import plugin_flavor_registry
plugin_flavor = plugin_flavor_registry().get_flavor_class(
name=self.name, _type=self.type, subtype=self.subtype
)
return plugin_flavor.get_flavor_response_model(hydrate=True)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base_plugin_flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BasePluginFlavorResponse[ActionFlavorResponseBody, ActionFlavorResponseMetadata, ActionFlavorResponseResources] (BasePluginFlavorResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base_plugin_flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BasePluginFlavorResponse[EventSourceFlavorResponseBody, EventSourceFlavorResponseMetadata, EventSourceFlavorResponseResources] (BasePluginFlavorResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/base_plugin_flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
BasePluginResponseBody (BaseResponseBody)
Response body for plugins.
Source code in zenml/models/v2/base/base_plugin_flavor.py
class BasePluginResponseBody(BaseResponseBody):
"""Response body for plugins."""
BasePluginResponseMetadata (BaseResponseMetadata)
Response metadata for plugins.
Source code in zenml/models/v2/base/base_plugin_flavor.py
class BasePluginResponseMetadata(BaseResponseMetadata):
"""Response metadata for plugins."""
BasePluginResponseResources (BaseResponseResources)
Response resources for plugins.
Source code in zenml/models/v2/base/base_plugin_flavor.py
class BasePluginResponseResources(BaseResponseResources):
"""Response resources for plugins."""
filter
Base filter model definitions.
BaseFilter (BaseModel)
Class to unify all filter, paginate and sort request parameters.
This Model allows fine-grained filtering, sorting and pagination of resources.
Usage example for subclasses of this class:
ResourceListModel(
name="contains:default",
workspace="default"
count_steps="gte:5"
sort_by="created",
page=2,
size=20
)
Source code in zenml/models/v2/base/filter.py
class BaseFilter(BaseModel):
"""Class to unify all filter, paginate and sort request parameters.
This Model allows fine-grained filtering, sorting and pagination of
resources.
Usage example for subclasses of this class:
```
ResourceListModel(
name="contains:default",
workspace="default"
count_steps="gte:5"
sort_by="created",
page=2,
size=20
)
```
"""
# List of fields that cannot be used as filters.
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
"sort_by",
"page",
"size",
"logical_operator",
]
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = []
# List of fields that are not even mentioned as options in the CLI.
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = []
# List of fields that are wrapped with `fastapi.Query(default)` in API.
API_MULTI_INPUT_PARAMS: ClassVar[List[str]] = []
sort_by: str = Field(
default="created", description="Which column to sort by."
)
logical_operator: LogicalOperators = Field(
default=LogicalOperators.AND,
description="Which logical operator to use between all filters "
"['and', 'or']",
)
page: int = Field(
default=PAGINATION_STARTING_PAGE, ge=1, description="Page number"
)
size: int = Field(
default=PAGE_SIZE_DEFAULT,
ge=1,
le=PAGE_SIZE_MAXIMUM,
description="Page size",
)
id: Optional[Union[UUID, str]] = Field(
default=None,
description="Id for this resource",
union_mode="left_to_right",
)
created: Optional[Union[datetime, str]] = Field(
default=None, description="Created", union_mode="left_to_right"
)
updated: Optional[Union[datetime, str]] = Field(
default=None, description="Updated", union_mode="left_to_right"
)
_rbac_configuration: Optional[
Tuple[UUID, Dict[str, Optional[Set[UUID]]]]
] = None
@field_validator("sort_by", mode="before")
@classmethod
def validate_sort_by(cls, value: Any) -> Any:
"""Validate that the sort_column is a valid column with a valid operand.
Args:
value: The sort_by field value.
Returns:
The validated sort_by field value.
Raises:
ValidationError: If the sort_by field is not a string.
ValueError: If the resource can't be sorted by this field.
"""
# Somehow pydantic allows you to pass in int values, which will be
# interpreted as string, however within the validator they are still
# integers, which don't have a .split() method
if not isinstance(value, str):
raise ValidationError(
f"str type expected for the sort_by field. "
f"Received a {type(value)}"
)
column = value
split_value = value.split(":", 1)
if len(split_value) == 2:
column = split_value[1]
if split_value[0] not in SorterOps.values():
logger.warning(
"Invalid operand used for column sorting. "
"Only the following operands are supported `%s`. "
"Defaulting to 'asc' on column `%s`.",
SorterOps.values(),
column,
)
value = column
if column in cls.FILTER_EXCLUDE_FIELDS:
raise ValueError(
f"This resource can not be sorted by this field: '{value}'"
)
elif column in cls.model_fields:
return value
elif column in cls.CUSTOM_SORTING_OPTIONS:
return value
else:
raise ValueError(
"You can only sort by valid fields of this resource"
)
@model_validator(mode="before")
@classmethod
@before_validator_handler
def filter_ops(cls, data: Dict[str, Any]) -> Dict[str, Any]:
"""Parse incoming filters to ensure all filters are legal.
Args:
data: The values of the class.
Returns:
The values of the class.
"""
cls._generate_filter_list(data)
return data
@property
def list_of_filters(self) -> List[Filter]:
"""Converts the class variables into a list of usable Filter Models.
Returns:
A list of Filter models.
"""
return self._generate_filter_list(
{key: getattr(self, key) for key in self.model_fields}
)
@property
def sorting_params(self) -> Tuple[str, SorterOps]:
"""Converts the class variables into a list of usable Filter Models.
Returns:
A tuple of the column to sort by and the sorting operand.
"""
column = self.sort_by
# The default sorting operand is asc
operator = SorterOps.ASCENDING
# Check if user explicitly set an operand
split_value = self.sort_by.split(":", 1)
if len(split_value) == 2:
column = split_value[1]
operator = SorterOps(split_value[0])
return column, operator
def configure_rbac(
self,
authenticated_user_id: UUID,
**column_allowed_ids: Optional[Set[UUID]],
) -> None:
"""Configure RBAC allowed column values.
Args:
authenticated_user_id: ID of the authenticated user. All entities
owned by this user will be included.
column_allowed_ids: Set of IDs per column to limit the query to.
If given, the remaining filters will be applied to entities
within this set only. If `None`, the remaining filters will
be applied to all entries in the table.
"""
self._rbac_configuration = (authenticated_user_id, column_allowed_ids)
def generate_rbac_filter(
self,
table: Type["AnySchema"],
) -> Optional["ColumnElement[bool]"]:
"""Generates an optional RBAC filter.
Args:
table: The query table.
Returns:
The RBAC filter.
"""
from sqlmodel import or_
if not self._rbac_configuration:
return None
expressions = []
for column_name, allowed_ids in self._rbac_configuration[1].items():
if allowed_ids is not None:
expression = getattr(table, column_name).in_(allowed_ids)
expressions.append(expression)
if expressions and hasattr(table, "user_id"):
# If `expressions` is not empty, we do not have full access to all
# rows of the table. In this case, we also include rows which the
# user owns.
# Unowned entities are considered server-owned and can be seen
# by anyone
expressions.append(getattr(table, "user_id").is_(None))
# The authenticated user owns this entity
expressions.append(
getattr(table, "user_id") == self._rbac_configuration[0]
)
if expressions:
return or_(*expressions)
else:
return None
@classmethod
def _generate_filter_list(cls, values: Dict[str, Any]) -> List[Filter]:
"""Create a list of filters from a (column, value) dictionary.
Args:
values: A dictionary of column names and values to filter on.
Returns:
A list of filters.
"""
list_of_filters: List[Filter] = []
for key, value in values.items():
# Ignore excluded filters
if key in cls.FILTER_EXCLUDE_FIELDS:
continue
# Skip filtering for None values
if value is None:
continue
# Determine the operator and filter value
value, operator = cls._resolve_operator(value)
# Define the filter
filter = FilterGenerator(cls).define_filter(
column=key, value=value, operator=operator
)
list_of_filters.append(filter)
return list_of_filters
@staticmethod
def _resolve_operator(value: Any) -> Tuple[Any, GenericFilterOps]:
"""Determine the operator and filter value from a user-provided value.
If the user-provided value is a string of the form "operator:value",
then the operator is extracted and the value is returned. Otherwise,
`GenericFilterOps.EQUALS` is used as default operator and the value
is returned as-is.
Args:
value: The user-provided value.
Returns:
A tuple of the filter value and the operator.
"""
operator = GenericFilterOps.EQUALS # Default operator
if isinstance(value, str):
split_value = value.split(":", 1)
if (
len(split_value) == 2
and split_value[0] in GenericFilterOps.values()
):
value = split_value[1]
operator = GenericFilterOps(split_value[0])
return value, operator
def generate_name_or_id_query_conditions(
self,
value: Union[UUID, str],
table: Type["NamedSchema"],
) -> "ColumnElement[bool]":
"""Generate filter conditions for name or id of a table.
Args:
value: The filter value.
table: The table to filter.
Returns:
The query conditions.
"""
from sqlmodel import or_
value, operator = BaseFilter._resolve_operator(value)
value = str(value)
conditions = []
try:
filter_ = FilterGenerator(table).define_filter(
column="id", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
except ValueError:
# UUID filter with equal operators and no full UUID fail with
# a ValueError. In this case, we already know that the filter
# will not produce any result and can simply ignore it.
pass
filter_ = FilterGenerator(table).define_filter(
column="name", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
return or_(*conditions)
def generate_custom_query_conditions_for_column(
self,
value: Any,
table: Type[SQLModel],
column: str,
) -> "ColumnElement[bool]":
"""Generate custom filter conditions for a column of a table.
Args:
value: The filter value.
table: The table which contains the column.
column: The column name.
Returns:
The query conditions.
"""
value, operator = BaseFilter._resolve_operator(value)
filter_ = FilterGenerator(table).define_filter(
column=column, value=value, operator=operator
)
return filter_.generate_query_conditions(table=table)
@property
def offset(self) -> int:
"""Returns the offset needed for the query on the data persistence layer.
Returns:
The offset for the query.
"""
return self.size * (self.page - 1)
def generate_filter(
self, table: Type[SQLModel]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
Raises:
RuntimeError: If a valid logical operator is not supplied.
"""
from sqlmodel import and_, or_
filters = []
for column_filter in self.list_of_filters:
filters.append(
column_filter.generate_query_conditions(table=table)
)
for custom_filter in self.get_custom_filters():
filters.append(custom_filter)
if self.logical_operator == LogicalOperators.OR:
return or_(False, *filters)
elif self.logical_operator == LogicalOperators.AND:
return and_(True, *filters)
else:
raise RuntimeError("No valid logical operator was supplied.")
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
This can be overridden by subclasses to define custom filters that are
not based on the columns of the underlying table.
Returns:
A list of custom filters.
"""
return []
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
rbac_filter = self.generate_rbac_filter(table=table)
if rbac_filter is not None:
query = query.where(rbac_filter)
filters = self.generate_filter(table=table)
if filters is not None:
query = query.where(filters)
return query
def apply_sorting(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Apply sorting to the query.
Args:
query: The query to which to apply the sorting.
table: The query table.
Returns:
The query with sorting applied.
"""
column, operand = self.sorting_params
if operand == SorterOps.DESCENDING:
sort_clause = desc(getattr(table, column)) # type: ignore[var-annotated]
else:
sort_clause = asc(getattr(table, column))
# We always add the `id` column as a tiebreaker to ensure a stable,
# repeatable order of items, otherwise subsequent pages might contain
# the same items.
query = query.order_by(sort_clause, asc(table.id)) # type: ignore[arg-type]
return query
list_of_filters: List[zenml.models.v2.base.filter.Filter]
property
readonly
Converts the class variables into a list of usable Filter Models.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.base.filter.Filter] |
A list of Filter models. |
offset: int
property
readonly
Returns the offset needed for the query on the data persistence layer.
Returns:
Type | Description |
---|---|
int |
The offset for the query. |
sorting_params: Tuple[str, zenml.enums.SorterOps]
property
readonly
Converts the class variables into a list of usable Filter Models.
Returns:
Type | Description |
---|---|
Tuple[str, zenml.enums.SorterOps] |
A tuple of the column to sort by and the sorting operand. |
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/base/filter.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
rbac_filter = self.generate_rbac_filter(table=table)
if rbac_filter is not None:
query = query.where(rbac_filter)
filters = self.generate_filter(table=table)
if filters is not None:
query = query.where(filters)
return query
apply_sorting(self, query, table)
Apply sorting to the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the sorting. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with sorting applied. |
Source code in zenml/models/v2/base/filter.py
def apply_sorting(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Apply sorting to the query.
Args:
query: The query to which to apply the sorting.
table: The query table.
Returns:
The query with sorting applied.
"""
column, operand = self.sorting_params
if operand == SorterOps.DESCENDING:
sort_clause = desc(getattr(table, column)) # type: ignore[var-annotated]
else:
sort_clause = asc(getattr(table, column))
# We always add the `id` column as a tiebreaker to ensure a stable,
# repeatable order of items, otherwise subsequent pages might contain
# the same items.
query = query.order_by(sort_clause, asc(table.id)) # type: ignore[arg-type]
return query
configure_rbac(self, authenticated_user_id, **column_allowed_ids)
Configure RBAC allowed column values.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
authenticated_user_id |
UUID |
ID of the authenticated user. All entities owned by this user will be included. |
required |
column_allowed_ids |
Optional[Set[uuid.UUID]] |
Set of IDs per column to limit the query to.
If given, the remaining filters will be applied to entities
within this set only. If |
{} |
Source code in zenml/models/v2/base/filter.py
def configure_rbac(
self,
authenticated_user_id: UUID,
**column_allowed_ids: Optional[Set[UUID]],
) -> None:
"""Configure RBAC allowed column values.
Args:
authenticated_user_id: ID of the authenticated user. All entities
owned by this user will be included.
column_allowed_ids: Set of IDs per column to limit the query to.
If given, the remaining filters will be applied to entities
within this set only. If `None`, the remaining filters will
be applied to all entries in the table.
"""
self._rbac_configuration = (authenticated_user_id, column_allowed_ids)
filter_ops(data, validation_info)
classmethod
Wrapper method to handle the raw data.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cls |
the class handler |
required | |
data |
Any |
the raw input data |
required |
validation_info |
ValidationInfo |
the context of the validation. |
required |
Returns:
Type | Description |
---|---|
Any |
the validated data |
Source code in zenml/models/v2/base/filter.py
def before_validator(
cls: Type[BaseModel], data: Any, validation_info: ValidationInfo
) -> Any:
"""Wrapper method to handle the raw data.
Args:
cls: the class handler
data: the raw input data
validation_info: the context of the validation.
Returns:
the validated data
"""
data = model_validator_data_handler(
raw_data=data, base_class=cls, validation_info=validation_info
)
return method(cls=cls, data=data)
generate_custom_query_conditions_for_column(self, value, table, column)
Generate custom filter conditions for a column of a table.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
The filter value. |
required |
table |
Type[sqlmodel.main.SQLModel] |
The table which contains the column. |
required |
column |
str |
The column name. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_custom_query_conditions_for_column(
self,
value: Any,
table: Type[SQLModel],
column: str,
) -> "ColumnElement[bool]":
"""Generate custom filter conditions for a column of a table.
Args:
value: The filter value.
table: The table which contains the column.
column: The column name.
Returns:
The query conditions.
"""
value, operator = BaseFilter._resolve_operator(value)
filter_ = FilterGenerator(table).define_filter(
column=column, value=value, operator=operator
)
return filter_.generate_query_conditions(table=table)
generate_filter(self, table)
Generate the filter for the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[sqlmodel.main.SQLModel] |
The Table that is being queried from. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The filter expression for the query. |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If a valid logical operator is not supplied. |
Source code in zenml/models/v2/base/filter.py
def generate_filter(
self, table: Type[SQLModel]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
Raises:
RuntimeError: If a valid logical operator is not supplied.
"""
from sqlmodel import and_, or_
filters = []
for column_filter in self.list_of_filters:
filters.append(
column_filter.generate_query_conditions(table=table)
)
for custom_filter in self.get_custom_filters():
filters.append(custom_filter)
if self.logical_operator == LogicalOperators.OR:
return or_(False, *filters)
elif self.logical_operator == LogicalOperators.AND:
return and_(True, *filters)
else:
raise RuntimeError("No valid logical operator was supplied.")
generate_name_or_id_query_conditions(self, value, table)
Generate filter conditions for name or id of a table.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Union[uuid.UUID, str] |
The filter value. |
required |
table |
Type[NamedSchema] |
The table to filter. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_name_or_id_query_conditions(
self,
value: Union[UUID, str],
table: Type["NamedSchema"],
) -> "ColumnElement[bool]":
"""Generate filter conditions for name or id of a table.
Args:
value: The filter value.
table: The table to filter.
Returns:
The query conditions.
"""
from sqlmodel import or_
value, operator = BaseFilter._resolve_operator(value)
value = str(value)
conditions = []
try:
filter_ = FilterGenerator(table).define_filter(
column="id", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
except ValueError:
# UUID filter with equal operators and no full UUID fail with
# a ValueError. In this case, we already know that the filter
# will not produce any result and can simply ignore it.
pass
filter_ = FilterGenerator(table).define_filter(
column="name", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
return or_(*conditions)
generate_rbac_filter(self, table)
Generates an optional RBAC filter.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
Optional[ColumnElement[bool]] |
The RBAC filter. |
Source code in zenml/models/v2/base/filter.py
def generate_rbac_filter(
self,
table: Type["AnySchema"],
) -> Optional["ColumnElement[bool]"]:
"""Generates an optional RBAC filter.
Args:
table: The query table.
Returns:
The RBAC filter.
"""
from sqlmodel import or_
if not self._rbac_configuration:
return None
expressions = []
for column_name, allowed_ids in self._rbac_configuration[1].items():
if allowed_ids is not None:
expression = getattr(table, column_name).in_(allowed_ids)
expressions.append(expression)
if expressions and hasattr(table, "user_id"):
# If `expressions` is not empty, we do not have full access to all
# rows of the table. In this case, we also include rows which the
# user owns.
# Unowned entities are considered server-owned and can be seen
# by anyone
expressions.append(getattr(table, "user_id").is_(None))
# The authenticated user owns this entity
expressions.append(
getattr(table, "user_id") == self._rbac_configuration[0]
)
if expressions:
return or_(*expressions)
else:
return None
get_custom_filters(self)
Get custom filters.
This can be overridden by subclasses to define custom filters that are not based on the columns of the underlying table.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/base/filter.py
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
This can be overridden by subclasses to define custom filters that are
not based on the columns of the underlying table.
Returns:
A list of custom filters.
"""
return []
model_post_init(/, self, context)
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
self |
BaseModel |
The BaseModel instance. |
required |
context |
Any |
The context. |
required |
Source code in zenml/models/v2/base/filter.py
def init_private_attributes(self: BaseModel, context: Any, /) -> None:
"""This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args:
self: The BaseModel instance.
context: The context.
"""
if getattr(self, '__pydantic_private__', None) is None:
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)
validate_sort_by(value)
classmethod
Validate that the sort_column is a valid column with a valid operand.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
The sort_by field value. |
required |
Returns:
Type | Description |
---|---|
Any |
The validated sort_by field value. |
Exceptions:
Type | Description |
---|---|
ValidationError |
If the sort_by field is not a string. |
ValueError |
If the resource can't be sorted by this field. |
Source code in zenml/models/v2/base/filter.py
@field_validator("sort_by", mode="before")
@classmethod
def validate_sort_by(cls, value: Any) -> Any:
"""Validate that the sort_column is a valid column with a valid operand.
Args:
value: The sort_by field value.
Returns:
The validated sort_by field value.
Raises:
ValidationError: If the sort_by field is not a string.
ValueError: If the resource can't be sorted by this field.
"""
# Somehow pydantic allows you to pass in int values, which will be
# interpreted as string, however within the validator they are still
# integers, which don't have a .split() method
if not isinstance(value, str):
raise ValidationError(
f"str type expected for the sort_by field. "
f"Received a {type(value)}"
)
column = value
split_value = value.split(":", 1)
if len(split_value) == 2:
column = split_value[1]
if split_value[0] not in SorterOps.values():
logger.warning(
"Invalid operand used for column sorting. "
"Only the following operands are supported `%s`. "
"Defaulting to 'asc' on column `%s`.",
SorterOps.values(),
column,
)
value = column
if column in cls.FILTER_EXCLUDE_FIELDS:
raise ValueError(
f"This resource can not be sorted by this field: '{value}'"
)
elif column in cls.model_fields:
return value
elif column in cls.CUSTOM_SORTING_OPTIONS:
return value
else:
raise ValueError(
"You can only sort by valid fields of this resource"
)
BoolFilter (Filter)
Filter for all Boolean fields.
Source code in zenml/models/v2/base/filter.py
class BoolFilter(Filter):
"""Filter for all Boolean fields."""
ALLOWED_OPS: ClassVar[List[str]] = [
GenericFilterOps.EQUALS,
GenericFilterOps.NOT_EQUALS,
]
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a boolean column.
Args:
column: The boolean column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
generate_query_conditions_from_column(self, column)
Generate query conditions for a boolean column.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
Any |
The boolean column of an SQLModel table on which to filter. |
required |
Returns:
Type | Description |
---|---|
Any |
A list of query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a boolean column.
Args:
column: The boolean column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
DatetimeFilter (Filter)
Filter for all datetime fields.
Source code in zenml/models/v2/base/filter.py
class DatetimeFilter(Filter):
"""Filter for all datetime fields."""
value: Union[datetime, Tuple[datetime, datetime]] = Field(
union_mode="left_to_right"
)
ALLOWED_OPS: ClassVar[List[str]] = [
GenericFilterOps.EQUALS,
GenericFilterOps.NOT_EQUALS,
GenericFilterOps.GT,
GenericFilterOps.GTE,
GenericFilterOps.LT,
GenericFilterOps.LTE,
GenericFilterOps.IN,
]
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a datetime column.
Args:
column: The datetime column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.IN:
assert isinstance(self.value, tuple)
lower_bound, upper_bound = self.value
return column.between(lower_bound, upper_bound)
assert isinstance(self.value, datetime)
if self.operation == GenericFilterOps.GTE:
return column >= self.value
if self.operation == GenericFilterOps.GT:
return column > self.value
if self.operation == GenericFilterOps.LTE:
return column <= self.value
if self.operation == GenericFilterOps.LT:
return column < self.value
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
generate_query_conditions_from_column(self, column)
Generate query conditions for a datetime column.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
Any |
The datetime column of an SQLModel table on which to filter. |
required |
Returns:
Type | Description |
---|---|
Any |
A list of query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a datetime column.
Args:
column: The datetime column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.IN:
assert isinstance(self.value, tuple)
lower_bound, upper_bound = self.value
return column.between(lower_bound, upper_bound)
assert isinstance(self.value, datetime)
if self.operation == GenericFilterOps.GTE:
return column >= self.value
if self.operation == GenericFilterOps.GT:
return column > self.value
if self.operation == GenericFilterOps.LTE:
return column <= self.value
if self.operation == GenericFilterOps.LT:
return column < self.value
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
Filter (BaseModel, ABC)
Filter for all fields.
A Filter is a combination of a column, a value that the user uses to
filter on this column and an operation to use. The easiest example
would be user equals aria
with column=user
, value=aria
and the
operation=equals
.
All subclasses of this class will support different sets of operations. This operation set is defined in the ALLOWED_OPS class variable.
Source code in zenml/models/v2/base/filter.py
class Filter(BaseModel, ABC):
"""Filter for all fields.
A Filter is a combination of a column, a value that the user uses to
filter on this column and an operation to use. The easiest example
would be `user equals aria` with column=`user`, value=`aria` and the
operation=`equals`.
All subclasses of this class will support different sets of operations.
This operation set is defined in the ALLOWED_OPS class variable.
"""
ALLOWED_OPS: ClassVar[List[str]] = []
operation: GenericFilterOps
column: str
value: Optional[Any] = None
@field_validator("operation", mode="before")
@classmethod
def validate_operation(cls, value: Any) -> Any:
"""Validate that the operation is a valid op for the field type.
Args:
value: The operation of this filter.
Returns:
The operation if it is valid.
Raises:
ValueError: If the operation is not valid for this field type.
"""
if value not in cls.ALLOWED_OPS:
raise ValueError(
f"This datatype can not be filtered using this operation: "
f"'{value}'. The allowed operations are: {cls.ALLOWED_OPS}"
)
else:
return value
def generate_query_conditions(
self,
table: Type[SQLModel],
) -> Union["ColumnElement[bool]"]:
"""Generate the query conditions for the database.
This method converts the Filter class into an appropriate SQLModel
query condition, to be used when filtering on the Database.
Args:
table: The SQLModel table to use for the query creation
Returns:
A list of conditions that will be combined using the `and` operation
"""
column = getattr(table, self.column)
conditions = self.generate_query_conditions_from_column(column)
return conditions # type:ignore[no-any-return]
@abstractmethod
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions given the corresponding database column.
This method should be overridden by subclasses to define how each
supported operation in `self.ALLOWED_OPS` can be used to filter the
given column by `self.value`.
Args:
column: The column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
generate_query_conditions(self, table)
Generate the query conditions for the database.
This method converts the Filter class into an appropriate SQLModel query condition, to be used when filtering on the Database.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[sqlmodel.main.SQLModel] |
The SQLModel table to use for the query creation |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
A list of conditions that will be combined using the |
Source code in zenml/models/v2/base/filter.py
def generate_query_conditions(
self,
table: Type[SQLModel],
) -> Union["ColumnElement[bool]"]:
"""Generate the query conditions for the database.
This method converts the Filter class into an appropriate SQLModel
query condition, to be used when filtering on the Database.
Args:
table: The SQLModel table to use for the query creation
Returns:
A list of conditions that will be combined using the `and` operation
"""
column = getattr(table, self.column)
conditions = self.generate_query_conditions_from_column(column)
return conditions # type:ignore[no-any-return]
generate_query_conditions_from_column(self, column)
Generate query conditions given the corresponding database column.
This method should be overridden by subclasses to define how each
supported operation in self.ALLOWED_OPS
can be used to filter the
given column by self.value
.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
Any |
The column of an SQLModel table on which to filter. |
required |
Returns:
Type | Description |
---|---|
Any |
A list of query conditions. |
Source code in zenml/models/v2/base/filter.py
@abstractmethod
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions given the corresponding database column.
This method should be overridden by subclasses to define how each
supported operation in `self.ALLOWED_OPS` can be used to filter the
given column by `self.value`.
Args:
column: The column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
validate_operation(value)
classmethod
Validate that the operation is a valid op for the field type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
The operation of this filter. |
required |
Returns:
Type | Description |
---|---|
Any |
The operation if it is valid. |
Exceptions:
Type | Description |
---|---|
ValueError |
If the operation is not valid for this field type. |
Source code in zenml/models/v2/base/filter.py
@field_validator("operation", mode="before")
@classmethod
def validate_operation(cls, value: Any) -> Any:
"""Validate that the operation is a valid op for the field type.
Args:
value: The operation of this filter.
Returns:
The operation if it is valid.
Raises:
ValueError: If the operation is not valid for this field type.
"""
if value not in cls.ALLOWED_OPS:
raise ValueError(
f"This datatype can not be filtered using this operation: "
f"'{value}'. The allowed operations are: {cls.ALLOWED_OPS}"
)
else:
return value
FilterGenerator
Helper class to define filters for a class.
Source code in zenml/models/v2/base/filter.py
class FilterGenerator:
"""Helper class to define filters for a class."""
def __init__(self, model_class: Type[BaseModel]) -> None:
"""Initialize the object.
Args:
model_class: The model class for which to define filters.
"""
self._model_class = model_class
def define_filter(
self, column: str, value: Any, operator: GenericFilterOps
) -> Filter:
"""Define a filter for a given column.
Args:
column: The column to filter on.
value: The value by which to filter.
operator: The operator to use for filtering.
Returns:
A Filter object.
"""
# Create datetime filters
if self.is_datetime_field(column):
return self._define_datetime_filter(
column=column,
value=value,
operator=operator,
)
# Create UUID filters
if self.is_uuid_field(column):
return self._define_uuid_filter(
column=column,
value=value,
operator=operator,
)
# Create int filters
if self.is_int_field(column):
return NumericFilter(
operation=GenericFilterOps(operator),
column=column,
value=int(value),
)
# Create bool filters
if self.is_bool_field(column):
return self._define_bool_filter(
column=column,
value=value,
operator=operator,
)
# Create str filters
if self.is_str_field(column):
return StrFilter(
operation=GenericFilterOps(operator),
column=column,
value=value,
)
# Handle unsupported datatypes
logger.warning(
f"The Datatype {self._model_class.model_fields[column].annotation} might "
"not be supported for filtering. Defaulting to a string filter."
)
return StrFilter(
operation=GenericFilterOps(operator),
column=column,
value=str(value),
)
def check_field_annotation(self, k: str, type_: Any) -> bool:
"""Checks whether a model field has a certain annotation.
Args:
k: The name of the field.
type_: The type to check.
Raises:
ValueError: if the model field within does not have an annotation.
Returns:
True if the annotation of the field matches the given type, False
otherwise.
"""
try:
annotation = self._model_class.model_fields[k].annotation
if annotation is not None:
return (
issubclass(type_, get_args(annotation))
or annotation is type_
)
else:
raise ValueError(
f"The field '{k}' inside the model {self._model_class.__name__} "
"does not have an annotation."
)
except TypeError:
return False
def is_datetime_field(self, k: str) -> bool:
"""Checks if it's a datetime field.
Args:
k: The key to check.
Returns:
True if the field is a datetime field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=datetime)
def is_uuid_field(self, k: str) -> bool:
"""Checks if it's a UUID field.
Args:
k: The key to check.
Returns:
True if the field is a UUID field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=UUID)
def is_int_field(self, k: str) -> bool:
"""Checks if it's an int field.
Args:
k: The key to check.
Returns:
True if the field is an int field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=int)
def is_bool_field(self, k: str) -> bool:
"""Checks if it's a bool field.
Args:
k: The key to check.
Returns:
True if the field is a bool field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=bool)
def is_str_field(self, k: str) -> bool:
"""Checks if it's a string field.
Args:
k: The key to check.
Returns:
True if the field is a string field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=str)
def is_sort_by_field(self, k: str) -> bool:
"""Checks if it's a sort by field.
Args:
k: The key to check.
Returns:
True if the field is a sort by field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=str) and k == "sort_by"
@staticmethod
def _define_datetime_filter(
column: str, value: Any, operator: GenericFilterOps
) -> DatetimeFilter:
"""Define a datetime filter for a given column.
Args:
column: The column to filter on.
value: The datetime value by which to filter.
operator: The operator to use for filtering.
Returns:
A Filter object.
Raises:
ValueError: If the value is not a valid datetime.
"""
try:
filter_value: Union[datetime, Tuple[datetime, datetime]]
if isinstance(value, datetime):
filter_value = value
elif "," in value:
lower_bound, upper_bound = value.split(",", 1)
filter_value = (
datetime.strptime(lower_bound, FILTERING_DATETIME_FORMAT),
datetime.strptime(upper_bound, FILTERING_DATETIME_FORMAT),
)
else:
filter_value = datetime.strptime(
value, FILTERING_DATETIME_FORMAT
)
except ValueError as e:
raise ValueError(
"The datetime filter only works with values in the following "
f"format: {FILTERING_DATETIME_FORMAT}"
) from e
if operator == GenericFilterOps.IN and not isinstance(
filter_value, tuple
):
raise ValueError(
"Two comma separated datetime values are required for the `in` "
"operator."
)
if operator != GenericFilterOps.IN and not isinstance(
filter_value, datetime
):
raise ValueError(
"Only a single datetime value is allowed for operator "
f"{operator}."
)
datetime_filter = DatetimeFilter(
operation=GenericFilterOps(operator),
column=column,
value=filter_value,
)
return datetime_filter
@staticmethod
def _define_uuid_filter(
column: str, value: Any, operator: GenericFilterOps
) -> UUIDFilter:
"""Define a UUID filter for a given column.
Args:
column: The column to filter on.
value: The UUID value by which to filter.
operator: The operator to use for filtering.
Returns:
A Filter object.
Raises:
ValueError: If the value is not a valid UUID.
"""
# For equality checks, ensure that the value is a valid UUID.
if operator == GenericFilterOps.EQUALS and not isinstance(value, UUID):
try:
UUID(value)
except ValueError as e:
raise ValueError(
"Invalid value passed as UUID query parameter."
) from e
# Cast the value to string for further comparisons.
value = str(value)
# Generate the filter.
uuid_filter = UUIDFilter(
operation=GenericFilterOps(operator),
column=column,
value=value,
)
return uuid_filter
@staticmethod
def _define_bool_filter(
column: str, value: Any, operator: GenericFilterOps
) -> BoolFilter:
"""Define a bool filter for a given column.
Args:
column: The column to filter on.
value: The bool value by which to filter.
operator: The operator to use for filtering.
Returns:
A Filter object.
"""
if GenericFilterOps(operator) != GenericFilterOps.EQUALS:
logger.warning(
"Boolean filters do not support any"
"operation except for equals. Defaulting"
"to an `equals` comparison."
)
return BoolFilter(
operation=GenericFilterOps.EQUALS,
column=column,
value=bool(value),
)
__init__(self, model_class)
special
Initialize the object.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model_class |
Type[pydantic.main.BaseModel] |
The model class for which to define filters. |
required |
Source code in zenml/models/v2/base/filter.py
def __init__(self, model_class: Type[BaseModel]) -> None:
"""Initialize the object.
Args:
model_class: The model class for which to define filters.
"""
self._model_class = model_class
check_field_annotation(self, k, type_)
Checks whether a model field has a certain annotation.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The name of the field. |
required |
type_ |
Any |
The type to check. |
required |
Exceptions:
Type | Description |
---|---|
ValueError |
if the model field within does not have an annotation. |
Returns:
Type | Description |
---|---|
bool |
True if the annotation of the field matches the given type, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def check_field_annotation(self, k: str, type_: Any) -> bool:
"""Checks whether a model field has a certain annotation.
Args:
k: The name of the field.
type_: The type to check.
Raises:
ValueError: if the model field within does not have an annotation.
Returns:
True if the annotation of the field matches the given type, False
otherwise.
"""
try:
annotation = self._model_class.model_fields[k].annotation
if annotation is not None:
return (
issubclass(type_, get_args(annotation))
or annotation is type_
)
else:
raise ValueError(
f"The field '{k}' inside the model {self._model_class.__name__} "
"does not have an annotation."
)
except TypeError:
return False
define_filter(self, column, value, operator)
Define a filter for a given column.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
str |
The column to filter on. |
required |
value |
Any |
The value by which to filter. |
required |
operator |
GenericFilterOps |
The operator to use for filtering. |
required |
Returns:
Type | Description |
---|---|
Filter |
A Filter object. |
Source code in zenml/models/v2/base/filter.py
def define_filter(
self, column: str, value: Any, operator: GenericFilterOps
) -> Filter:
"""Define a filter for a given column.
Args:
column: The column to filter on.
value: The value by which to filter.
operator: The operator to use for filtering.
Returns:
A Filter object.
"""
# Create datetime filters
if self.is_datetime_field(column):
return self._define_datetime_filter(
column=column,
value=value,
operator=operator,
)
# Create UUID filters
if self.is_uuid_field(column):
return self._define_uuid_filter(
column=column,
value=value,
operator=operator,
)
# Create int filters
if self.is_int_field(column):
return NumericFilter(
operation=GenericFilterOps(operator),
column=column,
value=int(value),
)
# Create bool filters
if self.is_bool_field(column):
return self._define_bool_filter(
column=column,
value=value,
operator=operator,
)
# Create str filters
if self.is_str_field(column):
return StrFilter(
operation=GenericFilterOps(operator),
column=column,
value=value,
)
# Handle unsupported datatypes
logger.warning(
f"The Datatype {self._model_class.model_fields[column].annotation} might "
"not be supported for filtering. Defaulting to a string filter."
)
return StrFilter(
operation=GenericFilterOps(operator),
column=column,
value=str(value),
)
is_bool_field(self, k)
Checks if it's a bool field.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The key to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the field is a bool field, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def is_bool_field(self, k: str) -> bool:
"""Checks if it's a bool field.
Args:
k: The key to check.
Returns:
True if the field is a bool field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=bool)
is_datetime_field(self, k)
Checks if it's a datetime field.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The key to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the field is a datetime field, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def is_datetime_field(self, k: str) -> bool:
"""Checks if it's a datetime field.
Args:
k: The key to check.
Returns:
True if the field is a datetime field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=datetime)
is_int_field(self, k)
Checks if it's an int field.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The key to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the field is an int field, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def is_int_field(self, k: str) -> bool:
"""Checks if it's an int field.
Args:
k: The key to check.
Returns:
True if the field is an int field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=int)
is_sort_by_field(self, k)
Checks if it's a sort by field.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The key to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the field is a sort by field, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def is_sort_by_field(self, k: str) -> bool:
"""Checks if it's a sort by field.
Args:
k: The key to check.
Returns:
True if the field is a sort by field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=str) and k == "sort_by"
is_str_field(self, k)
Checks if it's a string field.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The key to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the field is a string field, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def is_str_field(self, k: str) -> bool:
"""Checks if it's a string field.
Args:
k: The key to check.
Returns:
True if the field is a string field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=str)
is_uuid_field(self, k)
Checks if it's a UUID field.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
k |
str |
The key to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the field is a UUID field, False otherwise. |
Source code in zenml/models/v2/base/filter.py
def is_uuid_field(self, k: str) -> bool:
"""Checks if it's a UUID field.
Args:
k: The key to check.
Returns:
True if the field is a UUID field, False otherwise.
"""
return self.check_field_annotation(k=k, type_=UUID)
NumericFilter (Filter)
Filter for all numeric fields.
Source code in zenml/models/v2/base/filter.py
class NumericFilter(Filter):
"""Filter for all numeric fields."""
value: Union[float, datetime] = Field(union_mode="left_to_right")
ALLOWED_OPS: ClassVar[List[str]] = [
GenericFilterOps.EQUALS,
GenericFilterOps.NOT_EQUALS,
GenericFilterOps.GT,
GenericFilterOps.GTE,
GenericFilterOps.LT,
GenericFilterOps.LTE,
]
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a numeric column.
Args:
column: The numeric column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.GTE:
return column >= self.value
if self.operation == GenericFilterOps.GT:
return column > self.value
if self.operation == GenericFilterOps.LTE:
return column <= self.value
if self.operation == GenericFilterOps.LT:
return column < self.value
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
generate_query_conditions_from_column(self, column)
Generate query conditions for a numeric column.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
Any |
The numeric column of an SQLModel table on which to filter. |
required |
Returns:
Type | Description |
---|---|
Any |
A list of query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a numeric column.
Args:
column: The numeric column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.GTE:
return column >= self.value
if self.operation == GenericFilterOps.GT:
return column > self.value
if self.operation == GenericFilterOps.LTE:
return column <= self.value
if self.operation == GenericFilterOps.LT:
return column < self.value
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
StrFilter (Filter)
Filter for all string fields.
Source code in zenml/models/v2/base/filter.py
class StrFilter(Filter):
"""Filter for all string fields."""
ALLOWED_OPS: ClassVar[List[str]] = [
GenericFilterOps.EQUALS,
GenericFilterOps.NOT_EQUALS,
GenericFilterOps.STARTSWITH,
GenericFilterOps.CONTAINS,
GenericFilterOps.ENDSWITH,
]
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a string column.
Args:
column: The string column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.CONTAINS:
return column.like(f"%{self.value}%")
if self.operation == GenericFilterOps.STARTSWITH:
return column.startswith(f"{self.value}")
if self.operation == GenericFilterOps.ENDSWITH:
return column.endswith(f"{self.value}")
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
generate_query_conditions_from_column(self, column)
Generate query conditions for a string column.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
Any |
The string column of an SQLModel table on which to filter. |
required |
Returns:
Type | Description |
---|---|
Any |
A list of query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a string column.
Args:
column: The string column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
if self.operation == GenericFilterOps.CONTAINS:
return column.like(f"%{self.value}%")
if self.operation == GenericFilterOps.STARTSWITH:
return column.startswith(f"{self.value}")
if self.operation == GenericFilterOps.ENDSWITH:
return column.endswith(f"{self.value}")
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
return column == self.value
UUIDFilter (StrFilter)
Filter for all uuid fields which are mostly treated like strings.
Source code in zenml/models/v2/base/filter.py
class UUIDFilter(StrFilter):
"""Filter for all uuid fields which are mostly treated like strings."""
@field_validator("value", mode="before")
@classmethod
def _remove_hyphens_from_value(cls, value: Any) -> Any:
"""Remove hyphens from the value to enable string comparisons.
Args:
value: The filter value.
Returns:
The filter value with removed hyphens.
"""
if isinstance(value, str):
return value.replace("-", "")
return value
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a UUID column.
Args:
column: The UUID column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
import sqlalchemy
from sqlalchemy_utils.functions import cast_if
# For equality checks, compare the UUID directly
if self.operation == GenericFilterOps.EQUALS:
return column == self.value
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
# For all other operations, cast and handle the column as string
return super().generate_query_conditions_from_column(
column=cast_if(column, sqlalchemy.String)
)
generate_query_conditions_from_column(self, column)
Generate query conditions for a UUID column.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
column |
Any |
The UUID column of an SQLModel table on which to filter. |
required |
Returns:
Type | Description |
---|---|
Any |
A list of query conditions. |
Source code in zenml/models/v2/base/filter.py
def generate_query_conditions_from_column(self, column: Any) -> Any:
"""Generate query conditions for a UUID column.
Args:
column: The UUID column of an SQLModel table on which to filter.
Returns:
A list of query conditions.
"""
import sqlalchemy
from sqlalchemy_utils.functions import cast_if
# For equality checks, compare the UUID directly
if self.operation == GenericFilterOps.EQUALS:
return column == self.value
if self.operation == GenericFilterOps.NOT_EQUALS:
return column != self.value
# For all other operations, cast and handle the column as string
return super().generate_query_conditions_from_column(
column=cast_if(column, sqlalchemy.String)
)
page
Page model definitions.
Page (BaseModel, Generic)
Return Model for List Models to accommodate pagination.
Source code in zenml/models/v2/base/page.py
class Page(BaseModel, Generic[B]):
"""Return Model for List Models to accommodate pagination."""
index: PositiveInt
max_size: PositiveInt
total_pages: NonNegativeInt
total: NonNegativeInt
items: List[B]
__params_type__ = BaseFilter
@property
def size(self) -> int:
"""Return the item count of the page.
Returns:
The amount of items in the page.
"""
return len(self.items)
def __len__(self) -> int:
"""Return the item count of the page.
This enables `len(page)`.
Returns:
The amount of items in the page.
"""
return len(self.items)
def __getitem__(self, index: int) -> B:
"""Return the item at the given index.
This enables `page[index]`.
Args:
index: The index to get the item from.
Returns:
The item at the given index.
"""
return self.items[index]
def __iter__(self) -> Generator[B, None, None]: # type: ignore[override]
"""Return an iterator over the items in the page.
This enables `for item in page` loops, but breaks `dict(page)`.
Yields:
An iterator over the items in the page.
"""
for item in self.items.__iter__():
yield item
def __contains__(self, item: B) -> bool:
"""Returns whether the page contains a specific item.
This enables `item in page` checks.
Args:
item: The item to check for.
Returns:
Whether the item is in the page.
"""
return item in self.items
size: int
property
readonly
Return the item count of the page.
Returns:
Type | Description |
---|---|
int |
The amount of items in the page. |
__params_type__ (BaseModel)
Class to unify all filter, paginate and sort request parameters.
This Model allows fine-grained filtering, sorting and pagination of resources.
Usage example for subclasses of this class:
ResourceListModel(
name="contains:default",
workspace="default"
count_steps="gte:5"
sort_by="created",
page=2,
size=20
)
Source code in zenml/models/v2/base/page.py
class BaseFilter(BaseModel):
"""Class to unify all filter, paginate and sort request parameters.
This Model allows fine-grained filtering, sorting and pagination of
resources.
Usage example for subclasses of this class:
```
ResourceListModel(
name="contains:default",
workspace="default"
count_steps="gte:5"
sort_by="created",
page=2,
size=20
)
```
"""
# List of fields that cannot be used as filters.
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
"sort_by",
"page",
"size",
"logical_operator",
]
CUSTOM_SORTING_OPTIONS: ClassVar[List[str]] = []
# List of fields that are not even mentioned as options in the CLI.
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = []
# List of fields that are wrapped with `fastapi.Query(default)` in API.
API_MULTI_INPUT_PARAMS: ClassVar[List[str]] = []
sort_by: str = Field(
default="created", description="Which column to sort by."
)
logical_operator: LogicalOperators = Field(
default=LogicalOperators.AND,
description="Which logical operator to use between all filters "
"['and', 'or']",
)
page: int = Field(
default=PAGINATION_STARTING_PAGE, ge=1, description="Page number"
)
size: int = Field(
default=PAGE_SIZE_DEFAULT,
ge=1,
le=PAGE_SIZE_MAXIMUM,
description="Page size",
)
id: Optional[Union[UUID, str]] = Field(
default=None,
description="Id for this resource",
union_mode="left_to_right",
)
created: Optional[Union[datetime, str]] = Field(
default=None, description="Created", union_mode="left_to_right"
)
updated: Optional[Union[datetime, str]] = Field(
default=None, description="Updated", union_mode="left_to_right"
)
_rbac_configuration: Optional[
Tuple[UUID, Dict[str, Optional[Set[UUID]]]]
] = None
@field_validator("sort_by", mode="before")
@classmethod
def validate_sort_by(cls, value: Any) -> Any:
"""Validate that the sort_column is a valid column with a valid operand.
Args:
value: The sort_by field value.
Returns:
The validated sort_by field value.
Raises:
ValidationError: If the sort_by field is not a string.
ValueError: If the resource can't be sorted by this field.
"""
# Somehow pydantic allows you to pass in int values, which will be
# interpreted as string, however within the validator they are still
# integers, which don't have a .split() method
if not isinstance(value, str):
raise ValidationError(
f"str type expected for the sort_by field. "
f"Received a {type(value)}"
)
column = value
split_value = value.split(":", 1)
if len(split_value) == 2:
column = split_value[1]
if split_value[0] not in SorterOps.values():
logger.warning(
"Invalid operand used for column sorting. "
"Only the following operands are supported `%s`. "
"Defaulting to 'asc' on column `%s`.",
SorterOps.values(),
column,
)
value = column
if column in cls.FILTER_EXCLUDE_FIELDS:
raise ValueError(
f"This resource can not be sorted by this field: '{value}'"
)
elif column in cls.model_fields:
return value
elif column in cls.CUSTOM_SORTING_OPTIONS:
return value
else:
raise ValueError(
"You can only sort by valid fields of this resource"
)
@model_validator(mode="before")
@classmethod
@before_validator_handler
def filter_ops(cls, data: Dict[str, Any]) -> Dict[str, Any]:
"""Parse incoming filters to ensure all filters are legal.
Args:
data: The values of the class.
Returns:
The values of the class.
"""
cls._generate_filter_list(data)
return data
@property
def list_of_filters(self) -> List[Filter]:
"""Converts the class variables into a list of usable Filter Models.
Returns:
A list of Filter models.
"""
return self._generate_filter_list(
{key: getattr(self, key) for key in self.model_fields}
)
@property
def sorting_params(self) -> Tuple[str, SorterOps]:
"""Converts the class variables into a list of usable Filter Models.
Returns:
A tuple of the column to sort by and the sorting operand.
"""
column = self.sort_by
# The default sorting operand is asc
operator = SorterOps.ASCENDING
# Check if user explicitly set an operand
split_value = self.sort_by.split(":", 1)
if len(split_value) == 2:
column = split_value[1]
operator = SorterOps(split_value[0])
return column, operator
def configure_rbac(
self,
authenticated_user_id: UUID,
**column_allowed_ids: Optional[Set[UUID]],
) -> None:
"""Configure RBAC allowed column values.
Args:
authenticated_user_id: ID of the authenticated user. All entities
owned by this user will be included.
column_allowed_ids: Set of IDs per column to limit the query to.
If given, the remaining filters will be applied to entities
within this set only. If `None`, the remaining filters will
be applied to all entries in the table.
"""
self._rbac_configuration = (authenticated_user_id, column_allowed_ids)
def generate_rbac_filter(
self,
table: Type["AnySchema"],
) -> Optional["ColumnElement[bool]"]:
"""Generates an optional RBAC filter.
Args:
table: The query table.
Returns:
The RBAC filter.
"""
from sqlmodel import or_
if not self._rbac_configuration:
return None
expressions = []
for column_name, allowed_ids in self._rbac_configuration[1].items():
if allowed_ids is not None:
expression = getattr(table, column_name).in_(allowed_ids)
expressions.append(expression)
if expressions and hasattr(table, "user_id"):
# If `expressions` is not empty, we do not have full access to all
# rows of the table. In this case, we also include rows which the
# user owns.
# Unowned entities are considered server-owned and can be seen
# by anyone
expressions.append(getattr(table, "user_id").is_(None))
# The authenticated user owns this entity
expressions.append(
getattr(table, "user_id") == self._rbac_configuration[0]
)
if expressions:
return or_(*expressions)
else:
return None
@classmethod
def _generate_filter_list(cls, values: Dict[str, Any]) -> List[Filter]:
"""Create a list of filters from a (column, value) dictionary.
Args:
values: A dictionary of column names and values to filter on.
Returns:
A list of filters.
"""
list_of_filters: List[Filter] = []
for key, value in values.items():
# Ignore excluded filters
if key in cls.FILTER_EXCLUDE_FIELDS:
continue
# Skip filtering for None values
if value is None:
continue
# Determine the operator and filter value
value, operator = cls._resolve_operator(value)
# Define the filter
filter = FilterGenerator(cls).define_filter(
column=key, value=value, operator=operator
)
list_of_filters.append(filter)
return list_of_filters
@staticmethod
def _resolve_operator(value: Any) -> Tuple[Any, GenericFilterOps]:
"""Determine the operator and filter value from a user-provided value.
If the user-provided value is a string of the form "operator:value",
then the operator is extracted and the value is returned. Otherwise,
`GenericFilterOps.EQUALS` is used as default operator and the value
is returned as-is.
Args:
value: The user-provided value.
Returns:
A tuple of the filter value and the operator.
"""
operator = GenericFilterOps.EQUALS # Default operator
if isinstance(value, str):
split_value = value.split(":", 1)
if (
len(split_value) == 2
and split_value[0] in GenericFilterOps.values()
):
value = split_value[1]
operator = GenericFilterOps(split_value[0])
return value, operator
def generate_name_or_id_query_conditions(
self,
value: Union[UUID, str],
table: Type["NamedSchema"],
) -> "ColumnElement[bool]":
"""Generate filter conditions for name or id of a table.
Args:
value: The filter value.
table: The table to filter.
Returns:
The query conditions.
"""
from sqlmodel import or_
value, operator = BaseFilter._resolve_operator(value)
value = str(value)
conditions = []
try:
filter_ = FilterGenerator(table).define_filter(
column="id", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
except ValueError:
# UUID filter with equal operators and no full UUID fail with
# a ValueError. In this case, we already know that the filter
# will not produce any result and can simply ignore it.
pass
filter_ = FilterGenerator(table).define_filter(
column="name", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
return or_(*conditions)
def generate_custom_query_conditions_for_column(
self,
value: Any,
table: Type[SQLModel],
column: str,
) -> "ColumnElement[bool]":
"""Generate custom filter conditions for a column of a table.
Args:
value: The filter value.
table: The table which contains the column.
column: The column name.
Returns:
The query conditions.
"""
value, operator = BaseFilter._resolve_operator(value)
filter_ = FilterGenerator(table).define_filter(
column=column, value=value, operator=operator
)
return filter_.generate_query_conditions(table=table)
@property
def offset(self) -> int:
"""Returns the offset needed for the query on the data persistence layer.
Returns:
The offset for the query.
"""
return self.size * (self.page - 1)
def generate_filter(
self, table: Type[SQLModel]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
Raises:
RuntimeError: If a valid logical operator is not supplied.
"""
from sqlmodel import and_, or_
filters = []
for column_filter in self.list_of_filters:
filters.append(
column_filter.generate_query_conditions(table=table)
)
for custom_filter in self.get_custom_filters():
filters.append(custom_filter)
if self.logical_operator == LogicalOperators.OR:
return or_(False, *filters)
elif self.logical_operator == LogicalOperators.AND:
return and_(True, *filters)
else:
raise RuntimeError("No valid logical operator was supplied.")
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
This can be overridden by subclasses to define custom filters that are
not based on the columns of the underlying table.
Returns:
A list of custom filters.
"""
return []
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
rbac_filter = self.generate_rbac_filter(table=table)
if rbac_filter is not None:
query = query.where(rbac_filter)
filters = self.generate_filter(table=table)
if filters is not None:
query = query.where(filters)
return query
def apply_sorting(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Apply sorting to the query.
Args:
query: The query to which to apply the sorting.
table: The query table.
Returns:
The query with sorting applied.
"""
column, operand = self.sorting_params
if operand == SorterOps.DESCENDING:
sort_clause = desc(getattr(table, column)) # type: ignore[var-annotated]
else:
sort_clause = asc(getattr(table, column))
# We always add the `id` column as a tiebreaker to ensure a stable,
# repeatable order of items, otherwise subsequent pages might contain
# the same items.
query = query.order_by(sort_clause, asc(table.id)) # type: ignore[arg-type]
return query
list_of_filters: List[zenml.models.v2.base.filter.Filter]
property
readonly
Converts the class variables into a list of usable Filter Models.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.base.filter.Filter] |
A list of Filter models. |
offset: int
property
readonly
Returns the offset needed for the query on the data persistence layer.
Returns:
Type | Description |
---|---|
int |
The offset for the query. |
sorting_params: Tuple[str, zenml.enums.SorterOps]
property
readonly
Converts the class variables into a list of usable Filter Models.
Returns:
Type | Description |
---|---|
Tuple[str, zenml.enums.SorterOps] |
A tuple of the column to sort by and the sorting operand. |
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/base/page.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
rbac_filter = self.generate_rbac_filter(table=table)
if rbac_filter is not None:
query = query.where(rbac_filter)
filters = self.generate_filter(table=table)
if filters is not None:
query = query.where(filters)
return query
apply_sorting(self, query, table)
Apply sorting to the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the sorting. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with sorting applied. |
Source code in zenml/models/v2/base/page.py
def apply_sorting(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Apply sorting to the query.
Args:
query: The query to which to apply the sorting.
table: The query table.
Returns:
The query with sorting applied.
"""
column, operand = self.sorting_params
if operand == SorterOps.DESCENDING:
sort_clause = desc(getattr(table, column)) # type: ignore[var-annotated]
else:
sort_clause = asc(getattr(table, column))
# We always add the `id` column as a tiebreaker to ensure a stable,
# repeatable order of items, otherwise subsequent pages might contain
# the same items.
query = query.order_by(sort_clause, asc(table.id)) # type: ignore[arg-type]
return query
configure_rbac(self, authenticated_user_id, **column_allowed_ids)
Configure RBAC allowed column values.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
authenticated_user_id |
UUID |
ID of the authenticated user. All entities owned by this user will be included. |
required |
column_allowed_ids |
Optional[Set[uuid.UUID]] |
Set of IDs per column to limit the query to.
If given, the remaining filters will be applied to entities
within this set only. If |
{} |
Source code in zenml/models/v2/base/page.py
def configure_rbac(
self,
authenticated_user_id: UUID,
**column_allowed_ids: Optional[Set[UUID]],
) -> None:
"""Configure RBAC allowed column values.
Args:
authenticated_user_id: ID of the authenticated user. All entities
owned by this user will be included.
column_allowed_ids: Set of IDs per column to limit the query to.
If given, the remaining filters will be applied to entities
within this set only. If `None`, the remaining filters will
be applied to all entries in the table.
"""
self._rbac_configuration = (authenticated_user_id, column_allowed_ids)
filter_ops(data, validation_info)
classmethod
Wrapper method to handle the raw data.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
cls |
the class handler |
required | |
data |
Any |
the raw input data |
required |
validation_info |
ValidationInfo |
the context of the validation. |
required |
Returns:
Type | Description |
---|---|
Any |
the validated data |
Source code in zenml/models/v2/base/page.py
def before_validator(
cls: Type[BaseModel], data: Any, validation_info: ValidationInfo
) -> Any:
"""Wrapper method to handle the raw data.
Args:
cls: the class handler
data: the raw input data
validation_info: the context of the validation.
Returns:
the validated data
"""
data = model_validator_data_handler(
raw_data=data, base_class=cls, validation_info=validation_info
)
return method(cls=cls, data=data)
generate_custom_query_conditions_for_column(self, value, table, column)
Generate custom filter conditions for a column of a table.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
The filter value. |
required |
table |
Type[sqlmodel.main.SQLModel] |
The table which contains the column. |
required |
column |
str |
The column name. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The query conditions. |
Source code in zenml/models/v2/base/page.py
def generate_custom_query_conditions_for_column(
self,
value: Any,
table: Type[SQLModel],
column: str,
) -> "ColumnElement[bool]":
"""Generate custom filter conditions for a column of a table.
Args:
value: The filter value.
table: The table which contains the column.
column: The column name.
Returns:
The query conditions.
"""
value, operator = BaseFilter._resolve_operator(value)
filter_ = FilterGenerator(table).define_filter(
column=column, value=value, operator=operator
)
return filter_.generate_query_conditions(table=table)
generate_filter(self, table)
Generate the filter for the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[sqlmodel.main.SQLModel] |
The Table that is being queried from. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The filter expression for the query. |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If a valid logical operator is not supplied. |
Source code in zenml/models/v2/base/page.py
def generate_filter(
self, table: Type[SQLModel]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
Raises:
RuntimeError: If a valid logical operator is not supplied.
"""
from sqlmodel import and_, or_
filters = []
for column_filter in self.list_of_filters:
filters.append(
column_filter.generate_query_conditions(table=table)
)
for custom_filter in self.get_custom_filters():
filters.append(custom_filter)
if self.logical_operator == LogicalOperators.OR:
return or_(False, *filters)
elif self.logical_operator == LogicalOperators.AND:
return and_(True, *filters)
else:
raise RuntimeError("No valid logical operator was supplied.")
generate_name_or_id_query_conditions(self, value, table)
Generate filter conditions for name or id of a table.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Union[uuid.UUID, str] |
The filter value. |
required |
table |
Type[NamedSchema] |
The table to filter. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The query conditions. |
Source code in zenml/models/v2/base/page.py
def generate_name_or_id_query_conditions(
self,
value: Union[UUID, str],
table: Type["NamedSchema"],
) -> "ColumnElement[bool]":
"""Generate filter conditions for name or id of a table.
Args:
value: The filter value.
table: The table to filter.
Returns:
The query conditions.
"""
from sqlmodel import or_
value, operator = BaseFilter._resolve_operator(value)
value = str(value)
conditions = []
try:
filter_ = FilterGenerator(table).define_filter(
column="id", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
except ValueError:
# UUID filter with equal operators and no full UUID fail with
# a ValueError. In this case, we already know that the filter
# will not produce any result and can simply ignore it.
pass
filter_ = FilterGenerator(table).define_filter(
column="name", value=value, operator=operator
)
conditions.append(filter_.generate_query_conditions(table=table))
return or_(*conditions)
generate_rbac_filter(self, table)
Generates an optional RBAC filter.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
Optional[ColumnElement[bool]] |
The RBAC filter. |
Source code in zenml/models/v2/base/page.py
def generate_rbac_filter(
self,
table: Type["AnySchema"],
) -> Optional["ColumnElement[bool]"]:
"""Generates an optional RBAC filter.
Args:
table: The query table.
Returns:
The RBAC filter.
"""
from sqlmodel import or_
if not self._rbac_configuration:
return None
expressions = []
for column_name, allowed_ids in self._rbac_configuration[1].items():
if allowed_ids is not None:
expression = getattr(table, column_name).in_(allowed_ids)
expressions.append(expression)
if expressions and hasattr(table, "user_id"):
# If `expressions` is not empty, we do not have full access to all
# rows of the table. In this case, we also include rows which the
# user owns.
# Unowned entities are considered server-owned and can be seen
# by anyone
expressions.append(getattr(table, "user_id").is_(None))
# The authenticated user owns this entity
expressions.append(
getattr(table, "user_id") == self._rbac_configuration[0]
)
if expressions:
return or_(*expressions)
else:
return None
get_custom_filters(self)
Get custom filters.
This can be overridden by subclasses to define custom filters that are not based on the columns of the underlying table.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/base/page.py
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
This can be overridden by subclasses to define custom filters that are
not based on the columns of the underlying table.
Returns:
A list of custom filters.
"""
return []
model_post_init(/, self, context)
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
self |
BaseModel |
The BaseModel instance. |
required |
context |
Any |
The context. |
required |
Source code in zenml/models/v2/base/page.py
def init_private_attributes(self: BaseModel, context: Any, /) -> None:
"""This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args:
self: The BaseModel instance.
context: The context.
"""
if getattr(self, '__pydantic_private__', None) is None:
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)
validate_sort_by(value)
classmethod
Validate that the sort_column is a valid column with a valid operand.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
The sort_by field value. |
required |
Returns:
Type | Description |
---|---|
Any |
The validated sort_by field value. |
Exceptions:
Type | Description |
---|---|
ValidationError |
If the sort_by field is not a string. |
ValueError |
If the resource can't be sorted by this field. |
Source code in zenml/models/v2/base/page.py
@field_validator("sort_by", mode="before")
@classmethod
def validate_sort_by(cls, value: Any) -> Any:
"""Validate that the sort_column is a valid column with a valid operand.
Args:
value: The sort_by field value.
Returns:
The validated sort_by field value.
Raises:
ValidationError: If the sort_by field is not a string.
ValueError: If the resource can't be sorted by this field.
"""
# Somehow pydantic allows you to pass in int values, which will be
# interpreted as string, however within the validator they are still
# integers, which don't have a .split() method
if not isinstance(value, str):
raise ValidationError(
f"str type expected for the sort_by field. "
f"Received a {type(value)}"
)
column = value
split_value = value.split(":", 1)
if len(split_value) == 2:
column = split_value[1]
if split_value[0] not in SorterOps.values():
logger.warning(
"Invalid operand used for column sorting. "
"Only the following operands are supported `%s`. "
"Defaulting to 'asc' on column `%s`.",
SorterOps.values(),
column,
)
value = column
if column in cls.FILTER_EXCLUDE_FIELDS:
raise ValueError(
f"This resource can not be sorted by this field: '{value}'"
)
elif column in cls.model_fields:
return value
elif column in cls.CUSTOM_SORTING_OPTIONS:
return value
else:
raise ValueError(
"You can only sort by valid fields of this resource"
)
__contains__(self, item)
special
Returns whether the page contains a specific item.
This enables item in page
checks.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
item |
~B |
The item to check for. |
required |
Returns:
Type | Description |
---|---|
bool |
Whether the item is in the page. |
Source code in zenml/models/v2/base/page.py
def __contains__(self, item: B) -> bool:
"""Returns whether the page contains a specific item.
This enables `item in page` checks.
Args:
item: The item to check for.
Returns:
Whether the item is in the page.
"""
return item in self.items
__getitem__(self, index)
special
Return the item at the given index.
This enables page[index]
.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
index |
int |
The index to get the item from. |
required |
Returns:
Type | Description |
---|---|
~B |
The item at the given index. |
Source code in zenml/models/v2/base/page.py
def __getitem__(self, index: int) -> B:
"""Return the item at the given index.
This enables `page[index]`.
Args:
index: The index to get the item from.
Returns:
The item at the given index.
"""
return self.items[index]
__iter__(self)
special
Return an iterator over the items in the page.
This enables for item in page
loops, but breaks dict(page)
.
Yields:
Type | Description |
---|---|
Generator[~B, NoneType, NoneType] |
An iterator over the items in the page. |
Source code in zenml/models/v2/base/page.py
def __iter__(self) -> Generator[B, None, None]: # type: ignore[override]
"""Return an iterator over the items in the page.
This enables `for item in page` loops, but breaks `dict(page)`.
Yields:
An iterator over the items in the page.
"""
for item in self.items.__iter__():
yield item
__len__(self)
special
Return the item count of the page.
This enables len(page)
.
Returns:
Type | Description |
---|---|
int |
The amount of items in the page. |
Source code in zenml/models/v2/base/page.py
def __len__(self) -> int:
"""Return the item count of the page.
This enables `len(page)`.
Returns:
The amount of items in the page.
"""
return len(self.items)
scoped
Scoped model definitions.
UserScopedFilter (BaseFilter)
Model to enable advanced user-based scoping.
Source code in zenml/models/v2/base/scoped.py
class UserScopedFilter(BaseFilter):
"""Model to enable advanced user-based scoping."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*BaseFilter.FILTER_EXCLUDE_FIELDS,
"scope_user",
]
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*BaseFilter.CLI_EXCLUDE_FIELDS,
"scope_user",
]
scope_user: Optional[UUID] = Field(
default=None,
description="The user to scope this query to.",
)
def set_scope_user(self, user_id: UUID) -> None:
"""Set the user that is performing the filtering to scope the response.
Args:
user_id: The user ID to scope the response to.
"""
self.scope_user = user_id
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
if self.scope_user:
query = query.where(getattr(table, "user_id") == self.scope_user)
return query
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/base/scoped.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
if self.scope_user:
query = query.where(getattr(table, "user_id") == self.scope_user)
return query
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_scope_user(self, user_id)
Set the user that is performing the filtering to scope the response.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
user_id |
UUID |
The user ID to scope the response to. |
required |
Source code in zenml/models/v2/base/scoped.py
def set_scope_user(self, user_id: UUID) -> None:
"""Set the user that is performing the filtering to scope the response.
Args:
user_id: The user ID to scope the response to.
"""
self.scope_user = user_id
UserScopedRequest (BaseRequest)
Base user-owned request model.
Used as a base class for all domain models that are "owned" by a user.
Source code in zenml/models/v2/base/scoped.py
class UserScopedRequest(BaseRequest):
"""Base user-owned request model.
Used as a base class for all domain models that are "owned" by a user.
"""
user: UUID = Field(title="The id of the user that created this resource.")
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for user scoped models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata["user_id"] = self.user
return metadata
get_analytics_metadata(self)
Fetches the analytics metadata for user scoped models.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
The analytics metadata. |
Source code in zenml/models/v2/base/scoped.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for user scoped models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata["user_id"] = self.user
return metadata
UserScopedResponse (BaseIdentifiedResponse[~UserBody, ~UserMetadata, ~UserResources], Generic)
Base user-owned model.
Used as a base class for all domain models that are "owned" by a user.
Source code in zenml/models/v2/base/scoped.py
class UserScopedResponse(
BaseIdentifiedResponse[UserBody, UserMetadata, UserResources],
Generic[UserBody, UserMetadata, UserResources],
):
"""Base user-owned model.
Used as a base class for all domain models that are "owned" by a user.
"""
# Analytics
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for user scoped models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
if self.user is not None:
metadata["user_id"] = self.user.id
return metadata
# Body and metadata properties
@property
def user(self) -> Optional["UserResponse"]:
"""The `user` property.
Returns:
the value of the property.
"""
return self.get_body().user
user: Optional[UserResponse]
property
readonly
The user
property.
Returns:
Type | Description |
---|---|
Optional[UserResponse] |
the value of the property. |
get_analytics_metadata(self)
Fetches the analytics metadata for user scoped models.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
The analytics metadata. |
Source code in zenml/models/v2/base/scoped.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for user scoped models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
if self.user is not None:
metadata["user_id"] = self.user.id
return metadata
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
UserScopedResponseBody (BaseDatedResponseBody)
Base user-owned body.
Source code in zenml/models/v2/base/scoped.py
class UserScopedResponseBody(BaseDatedResponseBody):
"""Base user-owned body."""
user: Optional["UserResponse"] = Field(
title="The user who created this resource.", default=None
)
UserScopedResponseMetadata (BaseResponseMetadata)
Base user-owned metadata.
Source code in zenml/models/v2/base/scoped.py
class UserScopedResponseMetadata(BaseResponseMetadata):
"""Base user-owned metadata."""
UserScopedResponseResources (BaseResponseResources)
Base class for all resource models associated with the user.
Source code in zenml/models/v2/base/scoped.py
class UserScopedResponseResources(BaseResponseResources):
"""Base class for all resource models associated with the user."""
UserScopedResponse[FlavorResponseBody, FlavorResponseMetadata, FlavorResponseResources] (UserScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
UserScopedResponse[OAuthDeviceResponseBody, OAuthDeviceResponseMetadata, OAuthDeviceResponseResources] (UserScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
UserScopedResponse[~WorkspaceBody, ~WorkspaceMetadata, ~WorkspaceResources] (UserScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedFilter (BaseFilter)
Model to enable advanced scoping with workspace.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedFilter(BaseFilter):
"""Model to enable advanced scoping with workspace."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*BaseFilter.FILTER_EXCLUDE_FIELDS,
"scope_workspace",
]
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*BaseFilter.CLI_EXCLUDE_FIELDS,
"scope_workspace",
]
scope_workspace: Optional[UUID] = Field(
default=None,
description="The workspace to scope this query to.",
)
def set_scope_workspace(self, workspace_id: UUID) -> None:
"""Set the workspace to scope this response.
Args:
workspace_id: The workspace to scope this response to.
"""
self.scope_workspace = workspace_id
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
from sqlmodel import or_
query = super().apply_filter(query=query, table=table)
if self.scope_workspace:
scope_filter = or_(
getattr(table, "workspace_id") == self.scope_workspace,
getattr(table, "workspace_id").is_(None),
)
query = query.where(scope_filter)
return query
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/base/scoped.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
from sqlmodel import or_
query = super().apply_filter(query=query, table=table)
if self.scope_workspace:
scope_filter = or_(
getattr(table, "workspace_id") == self.scope_workspace,
getattr(table, "workspace_id").is_(None),
)
query = query.where(scope_filter)
return query
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_scope_workspace(self, workspace_id)
Set the workspace to scope this response.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
workspace_id |
UUID |
The workspace to scope this response to. |
required |
Source code in zenml/models/v2/base/scoped.py
def set_scope_workspace(self, workspace_id: UUID) -> None:
"""Set the workspace to scope this response.
Args:
workspace_id: The workspace to scope this response to.
"""
self.scope_workspace = workspace_id
WorkspaceScopedRequest (UserScopedRequest)
Base workspace-scoped request domain model.
Used as a base class for all domain models that are workspace-scoped.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedRequest(UserScopedRequest):
"""Base workspace-scoped request domain model.
Used as a base class for all domain models that are workspace-scoped.
"""
workspace: UUID = Field(
title="The workspace to which this resource belongs."
)
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for workspace scoped models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata["workspace_id"] = self.workspace
return metadata
get_analytics_metadata(self)
Fetches the analytics metadata for workspace scoped models.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
The analytics metadata. |
Source code in zenml/models/v2/base/scoped.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Fetches the analytics metadata for workspace scoped models.
Returns:
The analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata["workspace_id"] = self.workspace
return metadata
WorkspaceScopedResponse (UserScopedResponse[~WorkspaceBody, ~WorkspaceMetadata, ~WorkspaceResources], Generic)
Base workspace-scoped domain model.
Used as a base class for all domain models that are workspace-scoped.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedResponse(
UserScopedResponse[WorkspaceBody, WorkspaceMetadata, WorkspaceResources],
Generic[WorkspaceBody, WorkspaceMetadata, WorkspaceResources],
):
"""Base workspace-scoped domain model.
Used as a base class for all domain models that are workspace-scoped.
"""
# Body and metadata properties
@property
def workspace(self) -> "WorkspaceResponse":
"""The workspace property.
Returns:
the value of the property.
"""
return self.get_metadata().workspace
workspace: WorkspaceResponse
property
readonly
The workspace property.
Returns:
Type | Description |
---|---|
WorkspaceResponse |
the value of the property. |
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponseBody (UserScopedResponseBody)
Base workspace-scoped body.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedResponseBody(UserScopedResponseBody):
"""Base workspace-scoped body."""
WorkspaceScopedResponseMetadata (UserScopedResponseMetadata)
Base workspace-scoped metadata.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedResponseMetadata(UserScopedResponseMetadata):
"""Base workspace-scoped metadata."""
workspace: "WorkspaceResponse" = Field(
title="The workspace of this resource."
)
WorkspaceScopedResponseResources (UserScopedResponseResources)
Base workspace-scoped resources.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedResponseResources(UserScopedResponseResources):
"""Base workspace-scoped resources."""
WorkspaceScopedResponse[ActionResponseBody, ActionResponseMetadata, ActionResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ArtifactVersionResponseBody, ArtifactVersionResponseMetadata, ArtifactVersionResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[CodeRepositoryResponseBody, CodeRepositoryResponseMetadata, CodeRepositoryResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ComponentResponseBody, ComponentResponseMetadata, ComponentResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[EventSourceResponseBody, EventSourceResponseMetadata, EventSourceResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ModelResponseBody, ModelResponseMetadata, ModelResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ModelVersionResponseBody, ModelVersionResponseMetadata, ModelVersionResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[PipelineBuildResponseBody, PipelineBuildResponseMetadata, PipelineBuildResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[PipelineDeploymentResponseBody, PipelineDeploymentResponseMetadata, PipelineDeploymentResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[PipelineResponseBody, PipelineResponseMetadata, PipelineResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[PipelineRunResponseBody, PipelineRunResponseMetadata, PipelineRunResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[RunMetadataResponseBody, RunMetadataResponseMetadata, RunMetadataResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[RunTemplateResponseBody, RunTemplateResponseMetadata, RunTemplateResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ScheduleResponseBody, ScheduleResponseMetadata, ScheduleResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[SecretResponseBody, SecretResponseMetadata, SecretResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ServiceConnectorResponseBody, ServiceConnectorResponseMetadata, ServiceConnectorResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[ServiceResponseBody, ServiceResponseMetadata, ServiceResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[StackResponseBody, StackResponseMetadata, StackResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[StepRunResponseBody, StepRunResponseMetadata, StepRunResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedResponse[TriggerResponseBody, TriggerResponseMetadata, TriggerResponseResources] (WorkspaceScopedResponse)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceScopedTaggableFilter (WorkspaceScopedFilter)
Model to enable advanced scoping with workspace and tagging.
Source code in zenml/models/v2/base/scoped.py
class WorkspaceScopedTaggableFilter(WorkspaceScopedFilter):
"""Model to enable advanced scoping with workspace and tagging."""
tag: Optional[str] = Field(
description="Tag to apply to the filter query.", default=None
)
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"tag",
]
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
from zenml.zen_stores.schemas import TagResourceSchema
query = super().apply_filter(query=query, table=table)
if self.tag:
query = (
query.join(getattr(table, "tags"))
.join(TagResourceSchema.tag)
.distinct()
)
return query
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom tag filters.
Returns:
A list of custom filters.
"""
from zenml.zen_stores.schemas import TagSchema
custom_filters = super().get_custom_filters()
if self.tag:
custom_filters.append(
self.generate_custom_query_conditions_for_column(
value=self.tag, table=TagSchema, column="name"
)
)
return custom_filters
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/base/scoped.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
from zenml.zen_stores.schemas import TagResourceSchema
query = super().apply_filter(query=query, table=table)
if self.tag:
query = (
query.join(getattr(table, "tags"))
.join(TagResourceSchema.tag)
.distinct()
)
return query
get_custom_filters(self)
Get custom tag filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/base/scoped.py
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom tag filters.
Returns:
A list of custom filters.
"""
from zenml.zen_stores.schemas import TagSchema
custom_filters = super().get_custom_filters()
if self.tag:
custom_filters.append(
self.generate_custom_query_conditions_for_column(
value=self.tag, table=TagSchema, column="name"
)
)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/base/scoped.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
core
special
action
Collection of all models concerning actions.
ActionFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all actions.
Source code in zenml/models/v2/core/action.py
class ActionFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all actions."""
name: Optional[str] = Field(
default=None,
description="Name of the action.",
)
flavor: Optional[str] = Field(
default=None,
title="The flavor of the action.",
)
plugin_subtype: Optional[str] = Field(
default=None,
title="The subtype of the action.",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/action.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ActionRequest (WorkspaceScopedRequest)
Model for creating a new action.
Source code in zenml/models/v2/core/action.py
class ActionRequest(WorkspaceScopedRequest):
"""Model for creating a new action."""
name: str = Field(
title="The name of the action.", max_length=STR_FIELD_MAX_LENGTH
)
description: str = Field(
default="",
title="The description of the action",
max_length=STR_FIELD_MAX_LENGTH,
)
flavor: str = Field(
title="The flavor of the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
plugin_subtype: PluginSubType = Field(
title="The subtype of the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Dict[str, Any] = Field(
title="The configuration for the action.",
)
service_account_id: UUID = Field(
title="The service account that is used to execute the action.",
)
auth_window: Optional[int] = Field(
default=None,
title="The time window in minutes for which the service account is "
"authorized to execute the action. Set this to 0 to authorize the "
"service account indefinitely (not recommended). If not set, a "
"default value defined for each individual action type is used.",
)
ActionResponse (WorkspaceScopedResponse[ActionResponseBody, ActionResponseMetadata, ActionResponseResources])
Response model for actions.
Source code in zenml/models/v2/core/action.py
class ActionResponse(
WorkspaceScopedResponse[
ActionResponseBody, ActionResponseMetadata, ActionResponseResources
]
):
"""Response model for actions."""
name: str = Field(
title="The name of the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "ActionResponse":
"""Get the hydrated version of this action.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_action(self.id)
# Body and metadata properties
@property
def flavor(self) -> str:
"""The `flavor` property.
Returns:
the value of the property.
"""
return self.get_body().flavor
@property
def plugin_subtype(self) -> PluginSubType:
"""The `plugin_subtype` property.
Returns:
the value of the property.
"""
return self.get_body().plugin_subtype
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def auth_window(self) -> int:
"""The `auth_window` property.
Returns:
the value of the property.
"""
return self.get_metadata().auth_window
@property
def configuration(self) -> Dict[str, Any]:
"""The `configuration` property.
Returns:
the value of the property.
"""
return self.get_metadata().configuration
def set_configuration(self, configuration: Dict[str, Any]) -> None:
"""Set the `configuration` property.
Args:
configuration: The value to set.
"""
self.get_metadata().configuration = configuration
# Resource properties
@property
def service_account(self) -> "UserResponse":
"""The `service_account` property.
Returns:
the value of the property.
"""
return self.get_resources().service_account
auth_window: int
property
readonly
The auth_window
property.
Returns:
Type | Description |
---|---|
int |
the value of the property. |
configuration: Dict[str, Any]
property
readonly
The configuration
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
flavor: str
property
readonly
The flavor
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
plugin_subtype: PluginSubType
property
readonly
The plugin_subtype
property.
Returns:
Type | Description |
---|---|
PluginSubType |
the value of the property. |
service_account: UserResponse
property
readonly
The service_account
property.
Returns:
Type | Description |
---|---|
UserResponse |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this action.
Returns:
Type | Description |
---|---|
ActionResponse |
An instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/action.py
def get_hydrated_version(self) -> "ActionResponse":
"""Get the hydrated version of this action.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_action(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/action.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_configuration(self, configuration)
Set the configuration
property.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
configuration |
Dict[str, Any] |
The value to set. |
required |
Source code in zenml/models/v2/core/action.py
def set_configuration(self, configuration: Dict[str, Any]) -> None:
"""Set the `configuration` property.
Args:
configuration: The value to set.
"""
self.get_metadata().configuration = configuration
ActionResponseBody (WorkspaceScopedResponseBody)
Response body for actions.
Source code in zenml/models/v2/core/action.py
class ActionResponseBody(WorkspaceScopedResponseBody):
"""Response body for actions."""
flavor: str = Field(
title="The flavor of the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
plugin_subtype: PluginSubType = Field(
title="The subtype of the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
ActionResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for actions.
Source code in zenml/models/v2/core/action.py
class ActionResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for actions."""
description: str = Field(
default="",
title="The description of the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Dict[str, Any] = Field(
title="The configuration for the action.",
)
auth_window: int = Field(
title="The time window in minutes for which the service account is "
"authorized to execute the action."
)
ActionResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the action entity.
Source code in zenml/models/v2/core/action.py
class ActionResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the action entity."""
service_account: UserResponse = Field(
title="The service account that is used to execute the action.",
)
ActionUpdate (BaseUpdate)
Update model for actions.
Source code in zenml/models/v2/core/action.py
class ActionUpdate(BaseUpdate):
"""Update model for actions."""
name: Optional[str] = Field(
default=None,
title="The new name for the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The new description for the action.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Optional[Dict[str, Any]] = Field(
default=None,
title="The configuration for the action.",
)
service_account_id: Optional[UUID] = Field(
default=None,
title="The service account that is used to execute the action.",
)
auth_window: Optional[int] = Field(
default=None,
title="The time window in minutes for which the service account is "
"authorized to execute the action. Set this to 0 to authorize the "
"service account indefinitely (not recommended). If not set, a "
"default value defined for each individual action type is used.",
)
@classmethod
def from_response(cls, response: "ActionResponse") -> "ActionUpdate":
"""Create an update model from a response model.
Args:
response: The response model to create the update model from.
Returns:
The update model.
"""
return ActionUpdate(
configuration=copy.deepcopy(response.configuration),
)
from_response(response)
classmethod
Create an update model from a response model.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
response |
ActionResponse |
The response model to create the update model from. |
required |
Returns:
Type | Description |
---|---|
ActionUpdate |
The update model. |
Source code in zenml/models/v2/core/action.py
@classmethod
def from_response(cls, response: "ActionResponse") -> "ActionUpdate":
"""Create an update model from a response model.
Args:
response: The response model to create the update model from.
Returns:
The update model.
"""
return ActionUpdate(
configuration=copy.deepcopy(response.configuration),
)
action_flavor
Action flavor model definitions.
ActionFlavorResponse (BasePluginFlavorResponse[ActionFlavorResponseBody, ActionFlavorResponseMetadata, ActionFlavorResponseResources])
Response model for Action Flavors.
Source code in zenml/models/v2/core/action_flavor.py
class ActionFlavorResponse(
BasePluginFlavorResponse[
ActionFlavorResponseBody,
ActionFlavorResponseMetadata,
ActionFlavorResponseResources,
]
):
"""Response model for Action Flavors."""
# Body and metadata properties
@property
def config_schema(self) -> Dict[str, Any]:
"""The `source_config_schema` property.
Returns:
the value of the property.
"""
return self.get_metadata().config_schema
config_schema: Dict[str, Any]
property
readonly
The source_config_schema
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/action_flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ActionFlavorResponseBody (BasePluginResponseBody)
Response body for action flavors.
Source code in zenml/models/v2/core/action_flavor.py
class ActionFlavorResponseBody(BasePluginResponseBody):
"""Response body for action flavors."""
ActionFlavorResponseMetadata (BasePluginResponseMetadata)
Response metadata for action flavors.
Source code in zenml/models/v2/core/action_flavor.py
class ActionFlavorResponseMetadata(BasePluginResponseMetadata):
"""Response metadata for action flavors."""
config_schema: Dict[str, Any]
ActionFlavorResponseResources (BasePluginResponseResources)
Response resources for action flavors.
Source code in zenml/models/v2/core/action_flavor.py
class ActionFlavorResponseResources(BasePluginResponseResources):
"""Response resources for action flavors."""
api_key
Models representing API keys.
APIKey (BaseModel)
Encoded model for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKey(BaseModel):
"""Encoded model for API keys."""
id: UUID
key: str
@classmethod
def decode_api_key(cls, encoded_key: str) -> "APIKey":
"""Decodes an API key from a base64 string.
Args:
encoded_key: The encoded API key.
Returns:
The decoded API key.
Raises:
ValueError: If the key is not valid.
"""
if encoded_key.startswith(ZENML_API_KEY_PREFIX):
encoded_key = encoded_key[len(ZENML_API_KEY_PREFIX) :]
try:
json_key = b64_decode(encoded_key)
return cls.model_validate_json(json_key)
except Exception:
raise ValueError("Invalid API key.")
def encode(self) -> str:
"""Encodes the API key in a base64 string that includes the key ID and prefix.
Returns:
The encoded API key.
"""
encoded_key = b64_encode(self.model_dump_json())
return f"{ZENML_API_KEY_PREFIX}{encoded_key}"
decode_api_key(encoded_key)
classmethod
Decodes an API key from a base64 string.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
encoded_key |
str |
The encoded API key. |
required |
Returns:
Type | Description |
---|---|
APIKey |
The decoded API key. |
Exceptions:
Type | Description |
---|---|
ValueError |
If the key is not valid. |
Source code in zenml/models/v2/core/api_key.py
@classmethod
def decode_api_key(cls, encoded_key: str) -> "APIKey":
"""Decodes an API key from a base64 string.
Args:
encoded_key: The encoded API key.
Returns:
The decoded API key.
Raises:
ValueError: If the key is not valid.
"""
if encoded_key.startswith(ZENML_API_KEY_PREFIX):
encoded_key = encoded_key[len(ZENML_API_KEY_PREFIX) :]
try:
json_key = b64_decode(encoded_key)
return cls.model_validate_json(json_key)
except Exception:
raise ValueError("Invalid API key.")
encode(self)
Encodes the API key in a base64 string that includes the key ID and prefix.
Returns:
Type | Description |
---|---|
str |
The encoded API key. |
Source code in zenml/models/v2/core/api_key.py
def encode(self) -> str:
"""Encodes the API key in a base64 string that includes the key ID and prefix.
Returns:
The encoded API key.
"""
encoded_key = b64_encode(self.model_dump_json())
return f"{ZENML_API_KEY_PREFIX}{encoded_key}"
APIKeyFilter (BaseFilter)
Filter model for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKeyFilter(BaseFilter):
"""Filter model for API keys."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*BaseFilter.FILTER_EXCLUDE_FIELDS,
"service_account",
]
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*BaseFilter.CLI_EXCLUDE_FIELDS,
"service_account",
]
service_account: Optional[UUID] = Field(
default=None,
description="The service account to scope this query to.",
)
name: Optional[str] = Field(
default=None,
description="Name of the API key",
)
description: Optional[str] = Field(
default=None,
title="Filter by the API key description.",
)
active: Optional[Union[bool, str]] = Field(
default=None,
title="Whether the API key is active.",
union_mode="left_to_right",
)
last_login: Optional[Union[datetime, str]] = Field(
default=None,
title="Time when the API key was last used to log in.",
union_mode="left_to_right",
)
last_rotated: Optional[Union[datetime, str]] = Field(
default=None,
title="Time when the API key was last rotated.",
union_mode="left_to_right",
)
def set_service_account(self, service_account_id: UUID) -> None:
"""Set the service account by which to scope this query.
Args:
service_account_id: The service account ID.
"""
self.service_account = service_account_id
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Override to apply the service account scope as an additional filter.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
if self.service_account:
scope_filter = (
getattr(table, "service_account_id") == self.service_account
)
query = query.where(scope_filter)
return query
apply_filter(self, query, table)
Override to apply the service account scope as an additional filter.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/core/api_key.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Override to apply the service account scope as an additional filter.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
if self.service_account:
scope_filter = (
getattr(table, "service_account_id") == self.service_account
)
query = query.where(scope_filter)
return query
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/api_key.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_service_account(self, service_account_id)
Set the service account by which to scope this query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
service_account_id |
UUID |
The service account ID. |
required |
Source code in zenml/models/v2/core/api_key.py
def set_service_account(self, service_account_id: UUID) -> None:
"""Set the service account by which to scope this query.
Args:
service_account_id: The service account ID.
"""
self.service_account = service_account_id
APIKeyInternalResponse (APIKeyResponse)
Response model for API keys used internally.
Source code in zenml/models/v2/core/api_key.py
class APIKeyInternalResponse(APIKeyResponse):
"""Response model for API keys used internally."""
previous_key: Optional[str] = Field(
default=None,
title="The previous API key. Only set if the key was rotated.",
)
def verify_key(
self,
key: str,
) -> bool:
"""Verifies a given key against the stored (hashed) key(s).
Args:
key: Input key to be verified.
Returns:
True if the keys match.
"""
# even when the hashed key is not set, we still want to execute
# the hash verification to protect against response discrepancy
# attacks (https://cwe.mitre.org/data/definitions/204.html)
key_hash: Optional[str] = None
context = CryptContext(schemes=["bcrypt"], deprecated="auto")
if self.key is not None and self.active:
key_hash = self.key
result = context.verify(key, key_hash)
# same for the previous key, if set and if it's still valid
key_hash = None
if (
self.previous_key is not None
and self.last_rotated is not None
and self.active
and self.retain_period_minutes > 0
):
# check if the previous key is still valid
if datetime.utcnow() - self.last_rotated < timedelta(
minutes=self.retain_period_minutes
):
key_hash = self.previous_key
previous_result = context.verify(key, key_hash)
return result or previous_result
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/api_key.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
verify_key(self, key)
Verifies a given key against the stored (hashed) key(s).
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key |
str |
Input key to be verified. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the keys match. |
Source code in zenml/models/v2/core/api_key.py
def verify_key(
self,
key: str,
) -> bool:
"""Verifies a given key against the stored (hashed) key(s).
Args:
key: Input key to be verified.
Returns:
True if the keys match.
"""
# even when the hashed key is not set, we still want to execute
# the hash verification to protect against response discrepancy
# attacks (https://cwe.mitre.org/data/definitions/204.html)
key_hash: Optional[str] = None
context = CryptContext(schemes=["bcrypt"], deprecated="auto")
if self.key is not None and self.active:
key_hash = self.key
result = context.verify(key, key_hash)
# same for the previous key, if set and if it's still valid
key_hash = None
if (
self.previous_key is not None
and self.last_rotated is not None
and self.active
and self.retain_period_minutes > 0
):
# check if the previous key is still valid
if datetime.utcnow() - self.last_rotated < timedelta(
minutes=self.retain_period_minutes
):
key_hash = self.previous_key
previous_result = context.verify(key, key_hash)
return result or previous_result
APIKeyInternalUpdate (APIKeyUpdate)
Update model for API keys used internally.
Source code in zenml/models/v2/core/api_key.py
class APIKeyInternalUpdate(APIKeyUpdate):
"""Update model for API keys used internally."""
update_last_login: bool = Field(
default=False,
title="Whether to update the last login timestamp.",
)
APIKeyRequest (BaseRequest)
Request model for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKeyRequest(BaseRequest):
"""Request model for API keys."""
name: str = Field(
title="The name of the API Key.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The description of the API Key.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
APIKeyResponse (BaseIdentifiedResponse[APIKeyResponseBody, APIKeyResponseMetadata, APIKeyResponseResources])
Response model for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKeyResponse(
BaseIdentifiedResponse[
APIKeyResponseBody, APIKeyResponseMetadata, APIKeyResponseResources
]
):
"""Response model for API keys."""
name: str = Field(
title="The name of the API Key.",
max_length=STR_FIELD_MAX_LENGTH,
)
_warn_on_response_updates = False
def get_hydrated_version(self) -> "APIKeyResponse":
"""Get the hydrated version of this API key.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_api_key(
service_account_id=self.service_account.id,
api_key_name_or_id=self.id,
)
# Helper functions
def set_key(self, key: str) -> None:
"""Sets the API key and encodes it.
Args:
key: The API key value to be set.
"""
self.get_body().key = APIKey(id=self.id, key=key).encode()
# Body and metadata properties
@property
def key(self) -> Optional[str]:
"""The `key` property.
Returns:
the value of the property.
"""
return self.get_body().key
@property
def active(self) -> bool:
"""The `active` property.
Returns:
the value of the property.
"""
return self.get_body().active
@property
def service_account(self) -> "ServiceAccountResponse":
"""The `service_account` property.
Returns:
the value of the property.
"""
return self.get_body().service_account
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def retain_period_minutes(self) -> int:
"""The `retain_period_minutes` property.
Returns:
the value of the property.
"""
return self.get_metadata().retain_period_minutes
@property
def last_login(self) -> Optional[datetime]:
"""The `last_login` property.
Returns:
the value of the property.
"""
return self.get_metadata().last_login
@property
def last_rotated(self) -> Optional[datetime]:
"""The `last_rotated` property.
Returns:
the value of the property.
"""
return self.get_metadata().last_rotated
active: bool
property
readonly
The active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
key: Optional[str]
property
readonly
The key
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
last_login: Optional[datetime.datetime]
property
readonly
The last_login
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
last_rotated: Optional[datetime.datetime]
property
readonly
The last_rotated
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
retain_period_minutes: int
property
readonly
The retain_period_minutes
property.
Returns:
Type | Description |
---|---|
int |
the value of the property. |
service_account: ServiceAccountResponse
property
readonly
The service_account
property.
Returns:
Type | Description |
---|---|
ServiceAccountResponse |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this API key.
Returns:
Type | Description |
---|---|
APIKeyResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/api_key.py
def get_hydrated_version(self) -> "APIKeyResponse":
"""Get the hydrated version of this API key.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_api_key(
service_account_id=self.service_account.id,
api_key_name_or_id=self.id,
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/api_key.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_key(self, key)
Sets the API key and encodes it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key |
str |
The API key value to be set. |
required |
Source code in zenml/models/v2/core/api_key.py
def set_key(self, key: str) -> None:
"""Sets the API key and encodes it.
Args:
key: The API key value to be set.
"""
self.get_body().key = APIKey(id=self.id, key=key).encode()
APIKeyResponseBody (BaseDatedResponseBody)
Response body for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKeyResponseBody(BaseDatedResponseBody):
"""Response body for API keys."""
key: Optional[str] = Field(
default=None,
title="The API key. Only set immediately after creation or rotation.",
)
active: bool = Field(
default=True,
title="Whether the API key is active.",
)
service_account: "ServiceAccountResponse" = Field(
title="The service account associated with this API key."
)
APIKeyResponseMetadata (BaseResponseMetadata)
Response metadata for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKeyResponseMetadata(BaseResponseMetadata):
"""Response metadata for API keys."""
description: str = Field(
default="",
title="The description of the API Key.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
retain_period_minutes: int = Field(
title="Number of minutes for which the previous key is still valid "
"after it has been rotated.",
)
last_login: Optional[datetime] = Field(
default=None, title="Time when the API key was last used to log in."
)
last_rotated: Optional[datetime] = Field(
default=None, title="Time when the API key was last rotated."
)
APIKeyResponseResources (BaseResponseResources)
Class for all resource models associated with the APIKey entity.
Source code in zenml/models/v2/core/api_key.py
class APIKeyResponseResources(BaseResponseResources):
"""Class for all resource models associated with the APIKey entity."""
APIKeyRotateRequest (BaseModel)
Request model for API key rotation.
Source code in zenml/models/v2/core/api_key.py
class APIKeyRotateRequest(BaseModel):
"""Request model for API key rotation."""
retain_period_minutes: int = Field(
default=0,
title="Number of minutes for which the previous key is still valid "
"after it has been rotated.",
)
APIKeyUpdate (BaseUpdate)
Update model for API keys.
Source code in zenml/models/v2/core/api_key.py
class APIKeyUpdate(BaseUpdate):
"""Update model for API keys."""
name: Optional[str] = Field(
title="The name of the API Key.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
title="The description of the API Key.",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
active: Optional[bool] = Field(
title="Whether the API key is active.",
default=None,
)
artifact
Models representing artifacts.
ArtifactFilter (WorkspaceScopedTaggableFilter)
Model to enable advanced filtering of artifacts.
Source code in zenml/models/v2/core/artifact.py
class ArtifactFilter(WorkspaceScopedTaggableFilter):
"""Model to enable advanced filtering of artifacts."""
name: Optional[str] = None
has_custom_name: Optional[bool] = None
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/artifact.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ArtifactRequest (BaseRequest)
Artifact request model.
Source code in zenml/models/v2/core/artifact.py
class ArtifactRequest(BaseRequest):
"""Artifact request model."""
name: str = Field(
title="Name of the artifact.",
max_length=STR_FIELD_MAX_LENGTH,
)
has_custom_name: bool = Field(
title="Whether the name is custom (True) or auto-generated (False).",
default=False,
)
tags: Optional[List[str]] = Field(
title="Artifact tags.",
description="Should be a list of plain strings, e.g., ['tag1', 'tag2']",
default=None,
)
ArtifactResponse (BaseIdentifiedResponse[ArtifactResponseBody, ArtifactResponseMetadata, ArtifactResponseResources])
Artifact response model.
Source code in zenml/models/v2/core/artifact.py
class ArtifactResponse(
BaseIdentifiedResponse[
ArtifactResponseBody,
ArtifactResponseMetadata,
ArtifactResponseResources,
]
):
"""Artifact response model."""
def get_hydrated_version(self) -> "ArtifactResponse":
"""Get the hydrated version of this artifact.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_artifact(self.id)
name: str = Field(
title="Name of the output in the parent step.",
max_length=STR_FIELD_MAX_LENGTH,
)
# Body and metadata properties
@property
def tags(self) -> List[TagResponse]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_body().tags
@property
def latest_version_name(self) -> Optional[str]:
"""The `latest_version_name` property.
Returns:
the value of the property.
"""
return self.get_body().latest_version_name
@property
def latest_version_id(self) -> Optional[UUID]:
"""The `latest_version_id` property.
Returns:
the value of the property.
"""
return self.get_body().latest_version_id
@property
def has_custom_name(self) -> bool:
"""The `has_custom_name` property.
Returns:
the value of the property.
"""
return self.get_metadata().has_custom_name
# Helper methods
@property
def versions(self) -> Dict[str, "ArtifactVersionResponse"]:
"""Get a list of all versions of this artifact.
Returns:
A list of all versions of this artifact.
"""
from zenml.client import Client
responses = Client().list_artifact_versions(name=self.name)
return {str(response.version): response for response in responses}
has_custom_name: bool
property
readonly
The has_custom_name
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
latest_version_id: Optional[uuid.UUID]
property
readonly
The latest_version_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
latest_version_name: Optional[str]
property
readonly
The latest_version_name
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
tags: List[zenml.models.v2.core.tag.TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.tag.TagResponse] |
the value of the property. |
versions: Dict[str, ArtifactVersionResponse]
property
readonly
Get a list of all versions of this artifact.
Returns:
Type | Description |
---|---|
Dict[str, ArtifactVersionResponse] |
A list of all versions of this artifact. |
get_hydrated_version(self)
Get the hydrated version of this artifact.
Returns:
Type | Description |
---|---|
ArtifactResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/artifact.py
def get_hydrated_version(self) -> "ArtifactResponse":
"""Get the hydrated version of this artifact.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_artifact(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/artifact.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ArtifactResponseBody (BaseDatedResponseBody)
Response body for artifacts.
Source code in zenml/models/v2/core/artifact.py
class ArtifactResponseBody(BaseDatedResponseBody):
"""Response body for artifacts."""
tags: List[TagResponse] = Field(
title="Tags associated with the model",
)
latest_version_name: Optional[str] = None
latest_version_id: Optional[UUID] = None
ArtifactResponseMetadata (BaseResponseMetadata)
Response metadata for artifacts.
Source code in zenml/models/v2/core/artifact.py
class ArtifactResponseMetadata(BaseResponseMetadata):
"""Response metadata for artifacts."""
has_custom_name: bool = Field(
title="Whether the name is custom (True) or auto-generated (False).",
default=False,
)
ArtifactResponseResources (BaseResponseResources)
Class for all resource models associated with the Artifact Entity.
Source code in zenml/models/v2/core/artifact.py
class ArtifactResponseResources(BaseResponseResources):
"""Class for all resource models associated with the Artifact Entity."""
ArtifactUpdate (BaseModel)
Artifact update model.
Source code in zenml/models/v2/core/artifact.py
class ArtifactUpdate(BaseModel):
"""Artifact update model."""
name: Optional[str] = None
add_tags: Optional[List[str]] = None
remove_tags: Optional[List[str]] = None
has_custom_name: Optional[bool] = None
artifact_version
Models representing artifact versions.
ArtifactVersionFilter (WorkspaceScopedTaggableFilter)
Model to enable advanced filtering of artifact versions.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionFilter(WorkspaceScopedTaggableFilter):
"""Model to enable advanced filtering of artifact versions."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
"name",
"only_unused",
"has_custom_name",
"user",
"model",
"pipeline_run",
]
artifact_id: Optional[Union[UUID, str]] = Field(
default=None,
description="ID of the artifact to which this version belongs.",
union_mode="left_to_right",
)
name: Optional[str] = Field(
default=None,
description="Name of the artifact to which this version belongs.",
)
version: Optional[str] = Field(
default=None,
description="Version of the artifact",
)
version_number: Optional[Union[int, str]] = Field(
default=None,
description="Version of the artifact if it is an integer",
union_mode="left_to_right",
)
uri: Optional[str] = Field(
default=None,
description="Uri of the artifact",
)
materializer: Optional[str] = Field(
default=None,
description="Materializer used to produce the artifact",
)
type: Optional[str] = Field(
default=None,
description="Type of the artifact",
)
data_type: Optional[str] = Field(
default=None,
description="Datatype of the artifact",
)
artifact_store_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Artifact store for this artifact",
union_mode="left_to_right",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace for this artifact",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that produced this artifact",
union_mode="left_to_right",
)
only_unused: Optional[bool] = Field(
default=False, description="Filter only for unused artifacts"
)
has_custom_name: Optional[bool] = Field(
default=None,
description="Filter only artifacts with/without custom names.",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the artifact version.",
)
model: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the model that is associated with this "
"artifact version.",
)
pipeline_run: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of a pipeline run that is associated with this "
"artifact version.",
)
model_config = ConfigDict(protected_namespaces=())
def get_custom_filters(self) -> List[Union["ColumnElement[bool]"]]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_, or_, select
from zenml.zen_stores.schemas import (
ArtifactSchema,
ArtifactVersionSchema,
ModelSchema,
ModelVersionArtifactSchema,
PipelineRunSchema,
StepRunInputArtifactSchema,
StepRunOutputArtifactSchema,
StepRunSchema,
UserSchema,
)
if self.name:
value, filter_operator = self._resolve_operator(self.name)
filter_ = StrFilter(
operation=GenericFilterOps(filter_operator),
column="name",
value=value,
)
artifact_name_filter = and_(
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
filter_.generate_query_conditions(ArtifactSchema),
)
custom_filters.append(artifact_name_filter)
if self.only_unused:
unused_filter = and_(
ArtifactVersionSchema.id.notin_( # type: ignore[attr-defined]
select(StepRunOutputArtifactSchema.artifact_id)
),
ArtifactVersionSchema.id.notin_( # type: ignore[attr-defined]
select(StepRunInputArtifactSchema.artifact_id)
),
)
custom_filters.append(unused_filter)
if self.has_custom_name is not None:
custom_name_filter = and_(
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
ArtifactSchema.has_custom_name == self.has_custom_name,
)
custom_filters.append(custom_name_filter)
if self.user:
user_filter = and_(
ArtifactVersionSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.model:
model_filter = and_(
ArtifactVersionSchema.id
== ModelVersionArtifactSchema.artifact_version_id,
ModelVersionArtifactSchema.model_id == ModelSchema.id,
self.generate_name_or_id_query_conditions(
value=self.model, table=ModelSchema
),
)
custom_filters.append(model_filter)
if self.pipeline_run:
pipeline_run_filter = and_(
or_(
and_(
ArtifactVersionSchema.id
== StepRunOutputArtifactSchema.artifact_id,
StepRunOutputArtifactSchema.step_id
== StepRunSchema.id,
),
and_(
ArtifactVersionSchema.id
== StepRunInputArtifactSchema.artifact_id,
StepRunInputArtifactSchema.step_id == StepRunSchema.id,
),
),
StepRunSchema.pipeline_run_id == PipelineRunSchema.id,
self.generate_name_or_id_query_conditions(
value=self.pipeline_run, table=PipelineRunSchema
),
)
custom_filters.append(pipeline_run_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/artifact_version.py
def get_custom_filters(self) -> List[Union["ColumnElement[bool]"]]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_, or_, select
from zenml.zen_stores.schemas import (
ArtifactSchema,
ArtifactVersionSchema,
ModelSchema,
ModelVersionArtifactSchema,
PipelineRunSchema,
StepRunInputArtifactSchema,
StepRunOutputArtifactSchema,
StepRunSchema,
UserSchema,
)
if self.name:
value, filter_operator = self._resolve_operator(self.name)
filter_ = StrFilter(
operation=GenericFilterOps(filter_operator),
column="name",
value=value,
)
artifact_name_filter = and_(
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
filter_.generate_query_conditions(ArtifactSchema),
)
custom_filters.append(artifact_name_filter)
if self.only_unused:
unused_filter = and_(
ArtifactVersionSchema.id.notin_( # type: ignore[attr-defined]
select(StepRunOutputArtifactSchema.artifact_id)
),
ArtifactVersionSchema.id.notin_( # type: ignore[attr-defined]
select(StepRunInputArtifactSchema.artifact_id)
),
)
custom_filters.append(unused_filter)
if self.has_custom_name is not None:
custom_name_filter = and_(
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
ArtifactSchema.has_custom_name == self.has_custom_name,
)
custom_filters.append(custom_name_filter)
if self.user:
user_filter = and_(
ArtifactVersionSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.model:
model_filter = and_(
ArtifactVersionSchema.id
== ModelVersionArtifactSchema.artifact_version_id,
ModelVersionArtifactSchema.model_id == ModelSchema.id,
self.generate_name_or_id_query_conditions(
value=self.model, table=ModelSchema
),
)
custom_filters.append(model_filter)
if self.pipeline_run:
pipeline_run_filter = and_(
or_(
and_(
ArtifactVersionSchema.id
== StepRunOutputArtifactSchema.artifact_id,
StepRunOutputArtifactSchema.step_id
== StepRunSchema.id,
),
and_(
ArtifactVersionSchema.id
== StepRunInputArtifactSchema.artifact_id,
StepRunInputArtifactSchema.step_id == StepRunSchema.id,
),
),
StepRunSchema.pipeline_run_id == PipelineRunSchema.id,
self.generate_name_or_id_query_conditions(
value=self.pipeline_run, table=PipelineRunSchema
),
)
custom_filters.append(pipeline_run_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/artifact_version.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ArtifactVersionRequest (WorkspaceScopedRequest)
Request model for artifact versions.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionRequest(WorkspaceScopedRequest):
"""Request model for artifact versions."""
artifact_id: UUID = Field(
title="ID of the artifact to which this version belongs.",
)
version: Union[str, int] = Field(
title="Version of the artifact.", union_mode="left_to_right"
)
has_custom_name: bool = Field(
title="Whether the name is custom (True) or auto-generated (False).",
default=False,
)
type: ArtifactType = Field(title="Type of the artifact.")
artifact_store_id: Optional[UUID] = Field(
title="ID of the artifact store in which this artifact is stored.",
default=None,
)
uri: str = Field(
title="URI of the artifact.", max_length=TEXT_FIELD_MAX_LENGTH
)
materializer: SourceWithValidator = Field(
title="Materializer class to use for this artifact.",
)
data_type: SourceWithValidator = Field(
title="Data type of the artifact.",
)
tags: Optional[List[str]] = Field(
title="Tags of the artifact.",
description="Should be a list of plain strings, e.g., ['tag1', 'tag2']",
default=None,
)
visualizations: Optional[List["ArtifactVisualizationRequest"]] = Field(
default=None, title="Visualizations of the artifact."
)
@field_validator("version")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum str length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
str_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum str length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/artifact_version.py
@field_validator("version")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum str length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
ArtifactVersionResponse (WorkspaceScopedResponse[ArtifactVersionResponseBody, ArtifactVersionResponseMetadata, ArtifactVersionResponseResources])
Response model for artifact versions.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionResponse(
WorkspaceScopedResponse[
ArtifactVersionResponseBody,
ArtifactVersionResponseMetadata,
ArtifactVersionResponseResources,
]
):
"""Response model for artifact versions."""
def get_hydrated_version(self) -> "ArtifactVersionResponse":
"""Get the hydrated version of this artifact version.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_artifact_version(self.id)
# Body and metadata properties
@property
def artifact(self) -> "ArtifactResponse":
"""The `artifact` property.
Returns:
the value of the property.
"""
return self.get_body().artifact
@property
def version(self) -> Union[str, int]:
"""The `version` property.
Returns:
the value of the property.
"""
return self.get_body().version
@property
def uri(self) -> str:
"""The `uri` property.
Returns:
the value of the property.
"""
return self.get_body().uri
@property
def type(self) -> ArtifactType:
"""The `type` property.
Returns:
the value of the property.
"""
return self.get_body().type
@property
def tags(self) -> List[TagResponse]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_body().tags
@property
def producer_pipeline_run_id(self) -> Optional[UUID]:
"""The `producer_pipeline_run_id` property.
Returns:
the value of the property.
"""
return self.get_body().producer_pipeline_run_id
@property
def artifact_store_id(self) -> Optional[UUID]:
"""The `artifact_store_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().artifact_store_id
@property
def producer_step_run_id(self) -> Optional[UUID]:
"""The `producer_step_run_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().producer_step_run_id
@property
def visualizations(
self,
) -> Optional[List["ArtifactVisualizationResponse"]]:
"""The `visualizations` property.
Returns:
the value of the property.
"""
return self.get_metadata().visualizations
@property
def run_metadata(self) -> Dict[str, "RunMetadataResponse"]:
"""The `metadata` property.
Returns:
the value of the property.
"""
return self.get_metadata().run_metadata
@property
def materializer(self) -> Source:
"""The `materializer` property.
Returns:
the value of the property.
"""
return self.get_body().materializer
@property
def data_type(self) -> Source:
"""The `data_type` property.
Returns:
the value of the property.
"""
return self.get_body().data_type
# Helper methods
@property
def name(self) -> str:
"""The `name` property.
Returns:
the value of the property.
"""
return self.artifact.name
@property
def step(self) -> "StepRunResponse":
"""Get the step that produced this artifact.
Returns:
The step that produced this artifact.
"""
from zenml.artifacts.utils import get_producer_step_of_artifact
return get_producer_step_of_artifact(self)
@property
def run(self) -> "PipelineRunResponse":
"""Get the pipeline run that produced this artifact.
Returns:
The pipeline run that produced this artifact.
"""
from zenml.client import Client
return Client().get_pipeline_run(self.step.pipeline_run_id)
def load(self) -> Any:
"""Materializes (loads) the data stored in this artifact.
Returns:
The materialized data.
"""
from zenml.artifacts.utils import load_artifact_from_response
return load_artifact_from_response(self)
def download_files(self, path: str, overwrite: bool = False) -> None:
"""Downloads data for an artifact with no materializing.
Any artifacts will be saved as a zip file to the given path.
Args:
path: The path to save the binary data to.
overwrite: Whether to overwrite the file if it already exists.
Raises:
ValueError: If the path does not end with '.zip'.
"""
if not path.endswith(".zip"):
raise ValueError(
"The path should end with '.zip' to save the binary data."
)
from zenml.artifacts.utils import (
download_artifact_files_from_response,
)
download_artifact_files_from_response(
self,
path=path,
overwrite=overwrite,
)
def read(self) -> Any:
"""(Deprecated) Materializes (loads) the data stored in this artifact.
Returns:
The materialized data.
"""
logger.warning(
"`artifact.read()` is deprecated and will be removed in a future "
"release. Please use `artifact.load()` instead."
)
return self.load()
def visualize(self, title: Optional[str] = None) -> None:
"""Visualize the artifact in notebook environments.
Args:
title: Optional title to show before the visualizations.
"""
from zenml.utils.visualization_utils import visualize_artifact
visualize_artifact(self, title=title)
artifact: ArtifactResponse
property
readonly
The artifact
property.
Returns:
Type | Description |
---|---|
ArtifactResponse |
the value of the property. |
artifact_store_id: Optional[uuid.UUID]
property
readonly
The artifact_store_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
data_type: Source
property
readonly
The data_type
property.
Returns:
Type | Description |
---|---|
Source |
the value of the property. |
materializer: Source
property
readonly
The materializer
property.
Returns:
Type | Description |
---|---|
Source |
the value of the property. |
name: str
property
readonly
The name
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
producer_pipeline_run_id: Optional[uuid.UUID]
property
readonly
The producer_pipeline_run_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
producer_step_run_id: Optional[uuid.UUID]
property
readonly
The producer_step_run_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
run: PipelineRunResponse
property
readonly
Get the pipeline run that produced this artifact.
Returns:
Type | Description |
---|---|
PipelineRunResponse |
The pipeline run that produced this artifact. |
run_metadata: Dict[str, RunMetadataResponse]
property
readonly
The metadata
property.
Returns:
Type | Description |
---|---|
Dict[str, RunMetadataResponse] |
the value of the property. |
step: StepRunResponse
property
readonly
Get the step that produced this artifact.
Returns:
Type | Description |
---|---|
StepRunResponse |
The step that produced this artifact. |
tags: List[zenml.models.v2.core.tag.TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.tag.TagResponse] |
the value of the property. |
type: ArtifactType
property
readonly
The type
property.
Returns:
Type | Description |
---|---|
ArtifactType |
the value of the property. |
uri: str
property
readonly
The uri
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
version: Union[str, int]
property
readonly
The version
property.
Returns:
Type | Description |
---|---|
Union[str, int] |
the value of the property. |
visualizations: Optional[List[ArtifactVisualizationResponse]]
property
readonly
The visualizations
property.
Returns:
Type | Description |
---|---|
Optional[List[ArtifactVisualizationResponse]] |
the value of the property. |
download_files(self, path, overwrite=False)
Downloads data for an artifact with no materializing.
Any artifacts will be saved as a zip file to the given path.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
path |
str |
The path to save the binary data to. |
required |
overwrite |
bool |
Whether to overwrite the file if it already exists. |
False |
Exceptions:
Type | Description |
---|---|
ValueError |
If the path does not end with '.zip'. |
Source code in zenml/models/v2/core/artifact_version.py
def download_files(self, path: str, overwrite: bool = False) -> None:
"""Downloads data for an artifact with no materializing.
Any artifacts will be saved as a zip file to the given path.
Args:
path: The path to save the binary data to.
overwrite: Whether to overwrite the file if it already exists.
Raises:
ValueError: If the path does not end with '.zip'.
"""
if not path.endswith(".zip"):
raise ValueError(
"The path should end with '.zip' to save the binary data."
)
from zenml.artifacts.utils import (
download_artifact_files_from_response,
)
download_artifact_files_from_response(
self,
path=path,
overwrite=overwrite,
)
get_hydrated_version(self)
Get the hydrated version of this artifact version.
Returns:
Type | Description |
---|---|
ArtifactVersionResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/artifact_version.py
def get_hydrated_version(self) -> "ArtifactVersionResponse":
"""Get the hydrated version of this artifact version.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_artifact_version(self.id)
load(self)
Materializes (loads) the data stored in this artifact.
Returns:
Type | Description |
---|---|
Any |
The materialized data. |
Source code in zenml/models/v2/core/artifact_version.py
def load(self) -> Any:
"""Materializes (loads) the data stored in this artifact.
Returns:
The materialized data.
"""
from zenml.artifacts.utils import load_artifact_from_response
return load_artifact_from_response(self)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/artifact_version.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
read(self)
(Deprecated) Materializes (loads) the data stored in this artifact.
Returns:
Type | Description |
---|---|
Any |
The materialized data. |
Source code in zenml/models/v2/core/artifact_version.py
def read(self) -> Any:
"""(Deprecated) Materializes (loads) the data stored in this artifact.
Returns:
The materialized data.
"""
logger.warning(
"`artifact.read()` is deprecated and will be removed in a future "
"release. Please use `artifact.load()` instead."
)
return self.load()
visualize(self, title=None)
Visualize the artifact in notebook environments.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
title |
Optional[str] |
Optional title to show before the visualizations. |
None |
Source code in zenml/models/v2/core/artifact_version.py
def visualize(self, title: Optional[str] = None) -> None:
"""Visualize the artifact in notebook environments.
Args:
title: Optional title to show before the visualizations.
"""
from zenml.utils.visualization_utils import visualize_artifact
visualize_artifact(self, title=title)
ArtifactVersionResponseBody (WorkspaceScopedResponseBody)
Response body for artifact versions.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionResponseBody(WorkspaceScopedResponseBody):
"""Response body for artifact versions."""
artifact: ArtifactResponse = Field(
title="Artifact to which this version belongs."
)
version: str = Field(title="Version of the artifact.")
uri: str = Field(
title="URI of the artifact.", max_length=TEXT_FIELD_MAX_LENGTH
)
type: ArtifactType = Field(title="Type of the artifact.")
materializer: SourceWithValidator = Field(
title="Materializer class to use for this artifact.",
)
data_type: SourceWithValidator = Field(
title="Data type of the artifact.",
)
tags: List[TagResponse] = Field(
title="Tags associated with the model",
)
producer_pipeline_run_id: Optional[UUID] = Field(
title="The ID of the pipeline run that generated this artifact version.",
default=None,
)
@field_validator("version")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum str length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
str_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum str length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/artifact_version.py
@field_validator("version")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum str length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
ArtifactVersionResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for artifact versions.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for artifact versions."""
artifact_store_id: Optional[UUID] = Field(
title="ID of the artifact store in which this artifact is stored.",
default=None,
)
producer_step_run_id: Optional[UUID] = Field(
title="ID of the step run that produced this artifact.",
default=None,
)
visualizations: Optional[List["ArtifactVisualizationResponse"]] = Field(
default=None, title="Visualizations of the artifact."
)
run_metadata: Dict[str, "RunMetadataResponse"] = Field(
default={}, title="Metadata of the artifact."
)
ArtifactVersionResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the artifact version entity.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the artifact version entity."""
ArtifactVersionUpdate (BaseModel)
Artifact version update model.
Source code in zenml/models/v2/core/artifact_version.py
class ArtifactVersionUpdate(BaseModel):
"""Artifact version update model."""
name: Optional[str] = None
add_tags: Optional[List[str]] = None
remove_tags: Optional[List[str]] = None
LazyArtifactVersionResponse (ArtifactVersionResponse)
Lazy artifact version response.
Used if the artifact version is accessed from the model in a pipeline context available only during pipeline compilation.
Source code in zenml/models/v2/core/artifact_version.py
class LazyArtifactVersionResponse(ArtifactVersionResponse):
"""Lazy artifact version response.
Used if the artifact version is accessed from the model in
a pipeline context available only during pipeline compilation.
"""
id: Optional[UUID] = None # type: ignore[assignment]
lazy_load_name: Optional[str] = None
lazy_load_version: Optional[str] = None
lazy_load_model: Model
def get_body(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError("Cannot access artifact body before pipeline runs.")
def get_metadata(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError(
"Cannot access artifact metadata before pipeline runs."
)
@property
def run_metadata(self) -> Dict[str, "RunMetadataResponse"]:
"""The `metadata` property in lazy loading mode.
Returns:
getter of lazy responses for internal use.
"""
from zenml.metadata.lazy_load import RunMetadataLazyGetter
return RunMetadataLazyGetter( # type: ignore[return-value]
self.lazy_load_model,
self.lazy_load_name,
self.lazy_load_version,
)
run_metadata: Dict[str, RunMetadataResponse]
property
readonly
The metadata
property in lazy loading mode.
Returns:
Type | Description |
---|---|
Dict[str, RunMetadataResponse] |
getter of lazy responses for internal use. |
get_body(self)
Protects from misuse of the lazy loader.
Exceptions:
Type | Description |
---|---|
RuntimeError |
always |
Source code in zenml/models/v2/core/artifact_version.py
def get_body(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError("Cannot access artifact body before pipeline runs.")
get_metadata(self)
Protects from misuse of the lazy loader.
Exceptions:
Type | Description |
---|---|
RuntimeError |
always |
Source code in zenml/models/v2/core/artifact_version.py
def get_metadata(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError(
"Cannot access artifact metadata before pipeline runs."
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/artifact_version.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
artifact_visualization
Models representing artifact visualizations.
ArtifactVisualizationRequest (BaseRequest)
Request model for artifact visualization.
Source code in zenml/models/v2/core/artifact_visualization.py
class ArtifactVisualizationRequest(BaseRequest):
"""Request model for artifact visualization."""
type: VisualizationType
uri: str
ArtifactVisualizationResponse (BaseIdentifiedResponse[ArtifactVisualizationResponseBody, ArtifactVisualizationResponseMetadata, ArtifactVisualizationResponseResources])
Response model for artifact visualizations.
Source code in zenml/models/v2/core/artifact_visualization.py
class ArtifactVisualizationResponse(
BaseIdentifiedResponse[
ArtifactVisualizationResponseBody,
ArtifactVisualizationResponseMetadata,
ArtifactVisualizationResponseResources,
]
):
"""Response model for artifact visualizations."""
def get_hydrated_version(self) -> "ArtifactVisualizationResponse":
"""Get the hydrated version of this artifact visualization.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_artifact_visualization(self.id)
# Body and metadata properties
@property
def type(self) -> VisualizationType:
"""The `type` property.
Returns:
the value of the property.
"""
return self.get_body().type
@property
def uri(self) -> str:
"""The `uri` property.
Returns:
the value of the property.
"""
return self.get_body().uri
@property
def artifact_version_id(self) -> UUID:
"""The `artifact_version_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().artifact_version_id
artifact_version_id: UUID
property
readonly
The artifact_version_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
type: VisualizationType
property
readonly
The type
property.
Returns:
Type | Description |
---|---|
VisualizationType |
the value of the property. |
uri: str
property
readonly
The uri
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this artifact visualization.
Returns:
Type | Description |
---|---|
ArtifactVisualizationResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/artifact_visualization.py
def get_hydrated_version(self) -> "ArtifactVisualizationResponse":
"""Get the hydrated version of this artifact visualization.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_artifact_visualization(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/artifact_visualization.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ArtifactVisualizationResponseBody (BaseDatedResponseBody)
Response body for artifact visualizations.
Source code in zenml/models/v2/core/artifact_visualization.py
class ArtifactVisualizationResponseBody(BaseDatedResponseBody):
"""Response body for artifact visualizations."""
type: VisualizationType
uri: str
ArtifactVisualizationResponseMetadata (BaseResponseMetadata)
Response metadata model for artifact visualizations.
Source code in zenml/models/v2/core/artifact_visualization.py
class ArtifactVisualizationResponseMetadata(BaseResponseMetadata):
"""Response metadata model for artifact visualizations."""
artifact_version_id: UUID
ArtifactVisualizationResponseResources (BaseResponseResources)
Class for all resource models associated with the artifact visualization.
Source code in zenml/models/v2/core/artifact_visualization.py
class ArtifactVisualizationResponseResources(BaseResponseResources):
"""Class for all resource models associated with the artifact visualization."""
code_reference
Models representing code references.
CodeReferenceRequest (BaseRequest)
Request model for code references.
Source code in zenml/models/v2/core/code_reference.py
class CodeReferenceRequest(BaseRequest):
"""Request model for code references."""
commit: str = Field(description="The commit of the code reference.")
subdirectory: str = Field(
description="The subdirectory of the code reference."
)
code_repository: UUID = Field(
description="The repository of the code reference."
)
CodeReferenceResponse (BaseIdentifiedResponse[CodeReferenceResponseBody, CodeReferenceResponseMetadata, CodeReferenceResponseResources])
Response model for code references.
Source code in zenml/models/v2/core/code_reference.py
class CodeReferenceResponse(
BaseIdentifiedResponse[
CodeReferenceResponseBody,
CodeReferenceResponseMetadata,
CodeReferenceResponseResources,
]
):
"""Response model for code references."""
def get_hydrated_version(self) -> "CodeReferenceResponse":
"""Get the hydrated version of this code reference.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_code_reference(self.id)
# Body and metadata properties
@property
def commit(self) -> str:
"""The `commit` property.
Returns:
the value of the property.
"""
return self.get_body().commit
@property
def subdirectory(self) -> str:
"""The `subdirectory` property.
Returns:
the value of the property.
"""
return self.get_body().subdirectory
@property
def code_repository(self) -> "CodeRepositoryResponse":
"""The `code_repository` property.
Returns:
the value of the property.
"""
return self.get_body().code_repository
code_repository: CodeRepositoryResponse
property
readonly
The code_repository
property.
Returns:
Type | Description |
---|---|
CodeRepositoryResponse |
the value of the property. |
commit: str
property
readonly
The commit
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
subdirectory: str
property
readonly
The subdirectory
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this code reference.
Returns:
Type | Description |
---|---|
CodeReferenceResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/code_reference.py
def get_hydrated_version(self) -> "CodeReferenceResponse":
"""Get the hydrated version of this code reference.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_code_reference(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/code_reference.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
CodeReferenceResponseBody (BaseDatedResponseBody)
Response body for code references.
Source code in zenml/models/v2/core/code_reference.py
class CodeReferenceResponseBody(BaseDatedResponseBody):
"""Response body for code references."""
commit: str = Field(description="The commit of the code reference.")
subdirectory: str = Field(
description="The subdirectory of the code reference."
)
code_repository: "CodeRepositoryResponse" = Field(
description="The repository of the code reference."
)
CodeReferenceResponseMetadata (BaseResponseMetadata)
Response metadata for code references.
Source code in zenml/models/v2/core/code_reference.py
class CodeReferenceResponseMetadata(BaseResponseMetadata):
"""Response metadata for code references."""
CodeReferenceResponseResources (BaseResponseResources)
Class for all resource models associated with the code reference entity.
Source code in zenml/models/v2/core/code_reference.py
class CodeReferenceResponseResources(BaseResponseResources):
"""Class for all resource models associated with the code reference entity."""
code_repository
Models representing code repositories.
CodeRepositoryFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all code repositories.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all code repositories."""
name: Optional[str] = Field(
description="Name of the code repository.",
default=None,
)
workspace_id: Optional[Union[UUID, str]] = Field(
description="Workspace of the code repository.",
default=None,
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
description="User that created the code repository.",
default=None,
union_mode="left_to_right",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/code_repository.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
CodeRepositoryRequest (WorkspaceScopedRequest)
Request model for code repositories.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryRequest(WorkspaceScopedRequest):
"""Request model for code repositories."""
name: str = Field(
title="The name of the code repository.",
max_length=STR_FIELD_MAX_LENGTH,
)
config: Dict[str, Any] = Field(
description="Configuration for the code repository."
)
source: Source = Field(description="The code repository source.")
logo_url: Optional[str] = Field(
description="Optional URL of a logo (png, jpg or svg) for the "
"code repository.",
default=None,
)
description: Optional[str] = Field(
description="Code repository description.",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
CodeRepositoryResponse (WorkspaceScopedResponse[CodeRepositoryResponseBody, CodeRepositoryResponseMetadata, CodeRepositoryResponseResources])
Response model for code repositories.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryResponse(
WorkspaceScopedResponse[
CodeRepositoryResponseBody,
CodeRepositoryResponseMetadata,
CodeRepositoryResponseResources,
]
):
"""Response model for code repositories."""
name: str = Field(
title="The name of the code repository.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "CodeRepositoryResponse":
"""Get the hydrated version of this code repository.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_code_repository(self.id)
# Body and metadata properties
@property
def source(self) -> Source:
"""The `source` property.
Returns:
the value of the property.
"""
return self.get_body().source
@property
def logo_url(self) -> Optional[str]:
"""The `logo_url` property.
Returns:
the value of the property.
"""
return self.get_body().logo_url
@property
def config(self) -> Dict[str, Any]:
"""The `config` property.
Returns:
the value of the property.
"""
return self.get_metadata().config
@property
def description(self) -> Optional[str]:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
config: Dict[str, Any]
property
readonly
The config
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
description: Optional[str]
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
logo_url: Optional[str]
property
readonly
The logo_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
source: Source
property
readonly
The source
property.
Returns:
Type | Description |
---|---|
Source |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this code repository.
Returns:
Type | Description |
---|---|
CodeRepositoryResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/code_repository.py
def get_hydrated_version(self) -> "CodeRepositoryResponse":
"""Get the hydrated version of this code repository.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_code_repository(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/code_repository.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
CodeRepositoryResponseBody (WorkspaceScopedResponseBody)
Response body for code repositories.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryResponseBody(WorkspaceScopedResponseBody):
"""Response body for code repositories."""
source: Source = Field(description="The code repository source.")
logo_url: Optional[str] = Field(
default=None,
description="Optional URL of a logo (png, jpg or svg) for the "
"code repository.",
)
CodeRepositoryResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for code repositories.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for code repositories."""
config: Dict[str, Any] = Field(
description="Configuration for the code repository."
)
description: Optional[str] = Field(
default=None,
description="Code repository description.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
CodeRepositoryResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the code repository entity.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the code repository entity."""
CodeRepositoryUpdate (BaseUpdate)
Update model for code repositories.
Source code in zenml/models/v2/core/code_repository.py
class CodeRepositoryUpdate(BaseUpdate):
"""Update model for code repositories."""
name: Optional[str] = Field(
title="The name of the code repository.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
config: Optional[Dict[str, Any]] = Field(
description="Configuration for the code repository.",
default=None,
)
source: Optional[SourceWithValidator] = Field(
description="The code repository source.", default=None
)
logo_url: Optional[str] = Field(
description="Optional URL of a logo (png, jpg or svg) for the "
"code repository.",
default=None,
)
description: Optional[str] = Field(
description="Code repository description.",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
component
Models representing components.
ComponentBase (BaseModel)
Base model for components.
Source code in zenml/models/v2/core/component.py
class ComponentBase(BaseModel):
"""Base model for components."""
name: str = Field(
title="The name of the stack component.",
max_length=STR_FIELD_MAX_LENGTH,
)
type: StackComponentType = Field(
title="The type of the stack component.",
)
flavor: str = Field(
title="The flavor of the stack component.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Dict[str, Any] = Field(
title="The stack component configuration.",
)
connector_resource_id: Optional[str] = Field(
default=None,
description="The ID of a specific resource instance to "
"gain access to through the connector",
)
labels: Optional[Dict[str, Any]] = Field(
default=None,
title="The stack component labels.",
)
component_spec_path: Optional[str] = Field(
default=None,
title="The path to the component spec used for mlstacks deployments.",
)
ComponentFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all ComponentModels.
The Component Model needs additional scoping. As such the _scope_user
field can be set to the user that is doing the filtering. The
generate_filter()
method of the baseclass is overwritten to include the
scoping.
Source code in zenml/models/v2/core/component.py
class ComponentFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all ComponentModels.
The Component Model needs additional scoping. As such the `_scope_user`
field can be set to the user that is doing the filtering. The
`generate_filter()` method of the baseclass is overwritten to include the
scoping.
"""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"scope_type",
"stack_id",
]
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.CLI_EXCLUDE_FIELDS,
"scope_type",
]
scope_type: Optional[str] = Field(
default=None,
description="The type to scope this query to.",
)
name: Optional[str] = Field(
default=None,
description="Name of the stack component",
)
flavor: Optional[str] = Field(
default=None,
description="Flavor of the stack component",
)
type: Optional[str] = Field(
default=None,
description="Type of the stack component",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the stack component",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User of the stack component",
union_mode="left_to_right",
)
connector_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Connector linked to the stack component",
union_mode="left_to_right",
)
stack_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Stack of the stack component",
union_mode="left_to_right",
)
def set_scope_type(self, component_type: str) -> None:
"""Set the type of component on which to perform the filtering to scope the response.
Args:
component_type: The type of component to scope the query to.
"""
self.scope_type = component_type
def generate_filter(
self, table: Type["SQLModel"]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Stack components can be scoped by type to narrow the search.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
"""
from sqlmodel import and_, or_
from zenml.zen_stores.schemas import (
StackComponentSchema,
StackCompositionSchema,
)
base_filter = super().generate_filter(table)
if self.scope_type:
type_filter = getattr(table, "type") == self.scope_type
return and_(base_filter, type_filter)
if self.stack_id:
operator = (
or_ if self.logical_operator == LogicalOperators.OR else and_
)
stack_filter = and_(
StackCompositionSchema.stack_id == self.stack_id,
StackCompositionSchema.component_id == StackComponentSchema.id,
)
base_filter = operator(base_filter, stack_filter)
return base_filter
generate_filter(self, table)
Generate the filter for the query.
Stack components can be scoped by type to narrow the search.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[SQLModel] |
The Table that is being queried from. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The filter expression for the query. |
Source code in zenml/models/v2/core/component.py
def generate_filter(
self, table: Type["SQLModel"]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Stack components can be scoped by type to narrow the search.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
"""
from sqlmodel import and_, or_
from zenml.zen_stores.schemas import (
StackComponentSchema,
StackCompositionSchema,
)
base_filter = super().generate_filter(table)
if self.scope_type:
type_filter = getattr(table, "type") == self.scope_type
return and_(base_filter, type_filter)
if self.stack_id:
operator = (
or_ if self.logical_operator == LogicalOperators.OR else and_
)
stack_filter = and_(
StackCompositionSchema.stack_id == self.stack_id,
StackCompositionSchema.component_id == StackComponentSchema.id,
)
base_filter = operator(base_filter, stack_filter)
return base_filter
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/component.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_scope_type(self, component_type)
Set the type of component on which to perform the filtering to scope the response.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_type |
str |
The type of component to scope the query to. |
required |
Source code in zenml/models/v2/core/component.py
def set_scope_type(self, component_type: str) -> None:
"""Set the type of component on which to perform the filtering to scope the response.
Args:
component_type: The type of component to scope the query to.
"""
self.scope_type = component_type
ComponentRequest (ComponentBase, WorkspaceScopedRequest)
Request model for components.
Source code in zenml/models/v2/core/component.py
class ComponentRequest(ComponentBase, WorkspaceScopedRequest):
"""Request model for components."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["type", "flavor"]
connector: Optional[UUID] = Field(
default=None,
title="The service connector linked to this stack component.",
)
@field_validator("name")
@classmethod
def name_cant_be_a_secret_reference(cls, name: str) -> str:
"""Validator to ensure that the given name is not a secret reference.
Args:
name: The name to validate.
Returns:
The name if it is not a secret reference.
Raises:
ValueError: If the name is a secret reference.
"""
if secret_utils.is_secret_reference(name):
raise ValueError(
"Passing the `name` attribute of a stack component as a "
"secret reference is not allowed."
)
return name
name_cant_be_a_secret_reference(name)
classmethod
Validator to ensure that the given name is not a secret reference.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name to validate. |
required |
Returns:
Type | Description |
---|---|
str |
The name if it is not a secret reference. |
Exceptions:
Type | Description |
---|---|
ValueError |
If the name is a secret reference. |
Source code in zenml/models/v2/core/component.py
@field_validator("name")
@classmethod
def name_cant_be_a_secret_reference(cls, name: str) -> str:
"""Validator to ensure that the given name is not a secret reference.
Args:
name: The name to validate.
Returns:
The name if it is not a secret reference.
Raises:
ValueError: If the name is a secret reference.
"""
if secret_utils.is_secret_reference(name):
raise ValueError(
"Passing the `name` attribute of a stack component as a "
"secret reference is not allowed."
)
return name
ComponentResponse (WorkspaceScopedResponse[ComponentResponseBody, ComponentResponseMetadata, ComponentResponseResources])
Response model for components.
Source code in zenml/models/v2/core/component.py
class ComponentResponse(
WorkspaceScopedResponse[
ComponentResponseBody,
ComponentResponseMetadata,
ComponentResponseResources,
]
):
"""Response model for components."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["type", "flavor"]
name: str = Field(
title="The name of the stack component.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Add the component labels to analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
if self.labels is not None:
metadata.update(
{
label[6:]: value
for label, value in self.labels.items()
if label.startswith("zenml:")
}
)
return metadata
def get_hydrated_version(self) -> "ComponentResponse":
"""Get the hydrated version of this component.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_stack_component(self.id)
# Body and metadata properties
@property
def type(self) -> StackComponentType:
"""The `type` property.
Returns:
the value of the property.
"""
return self.get_body().type
@property
def flavor(self) -> str:
"""The `flavor` property.
Returns:
the value of the property.
"""
return self.get_body().flavor
@property
def integration(self) -> Optional[str]:
"""The `integration` property.
Returns:
the value of the property.
"""
return self.get_body().integration
@property
def logo_url(self) -> Optional[str]:
"""The `logo_url` property.
Returns:
the value of the property.
"""
return self.get_body().logo_url
@property
def configuration(self) -> Dict[str, Any]:
"""The `configuration` property.
Returns:
the value of the property.
"""
return self.get_metadata().configuration
@property
def labels(self) -> Optional[Dict[str, Any]]:
"""The `labels` property.
Returns:
the value of the property.
"""
return self.get_metadata().labels
@property
def component_spec_path(self) -> Optional[str]:
"""The `component_spec_path` property.
Returns:
the value of the property.
"""
return self.get_metadata().component_spec_path
@property
def connector_resource_id(self) -> Optional[str]:
"""The `connector_resource_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().connector_resource_id
@property
def connector(self) -> Optional["ServiceConnectorResponse"]:
"""The `connector` property.
Returns:
the value of the property.
"""
return self.get_metadata().connector
component_spec_path: Optional[str]
property
readonly
The component_spec_path
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
configuration: Dict[str, Any]
property
readonly
The configuration
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
connector: Optional[ServiceConnectorResponse]
property
readonly
The connector
property.
Returns:
Type | Description |
---|---|
Optional[ServiceConnectorResponse] |
the value of the property. |
connector_resource_id: Optional[str]
property
readonly
The connector_resource_id
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
flavor: str
property
readonly
The flavor
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
integration: Optional[str]
property
readonly
The integration
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
labels: Optional[Dict[str, Any]]
property
readonly
The labels
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
logo_url: Optional[str]
property
readonly
The logo_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
type: StackComponentType
property
readonly
The type
property.
Returns:
Type | Description |
---|---|
StackComponentType |
the value of the property. |
get_analytics_metadata(self)
Add the component labels to analytics metadata.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
Dict of analytics metadata. |
Source code in zenml/models/v2/core/component.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Add the component labels to analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
if self.labels is not None:
metadata.update(
{
label[6:]: value
for label, value in self.labels.items()
if label.startswith("zenml:")
}
)
return metadata
get_hydrated_version(self)
Get the hydrated version of this component.
Returns:
Type | Description |
---|---|
ComponentResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/component.py
def get_hydrated_version(self) -> "ComponentResponse":
"""Get the hydrated version of this component.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_stack_component(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/component.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ComponentResponseBody (WorkspaceScopedResponseBody)
Response body for components.
Source code in zenml/models/v2/core/component.py
class ComponentResponseBody(WorkspaceScopedResponseBody):
"""Response body for components."""
type: StackComponentType = Field(
title="The type of the stack component.",
)
flavor: str = Field(
title="The flavor of the stack component.",
max_length=STR_FIELD_MAX_LENGTH,
)
integration: Optional[str] = Field(
default=None,
title="The name of the integration that the component's flavor "
"belongs to.",
max_length=STR_FIELD_MAX_LENGTH,
)
logo_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to a png,"
"svg or jpg can be attached.",
)
ComponentResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for components.
Source code in zenml/models/v2/core/component.py
class ComponentResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for components."""
configuration: Dict[str, Any] = Field(
title="The stack component configuration.",
)
labels: Optional[Dict[str, Any]] = Field(
default=None,
title="The stack component labels.",
)
component_spec_path: Optional[str] = Field(
default=None,
title="The path to the component spec used for mlstacks deployments.",
)
connector_resource_id: Optional[str] = Field(
default=None,
description="The ID of a specific resource instance to "
"gain access to through the connector",
)
connector: Optional["ServiceConnectorResponse"] = Field(
default=None,
title="The service connector linked to this stack component.",
)
ComponentResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the component entity.
Source code in zenml/models/v2/core/component.py
class ComponentResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the component entity."""
ComponentUpdate (BaseUpdate)
Update model for stack components.
Source code in zenml/models/v2/core/component.py
class ComponentUpdate(BaseUpdate):
"""Update model for stack components."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["type", "flavor"]
name: Optional[str] = Field(
title="The name of the stack component.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
type: Optional[StackComponentType] = Field(
title="The type of the stack component.",
default=None,
)
flavor: Optional[str] = Field(
title="The flavor of the stack component.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
configuration: Optional[Dict[str, Any]] = Field(
title="The stack component configuration.",
default=None,
)
connector_resource_id: Optional[str] = Field(
description="The ID of a specific resource instance to "
"gain access to through the connector",
default=None,
)
labels: Optional[Dict[str, Any]] = Field(
title="The stack component labels.",
default=None,
)
component_spec_path: Optional[str] = Field(
title="The path to the component spec used for mlstacks deployments.",
default=None,
)
connector: Optional[UUID] = Field(
title="The service connector linked to this stack component.",
default=None,
)
InternalComponentRequest (ComponentRequest)
Internal component request model.
Source code in zenml/models/v2/core/component.py
class InternalComponentRequest(ComponentRequest):
"""Internal component request model."""
user: Optional[UUID] = Field( # type: ignore[assignment]
title="The id of the user that created this resource.",
default=None,
)
device
Models representing devices.
OAuthDeviceFilter (UserScopedFilter)
Model to enable advanced filtering of OAuth2 devices.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceFilter(UserScopedFilter):
"""Model to enable advanced filtering of OAuth2 devices."""
expires: Optional[Union[datetime, str, None]] = Field(
default=None,
description="The expiration date of the OAuth2 device.",
union_mode="left_to_right",
)
client_id: Union[UUID, str, None] = Field(
default=None,
description="The client ID of the OAuth2 device.",
union_mode="left_to_right",
)
status: Union[OAuthDeviceStatus, str, None] = Field(
default=None,
description="The status of the OAuth2 device.",
union_mode="left_to_right",
)
trusted_device: Union[bool, str, None] = Field(
default=None,
description="Whether the OAuth2 device was marked as trusted.",
union_mode="left_to_right",
)
failed_auth_attempts: Union[int, str, None] = Field(
default=None,
description="The number of failed authentication attempts.",
union_mode="left_to_right",
)
last_login: Optional[Union[datetime, str, None]] = Field(
default=None,
description="The date of the last successful login.",
union_mode="left_to_right",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/device.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
OAuthDeviceInternalRequest (BaseRequest)
Internal request model for OAuth2 devices.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceInternalRequest(BaseRequest):
"""Internal request model for OAuth2 devices."""
client_id: UUID = Field(description="The client ID of the OAuth2 device.")
expires_in: int = Field(
description="The number of seconds after which the OAuth2 device "
"expires and can no longer be used for authentication."
)
os: Optional[str] = Field(
default=None,
description="The operating system of the device used for "
"authentication.",
)
ip_address: Optional[str] = Field(
default=None,
description="The IP address of the device used for authentication.",
)
hostname: Optional[str] = Field(
default=None,
description="The hostname of the device used for authentication.",
)
python_version: Optional[str] = Field(
default=None,
description="The Python version of the device used for authentication.",
)
zenml_version: Optional[str] = Field(
default=None,
description="The ZenML version of the device used for authentication.",
)
city: Optional[str] = Field(
default=None,
description="The city where the device is located.",
)
region: Optional[str] = Field(
default=None,
description="The region where the device is located.",
)
country: Optional[str] = Field(
default=None,
description="The country where the device is located.",
)
OAuthDeviceInternalResponse (OAuthDeviceResponse)
OAuth2 device response model used internally for authentication.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceInternalResponse(OAuthDeviceResponse):
"""OAuth2 device response model used internally for authentication."""
user_code: str = Field(
title="The user code.",
)
device_code: str = Field(
title="The device code.",
)
def _verify_code(
self,
code: str,
code_hash: Optional[str],
) -> bool:
"""Verifies a given code against the stored (hashed) code.
Args:
code: The code to verify.
code_hash: The hashed code to verify against.
Returns:
True if the code is valid, False otherwise.
"""
context = CryptContext(schemes=["bcrypt"], deprecated="auto")
result = context.verify(code, code_hash)
return result
def verify_user_code(
self,
user_code: str,
) -> bool:
"""Verifies a given user code against the stored (hashed) user code.
Args:
user_code: The user code to verify.
Returns:
True if the user code is valid, False otherwise.
"""
return self._verify_code(user_code, self.user_code)
def verify_device_code(
self,
device_code: str,
) -> bool:
"""Verifies a given device code against the stored (hashed) device code.
Args:
device_code: The device code to verify.
Returns:
True if the device code is valid, False otherwise.
"""
return self._verify_code(device_code, self.device_code)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/device.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
verify_device_code(self, device_code)
Verifies a given device code against the stored (hashed) device code.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
device_code |
str |
The device code to verify. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the device code is valid, False otherwise. |
Source code in zenml/models/v2/core/device.py
def verify_device_code(
self,
device_code: str,
) -> bool:
"""Verifies a given device code against the stored (hashed) device code.
Args:
device_code: The device code to verify.
Returns:
True if the device code is valid, False otherwise.
"""
return self._verify_code(device_code, self.device_code)
verify_user_code(self, user_code)
Verifies a given user code against the stored (hashed) user code.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
user_code |
str |
The user code to verify. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the user code is valid, False otherwise. |
Source code in zenml/models/v2/core/device.py
def verify_user_code(
self,
user_code: str,
) -> bool:
"""Verifies a given user code against the stored (hashed) user code.
Args:
user_code: The user code to verify.
Returns:
True if the user code is valid, False otherwise.
"""
return self._verify_code(user_code, self.user_code)
OAuthDeviceInternalUpdate (OAuthDeviceUpdate)
OAuth2 device update model used internally for authentication.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceInternalUpdate(OAuthDeviceUpdate):
"""OAuth2 device update model used internally for authentication."""
user_id: Optional[UUID] = Field(
default=None, description="User that owns the OAuth2 device."
)
status: Optional[OAuthDeviceStatus] = Field(
default=None, description="The new status of the OAuth2 device."
)
expires_in: Optional[int] = Field(
default=None,
description="Set the device to expire in the given number of seconds. "
"If the value is 0 or negative, the device is set to never expire.",
)
failed_auth_attempts: Optional[int] = Field(
default=None,
description="Set the number of failed authentication attempts.",
)
trusted_device: Optional[bool] = Field(
default=None,
description="Whether to mark the OAuth2 device as trusted. A trusted "
"device has a much longer validity time.",
)
update_last_login: bool = Field(
default=False, description="Whether to update the last login date."
)
generate_new_codes: bool = Field(
default=False,
description="Whether to generate new user and device codes.",
)
os: Optional[str] = Field(
default=None,
description="The operating system of the device used for "
"authentication.",
)
ip_address: Optional[str] = Field(
default=None,
description="The IP address of the device used for authentication.",
)
hostname: Optional[str] = Field(
default=None,
description="The hostname of the device used for authentication.",
)
python_version: Optional[str] = Field(
default=None,
description="The Python version of the device used for authentication.",
)
zenml_version: Optional[str] = Field(
default=None,
description="The ZenML version of the device used for authentication.",
)
city: Optional[str] = Field(
default=None,
description="The city where the device is located.",
)
region: Optional[str] = Field(
default=None,
description="The region where the device is located.",
)
country: Optional[str] = Field(
default=None,
description="The country where the device is located.",
)
OAuthDeviceResponse (UserScopedResponse[OAuthDeviceResponseBody, OAuthDeviceResponseMetadata, OAuthDeviceResponseResources])
Response model for OAuth2 devices.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceResponse(
UserScopedResponse[
OAuthDeviceResponseBody,
OAuthDeviceResponseMetadata,
OAuthDeviceResponseResources,
]
):
"""Response model for OAuth2 devices."""
_warn_on_response_updates = False
def get_hydrated_version(self) -> "OAuthDeviceResponse":
"""Get the hydrated version of this OAuth2 device.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_authorized_device(self.id)
# Body and metadata properties
@property
def client_id(self) -> UUID:
"""The `client_id` property.
Returns:
the value of the property.
"""
return self.get_body().client_id
@property
def expires(self) -> Optional[datetime]:
"""The `expires` property.
Returns:
the value of the property.
"""
return self.get_body().expires
@property
def trusted_device(self) -> bool:
"""The `trusted_device` property.
Returns:
the value of the property.
"""
return self.get_body().trusted_device
@property
def status(self) -> OAuthDeviceStatus:
"""The `status` property.
Returns:
the value of the property.
"""
return self.get_body().status
@property
def os(self) -> Optional[str]:
"""The `os` property.
Returns:
the value of the property.
"""
return self.get_body().os
@property
def ip_address(self) -> Optional[str]:
"""The `ip_address` property.
Returns:
the value of the property.
"""
return self.get_body().ip_address
@property
def hostname(self) -> Optional[str]:
"""The `hostname` property.
Returns:
the value of the property.
"""
return self.get_body().hostname
@property
def python_version(self) -> Optional[str]:
"""The `python_version` property.
Returns:
the value of the property.
"""
return self.get_metadata().python_version
@property
def zenml_version(self) -> Optional[str]:
"""The `zenml_version` property.
Returns:
the value of the property.
"""
return self.get_metadata().zenml_version
@property
def city(self) -> Optional[str]:
"""The `city` property.
Returns:
the value of the property.
"""
return self.get_metadata().city
@property
def region(self) -> Optional[str]:
"""The `region` property.
Returns:
the value of the property.
"""
return self.get_metadata().region
@property
def country(self) -> Optional[str]:
"""The `country` property.
Returns:
the value of the property.
"""
return self.get_metadata().country
@property
def failed_auth_attempts(self) -> int:
"""The `failed_auth_attempts` property.
Returns:
the value of the property.
"""
return self.get_metadata().failed_auth_attempts
@property
def last_login(self) -> Optional[datetime]:
"""The `last_login` property.
Returns:
the value of the property.
"""
return self.get_metadata().last_login
city: Optional[str]
property
readonly
The city
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
client_id: UUID
property
readonly
The client_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
country: Optional[str]
property
readonly
The country
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
expires: Optional[datetime.datetime]
property
readonly
The expires
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
failed_auth_attempts: int
property
readonly
The failed_auth_attempts
property.
Returns:
Type | Description |
---|---|
int |
the value of the property. |
hostname: Optional[str]
property
readonly
The hostname
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
ip_address: Optional[str]
property
readonly
The ip_address
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
last_login: Optional[datetime.datetime]
property
readonly
The last_login
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
os: Optional[str]
property
readonly
The os
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
python_version: Optional[str]
property
readonly
The python_version
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
region: Optional[str]
property
readonly
The region
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
status: OAuthDeviceStatus
property
readonly
The status
property.
Returns:
Type | Description |
---|---|
OAuthDeviceStatus |
the value of the property. |
trusted_device: bool
property
readonly
The trusted_device
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
zenml_version: Optional[str]
property
readonly
The zenml_version
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this OAuth2 device.
Returns:
Type | Description |
---|---|
OAuthDeviceResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/device.py
def get_hydrated_version(self) -> "OAuthDeviceResponse":
"""Get the hydrated version of this OAuth2 device.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_authorized_device(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/device.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
OAuthDeviceResponseBody (UserScopedResponseBody)
Response body for OAuth2 devices.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceResponseBody(UserScopedResponseBody):
"""Response body for OAuth2 devices."""
client_id: UUID = Field(description="The client ID of the OAuth2 device.")
expires: Optional[datetime] = Field(
default=None,
description="The expiration date of the OAuth2 device after which "
"the device is no longer valid and cannot be used for "
"authentication.",
)
trusted_device: bool = Field(
description="Whether the OAuth2 device was marked as trusted. A "
"trusted device has a much longer validity time.",
)
status: OAuthDeviceStatus = Field(
description="The status of the OAuth2 device."
)
os: Optional[str] = Field(
default=None,
description="The operating system of the device used for "
"authentication.",
)
ip_address: Optional[str] = Field(
default=None,
description="The IP address of the device used for authentication.",
)
hostname: Optional[str] = Field(
default=None,
description="The hostname of the device used for authentication.",
)
OAuthDeviceResponseMetadata (UserScopedResponseMetadata)
Response metadata for OAuth2 devices.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceResponseMetadata(UserScopedResponseMetadata):
"""Response metadata for OAuth2 devices."""
python_version: Optional[str] = Field(
default=None,
description="The Python version of the device used for authentication.",
)
zenml_version: Optional[str] = Field(
default=None,
description="The ZenML version of the device used for authentication.",
)
city: Optional[str] = Field(
default=None,
description="The city where the device is located.",
)
region: Optional[str] = Field(
default=None,
description="The region where the device is located.",
)
country: Optional[str] = Field(
default=None,
description="The country where the device is located.",
)
failed_auth_attempts: int = Field(
description="The number of failed authentication attempts.",
)
last_login: Optional[datetime] = Field(
description="The date of the last successful login."
)
OAuthDeviceResponseResources (UserScopedResponseResources)
Class for all resource models associated with the OAuthDevice entity.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceResponseResources(UserScopedResponseResources):
"""Class for all resource models associated with the OAuthDevice entity."""
OAuthDeviceUpdate (BaseModel)
OAuth2 device update model.
Source code in zenml/models/v2/core/device.py
class OAuthDeviceUpdate(BaseModel):
"""OAuth2 device update model."""
locked: Optional[bool] = Field(
default=None,
description="Whether to lock or unlock the OAuth2 device. A locked "
"device cannot be used for authentication.",
)
event_source
Collection of all models concerning event configurations.
EventSourceFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all EventSourceModels.
Source code in zenml/models/v2/core/event_source.py
class EventSourceFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all EventSourceModels."""
name: Optional[str] = Field(
default=None,
description="Name of the event source",
)
flavor: Optional[str] = Field(
default=None,
description="Flavor of the event source",
)
plugin_subtype: Optional[str] = Field(
default=None,
title="The plugin sub type of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/event_source.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
EventSourceRequest (WorkspaceScopedRequest)
BaseModel for all event sources.
Source code in zenml/models/v2/core/event_source.py
class EventSourceRequest(WorkspaceScopedRequest):
"""BaseModel for all event sources."""
name: str = Field(
title="The name of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
flavor: str = Field(
title="The flavor of event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
plugin_subtype: PluginSubType = Field(
title="The plugin subtype of the event source.",
)
description: str = Field(
default="",
title="The description of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Dict[str, Any] = Field(
title="The event source configuration.",
)
EventSourceResponse (WorkspaceScopedResponse[EventSourceResponseBody, EventSourceResponseMetadata, EventSourceResponseResources])
Response model for event sources.
Source code in zenml/models/v2/core/event_source.py
class EventSourceResponse(
WorkspaceScopedResponse[
EventSourceResponseBody,
EventSourceResponseMetadata,
EventSourceResponseResources,
]
):
"""Response model for event sources."""
name: str = Field(
title="The name of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "EventSourceResponse":
"""Get the hydrated version of this event source.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_event_source(self.id)
# Body and metadata properties
@property
def flavor(self) -> str:
"""The `flavor` property.
Returns:
the value of the property.
"""
return self.get_body().flavor
@property
def is_active(self) -> bool:
"""The `is_active` property.
Returns:
the value of the property.
"""
return self.get_body().is_active
@property
def plugin_subtype(self) -> PluginSubType:
"""The `plugin_subtype` property.
Returns:
the value of the property.
"""
return self.get_body().plugin_subtype
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def configuration(self) -> Dict[str, Any]:
"""The `configuration` property.
Returns:
the value of the property.
"""
return self.get_metadata().configuration
def set_configuration(self, configuration: Dict[str, Any]) -> None:
"""Set the `configuration` property.
Args:
configuration: The value to set.
"""
self.get_metadata().configuration = configuration
configuration: Dict[str, Any]
property
readonly
The configuration
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
flavor: str
property
readonly
The flavor
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
is_active: bool
property
readonly
The is_active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
plugin_subtype: PluginSubType
property
readonly
The plugin_subtype
property.
Returns:
Type | Description |
---|---|
PluginSubType |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this event source.
Returns:
Type | Description |
---|---|
EventSourceResponse |
An instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/event_source.py
def get_hydrated_version(self) -> "EventSourceResponse":
"""Get the hydrated version of this event source.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_event_source(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/event_source.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_configuration(self, configuration)
Set the configuration
property.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
configuration |
Dict[str, Any] |
The value to set. |
required |
Source code in zenml/models/v2/core/event_source.py
def set_configuration(self, configuration: Dict[str, Any]) -> None:
"""Set the `configuration` property.
Args:
configuration: The value to set.
"""
self.get_metadata().configuration = configuration
EventSourceResponseBody (WorkspaceScopedResponseBody)
ResponseBody for event sources.
Source code in zenml/models/v2/core/event_source.py
class EventSourceResponseBody(WorkspaceScopedResponseBody):
"""ResponseBody for event sources."""
flavor: str = Field(
title="The flavor of event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
plugin_subtype: PluginSubType = Field(
title="The plugin subtype of the event source.",
)
is_active: bool = Field(
title="Whether the event source is active.",
)
EventSourceResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for event sources.
Source code in zenml/models/v2/core/event_source.py
class EventSourceResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for event sources."""
description: str = Field(
default="",
title="The description of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Dict[str, Any] = Field(
title="The event source configuration.",
)
EventSourceResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the code repository entity.
Source code in zenml/models/v2/core/event_source.py
class EventSourceResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the code repository entity."""
triggers: Page[TriggerResponse] = Field(
title="The triggers configured with this event source.",
)
EventSourceUpdate (BaseZenModel)
Update model for event sources.
Source code in zenml/models/v2/core/event_source.py
class EventSourceUpdate(BaseZenModel):
"""Update model for event sources."""
name: Optional[str] = Field(
default=None,
title="The updated name of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The updated description of the event source.",
max_length=STR_FIELD_MAX_LENGTH,
)
configuration: Optional[Dict[str, Any]] = Field(
default=None,
title="The updated event source configuration.",
)
is_active: Optional[bool] = Field(
default=None,
title="The status of the event source.",
)
@classmethod
def from_response(
cls, response: "EventSourceResponse"
) -> "EventSourceUpdate":
"""Create an update model from a response model.
Args:
response: The response model to create the update model from.
Returns:
The update model.
"""
return EventSourceUpdate(
name=response.name,
description=response.description,
configuration=copy.deepcopy(response.configuration),
is_active=response.is_active,
)
from_response(response)
classmethod
Create an update model from a response model.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
response |
EventSourceResponse |
The response model to create the update model from. |
required |
Returns:
Type | Description |
---|---|
EventSourceUpdate |
The update model. |
Source code in zenml/models/v2/core/event_source.py
@classmethod
def from_response(
cls, response: "EventSourceResponse"
) -> "EventSourceUpdate":
"""Create an update model from a response model.
Args:
response: The response model to create the update model from.
Returns:
The update model.
"""
return EventSourceUpdate(
name=response.name,
description=response.description,
configuration=copy.deepcopy(response.configuration),
is_active=response.is_active,
)
event_source_flavor
Models representing event source flavors..
EventSourceFlavorResponse (BasePluginFlavorResponse[EventSourceFlavorResponseBody, EventSourceFlavorResponseMetadata, EventSourceFlavorResponseResources])
Response model for Event Source Flavors.
Source code in zenml/models/v2/core/event_source_flavor.py
class EventSourceFlavorResponse(
BasePluginFlavorResponse[
EventSourceFlavorResponseBody,
EventSourceFlavorResponseMetadata,
EventSourceFlavorResponseResources,
]
):
"""Response model for Event Source Flavors."""
# Body and metadata properties
@property
def source_config_schema(self) -> Dict[str, Any]:
"""The `source_config_schema` property.
Returns:
the value of the property.
"""
return self.get_metadata().source_config_schema
@property
def filter_config_schema(self) -> Dict[str, Any]:
"""The `filter_config_schema` property.
Returns:
the value of the property.
"""
return self.get_metadata().filter_config_schema
filter_config_schema: Dict[str, Any]
property
readonly
The filter_config_schema
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
source_config_schema: Dict[str, Any]
property
readonly
The source_config_schema
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/event_source_flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
EventSourceFlavorResponseBody (BasePluginResponseBody)
Response body for event flavors.
Source code in zenml/models/v2/core/event_source_flavor.py
class EventSourceFlavorResponseBody(BasePluginResponseBody):
"""Response body for event flavors."""
EventSourceFlavorResponseMetadata (BasePluginResponseMetadata)
Response metadata for event flavors.
Source code in zenml/models/v2/core/event_source_flavor.py
class EventSourceFlavorResponseMetadata(BasePluginResponseMetadata):
"""Response metadata for event flavors."""
source_config_schema: Dict[str, Any]
filter_config_schema: Dict[str, Any]
EventSourceFlavorResponseResources (BasePluginResponseResources)
Response resources for event source flavors.
Source code in zenml/models/v2/core/event_source_flavor.py
class EventSourceFlavorResponseResources(BasePluginResponseResources):
"""Response resources for event source flavors."""
flavor
Models representing flavors.
FlavorFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all Flavors.
Source code in zenml/models/v2/core/flavor.py
class FlavorFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all Flavors."""
name: Optional[str] = Field(
default=None,
description="Name of the flavor",
)
type: Optional[str] = Field(
default=None,
description="Stack Component Type of the stack flavor",
)
integration: Optional[str] = Field(
default=None,
description="Integration associated with the flavor",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the stack",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User of the stack",
union_mode="left_to_right",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
FlavorRequest (UserScopedRequest)
Request model for flavors.
Source code in zenml/models/v2/core/flavor.py
class FlavorRequest(UserScopedRequest):
"""Request model for flavors."""
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"type",
"integration",
]
name: str = Field(
title="The name of the Flavor.",
max_length=STR_FIELD_MAX_LENGTH,
)
type: StackComponentType = Field(title="The type of the Flavor.")
config_schema: Dict[str, Any] = Field(
title="The JSON schema of this flavor's corresponding configuration.",
)
connector_type: Optional[str] = Field(
default=None,
title="The type of the connector that this flavor uses.",
max_length=STR_FIELD_MAX_LENGTH,
)
connector_resource_type: Optional[str] = Field(
default=None,
title="The resource type of the connector that this flavor uses.",
max_length=STR_FIELD_MAX_LENGTH,
)
connector_resource_id_attr: Optional[str] = Field(
default=None,
title="The name of an attribute in the stack component configuration "
"that plays the role of resource ID when linked to a service "
"connector.",
max_length=STR_FIELD_MAX_LENGTH,
)
source: str = Field(
title="The path to the module which contains this Flavor.",
max_length=STR_FIELD_MAX_LENGTH,
)
integration: Optional[str] = Field(
title="The name of the integration that the Flavor belongs to.",
max_length=STR_FIELD_MAX_LENGTH,
)
logo_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to a png,"
"svg or jpg can be attached.",
)
docs_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to docs, within docs.zenml.io.",
)
sdk_docs_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to SDK docs,"
"within sdkdocs.zenml.io.",
)
is_custom: bool = Field(
title="Whether or not this flavor is a custom, user created flavor.",
default=True,
)
workspace: Optional[UUID] = Field(
default=None, title="The workspace to which this resource belongs."
)
FlavorResponse (UserScopedResponse[FlavorResponseBody, FlavorResponseMetadata, FlavorResponseResources])
Response model for flavors.
Source code in zenml/models/v2/core/flavor.py
class FlavorResponse(
UserScopedResponse[
FlavorResponseBody, FlavorResponseMetadata, FlavorResponseResources
]
):
"""Response model for flavors."""
# Analytics
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"id",
"type",
"integration",
]
name: str = Field(
title="The name of the Flavor.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "FlavorResponse":
"""Get the hydrated version of the flavor.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_flavor(self.id)
# Helper methods
@property
def connector_requirements(
self,
) -> Optional["ServiceConnectorRequirements"]:
"""Returns the connector requirements for the flavor.
Returns:
The connector requirements for the flavor.
"""
from zenml.models import (
ServiceConnectorRequirements,
)
if not self.connector_resource_type:
return None
return ServiceConnectorRequirements(
connector_type=self.connector_type,
resource_type=self.connector_resource_type,
resource_id_attr=self.connector_resource_id_attr,
)
# Body and metadata properties
@property
def type(self) -> StackComponentType:
"""The `type` property.
Returns:
the value of the property.
"""
return self.get_body().type
@property
def integration(self) -> Optional[str]:
"""The `integration` property.
Returns:
the value of the property.
"""
return self.get_body().integration
@property
def logo_url(self) -> Optional[str]:
"""The `logo_url` property.
Returns:
the value of the property.
"""
return self.get_body().logo_url
@property
def workspace(self) -> Optional["WorkspaceResponse"]:
"""The `workspace` property.
Returns:
the value of the property.
"""
return self.get_metadata().workspace
@property
def config_schema(self) -> Dict[str, Any]:
"""The `config_schema` property.
Returns:
the value of the property.
"""
return self.get_metadata().config_schema
@property
def connector_type(self) -> Optional[str]:
"""The `connector_type` property.
Returns:
the value of the property.
"""
return self.get_metadata().connector_type
@property
def connector_resource_type(self) -> Optional[str]:
"""The `connector_resource_type` property.
Returns:
the value of the property.
"""
return self.get_metadata().connector_resource_type
@property
def connector_resource_id_attr(self) -> Optional[str]:
"""The `connector_resource_id_attr` property.
Returns:
the value of the property.
"""
return self.get_metadata().connector_resource_id_attr
@property
def source(self) -> str:
"""The `source` property.
Returns:
the value of the property.
"""
return self.get_metadata().source
@property
def docs_url(self) -> Optional[str]:
"""The `docs_url` property.
Returns:
the value of the property.
"""
return self.get_metadata().docs_url
@property
def sdk_docs_url(self) -> Optional[str]:
"""The `sdk_docs_url` property.
Returns:
the value of the property.
"""
return self.get_metadata().sdk_docs_url
@property
def is_custom(self) -> bool:
"""The `is_custom` property.
Returns:
the value of the property.
"""
return self.get_metadata().is_custom
config_schema: Dict[str, Any]
property
readonly
The config_schema
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
connector_requirements: Optional[ServiceConnectorRequirements]
property
readonly
Returns the connector requirements for the flavor.
Returns:
Type | Description |
---|---|
Optional[ServiceConnectorRequirements] |
The connector requirements for the flavor. |
connector_resource_id_attr: Optional[str]
property
readonly
The connector_resource_id_attr
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
connector_resource_type: Optional[str]
property
readonly
The connector_resource_type
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
connector_type: Optional[str]
property
readonly
The connector_type
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
docs_url: Optional[str]
property
readonly
The docs_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
integration: Optional[str]
property
readonly
The integration
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
is_custom: bool
property
readonly
The is_custom
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
logo_url: Optional[str]
property
readonly
The logo_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
sdk_docs_url: Optional[str]
property
readonly
The sdk_docs_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
source: str
property
readonly
The source
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
type: StackComponentType
property
readonly
The type
property.
Returns:
Type | Description |
---|---|
StackComponentType |
the value of the property. |
workspace: Optional[WorkspaceResponse]
property
readonly
The workspace
property.
Returns:
Type | Description |
---|---|
Optional[WorkspaceResponse] |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of the flavor.
Returns:
Type | Description |
---|---|
FlavorResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/flavor.py
def get_hydrated_version(self) -> "FlavorResponse":
"""Get the hydrated version of the flavor.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_flavor(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/flavor.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
FlavorResponseBody (UserScopedResponseBody)
Response body for flavor.
Source code in zenml/models/v2/core/flavor.py
class FlavorResponseBody(UserScopedResponseBody):
"""Response body for flavor."""
type: StackComponentType = Field(title="The type of the Flavor.")
integration: Optional[str] = Field(
title="The name of the integration that the Flavor belongs to.",
max_length=STR_FIELD_MAX_LENGTH,
)
logo_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to a png,"
"svg or jpg can be attached.",
)
FlavorResponseMetadata (UserScopedResponseMetadata)
Response metadata for flavors.
Source code in zenml/models/v2/core/flavor.py
class FlavorResponseMetadata(UserScopedResponseMetadata):
"""Response metadata for flavors."""
workspace: Optional["WorkspaceResponse"] = Field(
title="The project of this resource."
)
config_schema: Dict[str, Any] = Field(
title="The JSON schema of this flavor's corresponding configuration.",
)
connector_type: Optional[str] = Field(
default=None,
title="The type of the connector that this flavor uses.",
max_length=STR_FIELD_MAX_LENGTH,
)
connector_resource_type: Optional[str] = Field(
default=None,
title="The resource type of the connector that this flavor uses.",
max_length=STR_FIELD_MAX_LENGTH,
)
connector_resource_id_attr: Optional[str] = Field(
default=None,
title="The name of an attribute in the stack component configuration "
"that plays the role of resource ID when linked to a service "
"connector.",
max_length=STR_FIELD_MAX_LENGTH,
)
source: str = Field(
title="The path to the module which contains this Flavor.",
max_length=STR_FIELD_MAX_LENGTH,
)
docs_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to docs, within docs.zenml.io.",
)
sdk_docs_url: Optional[str] = Field(
default=None,
title="Optionally, a url pointing to SDK docs,"
"within sdkdocs.zenml.io.",
)
is_custom: bool = Field(
title="Whether or not this flavor is a custom, user created flavor.",
default=True,
)
FlavorResponseResources (UserScopedResponseResources)
Class for all resource models associated with the flavor entity.
Source code in zenml/models/v2/core/flavor.py
class FlavorResponseResources(UserScopedResponseResources):
"""Class for all resource models associated with the flavor entity."""
FlavorUpdate (BaseUpdate)
Update model for flavors.
Source code in zenml/models/v2/core/flavor.py
class FlavorUpdate(BaseUpdate):
"""Update model for flavors."""
name: Optional[str] = Field(
title="The name of the Flavor.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
type: Optional[StackComponentType] = Field(
title="The type of the Flavor.", default=None
)
config_schema: Optional[Dict[str, Any]] = Field(
title="The JSON schema of this flavor's corresponding configuration.",
default=None,
)
connector_type: Optional[str] = Field(
title="The type of the connector that this flavor uses.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
connector_resource_type: Optional[str] = Field(
title="The resource type of the connector that this flavor uses.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
connector_resource_id_attr: Optional[str] = Field(
title="The name of an attribute in the stack component configuration "
"that plays the role of resource ID when linked to a service "
"connector.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
source: Optional[str] = Field(
title="The path to the module which contains this Flavor.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
integration: Optional[str] = Field(
title="The name of the integration that the Flavor belongs to.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
logo_url: Optional[str] = Field(
title="Optionally, a url pointing to a png,"
"svg or jpg can be attached.",
default=None,
)
docs_url: Optional[str] = Field(
title="Optionally, a url pointing to docs, within docs.zenml.io.",
default=None,
)
sdk_docs_url: Optional[str] = Field(
title="Optionally, a url pointing to SDK docs,"
"within sdkdocs.zenml.io.",
default=None,
)
is_custom: Optional[bool] = Field(
title="Whether or not this flavor is a custom, user created flavor.",
default=None,
)
workspace: Optional[UUID] = Field(
title="The workspace to which this resource belongs.",
default=None,
)
InternalFlavorRequest (FlavorRequest)
Internal flavor request model.
Source code in zenml/models/v2/core/flavor.py
class InternalFlavorRequest(FlavorRequest):
"""Internal flavor request model."""
user: Optional[UUID] = Field( # type: ignore[assignment]
title="The id of the user that created this resource.",
default=None,
)
logs
Models representing logs.
LogsRequest (BaseRequest)
Request model for logs.
Source code in zenml/models/v2/core/logs.py
class LogsRequest(BaseRequest):
"""Request model for logs."""
uri: str = Field(title="The uri of the logs file")
artifact_store_id: Union[str, UUID] = Field(
title="The artifact store ID to associate the logs with.",
union_mode="left_to_right",
)
@field_validator("uri")
@classmethod
def text_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < TEXT_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {TEXT_FIELD_MAX_LENGTH}"
)
return value
@field_validator("artifact_store_id")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
str_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum text length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/logs.py
@field_validator("artifact_store_id")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
text_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum text length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/logs.py
@field_validator("uri")
@classmethod
def text_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < TEXT_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {TEXT_FIELD_MAX_LENGTH}"
)
return value
LogsResponse (BaseIdentifiedResponse[LogsResponseBody, LogsResponseMetadata, LogsResponseResources])
Response model for logs.
Source code in zenml/models/v2/core/logs.py
class LogsResponse(
BaseIdentifiedResponse[
LogsResponseBody, LogsResponseMetadata, LogsResponseResources
]
):
"""Response model for logs."""
def get_hydrated_version(self) -> "LogsResponse":
"""Get the hydrated version of these logs.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_logs(self.id)
# Body and metadata properties
@property
def uri(self) -> str:
"""The `uri` property.
Returns:
the value of the property.
"""
return self.get_body().uri
@property
def step_run_id(self) -> Optional[Union[str, UUID]]:
"""The `step_run_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().step_run_id
@property
def pipeline_run_id(self) -> Optional[Union[str, UUID]]:
"""The `pipeline_run_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_run_id
@property
def artifact_store_id(self) -> Union[str, UUID]:
"""The `artifact_store_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().artifact_store_id
artifact_store_id: Union[str, uuid.UUID]
property
readonly
The artifact_store_id
property.
Returns:
Type | Description |
---|---|
Union[str, uuid.UUID] |
the value of the property. |
pipeline_run_id: Union[uuid.UUID, str]
property
readonly
The pipeline_run_id
property.
Returns:
Type | Description |
---|---|
Union[uuid.UUID, str] |
the value of the property. |
step_run_id: Union[uuid.UUID, str]
property
readonly
The step_run_id
property.
Returns:
Type | Description |
---|---|
Union[uuid.UUID, str] |
the value of the property. |
uri: str
property
readonly
The uri
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of these logs.
Returns:
Type | Description |
---|---|
LogsResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/logs.py
def get_hydrated_version(self) -> "LogsResponse":
"""Get the hydrated version of these logs.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_logs(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/logs.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
LogsResponseBody (BaseDatedResponseBody)
Response body for logs.
Source code in zenml/models/v2/core/logs.py
class LogsResponseBody(BaseDatedResponseBody):
"""Response body for logs."""
uri: str = Field(
title="The uri of the logs file",
max_length=TEXT_FIELD_MAX_LENGTH,
)
LogsResponseMetadata (BaseResponseMetadata)
Response metadata for logs.
Source code in zenml/models/v2/core/logs.py
class LogsResponseMetadata(BaseResponseMetadata):
"""Response metadata for logs."""
step_run_id: Optional[Union[str, UUID]] = Field(
title="Step ID to associate the logs with.",
default=None,
description="When this is set, pipeline_run_id should be set to None.",
union_mode="left_to_right",
)
pipeline_run_id: Optional[Union[str, UUID]] = Field(
title="Pipeline run ID to associate the logs with.",
default=None,
description="When this is set, step_run_id should be set to None.",
union_mode="left_to_right",
)
artifact_store_id: Union[str, UUID] = Field(
title="The artifact store ID to associate the logs with.",
union_mode="left_to_right",
)
@field_validator("artifact_store_id")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH
return value
str_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum text length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/logs.py
@field_validator("artifact_store_id")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH
return value
LogsResponseResources (BaseResponseResources)
Class for all resource models associated with the Logs entity.
Source code in zenml/models/v2/core/logs.py
class LogsResponseResources(BaseResponseResources):
"""Class for all resource models associated with the Logs entity."""
model
Models representing models.
ModelFilter (WorkspaceScopedTaggableFilter)
Model to enable advanced filtering of all Workspaces.
Source code in zenml/models/v2/core/model.py
class ModelFilter(WorkspaceScopedTaggableFilter):
"""Model to enable advanced filtering of all Workspaces."""
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.CLI_EXCLUDE_FIELDS,
"workspace_id",
"user_id",
]
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
"user",
]
name: Optional[str] = Field(
default=None,
description="Name of the Model",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the Model",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User of the Model",
union_mode="left_to_right",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the model.",
)
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ModelSchema,
UserSchema,
)
if self.user:
user_filter = and_(
ModelSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/model.py
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ModelSchema,
UserSchema,
)
if self.user:
user_filter = and_(
ModelSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ModelRequest (WorkspaceScopedRequest)
Request model for models.
Source code in zenml/models/v2/core/model.py
class ModelRequest(WorkspaceScopedRequest):
"""Request model for models."""
name: str = Field(
title="The name of the model",
max_length=STR_FIELD_MAX_LENGTH,
)
license: Optional[str] = Field(
title="The license model created under",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
title="The description of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
audience: Optional[str] = Field(
title="The target audience of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
use_cases: Optional[str] = Field(
title="The use cases of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
limitations: Optional[str] = Field(
title="The know limitations of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
trade_offs: Optional[str] = Field(
title="The trade offs of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
ethics: Optional[str] = Field(
title="The ethical implications of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
tags: Optional[List[str]] = Field(
title="Tags associated with the model",
)
save_models_to_registry: bool = Field(
title="Whether to save all ModelArtifacts to Model Registry",
default=True,
)
ModelResponse (WorkspaceScopedResponse[ModelResponseBody, ModelResponseMetadata, ModelResponseResources])
Response model for models.
Source code in zenml/models/v2/core/model.py
class ModelResponse(
WorkspaceScopedResponse[
ModelResponseBody, ModelResponseMetadata, ModelResponseResources
]
):
"""Response model for models."""
name: str = Field(
title="The name of the model",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "ModelResponse":
"""Get the hydrated version of this model.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_model(self.id)
# Body and metadata properties
@property
def tags(self) -> List["TagResponse"]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_body().tags
@property
def latest_version_name(self) -> Optional[str]:
"""The `latest_version_name` property.
Returns:
the value of the property.
"""
return self.get_body().latest_version_name
@property
def latest_version_id(self) -> Optional[UUID]:
"""The `latest_version_id` property.
Returns:
the value of the property.
"""
return self.get_body().latest_version_id
@property
def license(self) -> Optional[str]:
"""The `license` property.
Returns:
the value of the property.
"""
return self.get_metadata().license
@property
def description(self) -> Optional[str]:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def audience(self) -> Optional[str]:
"""The `audience` property.
Returns:
the value of the property.
"""
return self.get_metadata().audience
@property
def use_cases(self) -> Optional[str]:
"""The `use_cases` property.
Returns:
the value of the property.
"""
return self.get_metadata().use_cases
@property
def limitations(self) -> Optional[str]:
"""The `limitations` property.
Returns:
the value of the property.
"""
return self.get_metadata().limitations
@property
def trade_offs(self) -> Optional[str]:
"""The `trade_offs` property.
Returns:
the value of the property.
"""
return self.get_metadata().trade_offs
@property
def ethics(self) -> Optional[str]:
"""The `ethics` property.
Returns:
the value of the property.
"""
return self.get_metadata().ethics
@property
def save_models_to_registry(self) -> bool:
"""The `save_models_to_registry` property.
Returns:
the value of the property.
"""
return self.get_metadata().save_models_to_registry
# Helper functions
@property
def versions(self) -> List["Model"]:
"""List all versions of the model.
Returns:
The list of all model version.
"""
from zenml.client import Client
client = Client()
model_versions = depaginate(
client.list_model_versions, model_name_or_id=self.id
)
return [
mv.to_model_class(suppress_class_validation_warnings=True)
for mv in model_versions
]
audience: Optional[str]
property
readonly
The audience
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
description: Optional[str]
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
ethics: Optional[str]
property
readonly
The ethics
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
latest_version_id: Optional[uuid.UUID]
property
readonly
The latest_version_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
latest_version_name: Optional[str]
property
readonly
The latest_version_name
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
license: Optional[str]
property
readonly
The license
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
limitations: Optional[str]
property
readonly
The limitations
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
save_models_to_registry: bool
property
readonly
The save_models_to_registry
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
tags: List[TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[TagResponse] |
the value of the property. |
trade_offs: Optional[str]
property
readonly
The trade_offs
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
use_cases: Optional[str]
property
readonly
The use_cases
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
versions: List[Model]
property
readonly
List all versions of the model.
Returns:
Type | Description |
---|---|
List[Model] |
The list of all model version. |
get_hydrated_version(self)
Get the hydrated version of this model.
Returns:
Type | Description |
---|---|
ModelResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/model.py
def get_hydrated_version(self) -> "ModelResponse":
"""Get the hydrated version of this model.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_model(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ModelResponseBody (WorkspaceScopedResponseBody)
Response body for models.
Source code in zenml/models/v2/core/model.py
class ModelResponseBody(WorkspaceScopedResponseBody):
"""Response body for models."""
tags: List["TagResponse"] = Field(
title="Tags associated with the model",
)
latest_version_name: Optional[str] = None
latest_version_id: Optional[UUID] = None
ModelResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for models.
Source code in zenml/models/v2/core/model.py
class ModelResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for models."""
license: Optional[str] = Field(
title="The license model created under",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
title="The description of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
audience: Optional[str] = Field(
title="The target audience of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
use_cases: Optional[str] = Field(
title="The use cases of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
limitations: Optional[str] = Field(
title="The know limitations of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
trade_offs: Optional[str] = Field(
title="The trade offs of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
ethics: Optional[str] = Field(
title="The ethical implications of the model",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
save_models_to_registry: bool = Field(
title="Whether to save all ModelArtifacts to Model Registry",
default=True,
)
ModelResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the model entity.
Source code in zenml/models/v2/core/model.py
class ModelResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the model entity."""
ModelUpdate (BaseModel)
Update model for models.
Source code in zenml/models/v2/core/model.py
class ModelUpdate(BaseModel):
"""Update model for models."""
name: Optional[str] = None
license: Optional[str] = None
description: Optional[str] = None
audience: Optional[str] = None
use_cases: Optional[str] = None
limitations: Optional[str] = None
trade_offs: Optional[str] = None
ethics: Optional[str] = None
add_tags: Optional[List[str]] = None
remove_tags: Optional[List[str]] = None
save_models_to_registry: Optional[bool] = None
model_version
Models representing model versions.
ModelVersionFilter (WorkspaceScopedTaggableFilter)
Filter model for model versions.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionFilter(WorkspaceScopedTaggableFilter):
"""Filter model for model versions."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
"user",
]
name: Optional[str] = Field(
default=None,
description="The name of the Model Version",
)
number: Optional[int] = Field(
default=None,
description="The number of the Model Version",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The workspace of the Model Version",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The user of the Model Version",
union_mode="left_to_right",
)
stage: Optional[Union[str, ModelStages]] = Field(
description="The model version stage",
default=None,
union_mode="left_to_right",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the model version.",
)
_model_id: UUID = PrivateAttr(None)
def set_scope_model(self, model_name_or_id: Union[str, UUID]) -> None:
"""Set the model to scope this response.
Args:
model_name_or_id: The model to scope this response to.
"""
try:
model_id = UUID(str(model_name_or_id))
except ValueError:
from zenml.client import Client
model_id = Client().get_model(model_name_or_id).id
self._model_id = model_id
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ModelVersionSchema,
UserSchema,
)
if self.user:
user_filter = and_(
ModelVersionSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
if self._model_id:
query = query.where(getattr(table, "model_id") == self._model_id)
return query
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/core/model_version.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
if self._model_id:
query = query.where(getattr(table, "model_id") == self._model_id)
return query
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/model_version.py
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ModelVersionSchema,
UserSchema,
)
if self.user:
user_filter = and_(
ModelVersionSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model_version.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_scope_model(self, model_name_or_id)
Set the model to scope this response.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model_name_or_id |
Union[str, uuid.UUID] |
The model to scope this response to. |
required |
Source code in zenml/models/v2/core/model_version.py
def set_scope_model(self, model_name_or_id: Union[str, UUID]) -> None:
"""Set the model to scope this response.
Args:
model_name_or_id: The model to scope this response to.
"""
try:
model_id = UUID(str(model_name_or_id))
except ValueError:
from zenml.client import Client
model_id = Client().get_model(model_name_or_id).id
self._model_id = model_id
ModelVersionRequest (WorkspaceScopedRequest)
Request model for model versions.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionRequest(WorkspaceScopedRequest):
"""Request model for model versions."""
name: Optional[str] = Field(
description="The name of the model version",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
description="The description of the model version",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
stage: Optional[str] = Field(
description="The stage of the model version",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
number: Optional[int] = Field(
description="The number of the model version",
default=None,
)
model: UUID = Field(
description="The ID of the model containing version",
)
tags: Optional[List[str]] = Field(
title="Tags associated with the model version",
default=None,
)
ModelVersionResponse (WorkspaceScopedResponse[ModelVersionResponseBody, ModelVersionResponseMetadata, ModelVersionResponseResources])
Response model for model versions.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionResponse(
WorkspaceScopedResponse[
ModelVersionResponseBody,
ModelVersionResponseMetadata,
ModelVersionResponseResources,
]
):
"""Response model for model versions."""
name: Optional[str] = Field(
description="The name of the model version",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
@property
def stage(self) -> Optional[str]:
"""The `stage` property.
Returns:
the value of the property.
"""
return self.get_body().stage
@property
def number(self) -> int:
"""The `number` property.
Returns:
the value of the property.
"""
return self.get_body().number
@property
def model(self) -> "ModelResponse":
"""The `model` property.
Returns:
the value of the property.
"""
return self.get_body().model
@property
def model_artifact_ids(self) -> Dict[str, Dict[str, UUID]]:
"""The `model_artifact_ids` property.
Returns:
the value of the property.
"""
return self.get_body().model_artifact_ids
@property
def data_artifact_ids(self) -> Dict[str, Dict[str, UUID]]:
"""The `data_artifact_ids` property.
Returns:
the value of the property.
"""
return self.get_body().data_artifact_ids
@property
def deployment_artifact_ids(self) -> Dict[str, Dict[str, UUID]]:
"""The `deployment_artifact_ids` property.
Returns:
the value of the property.
"""
return self.get_body().deployment_artifact_ids
@property
def pipeline_run_ids(self) -> Dict[str, UUID]:
"""The `pipeline_run_ids` property.
Returns:
the value of the property.
"""
return self.get_body().pipeline_run_ids
@property
def tags(self) -> List[TagResponse]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_body().tags
@property
def description(self) -> Optional[str]:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def run_metadata(self) -> Optional[Dict[str, "RunMetadataResponse"]]:
"""The `run_metadata` property.
Returns:
the value of the property.
"""
return self.get_metadata().run_metadata
def get_hydrated_version(self) -> "ModelVersionResponse":
"""Get the hydrated version of this model version.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_model_version(self.id)
# Helper functions
def to_model_class(
self,
was_created_in_this_run: bool = False,
suppress_class_validation_warnings: bool = False,
) -> "Model":
"""Convert response model to Model object.
Args:
was_created_in_this_run: Whether model version was created during
the current run.
suppress_class_validation_warnings: internally used to suppress
repeated warnings.
Returns:
Model object
"""
from zenml.model.model import Model
mv = Model(
name=self.model.name,
license=self.model.license,
description=self.description,
audience=self.model.audience,
use_cases=self.model.use_cases,
limitations=self.model.limitations,
trade_offs=self.model.trade_offs,
ethics=self.model.ethics,
tags=[t.name for t in self.tags],
version=self.name,
was_created_in_this_run=was_created_in_this_run,
suppress_class_validation_warnings=suppress_class_validation_warnings,
model_version_id=self.id,
)
return mv
@property
def model_artifacts(
self,
) -> Dict[str, Dict[str, "ArtifactVersionResponse"]]:
"""Get all model artifacts linked to this model version.
Returns:
Dictionary of model artifacts with versions as
Dict[str, Dict[str, ArtifactResponse]]
"""
from zenml.client import Client
return {
name: {
version: Client().get_artifact_version(a)
for version, a in self.model_artifact_ids[name].items()
}
for name in self.model_artifact_ids
}
@property
def data_artifacts(
self,
) -> Dict[str, Dict[str, "ArtifactVersionResponse"]]:
"""Get all data artifacts linked to this model version.
Returns:
Dictionary of data artifacts with versions as
Dict[str, Dict[str, ArtifactResponse]]
"""
from zenml.client import Client
return {
name: {
version: Client().get_artifact_version(a)
for version, a in self.data_artifact_ids[name].items()
}
for name in self.data_artifact_ids
}
@property
def deployment_artifacts(
self,
) -> Dict[str, Dict[str, "ArtifactVersionResponse"]]:
"""Get all deployment artifacts linked to this model version.
Returns:
Dictionary of deployment artifacts with versions as
Dict[str, Dict[str, ArtifactResponse]]
"""
from zenml.client import Client
return {
name: {
version: Client().get_artifact_version(a)
for version, a in self.deployment_artifact_ids[name].items()
}
for name in self.deployment_artifact_ids
}
@property
def pipeline_runs(self) -> Dict[str, "PipelineRunResponse"]:
"""Get all pipeline runs linked to this version.
Returns:
Dictionary of Pipeline Runs as PipelineRunResponseModel
"""
from zenml.client import Client
return {
name: Client().get_pipeline_run(pr)
for name, pr in self.pipeline_run_ids.items()
}
def _get_linked_object(
self,
collection: Dict[str, Dict[str, UUID]],
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the artifact linked to this model version given type.
Args:
collection: The collection to search in (one of
self.model_artifact_ids, self.data_artifact_ids,
self.deployment_artifact_ids)
name: The name of the artifact to retrieve.
version: The version of the artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of an artifact from collection or None
"""
from zenml.client import Client
client = Client()
if name not in collection:
return None
if version is None:
version = max(collection[name].keys())
return client.get_artifact_version(collection[name][version])
def get_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the artifact linked to this model version.
Args:
name: The name of the artifact to retrieve.
version: The version of the artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of an artifact or None
"""
all_artifact_ids = {
**self.model_artifact_ids,
**self.data_artifact_ids,
**self.deployment_artifact_ids,
}
return self._get_linked_object(all_artifact_ids, name, version)
def get_model_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the model artifact linked to this model version.
Args:
name: The name of the model artifact to retrieve.
version: The version of the model artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of the model artifact or None
"""
return self._get_linked_object(self.model_artifact_ids, name, version)
def get_data_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the data artifact linked to this model version.
Args:
name: The name of the data artifact to retrieve.
version: The version of the data artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of the data artifact or None
"""
return self._get_linked_object(
self.data_artifact_ids,
name,
version,
)
def get_deployment_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the deployment artifact linked to this model version.
Args:
name: The name of the deployment artifact to retrieve.
version: The version of the deployment artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of the deployment artifact or None
"""
return self._get_linked_object(
self.deployment_artifact_ids,
name,
version,
)
def get_pipeline_run(self, name: str) -> "PipelineRunResponse":
"""Get pipeline run linked to this version.
Args:
name: The name of the pipeline run to retrieve.
Returns:
PipelineRun as PipelineRunResponseModel
"""
from zenml.client import Client
return Client().get_pipeline_run(self.pipeline_run_ids[name])
def set_stage(
self, stage: Union[str, ModelStages], force: bool = False
) -> None:
"""Sets this Model Version to a desired stage.
Args:
stage: the target stage for model version.
force: whether to force archiving of current model version in
target stage or raise.
Raises:
ValueError: if model_stage is not valid.
"""
from zenml.client import Client
stage = getattr(stage, "value", stage)
if stage not in [stage.value for stage in ModelStages]:
raise ValueError(f"`{stage}` is not a valid model stage.")
Client().update_model_version(
model_name_or_id=self.model.id,
version_name_or_id=self.id,
stage=stage,
force=force,
)
# TODO in https://zenml.atlassian.net/browse/OSS-2433
# def generate_model_card(self, template_name: str) -> str:
# """Return HTML/PDF based on input template"""
data_artifact_ids: Dict[str, Dict[str, uuid.UUID]]
property
readonly
The data_artifact_ids
property.
Returns:
Type | Description |
---|---|
Dict[str, Dict[str, uuid.UUID]] |
the value of the property. |
data_artifacts: Dict[str, Dict[str, ArtifactVersionResponse]]
property
readonly
Get all data artifacts linked to this model version.
Returns:
Type | Description |
---|---|
Dict[str, Dict[str, ArtifactVersionResponse]] |
Dictionary of data artifacts with versions as Dict[str, Dict[str, ArtifactResponse]] |
deployment_artifact_ids: Dict[str, Dict[str, uuid.UUID]]
property
readonly
The deployment_artifact_ids
property.
Returns:
Type | Description |
---|---|
Dict[str, Dict[str, uuid.UUID]] |
the value of the property. |
deployment_artifacts: Dict[str, Dict[str, ArtifactVersionResponse]]
property
readonly
Get all deployment artifacts linked to this model version.
Returns:
Type | Description |
---|---|
Dict[str, Dict[str, ArtifactVersionResponse]] |
Dictionary of deployment artifacts with versions as Dict[str, Dict[str, ArtifactResponse]] |
description: Optional[str]
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
model: ModelResponse
property
readonly
The model
property.
Returns:
Type | Description |
---|---|
ModelResponse |
the value of the property. |
model_artifact_ids: Dict[str, Dict[str, uuid.UUID]]
property
readonly
The model_artifact_ids
property.
Returns:
Type | Description |
---|---|
Dict[str, Dict[str, uuid.UUID]] |
the value of the property. |
model_artifacts: Dict[str, Dict[str, ArtifactVersionResponse]]
property
readonly
Get all model artifacts linked to this model version.
Returns:
Type | Description |
---|---|
Dict[str, Dict[str, ArtifactVersionResponse]] |
Dictionary of model artifacts with versions as Dict[str, Dict[str, ArtifactResponse]] |
number: int
property
readonly
The number
property.
Returns:
Type | Description |
---|---|
int |
the value of the property. |
pipeline_run_ids: Dict[str, uuid.UUID]
property
readonly
The pipeline_run_ids
property.
Returns:
Type | Description |
---|---|
Dict[str, uuid.UUID] |
the value of the property. |
pipeline_runs: Dict[str, PipelineRunResponse]
property
readonly
Get all pipeline runs linked to this version.
Returns:
Type | Description |
---|---|
Dict[str, PipelineRunResponse] |
Dictionary of Pipeline Runs as PipelineRunResponseModel |
run_metadata: Optional[Dict[str, RunMetadataResponse]]
property
readonly
The run_metadata
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, RunMetadataResponse]] |
the value of the property. |
stage: Optional[str]
property
readonly
The stage
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
tags: List[zenml.models.v2.core.tag.TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.tag.TagResponse] |
the value of the property. |
get_artifact(self, name, version=None)
Get the artifact linked to this model version.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the artifact to retrieve. |
required |
version |
Optional[str] |
The version of the artifact to retrieve (None for latest/non-versioned) |
None |
Returns:
Type | Description |
---|---|
Optional[ArtifactVersionResponse] |
Specific version of an artifact or None |
Source code in zenml/models/v2/core/model_version.py
def get_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the artifact linked to this model version.
Args:
name: The name of the artifact to retrieve.
version: The version of the artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of an artifact or None
"""
all_artifact_ids = {
**self.model_artifact_ids,
**self.data_artifact_ids,
**self.deployment_artifact_ids,
}
return self._get_linked_object(all_artifact_ids, name, version)
get_data_artifact(self, name, version=None)
Get the data artifact linked to this model version.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the data artifact to retrieve. |
required |
version |
Optional[str] |
The version of the data artifact to retrieve (None for latest/non-versioned) |
None |
Returns:
Type | Description |
---|---|
Optional[ArtifactVersionResponse] |
Specific version of the data artifact or None |
Source code in zenml/models/v2/core/model_version.py
def get_data_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the data artifact linked to this model version.
Args:
name: The name of the data artifact to retrieve.
version: The version of the data artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of the data artifact or None
"""
return self._get_linked_object(
self.data_artifact_ids,
name,
version,
)
get_deployment_artifact(self, name, version=None)
Get the deployment artifact linked to this model version.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the deployment artifact to retrieve. |
required |
version |
Optional[str] |
The version of the deployment artifact to retrieve (None for latest/non-versioned) |
None |
Returns:
Type | Description |
---|---|
Optional[ArtifactVersionResponse] |
Specific version of the deployment artifact or None |
Source code in zenml/models/v2/core/model_version.py
def get_deployment_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the deployment artifact linked to this model version.
Args:
name: The name of the deployment artifact to retrieve.
version: The version of the deployment artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of the deployment artifact or None
"""
return self._get_linked_object(
self.deployment_artifact_ids,
name,
version,
)
get_hydrated_version(self)
Get the hydrated version of this model version.
Returns:
Type | Description |
---|---|
ModelVersionResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/model_version.py
def get_hydrated_version(self) -> "ModelVersionResponse":
"""Get the hydrated version of this model version.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_model_version(self.id)
get_model_artifact(self, name, version=None)
Get the model artifact linked to this model version.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the model artifact to retrieve. |
required |
version |
Optional[str] |
The version of the model artifact to retrieve (None for latest/non-versioned) |
None |
Returns:
Type | Description |
---|---|
Optional[ArtifactVersionResponse] |
Specific version of the model artifact or None |
Source code in zenml/models/v2/core/model_version.py
def get_model_artifact(
self,
name: str,
version: Optional[str] = None,
) -> Optional["ArtifactVersionResponse"]:
"""Get the model artifact linked to this model version.
Args:
name: The name of the model artifact to retrieve.
version: The version of the model artifact to retrieve (None for
latest/non-versioned)
Returns:
Specific version of the model artifact or None
"""
return self._get_linked_object(self.model_artifact_ids, name, version)
get_pipeline_run(self, name)
Get pipeline run linked to this version.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name |
str |
The name of the pipeline run to retrieve. |
required |
Returns:
Type | Description |
---|---|
PipelineRunResponse |
PipelineRun as PipelineRunResponseModel |
Source code in zenml/models/v2/core/model_version.py
def get_pipeline_run(self, name: str) -> "PipelineRunResponse":
"""Get pipeline run linked to this version.
Args:
name: The name of the pipeline run to retrieve.
Returns:
PipelineRun as PipelineRunResponseModel
"""
from zenml.client import Client
return Client().get_pipeline_run(self.pipeline_run_ids[name])
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model_version.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_stage(self, stage, force=False)
Sets this Model Version to a desired stage.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
stage |
Union[str, zenml.enums.ModelStages] |
the target stage for model version. |
required |
force |
bool |
whether to force archiving of current model version in target stage or raise. |
False |
Exceptions:
Type | Description |
---|---|
ValueError |
if model_stage is not valid. |
Source code in zenml/models/v2/core/model_version.py
def set_stage(
self, stage: Union[str, ModelStages], force: bool = False
) -> None:
"""Sets this Model Version to a desired stage.
Args:
stage: the target stage for model version.
force: whether to force archiving of current model version in
target stage or raise.
Raises:
ValueError: if model_stage is not valid.
"""
from zenml.client import Client
stage = getattr(stage, "value", stage)
if stage not in [stage.value for stage in ModelStages]:
raise ValueError(f"`{stage}` is not a valid model stage.")
Client().update_model_version(
model_name_or_id=self.model.id,
version_name_or_id=self.id,
stage=stage,
force=force,
)
to_model_class(self, was_created_in_this_run=False, suppress_class_validation_warnings=False)
Convert response model to Model object.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
was_created_in_this_run |
bool |
Whether model version was created during the current run. |
False |
suppress_class_validation_warnings |
bool |
internally used to suppress repeated warnings. |
False |
Returns:
Type | Description |
---|---|
Model |
Model object |
Source code in zenml/models/v2/core/model_version.py
def to_model_class(
self,
was_created_in_this_run: bool = False,
suppress_class_validation_warnings: bool = False,
) -> "Model":
"""Convert response model to Model object.
Args:
was_created_in_this_run: Whether model version was created during
the current run.
suppress_class_validation_warnings: internally used to suppress
repeated warnings.
Returns:
Model object
"""
from zenml.model.model import Model
mv = Model(
name=self.model.name,
license=self.model.license,
description=self.description,
audience=self.model.audience,
use_cases=self.model.use_cases,
limitations=self.model.limitations,
trade_offs=self.model.trade_offs,
ethics=self.model.ethics,
tags=[t.name for t in self.tags],
version=self.name,
was_created_in_this_run=was_created_in_this_run,
suppress_class_validation_warnings=suppress_class_validation_warnings,
model_version_id=self.id,
)
return mv
ModelVersionResponseBody (WorkspaceScopedResponseBody)
Response body for model versions.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionResponseBody(WorkspaceScopedResponseBody):
"""Response body for model versions."""
stage: Optional[str] = Field(
description="The stage of the model version",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
number: int = Field(
description="The number of the model version",
)
model: "ModelResponse" = Field(
description="The model containing version",
)
model_artifact_ids: Dict[str, Dict[str, UUID]] = Field(
description="Model artifacts linked to the model version",
default={},
)
data_artifact_ids: Dict[str, Dict[str, UUID]] = Field(
description="Data artifacts linked to the model version",
default={},
)
deployment_artifact_ids: Dict[str, Dict[str, UUID]] = Field(
description="Deployment artifacts linked to the model version",
default={},
)
pipeline_run_ids: Dict[str, UUID] = Field(
description="Pipeline runs linked to the model version",
default={},
)
tags: List[TagResponse] = Field(
title="Tags associated with the model version", default=[]
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
ModelVersionResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for model versions.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for model versions."""
description: Optional[str] = Field(
description="The description of the model version",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
run_metadata: Dict[str, "RunMetadataResponse"] = Field(
description="Metadata linked to the model version",
default={},
)
ModelVersionResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the model version entity.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the model version entity."""
services: Page[ServiceResponse] = Field(
description="Services linked to the model version",
)
ModelVersionUpdate (BaseModel)
Update model for model versions.
Source code in zenml/models/v2/core/model_version.py
class ModelVersionUpdate(BaseModel):
"""Update model for model versions."""
model: UUID = Field(
description="The ID of the model containing version",
)
stage: Optional[Union[str, ModelStages]] = Field(
description="Target model version stage to be set",
default=None,
union_mode="left_to_right",
)
force: bool = Field(
description="Whether existing model version in target stage should be "
"silently archived or an error should be raised.",
default=False,
)
name: Optional[str] = Field(
description="Target model version name to be set",
default=None,
)
description: Optional[str] = Field(
description="Target model version description to be set",
default=None,
)
add_tags: Optional[List[str]] = Field(
description="Tags to be added to the model version",
default=None,
)
remove_tags: Optional[List[str]] = Field(
description="Tags to be removed from the model version",
default=None,
)
@field_validator("stage")
@classmethod
def _validate_stage(cls, stage: str) -> str:
stage = getattr(stage, "value", stage)
if stage is not None and stage not in [
stage.value for stage in ModelStages
]:
raise ValueError(f"`{stage}` is not a valid model stage.")
return stage
model_version_artifact
Models representing the link between model versions and artifacts.
ModelVersionArtifactFilter (WorkspaceScopedFilter)
Model version pipeline run links filter model.
Source code in zenml/models/v2/core/model_version_artifact.py
class ModelVersionArtifactFilter(WorkspaceScopedFilter):
"""Model version pipeline run links filter model."""
# Artifact name and type are not DB fields and need to be handled separately
FILTER_EXCLUDE_FIELDS = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"artifact_name",
"only_data_artifacts",
"only_model_artifacts",
"only_deployment_artifacts",
"has_custom_name",
"user",
]
CLI_EXCLUDE_FIELDS = [
*WorkspaceScopedFilter.CLI_EXCLUDE_FIELDS,
"only_data_artifacts",
"only_model_artifacts",
"only_deployment_artifacts",
"has_custom_name",
"model_id",
"model_version_id",
"user_id",
"workspace_id",
"updated",
"id",
]
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The workspace of the Model Version",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The user of the Model Version",
union_mode="left_to_right",
)
model_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Filter by model ID",
union_mode="left_to_right",
)
model_version_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Filter by model version ID",
union_mode="left_to_right",
)
artifact_version_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Filter by artifact ID",
union_mode="left_to_right",
)
artifact_name: Optional[str] = Field(
default=None,
description="Name of the artifact",
)
only_data_artifacts: Optional[bool] = False
only_model_artifacts: Optional[bool] = False
only_deployment_artifacts: Optional[bool] = False
has_custom_name: Optional[bool] = None
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the artifact.",
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
def get_custom_filters(self) -> List[Union["ColumnElement[bool]"]]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ArtifactSchema,
ArtifactVersionSchema,
ModelVersionArtifactSchema,
UserSchema,
)
if self.artifact_name:
value, filter_operator = self._resolve_operator(self.artifact_name)
filter_ = StrFilter(
operation=GenericFilterOps(filter_operator),
column="name",
value=value,
)
artifact_name_filter = and_(
ModelVersionArtifactSchema.artifact_version_id
== ArtifactVersionSchema.id,
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
filter_.generate_query_conditions(ArtifactSchema),
)
custom_filters.append(artifact_name_filter)
if self.only_data_artifacts:
data_artifact_filter = and_(
ModelVersionArtifactSchema.is_model_artifact.is_(False), # type: ignore[attr-defined]
ModelVersionArtifactSchema.is_deployment_artifact.is_(False), # type: ignore[attr-defined]
)
custom_filters.append(data_artifact_filter)
if self.only_model_artifacts:
model_artifact_filter = and_(
ModelVersionArtifactSchema.is_model_artifact.is_(True), # type: ignore[attr-defined]
)
custom_filters.append(model_artifact_filter)
if self.only_deployment_artifacts:
deployment_artifact_filter = and_(
ModelVersionArtifactSchema.is_deployment_artifact.is_(True), # type: ignore[attr-defined]
)
custom_filters.append(deployment_artifact_filter)
if self.has_custom_name is not None:
custom_name_filter = and_(
ModelVersionArtifactSchema.artifact_version_id
== ArtifactVersionSchema.id,
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
ArtifactSchema.has_custom_name == self.has_custom_name,
)
custom_filters.append(custom_name_filter)
if self.user:
user_filter = and_(
ModelVersionArtifactSchema.artifact_version_id
== ArtifactVersionSchema.id,
ArtifactVersionSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/model_version_artifact.py
def get_custom_filters(self) -> List[Union["ColumnElement[bool]"]]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ArtifactSchema,
ArtifactVersionSchema,
ModelVersionArtifactSchema,
UserSchema,
)
if self.artifact_name:
value, filter_operator = self._resolve_operator(self.artifact_name)
filter_ = StrFilter(
operation=GenericFilterOps(filter_operator),
column="name",
value=value,
)
artifact_name_filter = and_(
ModelVersionArtifactSchema.artifact_version_id
== ArtifactVersionSchema.id,
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
filter_.generate_query_conditions(ArtifactSchema),
)
custom_filters.append(artifact_name_filter)
if self.only_data_artifacts:
data_artifact_filter = and_(
ModelVersionArtifactSchema.is_model_artifact.is_(False), # type: ignore[attr-defined]
ModelVersionArtifactSchema.is_deployment_artifact.is_(False), # type: ignore[attr-defined]
)
custom_filters.append(data_artifact_filter)
if self.only_model_artifacts:
model_artifact_filter = and_(
ModelVersionArtifactSchema.is_model_artifact.is_(True), # type: ignore[attr-defined]
)
custom_filters.append(model_artifact_filter)
if self.only_deployment_artifacts:
deployment_artifact_filter = and_(
ModelVersionArtifactSchema.is_deployment_artifact.is_(True), # type: ignore[attr-defined]
)
custom_filters.append(deployment_artifact_filter)
if self.has_custom_name is not None:
custom_name_filter = and_(
ModelVersionArtifactSchema.artifact_version_id
== ArtifactVersionSchema.id,
ArtifactVersionSchema.artifact_id == ArtifactSchema.id,
ArtifactSchema.has_custom_name == self.has_custom_name,
)
custom_filters.append(custom_name_filter)
if self.user:
user_filter = and_(
ModelVersionArtifactSchema.artifact_version_id
== ArtifactVersionSchema.id,
ArtifactVersionSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model_version_artifact.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ModelVersionArtifactRequest (WorkspaceScopedRequest)
Request model for links between model versions and artifacts.
Source code in zenml/models/v2/core/model_version_artifact.py
class ModelVersionArtifactRequest(WorkspaceScopedRequest):
"""Request model for links between model versions and artifacts."""
model: UUID
model_version: UUID
artifact_version: UUID
is_model_artifact: bool = False
is_deployment_artifact: bool = False
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
@model_validator(mode="after")
def _validate_is_endpoint_artifact(self) -> "ModelVersionArtifactRequest":
if self.is_model_artifact and self.is_deployment_artifact:
raise ValueError(
"Artifact cannot be a model artifact and deployment artifact "
"at the same time."
)
return self
ModelVersionArtifactResponse (BaseIdentifiedResponse[ModelVersionArtifactResponseBody, BaseResponseMetadata, ModelVersionArtifactResponseResources])
Response model for links between model versions and artifacts.
Source code in zenml/models/v2/core/model_version_artifact.py
class ModelVersionArtifactResponse(
BaseIdentifiedResponse[
ModelVersionArtifactResponseBody,
BaseResponseMetadata,
ModelVersionArtifactResponseResources,
]
):
"""Response model for links between model versions and artifacts."""
# Body and metadata properties
@property
def model(self) -> UUID:
"""The `model` property.
Returns:
the value of the property.
"""
return self.get_body().model
@property
def model_version(self) -> UUID:
"""The `model_version` property.
Returns:
the value of the property.
"""
return self.get_body().model_version
@property
def artifact_version(self) -> "ArtifactVersionResponse":
"""The `artifact_version` property.
Returns:
the value of the property.
"""
return self.get_body().artifact_version
@property
def is_model_artifact(self) -> bool:
"""The `is_model_artifact` property.
Returns:
the value of the property.
"""
return self.get_body().is_model_artifact
@property
def is_deployment_artifact(self) -> bool:
"""The `is_deployment_artifact` property.
Returns:
the value of the property.
"""
return self.get_body().is_deployment_artifact
artifact_version: ArtifactVersionResponse
property
readonly
The artifact_version
property.
Returns:
Type | Description |
---|---|
ArtifactVersionResponse |
the value of the property. |
is_deployment_artifact: bool
property
readonly
The is_deployment_artifact
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
is_model_artifact: bool
property
readonly
The is_model_artifact
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
model: UUID
property
readonly
The model
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
model_version: UUID
property
readonly
The model_version
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model_version_artifact.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ModelVersionArtifactResponseBody (BaseDatedResponseBody)
Response body for links between model versions and artifacts.
Source code in zenml/models/v2/core/model_version_artifact.py
class ModelVersionArtifactResponseBody(BaseDatedResponseBody):
"""Response body for links between model versions and artifacts."""
model: UUID
model_version: UUID
artifact_version: "ArtifactVersionResponse"
is_model_artifact: bool = False
is_deployment_artifact: bool = False
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
ModelVersionArtifactResponseResources (BaseResponseResources)
Class for all resource models associated with the model version artifact entity.
Source code in zenml/models/v2/core/model_version_artifact.py
class ModelVersionArtifactResponseResources(BaseResponseResources):
"""Class for all resource models associated with the model version artifact entity."""
model_version_pipeline_run
Models representing the link between model versions and pipeline runs.
ModelVersionPipelineRunFilter (WorkspaceScopedFilter)
Model version pipeline run links filter model.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
class ModelVersionPipelineRunFilter(WorkspaceScopedFilter):
"""Model version pipeline run links filter model."""
FILTER_EXCLUDE_FIELDS = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"pipeline_run_name",
"user",
]
CLI_EXCLUDE_FIELDS = [
*WorkspaceScopedFilter.CLI_EXCLUDE_FIELDS,
"model_id",
"model_version_id",
"user_id",
"workspace_id",
"updated",
"id",
]
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The workspace of the Model Version",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The user of the Model Version",
union_mode="left_to_right",
)
model_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Filter by model ID",
union_mode="left_to_right",
)
model_version_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Filter by model version ID",
union_mode="left_to_right",
)
pipeline_run_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Filter by pipeline run ID",
union_mode="left_to_right",
)
pipeline_run_name: Optional[str] = Field(
default=None,
description="Name of the pipeline run",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the pipeline run.",
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ModelVersionPipelineRunSchema,
PipelineRunSchema,
UserSchema,
)
if self.pipeline_run_name:
value, filter_operator = self._resolve_operator(
self.pipeline_run_name
)
filter_ = StrFilter(
operation=GenericFilterOps(filter_operator),
column="name",
value=value,
)
pipeline_run_name_filter = and_(
ModelVersionPipelineRunSchema.pipeline_run_id
== PipelineRunSchema.id,
filter_.generate_query_conditions(PipelineRunSchema),
)
custom_filters.append(pipeline_run_name_filter)
if self.user:
user_filter = and_(
ModelVersionPipelineRunSchema.pipeline_run_id
== PipelineRunSchema.id,
PipelineRunSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/model_version_pipeline_run.py
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ModelVersionPipelineRunSchema,
PipelineRunSchema,
UserSchema,
)
if self.pipeline_run_name:
value, filter_operator = self._resolve_operator(
self.pipeline_run_name
)
filter_ = StrFilter(
operation=GenericFilterOps(filter_operator),
column="name",
value=value,
)
pipeline_run_name_filter = and_(
ModelVersionPipelineRunSchema.pipeline_run_id
== PipelineRunSchema.id,
filter_.generate_query_conditions(PipelineRunSchema),
)
custom_filters.append(pipeline_run_name_filter)
if self.user:
user_filter = and_(
ModelVersionPipelineRunSchema.pipeline_run_id
== PipelineRunSchema.id,
PipelineRunSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ModelVersionPipelineRunRequest (WorkspaceScopedRequest)
Request model for links between model versions and pipeline runs.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
class ModelVersionPipelineRunRequest(WorkspaceScopedRequest):
"""Request model for links between model versions and pipeline runs."""
model: UUID
model_version: UUID
pipeline_run: UUID
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
ModelVersionPipelineRunResponse (BaseIdentifiedResponse[ModelVersionPipelineRunResponseBody, BaseResponseMetadata, ModelVersionPipelineRunResponseResources])
Response model for links between model versions and pipeline runs.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
class ModelVersionPipelineRunResponse(
BaseIdentifiedResponse[
ModelVersionPipelineRunResponseBody,
BaseResponseMetadata,
ModelVersionPipelineRunResponseResources,
]
):
"""Response model for links between model versions and pipeline runs."""
# Body and metadata properties
@property
def model(self) -> UUID:
"""The `model` property.
Returns:
the value of the property.
"""
return self.get_body().model
@property
def model_version(self) -> UUID:
"""The `model_version` property.
Returns:
the value of the property.
"""
return self.get_body().model_version
@property
def pipeline_run(self) -> "PipelineRunResponse":
"""The `pipeline_run` property.
Returns:
the value of the property.
"""
return self.get_body().pipeline_run
model: UUID
property
readonly
The model
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
model_version: UUID
property
readonly
The model_version
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
pipeline_run: PipelineRunResponse
property
readonly
The pipeline_run
property.
Returns:
Type | Description |
---|---|
PipelineRunResponse |
the value of the property. |
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ModelVersionPipelineRunResponseBody (BaseDatedResponseBody)
Response body for links between model versions and pipeline runs.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
class ModelVersionPipelineRunResponseBody(BaseDatedResponseBody):
"""Response body for links between model versions and pipeline runs."""
model: UUID
model_version: UUID
pipeline_run: PipelineRunResponse
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
ModelVersionPipelineRunResponseResources (BaseResponseResources)
Class for all resource models associated with the model version pipeline run entity.
Source code in zenml/models/v2/core/model_version_pipeline_run.py
class ModelVersionPipelineRunResponseResources(BaseResponseResources):
"""Class for all resource models associated with the model version pipeline run entity."""
pipeline
Models representing pipelines.
PipelineFilter (WorkspaceScopedTaggableFilter)
Pipeline filter model.
Source code in zenml/models/v2/core/pipeline.py
class PipelineFilter(WorkspaceScopedTaggableFilter):
"""Pipeline filter model."""
CUSTOM_SORTING_OPTIONS = [SORT_PIPELINES_BY_LATEST_RUN_KEY]
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
"user",
"latest_run_status",
]
name: Optional[str] = Field(
default=None,
description="Name of the Pipeline",
)
latest_run_status: Optional[str] = Field(
default=None,
description="Filter by the status of the latest run of a pipeline. "
"This will always be applied as an `AND` filter for now.",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the Pipeline",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User of the Pipeline",
union_mode="left_to_right",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the pipeline.",
)
def apply_filter(
self, query: AnyQuery, table: Type["AnySchema"]
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query, table)
from sqlmodel import and_, col, func, select
from zenml.zen_stores.schemas import PipelineRunSchema, PipelineSchema
if self.latest_run_status:
latest_pipeline_run_subquery = (
select(
PipelineRunSchema.pipeline_id,
func.max(PipelineRunSchema.created).label("created"),
)
.where(col(PipelineRunSchema.pipeline_id).is_not(None))
.group_by(col(PipelineRunSchema.pipeline_id))
.subquery()
)
query = (
query.join(
PipelineRunSchema,
PipelineSchema.id == PipelineRunSchema.pipeline_id,
)
.join(
latest_pipeline_run_subquery,
and_(
PipelineRunSchema.pipeline_id
== latest_pipeline_run_subquery.c.pipeline_id,
PipelineRunSchema.created
== latest_pipeline_run_subquery.c.created,
),
)
.where(
self.generate_custom_query_conditions_for_column(
value=self.latest_run_status,
table=PipelineRunSchema,
column="status",
)
)
)
return query
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
PipelineSchema,
UserSchema,
)
if self.user:
user_filter = and_(
PipelineSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
def apply_sorting(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Apply sorting to the query.
Args:
query: The query to which to apply the sorting.
table: The query table.
Returns:
The query with sorting applied.
"""
column, _ = self.sorting_params
if column == SORT_PIPELINES_BY_LATEST_RUN_KEY:
# If sorting by the latest run, the sorting is already done in the
# base query in `SqlZenStore.list_pipelines(...)` and we don't need
# to to anything here
return query
else:
return super().apply_sorting(query=query, table=table)
apply_filter(self, query, table)
Applies the filter to a query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/core/pipeline.py
def apply_filter(
self, query: AnyQuery, table: Type["AnySchema"]
) -> AnyQuery:
"""Applies the filter to a query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query, table)
from sqlmodel import and_, col, func, select
from zenml.zen_stores.schemas import PipelineRunSchema, PipelineSchema
if self.latest_run_status:
latest_pipeline_run_subquery = (
select(
PipelineRunSchema.pipeline_id,
func.max(PipelineRunSchema.created).label("created"),
)
.where(col(PipelineRunSchema.pipeline_id).is_not(None))
.group_by(col(PipelineRunSchema.pipeline_id))
.subquery()
)
query = (
query.join(
PipelineRunSchema,
PipelineSchema.id == PipelineRunSchema.pipeline_id,
)
.join(
latest_pipeline_run_subquery,
and_(
PipelineRunSchema.pipeline_id
== latest_pipeline_run_subquery.c.pipeline_id,
PipelineRunSchema.created
== latest_pipeline_run_subquery.c.created,
),
)
.where(
self.generate_custom_query_conditions_for_column(
value=self.latest_run_status,
table=PipelineRunSchema,
column="status",
)
)
)
return query
apply_sorting(self, query, table)
Apply sorting to the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the sorting. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with sorting applied. |
Source code in zenml/models/v2/core/pipeline.py
def apply_sorting(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Apply sorting to the query.
Args:
query: The query to which to apply the sorting.
table: The query table.
Returns:
The query with sorting applied.
"""
column, _ = self.sorting_params
if column == SORT_PIPELINES_BY_LATEST_RUN_KEY:
# If sorting by the latest run, the sorting is already done in the
# base query in `SqlZenStore.list_pipelines(...)` and we don't need
# to to anything here
return query
else:
return super().apply_sorting(query=query, table=table)
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/pipeline.py
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
PipelineSchema,
UserSchema,
)
if self.user:
user_filter = and_(
PipelineSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
PipelineRequest (WorkspaceScopedRequest)
Request model for pipelines.
Source code in zenml/models/v2/core/pipeline.py
class PipelineRequest(WorkspaceScopedRequest):
"""Request model for pipelines."""
name: str = Field(
title="The name of the pipeline.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The description of the pipeline.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
tags: Optional[List[str]] = Field(
default=None,
title="Tags of the pipeline.",
)
PipelineResponse (WorkspaceScopedResponse[PipelineResponseBody, PipelineResponseMetadata, PipelineResponseResources])
Response model for pipelines.
Source code in zenml/models/v2/core/pipeline.py
class PipelineResponse(
WorkspaceScopedResponse[
PipelineResponseBody,
PipelineResponseMetadata,
PipelineResponseResources,
]
):
"""Response model for pipelines."""
name: str = Field(
title="The name of the pipeline.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "PipelineResponse":
"""Get the hydrated version of this pipeline.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_pipeline(self.id)
# Helper methods
def get_runs(self, **kwargs: Any) -> List["PipelineRunResponse"]:
"""Get runs of this pipeline.
Can be used to fetch runs other than `self.runs` and supports
fine-grained filtering and pagination.
Args:
**kwargs: Further arguments for filtering or pagination that are
passed to `client.list_pipeline_runs()`.
Returns:
List of runs of this pipeline.
"""
from zenml.client import Client
return Client().list_pipeline_runs(pipeline_id=self.id, **kwargs).items
@property
def runs(self) -> List["PipelineRunResponse"]:
"""Returns the 20 most recent runs of this pipeline in descending order.
Returns:
The 20 most recent runs of this pipeline in descending order.
"""
return self.get_runs()
@property
def num_runs(self) -> int:
"""Returns the number of runs of this pipeline.
Returns:
The number of runs of this pipeline.
"""
from zenml.client import Client
return Client().list_pipeline_runs(pipeline_id=self.id, size=1).total
@property
def last_run(self) -> "PipelineRunResponse":
"""Returns the last run of this pipeline.
Returns:
The last run of this pipeline.
Raises:
RuntimeError: If no runs were found for this pipeline.
"""
runs = self.get_runs(size=1)
if not runs:
raise RuntimeError(
f"No runs found for pipeline '{self.name}' with id {self.id}."
)
return runs[0]
@property
def last_successful_run(self) -> "PipelineRunResponse":
"""Returns the last successful run of this pipeline.
Returns:
The last successful run of this pipeline.
Raises:
RuntimeError: If no successful runs were found for this pipeline.
"""
runs = self.get_runs(status=ExecutionStatus.COMPLETED, size=1)
if not runs:
raise RuntimeError(
f"No successful runs found for pipeline '{self.name}' with id "
f"{self.id}."
)
return runs[0]
@property
def latest_run_id(self) -> Optional[UUID]:
"""The `latest_run_id` property.
Returns:
the value of the property.
"""
return self.get_body().latest_run_id
@property
def latest_run_status(self) -> Optional[ExecutionStatus]:
"""The `latest_run_status` property.
Returns:
the value of the property.
"""
return self.get_body().latest_run_status
@property
def tags(self) -> List[TagResponse]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_resources().tags
last_run: PipelineRunResponse
property
readonly
Returns the last run of this pipeline.
Returns:
Type | Description |
---|---|
PipelineRunResponse |
The last run of this pipeline. |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If no runs were found for this pipeline. |
last_successful_run: PipelineRunResponse
property
readonly
Returns the last successful run of this pipeline.
Returns:
Type | Description |
---|---|
PipelineRunResponse |
The last successful run of this pipeline. |
Exceptions:
Type | Description |
---|---|
RuntimeError |
If no successful runs were found for this pipeline. |
latest_run_id: Optional[uuid.UUID]
property
readonly
The latest_run_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
latest_run_status: Optional[zenml.enums.ExecutionStatus]
property
readonly
The latest_run_status
property.
Returns:
Type | Description |
---|---|
Optional[zenml.enums.ExecutionStatus] |
the value of the property. |
num_runs: int
property
readonly
Returns the number of runs of this pipeline.
Returns:
Type | Description |
---|---|
int |
The number of runs of this pipeline. |
runs: List[PipelineRunResponse]
property
readonly
Returns the 20 most recent runs of this pipeline in descending order.
Returns:
Type | Description |
---|---|
List[PipelineRunResponse] |
The 20 most recent runs of this pipeline in descending order. |
tags: List[zenml.models.v2.core.tag.TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.tag.TagResponse] |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this pipeline.
Returns:
Type | Description |
---|---|
PipelineResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/pipeline.py
def get_hydrated_version(self) -> "PipelineResponse":
"""Get the hydrated version of this pipeline.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_pipeline(self.id)
get_runs(self, **kwargs)
Get runs of this pipeline.
Can be used to fetch runs other than self.runs
and supports
fine-grained filtering and pagination.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
**kwargs |
Any |
Further arguments for filtering or pagination that are
passed to |
{} |
Returns:
Type | Description |
---|---|
List[PipelineRunResponse] |
List of runs of this pipeline. |
Source code in zenml/models/v2/core/pipeline.py
def get_runs(self, **kwargs: Any) -> List["PipelineRunResponse"]:
"""Get runs of this pipeline.
Can be used to fetch runs other than `self.runs` and supports
fine-grained filtering and pagination.
Args:
**kwargs: Further arguments for filtering or pagination that are
passed to `client.list_pipeline_runs()`.
Returns:
List of runs of this pipeline.
"""
from zenml.client import Client
return Client().list_pipeline_runs(pipeline_id=self.id, **kwargs).items
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
PipelineResponseBody (WorkspaceScopedResponseBody)
Response body for pipelines.
Source code in zenml/models/v2/core/pipeline.py
class PipelineResponseBody(WorkspaceScopedResponseBody):
"""Response body for pipelines."""
latest_run_id: Optional[UUID] = Field(
default=None,
title="The ID of the latest run of the pipeline.",
)
latest_run_status: Optional[ExecutionStatus] = Field(
default=None,
title="The status of the latest run of the pipeline.",
)
PipelineResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for pipelines.
Source code in zenml/models/v2/core/pipeline.py
class PipelineResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for pipelines."""
description: Optional[str] = Field(
default=None,
title="The description of the pipeline.",
)
PipelineResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the pipeline entity.
Source code in zenml/models/v2/core/pipeline.py
class PipelineResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the pipeline entity."""
tags: List[TagResponse] = Field(
title="Tags associated with the pipeline.",
)
PipelineUpdate (BaseUpdate)
Update model for pipelines.
Source code in zenml/models/v2/core/pipeline.py
class PipelineUpdate(BaseUpdate):
"""Update model for pipelines."""
description: Optional[str] = Field(
default=None,
title="The description of the pipeline.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
add_tags: Optional[List[str]] = Field(
default=None, title="New tags to add to the pipeline."
)
remove_tags: Optional[List[str]] = Field(
default=None, title="Tags to remove from the pipeline."
)
pipeline_build
Models representing pipeline builds.
PipelineBuildBase (BaseZenModel)
Base model for pipeline builds.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildBase(BaseZenModel):
"""Base model for pipeline builds."""
images: Dict[str, BuildItem] = Field(
default={}, title="The images of this build."
)
is_local: bool = Field(
title="Whether the build images are stored in a container registry "
"or locally.",
)
contains_code: bool = Field(
title="Whether any image of the build contains user code.",
)
zenml_version: Optional[str] = Field(
title="The version of ZenML used for this build.", default=None
)
python_version: Optional[str] = Field(
title="The Python version used for this build.", default=None
)
# Helper methods
@property
def requires_code_download(self) -> bool:
"""Whether the build requires code download.
Returns:
Whether the build requires code download.
"""
return any(
item.requires_code_download for item in self.images.values()
)
@staticmethod
def get_image_key(component_key: str, step: Optional[str] = None) -> str:
"""Get the image key.
Args:
component_key: The component key.
step: The pipeline step for which the image was built.
Returns:
The image key.
"""
if step:
return f"{step}.{component_key}"
else:
return component_key
def get_image(self, component_key: str, step: Optional[str] = None) -> str:
"""Get the image built for a specific key.
Args:
component_key: The key for which to get the image.
step: The pipeline step for which to get the image. If no image
exists for this step, will fall back to the pipeline image for
the same key.
Returns:
The image name or digest.
"""
return self._get_item(component_key=component_key, step=step).image
def get_settings_checksum(
self, component_key: str, step: Optional[str] = None
) -> Optional[str]:
"""Get the settings checksum for a specific key.
Args:
component_key: The key for which to get the checksum.
step: The pipeline step for which to get the checksum. If no
image exists for this step, will fall back to the pipeline image
for the same key.
Returns:
The settings checksum.
"""
return self._get_item(
component_key=component_key, step=step
).settings_checksum
def _get_item(
self, component_key: str, step: Optional[str] = None
) -> "BuildItem":
"""Get the item for a specific key.
Args:
component_key: The key for which to get the item.
step: The pipeline step for which to get the item. If no item
exists for this step, will fall back to the item for
the same key.
Raises:
KeyError: If no item exists for the given key.
Returns:
The build item.
"""
if step:
try:
combined_key = self.get_image_key(
component_key=component_key, step=step
)
return self.images[combined_key]
except KeyError:
pass
try:
return self.images[component_key]
except KeyError:
raise KeyError(
f"Unable to find image for key {component_key}. Available keys: "
f"{set(self.images)}."
)
requires_code_download: bool
property
readonly
Whether the build requires code download.
Returns:
Type | Description |
---|---|
bool |
Whether the build requires code download. |
get_image(self, component_key, step=None)
Get the image built for a specific key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_key |
str |
The key for which to get the image. |
required |
step |
Optional[str] |
The pipeline step for which to get the image. If no image exists for this step, will fall back to the pipeline image for the same key. |
None |
Returns:
Type | Description |
---|---|
str |
The image name or digest. |
Source code in zenml/models/v2/core/pipeline_build.py
def get_image(self, component_key: str, step: Optional[str] = None) -> str:
"""Get the image built for a specific key.
Args:
component_key: The key for which to get the image.
step: The pipeline step for which to get the image. If no image
exists for this step, will fall back to the pipeline image for
the same key.
Returns:
The image name or digest.
"""
return self._get_item(component_key=component_key, step=step).image
get_image_key(component_key, step=None)
staticmethod
Get the image key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_key |
str |
The component key. |
required |
step |
Optional[str] |
The pipeline step for which the image was built. |
None |
Returns:
Type | Description |
---|---|
str |
The image key. |
Source code in zenml/models/v2/core/pipeline_build.py
@staticmethod
def get_image_key(component_key: str, step: Optional[str] = None) -> str:
"""Get the image key.
Args:
component_key: The component key.
step: The pipeline step for which the image was built.
Returns:
The image key.
"""
if step:
return f"{step}.{component_key}"
else:
return component_key
get_settings_checksum(self, component_key, step=None)
Get the settings checksum for a specific key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_key |
str |
The key for which to get the checksum. |
required |
step |
Optional[str] |
The pipeline step for which to get the checksum. If no image exists for this step, will fall back to the pipeline image for the same key. |
None |
Returns:
Type | Description |
---|---|
Optional[str] |
The settings checksum. |
Source code in zenml/models/v2/core/pipeline_build.py
def get_settings_checksum(
self, component_key: str, step: Optional[str] = None
) -> Optional[str]:
"""Get the settings checksum for a specific key.
Args:
component_key: The key for which to get the checksum.
step: The pipeline step for which to get the checksum. If no
image exists for this step, will fall back to the pipeline image
for the same key.
Returns:
The settings checksum.
"""
return self._get_item(
component_key=component_key, step=step
).settings_checksum
PipelineBuildFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all pipeline builds.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all pipeline builds."""
workspace_id: Optional[Union[UUID, str]] = Field(
description="Workspace for this pipeline build.",
default=None,
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
description="User that produced this pipeline build.",
default=None,
union_mode="left_to_right",
)
pipeline_id: Optional[Union[UUID, str]] = Field(
description="Pipeline associated with the pipeline build.",
default=None,
union_mode="left_to_right",
)
stack_id: Optional[Union[UUID, str]] = Field(
description="Stack used for the Pipeline Run",
default=None,
union_mode="left_to_right",
)
is_local: Optional[bool] = Field(
description="Whether the build images are stored in a container "
"registry or locally.",
default=None,
)
contains_code: Optional[bool] = Field(
description="Whether any image of the build contains user code.",
default=None,
)
zenml_version: Optional[str] = Field(
description="The version of ZenML used for this build.", default=None
)
python_version: Optional[str] = Field(
description="The Python version used for this build.", default=None
)
checksum: Optional[str] = Field(
description="The build checksum.", default=None
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline_build.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
PipelineBuildRequest (PipelineBuildBase, WorkspaceScopedRequest)
Request model for pipelines builds.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildRequest(PipelineBuildBase, WorkspaceScopedRequest):
"""Request model for pipelines builds."""
checksum: Optional[str] = Field(title="The build checksum.", default=None)
stack_checksum: Optional[str] = Field(
title="The stack checksum.", default=None
)
stack: Optional[UUID] = Field(
title="The stack that was used for this build.", default=None
)
pipeline: Optional[UUID] = Field(
title="The pipeline that was used for this build.", default=None
)
PipelineBuildResponse (WorkspaceScopedResponse[PipelineBuildResponseBody, PipelineBuildResponseMetadata, PipelineBuildResponseResources])
Response model for pipeline builds.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildResponse(
WorkspaceScopedResponse[
PipelineBuildResponseBody,
PipelineBuildResponseMetadata,
PipelineBuildResponseResources,
]
):
"""Response model for pipeline builds."""
def get_hydrated_version(self) -> "PipelineBuildResponse":
"""Return the hydrated version of this pipeline build.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_build(self.id)
# Helper methods
def to_yaml(self) -> Dict[str, Any]:
"""Create a yaml representation of the pipeline build.
Create a yaml representation of the pipeline build that can be used
to create a PipelineBuildBase instance.
Returns:
The yaml representation of the pipeline build.
"""
# Get the base attributes
yaml_dict: Dict[str, Any] = json.loads(
self.model_dump_json(
exclude={
"body",
"metadata",
}
)
)
images = json.loads(
self.get_metadata().model_dump_json(
exclude={
"pipeline",
"stack",
"workspace",
}
)
)
yaml_dict.update(images)
return yaml_dict
@property
def requires_code_download(self) -> bool:
"""Whether the build requires code download.
Returns:
Whether the build requires code download.
"""
return any(
item.requires_code_download for item in self.images.values()
)
@staticmethod
def get_image_key(component_key: str, step: Optional[str] = None) -> str:
"""Get the image key.
Args:
component_key: The component key.
step: The pipeline step for which the image was built.
Returns:
The image key.
"""
if step:
return f"{step}.{component_key}"
else:
return component_key
def get_image(self, component_key: str, step: Optional[str] = None) -> str:
"""Get the image built for a specific key.
Args:
component_key: The key for which to get the image.
step: The pipeline step for which to get the image. If no image
exists for this step, will fall back to the pipeline image for
the same key.
Returns:
The image name or digest.
"""
return self._get_item(component_key=component_key, step=step).image
def get_settings_checksum(
self, component_key: str, step: Optional[str] = None
) -> Optional[str]:
"""Get the settings checksum for a specific key.
Args:
component_key: The key for which to get the checksum.
step: The pipeline step for which to get the checksum. If no
image exists for this step, will fall back to the pipeline image
for the same key.
Returns:
The settings checksum.
"""
return self._get_item(
component_key=component_key, step=step
).settings_checksum
def _get_item(
self, component_key: str, step: Optional[str] = None
) -> "BuildItem":
"""Get the item for a specific key.
Args:
component_key: The key for which to get the item.
step: The pipeline step for which to get the item. If no item
exists for this step, will fall back to the item for
the same key.
Raises:
KeyError: If no item exists for the given key.
Returns:
The build item.
"""
if step:
try:
combined_key = self.get_image_key(
component_key=component_key, step=step
)
return self.images[combined_key]
except KeyError:
pass
try:
return self.images[component_key]
except KeyError:
raise KeyError(
f"Unable to find image for key {component_key}. Available keys: "
f"{set(self.images)}."
)
# Body and metadata properties
@property
def pipeline(self) -> Optional["PipelineResponse"]:
"""The `pipeline` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline
@property
def stack(self) -> Optional["StackResponse"]:
"""The `stack` property.
Returns:
the value of the property.
"""
return self.get_metadata().stack
@property
def images(self) -> Dict[str, "BuildItem"]:
"""The `images` property.
Returns:
the value of the property.
"""
return self.get_metadata().images
@property
def zenml_version(self) -> Optional[str]:
"""The `zenml_version` property.
Returns:
the value of the property.
"""
return self.get_metadata().zenml_version
@property
def python_version(self) -> Optional[str]:
"""The `python_version` property.
Returns:
the value of the property.
"""
return self.get_metadata().python_version
@property
def checksum(self) -> Optional[str]:
"""The `checksum` property.
Returns:
the value of the property.
"""
return self.get_metadata().checksum
@property
def stack_checksum(self) -> Optional[str]:
"""The `stack_checksum` property.
Returns:
the value of the property.
"""
return self.get_metadata().stack_checksum
@property
def is_local(self) -> bool:
"""The `is_local` property.
Returns:
the value of the property.
"""
return self.get_metadata().is_local
@property
def contains_code(self) -> bool:
"""The `contains_code` property.
Returns:
the value of the property.
"""
return self.get_metadata().contains_code
checksum: Optional[str]
property
readonly
The checksum
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
contains_code: bool
property
readonly
The contains_code
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
images: Dict[str, BuildItem]
property
readonly
The images
property.
Returns:
Type | Description |
---|---|
Dict[str, BuildItem] |
the value of the property. |
is_local: bool
property
readonly
The is_local
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
pipeline: Optional[PipelineResponse]
property
readonly
The pipeline
property.
Returns:
Type | Description |
---|---|
Optional[PipelineResponse] |
the value of the property. |
python_version: Optional[str]
property
readonly
The python_version
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
requires_code_download: bool
property
readonly
Whether the build requires code download.
Returns:
Type | Description |
---|---|
bool |
Whether the build requires code download. |
stack: Optional[StackResponse]
property
readonly
The stack
property.
Returns:
Type | Description |
---|---|
Optional[StackResponse] |
the value of the property. |
stack_checksum: Optional[str]
property
readonly
The stack_checksum
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
zenml_version: Optional[str]
property
readonly
The zenml_version
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
get_hydrated_version(self)
Return the hydrated version of this pipeline build.
Returns:
Type | Description |
---|---|
PipelineBuildResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/pipeline_build.py
def get_hydrated_version(self) -> "PipelineBuildResponse":
"""Return the hydrated version of this pipeline build.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_build(self.id)
get_image(self, component_key, step=None)
Get the image built for a specific key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_key |
str |
The key for which to get the image. |
required |
step |
Optional[str] |
The pipeline step for which to get the image. If no image exists for this step, will fall back to the pipeline image for the same key. |
None |
Returns:
Type | Description |
---|---|
str |
The image name or digest. |
Source code in zenml/models/v2/core/pipeline_build.py
def get_image(self, component_key: str, step: Optional[str] = None) -> str:
"""Get the image built for a specific key.
Args:
component_key: The key for which to get the image.
step: The pipeline step for which to get the image. If no image
exists for this step, will fall back to the pipeline image for
the same key.
Returns:
The image name or digest.
"""
return self._get_item(component_key=component_key, step=step).image
get_image_key(component_key, step=None)
staticmethod
Get the image key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_key |
str |
The component key. |
required |
step |
Optional[str] |
The pipeline step for which the image was built. |
None |
Returns:
Type | Description |
---|---|
str |
The image key. |
Source code in zenml/models/v2/core/pipeline_build.py
@staticmethod
def get_image_key(component_key: str, step: Optional[str] = None) -> str:
"""Get the image key.
Args:
component_key: The component key.
step: The pipeline step for which the image was built.
Returns:
The image key.
"""
if step:
return f"{step}.{component_key}"
else:
return component_key
get_settings_checksum(self, component_key, step=None)
Get the settings checksum for a specific key.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
component_key |
str |
The key for which to get the checksum. |
required |
step |
Optional[str] |
The pipeline step for which to get the checksum. If no image exists for this step, will fall back to the pipeline image for the same key. |
None |
Returns:
Type | Description |
---|---|
Optional[str] |
The settings checksum. |
Source code in zenml/models/v2/core/pipeline_build.py
def get_settings_checksum(
self, component_key: str, step: Optional[str] = None
) -> Optional[str]:
"""Get the settings checksum for a specific key.
Args:
component_key: The key for which to get the checksum.
step: The pipeline step for which to get the checksum. If no
image exists for this step, will fall back to the pipeline image
for the same key.
Returns:
The settings checksum.
"""
return self._get_item(
component_key=component_key, step=step
).settings_checksum
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline_build.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
to_yaml(self)
Create a yaml representation of the pipeline build.
Create a yaml representation of the pipeline build that can be used to create a PipelineBuildBase instance.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
The yaml representation of the pipeline build. |
Source code in zenml/models/v2/core/pipeline_build.py
def to_yaml(self) -> Dict[str, Any]:
"""Create a yaml representation of the pipeline build.
Create a yaml representation of the pipeline build that can be used
to create a PipelineBuildBase instance.
Returns:
The yaml representation of the pipeline build.
"""
# Get the base attributes
yaml_dict: Dict[str, Any] = json.loads(
self.model_dump_json(
exclude={
"body",
"metadata",
}
)
)
images = json.loads(
self.get_metadata().model_dump_json(
exclude={
"pipeline",
"stack",
"workspace",
}
)
)
yaml_dict.update(images)
return yaml_dict
PipelineBuildResponseBody (WorkspaceScopedResponseBody)
Response body for pipeline builds.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildResponseBody(WorkspaceScopedResponseBody):
"""Response body for pipeline builds."""
PipelineBuildResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for pipeline builds.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for pipeline builds."""
pipeline: Optional["PipelineResponse"] = Field(
default=None, title="The pipeline that was used for this build."
)
stack: Optional["StackResponse"] = Field(
default=None, title="The stack that was used for this build."
)
images: Dict[str, "BuildItem"] = Field(
default={}, title="The images of this build."
)
zenml_version: Optional[str] = Field(
default=None, title="The version of ZenML used for this build."
)
python_version: Optional[str] = Field(
default=None, title="The Python version used for this build."
)
checksum: Optional[str] = Field(default=None, title="The build checksum.")
stack_checksum: Optional[str] = Field(
default=None, title="The stack checksum."
)
is_local: bool = Field(
title="Whether the build images are stored in a container "
"registry or locally.",
)
contains_code: bool = Field(
title="Whether any image of the build contains user code.",
)
PipelineBuildResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the pipeline build entity.
Source code in zenml/models/v2/core/pipeline_build.py
class PipelineBuildResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the pipeline build entity."""
pipeline_deployment
Models representing pipeline deployments.
PipelineDeploymentBase (BaseZenModel)
Base model for pipeline deployments.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentBase(BaseZenModel):
"""Base model for pipeline deployments."""
run_name_template: str = Field(
title="The run name template for runs created using this deployment.",
)
pipeline_configuration: PipelineConfiguration = Field(
title="The pipeline configuration for this deployment."
)
step_configurations: Dict[str, Step] = Field(
default={}, title="The step configurations for this deployment."
)
client_environment: Dict[str, str] = Field(
default={}, title="The client environment for this deployment."
)
client_version: Optional[str] = Field(
default=None,
title="The version of the ZenML installation on the client side.",
)
server_version: Optional[str] = Field(
default=None,
title="The version of the ZenML installation on the server side.",
)
pipeline_version_hash: Optional[str] = Field(
default=None,
title="The pipeline version hash of the deployment.",
)
pipeline_spec: Optional[PipelineSpec] = Field(
default=None,
title="The pipeline spec of the deployment.",
)
@property
def should_prevent_build_reuse(self) -> bool:
"""Whether the deployment prevents a build reuse.
Returns:
Whether the deployment prevents a build reuse.
"""
return any(
step.config.docker_settings.prevent_build_reuse
for step in self.step_configurations.values()
)
should_prevent_build_reuse: bool
property
readonly
Whether the deployment prevents a build reuse.
Returns:
Type | Description |
---|---|
bool |
Whether the deployment prevents a build reuse. |
PipelineDeploymentFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all pipeline deployments.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all pipeline deployments."""
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace for this deployment.",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that created this deployment.",
union_mode="left_to_right",
)
pipeline_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Pipeline associated with the deployment.",
union_mode="left_to_right",
)
stack_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Stack associated with the deployment.",
union_mode="left_to_right",
)
build_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Build associated with the deployment.",
union_mode="left_to_right",
)
schedule_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Schedule associated with the deployment.",
union_mode="left_to_right",
)
template_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Template used as base for the deployment.",
union_mode="left_to_right",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline_deployment.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
PipelineDeploymentRequest (PipelineDeploymentBase, WorkspaceScopedRequest)
Request model for pipeline deployments.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentRequest(
PipelineDeploymentBase, WorkspaceScopedRequest
):
"""Request model for pipeline deployments."""
stack: UUID = Field(title="The stack associated with the deployment.")
pipeline: Optional[UUID] = Field(
default=None, title="The pipeline associated with the deployment."
)
build: Optional[UUID] = Field(
default=None, title="The build associated with the deployment."
)
schedule: Optional[UUID] = Field(
default=None, title="The schedule associated with the deployment."
)
code_reference: Optional["CodeReferenceRequest"] = Field(
default=None,
title="The code reference associated with the deployment.",
)
code_path: Optional[str] = Field(
default=None,
title="Optional path where the code is stored in the artifact store.",
)
template: Optional[UUID] = Field(
default=None,
description="Template used for the deployment.",
)
PipelineDeploymentResponse (WorkspaceScopedResponse[PipelineDeploymentResponseBody, PipelineDeploymentResponseMetadata, PipelineDeploymentResponseResources])
Response model for pipeline deployments.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentResponse(
WorkspaceScopedResponse[
PipelineDeploymentResponseBody,
PipelineDeploymentResponseMetadata,
PipelineDeploymentResponseResources,
]
):
"""Response model for pipeline deployments."""
def get_hydrated_version(self) -> "PipelineDeploymentResponse":
"""Return the hydrated version of this pipeline deployment.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_deployment(self.id)
# Body and metadata properties
@property
def run_name_template(self) -> str:
"""The `run_name_template` property.
Returns:
the value of the property.
"""
return self.get_metadata().run_name_template
@property
def pipeline_configuration(self) -> PipelineConfiguration:
"""The `pipeline_configuration` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_configuration
@property
def step_configurations(self) -> Dict[str, Step]:
"""The `step_configurations` property.
Returns:
the value of the property.
"""
return self.get_metadata().step_configurations
@property
def client_environment(self) -> Dict[str, str]:
"""The `client_environment` property.
Returns:
the value of the property.
"""
return self.get_metadata().client_environment
@property
def client_version(self) -> Optional[str]:
"""The `client_version` property.
Returns:
the value of the property.
"""
return self.get_metadata().client_version
@property
def server_version(self) -> Optional[str]:
"""The `server_version` property.
Returns:
the value of the property.
"""
return self.get_metadata().server_version
@property
def pipeline_version_hash(self) -> Optional[str]:
"""The `pipeline_version_hash` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_version_hash
@property
def pipeline_spec(self) -> Optional[PipelineSpec]:
"""The `pipeline_spec` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_spec
@property
def code_path(self) -> Optional[str]:
"""The `code_path` property.
Returns:
the value of the property.
"""
return self.get_metadata().code_path
@property
def pipeline(self) -> Optional[PipelineResponse]:
"""The `pipeline` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline
@property
def stack(self) -> Optional[StackResponse]:
"""The `stack` property.
Returns:
the value of the property.
"""
return self.get_metadata().stack
@property
def build(self) -> Optional[PipelineBuildResponse]:
"""The `build` property.
Returns:
the value of the property.
"""
return self.get_metadata().build
@property
def schedule(self) -> Optional[ScheduleResponse]:
"""The `schedule` property.
Returns:
the value of the property.
"""
return self.get_metadata().schedule
@property
def code_reference(self) -> Optional[CodeReferenceResponse]:
"""The `code_reference` property.
Returns:
the value of the property.
"""
return self.get_metadata().code_reference
@property
def template_id(self) -> Optional[UUID]:
"""The `template_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().template_id
build: Optional[zenml.models.v2.core.pipeline_build.PipelineBuildResponse]
property
readonly
The build
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.pipeline_build.PipelineBuildResponse] |
the value of the property. |
client_environment: Dict[str, str]
property
readonly
The client_environment
property.
Returns:
Type | Description |
---|---|
Dict[str, str] |
the value of the property. |
client_version: Optional[str]
property
readonly
The client_version
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
code_path: Optional[str]
property
readonly
The code_path
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
code_reference: Optional[zenml.models.v2.core.code_reference.CodeReferenceResponse]
property
readonly
The code_reference
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.code_reference.CodeReferenceResponse] |
the value of the property. |
pipeline: Optional[zenml.models.v2.core.pipeline.PipelineResponse]
property
readonly
The pipeline
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.pipeline.PipelineResponse] |
the value of the property. |
pipeline_configuration: PipelineConfiguration
property
readonly
The pipeline_configuration
property.
Returns:
Type | Description |
---|---|
PipelineConfiguration |
the value of the property. |
pipeline_spec: Optional[zenml.config.pipeline_spec.PipelineSpec]
property
readonly
The pipeline_spec
property.
Returns:
Type | Description |
---|---|
Optional[zenml.config.pipeline_spec.PipelineSpec] |
the value of the property. |
pipeline_version_hash: Optional[str]
property
readonly
The pipeline_version_hash
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
run_name_template: str
property
readonly
The run_name_template
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
schedule: Optional[zenml.models.v2.core.schedule.ScheduleResponse]
property
readonly
The schedule
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.schedule.ScheduleResponse] |
the value of the property. |
server_version: Optional[str]
property
readonly
The server_version
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
stack: Optional[zenml.models.v2.core.stack.StackResponse]
property
readonly
The stack
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.stack.StackResponse] |
the value of the property. |
step_configurations: Dict[str, zenml.config.step_configurations.Step]
property
readonly
The step_configurations
property.
Returns:
Type | Description |
---|---|
Dict[str, zenml.config.step_configurations.Step] |
the value of the property. |
template_id: Optional[uuid.UUID]
property
readonly
The template_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
get_hydrated_version(self)
Return the hydrated version of this pipeline deployment.
Returns:
Type | Description |
---|---|
PipelineDeploymentResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/pipeline_deployment.py
def get_hydrated_version(self) -> "PipelineDeploymentResponse":
"""Return the hydrated version of this pipeline deployment.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_deployment(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline_deployment.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
PipelineDeploymentResponseBody (WorkspaceScopedResponseBody)
Response body for pipeline deployments.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentResponseBody(WorkspaceScopedResponseBody):
"""Response body for pipeline deployments."""
PipelineDeploymentResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for pipeline deployments.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for pipeline deployments."""
run_name_template: str = Field(
title="The run name template for runs created using this deployment.",
)
pipeline_configuration: PipelineConfiguration = Field(
title="The pipeline configuration for this deployment."
)
step_configurations: Dict[str, Step] = Field(
default={}, title="The step configurations for this deployment."
)
client_environment: Dict[str, str] = Field(
default={}, title="The client environment for this deployment."
)
client_version: Optional[str] = Field(
title="The version of the ZenML installation on the client side."
)
server_version: Optional[str] = Field(
title="The version of the ZenML installation on the server side."
)
pipeline_version_hash: Optional[str] = Field(
default=None, title="The pipeline version hash of the deployment."
)
pipeline_spec: Optional[PipelineSpec] = Field(
default=None, title="The pipeline spec of the deployment."
)
code_path: Optional[str] = Field(
default=None,
title="Optional path where the code is stored in the artifact store.",
)
pipeline: Optional[PipelineResponse] = Field(
default=None, title="The pipeline associated with the deployment."
)
stack: Optional[StackResponse] = Field(
default=None, title="The stack associated with the deployment."
)
build: Optional[PipelineBuildResponse] = Field(
default=None,
title="The pipeline build associated with the deployment.",
)
schedule: Optional[ScheduleResponse] = Field(
default=None, title="The schedule associated with the deployment."
)
code_reference: Optional[CodeReferenceResponse] = Field(
default=None,
title="The code reference associated with the deployment.",
)
template_id: Optional[UUID] = Field(
default=None,
description="Template used for the pipeline run.",
)
PipelineDeploymentResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the pipeline deployment entity.
Source code in zenml/models/v2/core/pipeline_deployment.py
class PipelineDeploymentResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the pipeline deployment entity."""
triggers: TriggerPage = Field( # type: ignore[valid-type]
title="The triggers configured with this event source.",
)
pipeline_run
Models representing pipeline runs.
PipelineRunFilter (WorkspaceScopedTaggableFilter)
Model to enable advanced filtering of all Workspaces.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunFilter(WorkspaceScopedTaggableFilter):
"""Model to enable advanced filtering of all Workspaces."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"unlisted",
"code_repository_id",
"build_id",
"schedule_id",
"stack_id",
"template_id",
"user",
"pipeline",
"stack",
"code_repository",
"model",
"pipeline_name",
"templatable",
]
name: Optional[str] = Field(
default=None,
description="Name of the Pipeline Run",
)
orchestrator_run_id: Optional[str] = Field(
default=None,
description="Name of the Pipeline Run within the orchestrator",
)
pipeline_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Pipeline associated with the Pipeline Run",
union_mode="left_to_right",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the Pipeline Run",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that created the Pipeline Run",
union_mode="left_to_right",
)
stack_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Stack used for the Pipeline Run",
union_mode="left_to_right",
)
schedule_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Schedule that triggered the Pipeline Run",
union_mode="left_to_right",
)
build_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Build used for the Pipeline Run",
union_mode="left_to_right",
)
deployment_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Deployment used for the Pipeline Run",
union_mode="left_to_right",
)
code_repository_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Code repository used for the Pipeline Run",
union_mode="left_to_right",
)
template_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Template used for the pipeline run.",
union_mode="left_to_right",
)
model_version_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Model version associated with the pipeline run.",
union_mode="left_to_right",
)
status: Optional[str] = Field(
default=None,
description="Name of the Pipeline Run",
)
start_time: Optional[Union[datetime, str]] = Field(
default=None,
description="Start time for this run",
union_mode="left_to_right",
)
end_time: Optional[Union[datetime, str]] = Field(
default=None,
description="End time for this run",
union_mode="left_to_right",
)
unlisted: Optional[bool] = None
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the run.",
)
# TODO: Remove once frontend is ready for it. This is replaced by the more
# generic `pipeline` filter below.
pipeline_name: Optional[str] = Field(
default=None,
description="Name of the pipeline associated with the run",
)
pipeline: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the pipeline associated with the run.",
)
stack: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the stack associated with the run.",
)
code_repository: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the code repository associated with the run.",
)
model: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the model associated with the run.",
)
templatable: Optional[bool] = Field(
default=None, description="Whether the run is templatable."
)
model_config = ConfigDict(protected_namespaces=())
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_, col, or_
from zenml.zen_stores.schemas import (
CodeReferenceSchema,
CodeRepositorySchema,
ModelSchema,
ModelVersionSchema,
PipelineBuildSchema,
PipelineDeploymentSchema,
PipelineRunSchema,
PipelineSchema,
ScheduleSchema,
StackSchema,
UserSchema,
)
if self.unlisted is not None:
if self.unlisted is True:
unlisted_filter = PipelineRunSchema.pipeline_id.is_(None) # type: ignore[union-attr]
else:
unlisted_filter = PipelineRunSchema.pipeline_id.is_not(None) # type: ignore[union-attr]
custom_filters.append(unlisted_filter)
if self.code_repository_id:
code_repo_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.code_reference_id
== CodeReferenceSchema.id,
CodeReferenceSchema.code_repository_id
== self.code_repository_id,
)
custom_filters.append(code_repo_filter)
if self.stack_id:
stack_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == StackSchema.id,
StackSchema.id == self.stack_id,
)
custom_filters.append(stack_filter)
if self.schedule_id:
schedule_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.schedule_id == ScheduleSchema.id,
ScheduleSchema.id == self.schedule_id,
)
custom_filters.append(schedule_filter)
if self.build_id:
pipeline_build_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id == PipelineBuildSchema.id,
PipelineBuildSchema.id == self.build_id,
)
custom_filters.append(pipeline_build_filter)
if self.template_id:
run_template_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.template_id == self.template_id,
)
custom_filters.append(run_template_filter)
if self.user:
user_filter = and_(
PipelineRunSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.pipeline:
pipeline_filter = and_(
PipelineRunSchema.pipeline_id == PipelineSchema.id,
self.generate_name_or_id_query_conditions(
value=self.pipeline, table=PipelineSchema
),
)
custom_filters.append(pipeline_filter)
if self.stack:
stack_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == StackSchema.id,
self.generate_name_or_id_query_conditions(
value=self.stack,
table=StackSchema,
),
)
custom_filters.append(stack_filter)
if self.code_repository:
code_repo_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.code_reference_id
== CodeReferenceSchema.id,
CodeReferenceSchema.code_repository_id
== CodeRepositorySchema.id,
self.generate_name_or_id_query_conditions(
value=self.code_repository,
table=CodeRepositorySchema,
),
)
custom_filters.append(code_repo_filter)
if self.model:
model_filter = and_(
PipelineRunSchema.model_version_id == ModelVersionSchema.id,
ModelVersionSchema.model_id == ModelSchema.id,
self.generate_name_or_id_query_conditions(
value=self.model, table=ModelSchema
),
)
custom_filters.append(model_filter)
if self.pipeline_name:
pipeline_name_filter = and_(
PipelineRunSchema.pipeline_id == PipelineSchema.id,
self.generate_custom_query_conditions_for_column(
value=self.pipeline_name,
table=PipelineSchema,
column="name",
),
)
custom_filters.append(pipeline_name_filter)
if self.templatable is not None:
if self.templatable is True:
templatable_filter = and_(
# The following condition is not perfect as it does not
# consider stacks with custom flavor components or local
# components, but the best we can do currently with our
# table columns.
PipelineRunSchema.deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id
== PipelineBuildSchema.id,
col(PipelineBuildSchema.is_local).is_(False),
col(PipelineBuildSchema.stack_id).is_not(None),
)
else:
templatable_filter = or_(
col(PipelineRunSchema.deployment_id).is_(None),
and_(
PipelineRunSchema.deployment_id
== PipelineDeploymentSchema.id,
col(PipelineDeploymentSchema.build_id).is_(None),
),
and_(
PipelineRunSchema.deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id
== PipelineBuildSchema.id,
or_(
col(PipelineBuildSchema.is_local).is_(True),
col(PipelineBuildSchema.stack_id).is_(None),
),
),
)
custom_filters.append(templatable_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/pipeline_run.py
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_, col, or_
from zenml.zen_stores.schemas import (
CodeReferenceSchema,
CodeRepositorySchema,
ModelSchema,
ModelVersionSchema,
PipelineBuildSchema,
PipelineDeploymentSchema,
PipelineRunSchema,
PipelineSchema,
ScheduleSchema,
StackSchema,
UserSchema,
)
if self.unlisted is not None:
if self.unlisted is True:
unlisted_filter = PipelineRunSchema.pipeline_id.is_(None) # type: ignore[union-attr]
else:
unlisted_filter = PipelineRunSchema.pipeline_id.is_not(None) # type: ignore[union-attr]
custom_filters.append(unlisted_filter)
if self.code_repository_id:
code_repo_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.code_reference_id
== CodeReferenceSchema.id,
CodeReferenceSchema.code_repository_id
== self.code_repository_id,
)
custom_filters.append(code_repo_filter)
if self.stack_id:
stack_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == StackSchema.id,
StackSchema.id == self.stack_id,
)
custom_filters.append(stack_filter)
if self.schedule_id:
schedule_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.schedule_id == ScheduleSchema.id,
ScheduleSchema.id == self.schedule_id,
)
custom_filters.append(schedule_filter)
if self.build_id:
pipeline_build_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id == PipelineBuildSchema.id,
PipelineBuildSchema.id == self.build_id,
)
custom_filters.append(pipeline_build_filter)
if self.template_id:
run_template_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.template_id == self.template_id,
)
custom_filters.append(run_template_filter)
if self.user:
user_filter = and_(
PipelineRunSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.pipeline:
pipeline_filter = and_(
PipelineRunSchema.pipeline_id == PipelineSchema.id,
self.generate_name_or_id_query_conditions(
value=self.pipeline, table=PipelineSchema
),
)
custom_filters.append(pipeline_filter)
if self.stack:
stack_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == StackSchema.id,
self.generate_name_or_id_query_conditions(
value=self.stack,
table=StackSchema,
),
)
custom_filters.append(stack_filter)
if self.code_repository:
code_repo_filter = and_(
PipelineRunSchema.deployment_id == PipelineDeploymentSchema.id,
PipelineDeploymentSchema.code_reference_id
== CodeReferenceSchema.id,
CodeReferenceSchema.code_repository_id
== CodeRepositorySchema.id,
self.generate_name_or_id_query_conditions(
value=self.code_repository,
table=CodeRepositorySchema,
),
)
custom_filters.append(code_repo_filter)
if self.model:
model_filter = and_(
PipelineRunSchema.model_version_id == ModelVersionSchema.id,
ModelVersionSchema.model_id == ModelSchema.id,
self.generate_name_or_id_query_conditions(
value=self.model, table=ModelSchema
),
)
custom_filters.append(model_filter)
if self.pipeline_name:
pipeline_name_filter = and_(
PipelineRunSchema.pipeline_id == PipelineSchema.id,
self.generate_custom_query_conditions_for_column(
value=self.pipeline_name,
table=PipelineSchema,
column="name",
),
)
custom_filters.append(pipeline_name_filter)
if self.templatable is not None:
if self.templatable is True:
templatable_filter = and_(
# The following condition is not perfect as it does not
# consider stacks with custom flavor components or local
# components, but the best we can do currently with our
# table columns.
PipelineRunSchema.deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id
== PipelineBuildSchema.id,
col(PipelineBuildSchema.is_local).is_(False),
col(PipelineBuildSchema.stack_id).is_not(None),
)
else:
templatable_filter = or_(
col(PipelineRunSchema.deployment_id).is_(None),
and_(
PipelineRunSchema.deployment_id
== PipelineDeploymentSchema.id,
col(PipelineDeploymentSchema.build_id).is_(None),
),
and_(
PipelineRunSchema.deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id
== PipelineBuildSchema.id,
or_(
col(PipelineBuildSchema.is_local).is_(True),
col(PipelineBuildSchema.stack_id).is_(None),
),
),
)
custom_filters.append(templatable_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline_run.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
PipelineRunRequest (WorkspaceScopedRequest)
Request model for pipeline runs.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunRequest(WorkspaceScopedRequest):
"""Request model for pipeline runs."""
name: str = Field(
title="The name of the pipeline run.",
max_length=STR_FIELD_MAX_LENGTH,
)
deployment: UUID = Field(
title="The deployment associated with the pipeline run."
)
pipeline: Optional[UUID] = Field(
title="The pipeline associated with the pipeline run.",
default=None,
)
orchestrator_run_id: Optional[str] = Field(
title="The orchestrator run ID.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
start_time: Optional[datetime] = Field(
title="The start time of the pipeline run.",
default=None,
)
end_time: Optional[datetime] = Field(
title="The end time of the pipeline run.",
default=None,
)
status: ExecutionStatus = Field(
title="The status of the pipeline run.",
)
client_environment: Dict[str, str] = Field(
default={},
title=(
"Environment of the client that initiated this pipeline run "
"(OS, Python version, etc.)."
),
)
orchestrator_environment: Dict[str, str] = Field(
default={},
title=(
"Environment of the orchestrator that executed this pipeline run "
"(OS, Python version, etc.)."
),
)
trigger_execution_id: Optional[UUID] = Field(
default=None,
title="ID of the trigger execution that triggered this run.",
)
tags: Optional[List[str]] = Field(
default=None,
title="Tags of the pipeline run.",
)
model_version_id: Optional[UUID] = Field(
title="The ID of the model version that was "
"configured by this pipeline run explicitly.",
default=None,
)
model_config = ConfigDict(protected_namespaces=())
PipelineRunResponse (WorkspaceScopedResponse[PipelineRunResponseBody, PipelineRunResponseMetadata, PipelineRunResponseResources])
Response model for pipeline runs.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunResponse(
WorkspaceScopedResponse[
PipelineRunResponseBody,
PipelineRunResponseMetadata,
PipelineRunResponseResources,
]
):
"""Response model for pipeline runs."""
name: str = Field(
title="The name of the pipeline run.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "PipelineRunResponse":
"""Get the hydrated version of this pipeline run.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_run(self.id)
# Helper methods
@property
def artifact_versions(self) -> List["ArtifactVersionResponse"]:
"""Get all artifact versions that are outputs of steps of this run.
Returns:
All output artifact versions of this run (including cached ones).
"""
from zenml.artifacts.utils import (
get_artifacts_versions_of_pipeline_run,
)
return get_artifacts_versions_of_pipeline_run(self)
@property
def produced_artifact_versions(self) -> List["ArtifactVersionResponse"]:
"""Get all artifact versions produced during this pipeline run.
Returns:
A list of all artifact versions produced during this pipeline run.
"""
from zenml.artifacts.utils import (
get_artifacts_versions_of_pipeline_run,
)
return get_artifacts_versions_of_pipeline_run(self, only_produced=True)
def refresh_run_status(self) -> "PipelineRunResponse":
"""Method to refresh the status of a run if it is initializing/running.
Returns:
The updated pipeline.
Raises:
ValueError: If the stack of the run response is None.
"""
if self.status in [
ExecutionStatus.INITIALIZING,
ExecutionStatus.RUNNING,
]:
# Check if the stack still accessible
if self.stack is None:
raise ValueError(
"The stack that this pipeline run response was executed on"
"has been deleted."
)
# Create the orchestrator instance
from zenml.enums import StackComponentType
from zenml.orchestrators.base_orchestrator import BaseOrchestrator
from zenml.stack.stack_component import StackComponent
# Check if the stack still accessible
orchestrator_list = self.stack.components.get(
StackComponentType.ORCHESTRATOR, []
)
if len(orchestrator_list) == 0:
raise ValueError(
"The orchestrator that this pipeline run response was "
"executed with has been deleted."
)
orchestrator = cast(
BaseOrchestrator,
StackComponent.from_model(
component_model=orchestrator_list[0]
),
)
# Fetch the status
status = orchestrator.fetch_status(run=self)
# If it is different from the current status, update it
if status != self.status:
from zenml.client import Client
from zenml.models import PipelineRunUpdate
client = Client()
return client.zen_store.update_run(
run_id=self.id,
run_update=PipelineRunUpdate(status=status),
)
return self
# Body and metadata properties
@property
def status(self) -> ExecutionStatus:
"""The `status` property.
Returns:
the value of the property.
"""
return self.get_body().status
@property
def stack(self) -> Optional["StackResponse"]:
"""The `stack` property.
Returns:
the value of the property.
"""
return self.get_body().stack
@property
def pipeline(self) -> Optional["PipelineResponse"]:
"""The `pipeline` property.
Returns:
the value of the property.
"""
return self.get_body().pipeline
@property
def build(self) -> Optional["PipelineBuildResponse"]:
"""The `build` property.
Returns:
the value of the property.
"""
return self.get_body().build
@property
def schedule(self) -> Optional["ScheduleResponse"]:
"""The `schedule` property.
Returns:
the value of the property.
"""
return self.get_body().schedule
@property
def trigger_execution(self) -> Optional["TriggerExecutionResponse"]:
"""The `trigger_execution` property.
Returns:
the value of the property.
"""
return self.get_body().trigger_execution
@property
def code_reference(self) -> Optional["CodeReferenceResponse"]:
"""The `schedule` property.
Returns:
the value of the property.
"""
return self.get_body().code_reference
@property
def deployment_id(self) -> Optional["UUID"]:
"""The `deployment_id` property.
Returns:
the value of the property.
"""
return self.get_body().deployment_id
@property
def model_version_id(self) -> Optional[UUID]:
"""The `model_version_id` property.
Returns:
the value of the property.
"""
return self.get_body().model_version_id
@property
def run_metadata(self) -> Dict[str, "RunMetadataResponse"]:
"""The `run_metadata` property.
Returns:
the value of the property.
"""
return self.get_metadata().run_metadata
@property
def steps(self) -> Dict[str, "StepRunResponse"]:
"""The `steps` property.
Returns:
the value of the property.
"""
return self.get_metadata().steps
@property
def config(self) -> PipelineConfiguration:
"""The `config` property.
Returns:
the value of the property.
"""
return self.get_metadata().config
@property
def start_time(self) -> Optional[datetime]:
"""The `start_time` property.
Returns:
the value of the property.
"""
return self.get_metadata().start_time
@property
def end_time(self) -> Optional[datetime]:
"""The `end_time` property.
Returns:
the value of the property.
"""
return self.get_metadata().end_time
@property
def client_environment(self) -> Dict[str, str]:
"""The `client_environment` property.
Returns:
the value of the property.
"""
return self.get_metadata().client_environment
@property
def orchestrator_environment(self) -> Dict[str, str]:
"""The `orchestrator_environment` property.
Returns:
the value of the property.
"""
return self.get_metadata().orchestrator_environment
@property
def orchestrator_run_id(self) -> Optional[str]:
"""The `orchestrator_run_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().orchestrator_run_id
@property
def code_path(self) -> Optional[str]:
"""The `code_path` property.
Returns:
the value of the property.
"""
return self.get_metadata().code_path
@property
def template_id(self) -> Optional[UUID]:
"""The `template_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().template_id
@property
def is_templatable(self) -> bool:
"""The `is_templatable` property.
Returns:
the value of the property.
"""
return self.get_metadata().is_templatable
@property
def model_version(self) -> Optional[ModelVersionResponse]:
"""The `model_version` property.
Returns:
the value of the property.
"""
return self.get_resources().model_version
@property
def tags(self) -> List[TagResponse]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_resources().tags
artifact_versions: List[ArtifactVersionResponse]
property
readonly
Get all artifact versions that are outputs of steps of this run.
Returns:
Type | Description |
---|---|
List[ArtifactVersionResponse] |
All output artifact versions of this run (including cached ones). |
build: Optional[PipelineBuildResponse]
property
readonly
The build
property.
Returns:
Type | Description |
---|---|
Optional[PipelineBuildResponse] |
the value of the property. |
client_environment: Dict[str, str]
property
readonly
The client_environment
property.
Returns:
Type | Description |
---|---|
Dict[str, str] |
the value of the property. |
code_path: Optional[str]
property
readonly
The code_path
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
code_reference: Optional[CodeReferenceResponse]
property
readonly
The schedule
property.
Returns:
Type | Description |
---|---|
Optional[CodeReferenceResponse] |
the value of the property. |
config: PipelineConfiguration
property
readonly
The config
property.
Returns:
Type | Description |
---|---|
PipelineConfiguration |
the value of the property. |
deployment_id: Optional[UUID]
property
readonly
The deployment_id
property.
Returns:
Type | Description |
---|---|
Optional[UUID] |
the value of the property. |
end_time: Optional[datetime.datetime]
property
readonly
The end_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
is_templatable: bool
property
readonly
The is_templatable
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
model_version: Optional[zenml.models.v2.core.model_version.ModelVersionResponse]
property
readonly
The model_version
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.model_version.ModelVersionResponse] |
the value of the property. |
model_version_id: Optional[uuid.UUID]
property
readonly
The model_version_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
orchestrator_environment: Dict[str, str]
property
readonly
The orchestrator_environment
property.
Returns:
Type | Description |
---|---|
Dict[str, str] |
the value of the property. |
orchestrator_run_id: Optional[str]
property
readonly
The orchestrator_run_id
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
pipeline: Optional[PipelineResponse]
property
readonly
The pipeline
property.
Returns:
Type | Description |
---|---|
Optional[PipelineResponse] |
the value of the property. |
produced_artifact_versions: List[ArtifactVersionResponse]
property
readonly
Get all artifact versions produced during this pipeline run.
Returns:
Type | Description |
---|---|
List[ArtifactVersionResponse] |
A list of all artifact versions produced during this pipeline run. |
run_metadata: Dict[str, RunMetadataResponse]
property
readonly
The run_metadata
property.
Returns:
Type | Description |
---|---|
Dict[str, RunMetadataResponse] |
the value of the property. |
schedule: Optional[ScheduleResponse]
property
readonly
The schedule
property.
Returns:
Type | Description |
---|---|
Optional[ScheduleResponse] |
the value of the property. |
stack: Optional[StackResponse]
property
readonly
The stack
property.
Returns:
Type | Description |
---|---|
Optional[StackResponse] |
the value of the property. |
start_time: Optional[datetime.datetime]
property
readonly
The start_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
status: ExecutionStatus
property
readonly
The status
property.
Returns:
Type | Description |
---|---|
ExecutionStatus |
the value of the property. |
steps: Dict[str, StepRunResponse]
property
readonly
The steps
property.
Returns:
Type | Description |
---|---|
Dict[str, StepRunResponse] |
the value of the property. |
tags: List[zenml.models.v2.core.tag.TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.tag.TagResponse] |
the value of the property. |
template_id: Optional[uuid.UUID]
property
readonly
The template_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
trigger_execution: Optional[TriggerExecutionResponse]
property
readonly
The trigger_execution
property.
Returns:
Type | Description |
---|---|
Optional[TriggerExecutionResponse] |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this pipeline run.
Returns:
Type | Description |
---|---|
PipelineRunResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/pipeline_run.py
def get_hydrated_version(self) -> "PipelineRunResponse":
"""Get the hydrated version of this pipeline run.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_run(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/pipeline_run.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
refresh_run_status(self)
Method to refresh the status of a run if it is initializing/running.
Returns:
Type | Description |
---|---|
PipelineRunResponse |
The updated pipeline. |
Exceptions:
Type | Description |
---|---|
ValueError |
If the stack of the run response is None. |
Source code in zenml/models/v2/core/pipeline_run.py
def refresh_run_status(self) -> "PipelineRunResponse":
"""Method to refresh the status of a run if it is initializing/running.
Returns:
The updated pipeline.
Raises:
ValueError: If the stack of the run response is None.
"""
if self.status in [
ExecutionStatus.INITIALIZING,
ExecutionStatus.RUNNING,
]:
# Check if the stack still accessible
if self.stack is None:
raise ValueError(
"The stack that this pipeline run response was executed on"
"has been deleted."
)
# Create the orchestrator instance
from zenml.enums import StackComponentType
from zenml.orchestrators.base_orchestrator import BaseOrchestrator
from zenml.stack.stack_component import StackComponent
# Check if the stack still accessible
orchestrator_list = self.stack.components.get(
StackComponentType.ORCHESTRATOR, []
)
if len(orchestrator_list) == 0:
raise ValueError(
"The orchestrator that this pipeline run response was "
"executed with has been deleted."
)
orchestrator = cast(
BaseOrchestrator,
StackComponent.from_model(
component_model=orchestrator_list[0]
),
)
# Fetch the status
status = orchestrator.fetch_status(run=self)
# If it is different from the current status, update it
if status != self.status:
from zenml.client import Client
from zenml.models import PipelineRunUpdate
client = Client()
return client.zen_store.update_run(
run_id=self.id,
run_update=PipelineRunUpdate(status=status),
)
return self
PipelineRunResponseBody (WorkspaceScopedResponseBody)
Response body for pipeline runs.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunResponseBody(WorkspaceScopedResponseBody):
"""Response body for pipeline runs."""
status: ExecutionStatus = Field(
title="The status of the pipeline run.",
)
stack: Optional["StackResponse"] = Field(
default=None, title="The stack that was used for this run."
)
pipeline: Optional["PipelineResponse"] = Field(
default=None, title="The pipeline this run belongs to."
)
build: Optional["PipelineBuildResponse"] = Field(
default=None, title="The pipeline build that was used for this run."
)
schedule: Optional["ScheduleResponse"] = Field(
default=None, title="The schedule that was used for this run."
)
code_reference: Optional["CodeReferenceResponse"] = Field(
default=None, title="The code reference that was used for this run."
)
deployment_id: Optional[UUID] = Field(
default=None, title="The deployment that was used for this run."
)
trigger_execution: Optional["TriggerExecutionResponse"] = Field(
default=None, title="The trigger execution that triggered this run."
)
model_version_id: Optional[UUID] = Field(
title="The ID of the model version that was "
"configured by this pipeline run explicitly.",
default=None,
)
model_config = ConfigDict(protected_namespaces=())
PipelineRunResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for pipeline runs.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for pipeline runs."""
run_metadata: Dict[str, "RunMetadataResponse"] = Field(
default={},
title="Metadata associated with this pipeline run.",
)
steps: Dict[str, "StepRunResponse"] = Field(
default={}, title="The steps of this run."
)
config: PipelineConfiguration = Field(
title="The pipeline configuration used for this pipeline run.",
)
start_time: Optional[datetime] = Field(
title="The start time of the pipeline run.",
default=None,
)
end_time: Optional[datetime] = Field(
title="The end time of the pipeline run.",
default=None,
)
client_environment: Dict[str, str] = Field(
default={},
title=(
"Environment of the client that initiated this pipeline run "
"(OS, Python version, etc.)."
),
)
orchestrator_environment: Dict[str, str] = Field(
default={},
title=(
"Environment of the orchestrator that executed this pipeline run "
"(OS, Python version, etc.)."
),
)
orchestrator_run_id: Optional[str] = Field(
title="The orchestrator run ID.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
code_path: Optional[str] = Field(
default=None,
title="Optional path where the code is stored in the artifact store.",
)
template_id: Optional[UUID] = Field(
default=None,
description="Template used for the pipeline run.",
)
is_templatable: bool = Field(
default=False,
description="Whether a template can be created from this run.",
)
PipelineRunResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the pipeline run entity.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the pipeline run entity."""
model_version: Optional[ModelVersionResponse] = None
tags: List[TagResponse] = Field(
title="Tags associated with the pipeline run.",
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
PipelineRunUpdate (BaseModel)
Pipeline run update model.
Source code in zenml/models/v2/core/pipeline_run.py
class PipelineRunUpdate(BaseModel):
"""Pipeline run update model."""
status: Optional[ExecutionStatus] = None
end_time: Optional[datetime] = None
model_version_id: Optional[UUID] = Field(
title="The ID of the model version that was "
"configured by this pipeline run explicitly.",
default=None,
)
# TODO: we should maybe have a different update model here, the upper
# three attributes should only be for internal use
add_tags: Optional[List[str]] = Field(
default=None, title="New tags to add to the pipeline run."
)
remove_tags: Optional[List[str]] = Field(
default=None, title="Tags to remove from the pipeline run."
)
model_config = ConfigDict(protected_namespaces=())
run_metadata
Models representing run metadata.
LazyRunMetadataResponse (RunMetadataResponse)
Lazy run metadata response.
Used if the run metadata is accessed from the model in a pipeline context available only during pipeline compilation.
Source code in zenml/models/v2/core/run_metadata.py
class LazyRunMetadataResponse(RunMetadataResponse):
"""Lazy run metadata response.
Used if the run metadata is accessed from the model in
a pipeline context available only during pipeline compilation.
"""
id: Optional[UUID] = None # type: ignore[assignment]
lazy_load_artifact_name: Optional[str] = None
lazy_load_artifact_version: Optional[str] = None
lazy_load_metadata_name: Optional[str] = None
lazy_load_model: Model
def get_body(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError(
"Cannot access run metadata body before pipeline runs."
)
def get_metadata(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError(
"Cannot access run metadata metadata before pipeline runs."
)
get_body(self)
Protects from misuse of the lazy loader.
Exceptions:
Type | Description |
---|---|
RuntimeError |
always |
Source code in zenml/models/v2/core/run_metadata.py
def get_body(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError(
"Cannot access run metadata body before pipeline runs."
)
get_metadata(self)
Protects from misuse of the lazy loader.
Exceptions:
Type | Description |
---|---|
RuntimeError |
always |
Source code in zenml/models/v2/core/run_metadata.py
def get_metadata(self) -> None: # type: ignore[override]
"""Protects from misuse of the lazy loader.
Raises:
RuntimeError: always
"""
raise RuntimeError(
"Cannot access run metadata metadata before pipeline runs."
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/run_metadata.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
RunMetadataFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of run metadata.
Source code in zenml/models/v2/core/run_metadata.py
class RunMetadataFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of run metadata."""
resource_id: Optional[Union[str, UUID]] = Field(
default=None, union_mode="left_to_right"
)
resource_type: Optional[MetadataResourceTypes] = None
stack_component_id: Optional[Union[str, UUID]] = Field(
default=None, union_mode="left_to_right"
)
key: Optional[str] = None
type: Optional[Union[str, MetadataTypeEnum]] = Field(
default=None, union_mode="left_to_right"
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/run_metadata.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
RunMetadataRequest (WorkspaceScopedRequest)
Request model for run metadata.
Source code in zenml/models/v2/core/run_metadata.py
class RunMetadataRequest(WorkspaceScopedRequest):
"""Request model for run metadata."""
resource_id: UUID = Field(
title="The ID of the resource that this metadata belongs to.",
)
resource_type: MetadataResourceTypes = Field(
title="The type of the resource that this metadata belongs to.",
)
stack_component_id: Optional[UUID] = Field(
title="The ID of the stack component that this metadata belongs to."
)
values: Dict[str, "MetadataType"] = Field(
title="The metadata to be created.",
)
types: Dict[str, "MetadataTypeEnum"] = Field(
title="The types of the metadata to be created.",
)
RunMetadataResponse (WorkspaceScopedResponse[RunMetadataResponseBody, RunMetadataResponseMetadata, RunMetadataResponseResources])
Response model for run metadata.
Source code in zenml/models/v2/core/run_metadata.py
class RunMetadataResponse(
WorkspaceScopedResponse[
RunMetadataResponseBody,
RunMetadataResponseMetadata,
RunMetadataResponseResources,
]
):
"""Response model for run metadata."""
def get_hydrated_version(self) -> "RunMetadataResponse":
"""Get the hydrated version of this run metadata.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_run_metadata(self.id)
# Body and metadata properties
@property
def key(self) -> str:
"""The `key` property.
Returns:
the value of the property.
"""
return self.get_body().key
@property
def value(self) -> MetadataType:
"""The `value` property.
Returns:
the value of the property.
"""
return self.get_body().value
@property
def type(self) -> MetadataTypeEnum:
"""The `type` property.
Returns:
the value of the property.
"""
return self.get_body().type
@property
def resource_id(self) -> UUID:
"""The `resource_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().resource_id
@property
def resource_type(self) -> MetadataResourceTypes:
"""The `resource_type` property.
Returns:
the value of the property.
"""
return MetadataResourceTypes(self.get_metadata().resource_type)
@property
def stack_component_id(self) -> Optional[UUID]:
"""The `stack_component_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().stack_component_id
key: str
property
readonly
The key
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
resource_id: UUID
property
readonly
The resource_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
resource_type: MetadataResourceTypes
property
readonly
The resource_type
property.
Returns:
Type | Description |
---|---|
MetadataResourceTypes |
the value of the property. |
stack_component_id: Optional[uuid.UUID]
property
readonly
The stack_component_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
type: MetadataTypeEnum
property
readonly
The type
property.
Returns:
Type | Description |
---|---|
MetadataTypeEnum |
the value of the property. |
value: Union[str, int, float, bool, Dict[Any, Any], List[Any], Set[Any], Tuple[Any, ...], zenml.metadata.metadata_types.Uri, zenml.metadata.metadata_types.Path, zenml.metadata.metadata_types.DType, zenml.metadata.metadata_types.StorageSize]
property
readonly
The value
property.
Returns:
Type | Description |
---|---|
Union[str, int, float, bool, Dict[Any, Any], List[Any], Set[Any], Tuple[Any, ...], zenml.metadata.metadata_types.Uri, zenml.metadata.metadata_types.Path, zenml.metadata.metadata_types.DType, zenml.metadata.metadata_types.StorageSize] |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this run metadata.
Returns:
Type | Description |
---|---|
RunMetadataResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/run_metadata.py
def get_hydrated_version(self) -> "RunMetadataResponse":
"""Get the hydrated version of this run metadata.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_run_metadata(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/run_metadata.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
RunMetadataResponseBody (WorkspaceScopedResponseBody)
Response body for run metadata.
Source code in zenml/models/v2/core/run_metadata.py
class RunMetadataResponseBody(WorkspaceScopedResponseBody):
"""Response body for run metadata."""
key: str = Field(title="The key of the metadata.")
value: MetadataType = Field(
title="The value of the metadata.", union_mode="smart"
)
type: MetadataTypeEnum = Field(title="The type of the metadata.")
@field_validator("key", "type")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum str length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
@field_validator("value")
@classmethod
def text_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < TEXT_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {TEXT_FIELD_MAX_LENGTH}"
)
return value
str_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum str length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/run_metadata.py
@field_validator("key", "type")
@classmethod
def str_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum str length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < STR_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {STR_FIELD_MAX_LENGTH}"
)
return value
text_field_max_length_check(value)
classmethod
Checks if the length of the value exceeds the maximum text length.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Any |
the value set in the field |
required |
Returns:
Type | Description |
---|---|
Any |
the value itself. |
Exceptions:
Type | Description |
---|---|
AssertionError |
if the length of the field is longer than the maximum threshold. |
Source code in zenml/models/v2/core/run_metadata.py
@field_validator("value")
@classmethod
def text_field_max_length_check(cls, value: Any) -> Any:
"""Checks if the length of the value exceeds the maximum text length.
Args:
value: the value set in the field
Returns:
the value itself.
Raises:
AssertionError: if the length of the field is longer than the
maximum threshold.
"""
assert len(str(value)) < TEXT_FIELD_MAX_LENGTH, (
"The length of the value for this field can not "
f"exceed {TEXT_FIELD_MAX_LENGTH}"
)
return value
RunMetadataResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for run metadata.
Source code in zenml/models/v2/core/run_metadata.py
class RunMetadataResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for run metadata."""
resource_id: UUID = Field(
title="The ID of the resource that this metadata belongs to.",
)
resource_type: MetadataResourceTypes = Field(
title="The type of the resource that this metadata belongs to.",
)
stack_component_id: Optional[UUID] = Field(
title="The ID of the stack component that this metadata belongs to."
)
RunMetadataResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the run metadata entity.
Source code in zenml/models/v2/core/run_metadata.py
class RunMetadataResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the run metadata entity."""
run_template
Models representing pipeline templates.
RunTemplateFilter (WorkspaceScopedTaggableFilter)
Model for filtering of run templates.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateFilter(WorkspaceScopedTaggableFilter):
"""Model for filtering of run templates."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.FILTER_EXCLUDE_FIELDS,
"code_repository_id",
"stack_id",
"build_id",
"pipeline_id",
"user",
"pipeline",
"stack",
]
name: Optional[str] = Field(
default=None,
description="Name of the run template.",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace associated with the template.",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that created the template.",
union_mode="left_to_right",
)
pipeline_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Pipeline associated with the template.",
union_mode="left_to_right",
)
build_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Build associated with the template.",
union_mode="left_to_right",
)
stack_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Stack associated with the template.",
union_mode="left_to_right",
)
code_repository_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Code repository associated with the template.",
union_mode="left_to_right",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the template.",
)
pipeline: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the pipeline associated with the template.",
)
stack: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the stack associated with the template.",
)
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
CodeReferenceSchema,
PipelineDeploymentSchema,
PipelineSchema,
RunTemplateSchema,
StackSchema,
UserSchema,
)
if self.code_repository_id:
code_repo_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.code_reference_id
== CodeReferenceSchema.id,
CodeReferenceSchema.code_repository_id
== self.code_repository_id,
)
custom_filters.append(code_repo_filter)
if self.stack_id:
stack_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == self.stack_id,
)
custom_filters.append(stack_filter)
if self.build_id:
build_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id == self.build_id,
)
custom_filters.append(build_filter)
if self.pipeline_id:
pipeline_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.pipeline_id == self.pipeline_id,
)
custom_filters.append(pipeline_filter)
if self.user:
user_filter = and_(
RunTemplateSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.pipeline:
pipeline_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.pipeline_id == PipelineSchema.id,
self.generate_name_or_id_query_conditions(
value=self.pipeline,
table=PipelineSchema,
),
)
custom_filters.append(pipeline_filter)
if self.stack:
stack_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == StackSchema.id,
self.generate_name_or_id_query_conditions(
value=self.stack,
table=StackSchema,
),
)
custom_filters.append(stack_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/run_template.py
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from sqlmodel import and_
from zenml.zen_stores.schemas import (
CodeReferenceSchema,
PipelineDeploymentSchema,
PipelineSchema,
RunTemplateSchema,
StackSchema,
UserSchema,
)
if self.code_repository_id:
code_repo_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.code_reference_id
== CodeReferenceSchema.id,
CodeReferenceSchema.code_repository_id
== self.code_repository_id,
)
custom_filters.append(code_repo_filter)
if self.stack_id:
stack_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == self.stack_id,
)
custom_filters.append(stack_filter)
if self.build_id:
build_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.build_id == self.build_id,
)
custom_filters.append(build_filter)
if self.pipeline_id:
pipeline_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.pipeline_id == self.pipeline_id,
)
custom_filters.append(pipeline_filter)
if self.user:
user_filter = and_(
RunTemplateSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.pipeline:
pipeline_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.pipeline_id == PipelineSchema.id,
self.generate_name_or_id_query_conditions(
value=self.pipeline,
table=PipelineSchema,
),
)
custom_filters.append(pipeline_filter)
if self.stack:
stack_filter = and_(
RunTemplateSchema.source_deployment_id
== PipelineDeploymentSchema.id,
PipelineDeploymentSchema.stack_id == StackSchema.id,
self.generate_name_or_id_query_conditions(
value=self.stack,
table=StackSchema,
),
)
custom_filters.append(stack_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/run_template.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
RunTemplateRequest (WorkspaceScopedRequest)
Request model for run templates.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateRequest(WorkspaceScopedRequest):
"""Request model for run templates."""
name: str = Field(
title="The name of the run template.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The description of the run template.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
source_deployment_id: UUID = Field(
title="The deployment that should be the base of the created template."
)
tags: Optional[List[str]] = Field(
default=None,
title="Tags of the run template.",
)
RunTemplateResponse (WorkspaceScopedResponse[RunTemplateResponseBody, RunTemplateResponseMetadata, RunTemplateResponseResources])
Response model for run templates.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateResponse(
WorkspaceScopedResponse[
RunTemplateResponseBody,
RunTemplateResponseMetadata,
RunTemplateResponseResources,
]
):
"""Response model for run templates."""
name: str = Field(
title="The name of the run template.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "RunTemplateResponse":
"""Return the hydrated version of this run template.
Returns:
The hydrated run template.
"""
from zenml.client import Client
return Client().zen_store.get_run_template(
template_id=self.id, hydrate=True
)
# Body and metadata properties
@property
def runnable(self) -> bool:
"""The `runnable` property.
Returns:
the value of the property.
"""
return self.get_body().runnable
@property
def latest_run_id(self) -> Optional[UUID]:
"""The `latest_run_id` property.
Returns:
the value of the property.
"""
return self.get_body().latest_run_id
@property
def latest_run_status(self) -> Optional[ExecutionStatus]:
"""The `latest_run_status` property.
Returns:
the value of the property.
"""
return self.get_body().latest_run_status
@property
def description(self) -> Optional[str]:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def pipeline_spec(self) -> Optional[PipelineSpec]:
"""The `pipeline_spec` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_spec
@property
def config_template(self) -> Optional[Dict[str, Any]]:
"""The `config_template` property.
Returns:
the value of the property.
"""
return self.get_metadata().config_template
@property
def config_schema(self) -> Optional[Dict[str, Any]]:
"""The `config_schema` property.
Returns:
the value of the property.
"""
return self.get_metadata().config_schema
@property
def source_deployment(self) -> Optional[PipelineDeploymentResponse]:
"""The `source_deployment` property.
Returns:
the value of the property.
"""
return self.get_resources().source_deployment
@property
def pipeline(self) -> Optional[PipelineResponse]:
"""The `pipeline` property.
Returns:
the value of the property.
"""
return self.get_resources().pipeline
@property
def build(self) -> Optional[PipelineBuildResponse]:
"""The `build` property.
Returns:
the value of the property.
"""
return self.get_resources().build
@property
def code_reference(self) -> Optional[CodeReferenceResponse]:
"""The `code_reference` property.
Returns:
the value of the property.
"""
return self.get_resources().code_reference
@property
def tags(self) -> List[TagResponse]:
"""The `tags` property.
Returns:
the value of the property.
"""
return self.get_resources().tags
build: Optional[zenml.models.v2.core.pipeline_build.PipelineBuildResponse]
property
readonly
The build
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.pipeline_build.PipelineBuildResponse] |
the value of the property. |
code_reference: Optional[zenml.models.v2.core.code_reference.CodeReferenceResponse]
property
readonly
The code_reference
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.code_reference.CodeReferenceResponse] |
the value of the property. |
config_schema: Optional[Dict[str, Any]]
property
readonly
The config_schema
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
config_template: Optional[Dict[str, Any]]
property
readonly
The config_template
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
description: Optional[str]
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
latest_run_id: Optional[uuid.UUID]
property
readonly
The latest_run_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
latest_run_status: Optional[zenml.enums.ExecutionStatus]
property
readonly
The latest_run_status
property.
Returns:
Type | Description |
---|---|
Optional[zenml.enums.ExecutionStatus] |
the value of the property. |
pipeline: Optional[zenml.models.v2.core.pipeline.PipelineResponse]
property
readonly
The pipeline
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.pipeline.PipelineResponse] |
the value of the property. |
pipeline_spec: Optional[zenml.config.pipeline_spec.PipelineSpec]
property
readonly
The pipeline_spec
property.
Returns:
Type | Description |
---|---|
Optional[zenml.config.pipeline_spec.PipelineSpec] |
the value of the property. |
runnable: bool
property
readonly
The runnable
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
source_deployment: Optional[zenml.models.v2.core.pipeline_deployment.PipelineDeploymentResponse]
property
readonly
The source_deployment
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.pipeline_deployment.PipelineDeploymentResponse] |
the value of the property. |
tags: List[zenml.models.v2.core.tag.TagResponse]
property
readonly
The tags
property.
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.tag.TagResponse] |
the value of the property. |
get_hydrated_version(self)
Return the hydrated version of this run template.
Returns:
Type | Description |
---|---|
RunTemplateResponse |
The hydrated run template. |
Source code in zenml/models/v2/core/run_template.py
def get_hydrated_version(self) -> "RunTemplateResponse":
"""Return the hydrated version of this run template.
Returns:
The hydrated run template.
"""
from zenml.client import Client
return Client().zen_store.get_run_template(
template_id=self.id, hydrate=True
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/run_template.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
RunTemplateResponseBody (WorkspaceScopedResponseBody)
Response body for run templates.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateResponseBody(WorkspaceScopedResponseBody):
"""Response body for run templates."""
runnable: bool = Field(
title="If a run can be started from the template.",
)
latest_run_id: Optional[UUID] = Field(
default=None,
title="The ID of the latest run of the run template.",
)
latest_run_status: Optional[ExecutionStatus] = Field(
default=None,
title="The status of the latest run of the run template.",
)
RunTemplateResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for run templates.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for run templates."""
description: Optional[str] = Field(
default=None,
title="The description of the run template.",
)
pipeline_spec: Optional[PipelineSpec] = Field(
default=None, title="The spec of the pipeline."
)
config_template: Optional[Dict[str, Any]] = Field(
default=None, title="Run configuration template."
)
config_schema: Optional[Dict[str, Any]] = Field(
default=None, title="Run configuration schema."
)
RunTemplateResponseResources (WorkspaceScopedResponseResources)
All resource models associated with the run template.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateResponseResources(WorkspaceScopedResponseResources):
"""All resource models associated with the run template."""
source_deployment: Optional[PipelineDeploymentResponse] = Field(
default=None,
title="The deployment that is the source of the template.",
)
pipeline: Optional[PipelineResponse] = Field(
default=None, title="The pipeline associated with the template."
)
build: Optional[PipelineBuildResponse] = Field(
default=None,
title="The pipeline build associated with the template.",
)
code_reference: Optional[CodeReferenceResponse] = Field(
default=None,
title="The code reference associated with the template.",
)
tags: List[TagResponse] = Field(
title="Tags associated with the run template.",
)
RunTemplateUpdate (BaseUpdate)
Run template update model.
Source code in zenml/models/v2/core/run_template.py
class RunTemplateUpdate(BaseUpdate):
"""Run template update model."""
name: Optional[str] = Field(
default=None,
title="The name of the run template.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The description of the run template.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
add_tags: Optional[List[str]] = Field(
default=None, title="New tags to add to the run template."
)
remove_tags: Optional[List[str]] = Field(
default=None, title="Tags to remove from the run template."
)
schedule
Models representing schedules.
ScheduleFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all Users.
Source code in zenml/models/v2/core/schedule.py
class ScheduleFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all Users."""
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace scope of the schedule.",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that created the schedule",
union_mode="left_to_right",
)
pipeline_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Pipeline that the schedule is attached to.",
union_mode="left_to_right",
)
orchestrator_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Orchestrator that the schedule is attached to.",
union_mode="left_to_right",
)
active: Optional[bool] = Field(
default=None,
description="If the schedule is active",
)
cron_expression: Optional[str] = Field(
default=None,
description="The cron expression, describing the schedule",
)
start_time: Optional[Union[datetime.datetime, str]] = Field(
default=None, description="Start time", union_mode="left_to_right"
)
end_time: Optional[Union[datetime.datetime, str]] = Field(
default=None, description="End time", union_mode="left_to_right"
)
interval_second: Optional[Optional[float]] = Field(
default=None,
description="The repetition interval in seconds",
)
catchup: Optional[bool] = Field(
default=None,
description="Whether or not the schedule is set to catchup past missed "
"events",
)
name: Optional[str] = Field(
default=None,
description="Name of the schedule",
)
run_once_start_time: Optional[Union[datetime.datetime, str]] = Field(
default=None,
description="The time at which the schedule should run once",
union_mode="left_to_right",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/schedule.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ScheduleRequest (WorkspaceScopedRequest)
Request model for schedules.
Source code in zenml/models/v2/core/schedule.py
class ScheduleRequest(WorkspaceScopedRequest):
"""Request model for schedules."""
name: str
active: bool
cron_expression: Optional[str] = None
start_time: Optional[datetime.datetime] = None
end_time: Optional[datetime.datetime] = None
interval_second: Optional[datetime.timedelta] = None
catchup: bool = False
run_once_start_time: Optional[datetime.datetime] = None
orchestrator_id: Optional[UUID]
pipeline_id: Optional[UUID]
@model_validator(mode="after")
def _ensure_cron_or_periodic_schedule_configured(
self,
) -> "ScheduleRequest":
"""Ensures that the cron expression or start time + interval are set.
Returns:
All schedule attributes.
Raises:
ValueError: If no cron expression or start time + interval were
provided.
"""
cron_expression = self.cron_expression
periodic_schedule = self.start_time and self.interval_second
run_once_starts_at = self.run_once_start_time
if cron_expression and periodic_schedule:
logger.warning(
"This schedule was created with a cron expression as well as "
"values for `start_time` and `interval_seconds`. The resulting "
"behavior depends on the concrete orchestrator implementation "
"but will usually ignore the interval and use the cron "
"expression."
)
return self
elif cron_expression and run_once_starts_at:
logger.warning(
"This schedule was created with a cron expression as well as "
"a value for `run_once_start_time`. The resulting behavior "
"depends on the concrete orchestrator implementation but will "
"usually ignore the `run_once_start_time`."
)
return self
elif cron_expression or periodic_schedule or run_once_starts_at:
return self
else:
raise ValueError(
"Either a cron expression, a start time and interval seconds "
"or a run once start time "
"need to be set for a valid schedule."
)
ScheduleResponse (WorkspaceScopedResponse[ScheduleResponseBody, ScheduleResponseMetadata, ScheduleResponseResources])
Response model for schedules.
Source code in zenml/models/v2/core/schedule.py
class ScheduleResponse(
WorkspaceScopedResponse[
ScheduleResponseBody,
ScheduleResponseMetadata,
ScheduleResponseResources,
],
):
"""Response model for schedules."""
name: str = Field(
title="Name of this schedule.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "ScheduleResponse":
"""Get the hydrated version of this schedule.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_schedule(self.id)
# Helper methods
@property
def utc_start_time(self) -> Optional[str]:
"""Optional ISO-formatted string of the UTC start time.
Returns:
Optional ISO-formatted string of the UTC start time.
"""
if not self.start_time:
return None
return self.start_time.astimezone(datetime.timezone.utc).isoformat()
@property
def utc_end_time(self) -> Optional[str]:
"""Optional ISO-formatted string of the UTC end time.
Returns:
Optional ISO-formatted string of the UTC end time.
"""
if not self.end_time:
return None
return self.end_time.astimezone(datetime.timezone.utc).isoformat()
# Body and metadata properties
@property
def active(self) -> bool:
"""The `active` property.
Returns:
the value of the property.
"""
return self.get_body().active
@property
def cron_expression(self) -> Optional[str]:
"""The `cron_expression` property.
Returns:
the value of the property.
"""
return self.get_body().cron_expression
@property
def start_time(self) -> Optional[datetime.datetime]:
"""The `start_time` property.
Returns:
the value of the property.
"""
return self.get_body().start_time
@property
def end_time(self) -> Optional[datetime.datetime]:
"""The `end_time` property.
Returns:
the value of the property.
"""
return self.get_body().end_time
@property
def run_once_start_time(self) -> Optional[datetime.datetime]:
"""The `run_once_start_time` property.
Returns:
the value of the property.
"""
return self.get_body().run_once_start_time
@property
def interval_second(self) -> Optional[datetime.timedelta]:
"""The `interval_second` property.
Returns:
the value of the property.
"""
return self.get_body().interval_second
@property
def catchup(self) -> bool:
"""The `catchup` property.
Returns:
the value of the property.
"""
return self.get_body().catchup
@property
def orchestrator_id(self) -> Optional[UUID]:
"""The `orchestrator_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().orchestrator_id
@property
def pipeline_id(self) -> Optional[UUID]:
"""The `pipeline_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_id
active: bool
property
readonly
The active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
catchup: bool
property
readonly
The catchup
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
cron_expression: Optional[str]
property
readonly
The cron_expression
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
end_time: Optional[datetime.datetime]
property
readonly
The end_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
interval_second: Optional[datetime.timedelta]
property
readonly
The interval_second
property.
Returns:
Type | Description |
---|---|
Optional[datetime.timedelta] |
the value of the property. |
orchestrator_id: Optional[uuid.UUID]
property
readonly
The orchestrator_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
pipeline_id: Optional[uuid.UUID]
property
readonly
The pipeline_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
run_once_start_time: Optional[datetime.datetime]
property
readonly
The run_once_start_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
start_time: Optional[datetime.datetime]
property
readonly
The start_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
utc_end_time: Optional[str]
property
readonly
Optional ISO-formatted string of the UTC end time.
Returns:
Type | Description |
---|---|
Optional[str] |
Optional ISO-formatted string of the UTC end time. |
utc_start_time: Optional[str]
property
readonly
Optional ISO-formatted string of the UTC start time.
Returns:
Type | Description |
---|---|
Optional[str] |
Optional ISO-formatted string of the UTC start time. |
get_hydrated_version(self)
Get the hydrated version of this schedule.
Returns:
Type | Description |
---|---|
ScheduleResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/schedule.py
def get_hydrated_version(self) -> "ScheduleResponse":
"""Get the hydrated version of this schedule.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_schedule(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/schedule.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ScheduleResponseBody (WorkspaceScopedResponseBody)
Response body for schedules.
Source code in zenml/models/v2/core/schedule.py
class ScheduleResponseBody(WorkspaceScopedResponseBody):
"""Response body for schedules."""
active: bool
cron_expression: Optional[str] = None
start_time: Optional[datetime.datetime] = None
end_time: Optional[datetime.datetime] = None
interval_second: Optional[datetime.timedelta] = None
catchup: bool = False
run_once_start_time: Optional[datetime.datetime] = None
ScheduleResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for schedules.
Source code in zenml/models/v2/core/schedule.py
class ScheduleResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for schedules."""
orchestrator_id: Optional[UUID]
pipeline_id: Optional[UUID]
ScheduleResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the schedule entity.
Source code in zenml/models/v2/core/schedule.py
class ScheduleResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the schedule entity."""
ScheduleUpdate (BaseUpdate)
Update model for schedules.
Source code in zenml/models/v2/core/schedule.py
class ScheduleUpdate(BaseUpdate):
"""Update model for schedules."""
name: Optional[str] = None
active: Optional[bool] = None
cron_expression: Optional[str] = None
start_time: Optional[datetime.datetime] = None
end_time: Optional[datetime.datetime] = None
interval_second: Optional[datetime.timedelta] = None
catchup: Optional[bool] = None
run_once_start_time: Optional[datetime.datetime] = None
orchestrator_id: Optional[UUID] = None
pipeline_id: Optional[UUID] = None
secret
Models representing secrets.
SecretFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all Secrets.
Source code in zenml/models/v2/core/secret.py
class SecretFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all Secrets."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"values",
]
name: Optional[str] = Field(
default=None,
description="Name of the secret",
)
scope: Optional[Union[SecretScope, str]] = Field(
default=None,
description="Scope in which to filter secrets",
union_mode="left_to_right",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the Secret",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that created the Secret",
union_mode="left_to_right",
)
@staticmethod
def _get_filtering_value(value: Optional[Any]) -> str:
"""Convert the value to a string that can be used for lexicographical filtering and sorting.
Args:
value: The value to convert.
Returns:
The value converted to string format that can be used for
lexicographical sorting and filtering.
"""
if value is None:
return ""
str_value = str(value)
if isinstance(value, datetime):
str_value = value.strftime("%Y-%m-%d %H:%M:%S")
return str_value
def secret_matches(self, secret: SecretResponse) -> bool:
"""Checks if a secret matches the filter criteria.
Args:
secret: The secret to check.
Returns:
True if the secret matches the filter criteria, False otherwise.
"""
for filter in self.list_of_filters:
column_value: Optional[Any] = None
if filter.column == "workspace_id":
column_value = secret.workspace.id
elif filter.column == "user_id":
column_value = secret.user.id if secret.user else None
else:
column_value = getattr(secret, filter.column)
# Convert the values to strings for lexicographical comparison.
str_column_value = self._get_filtering_value(column_value)
str_filter_value = self._get_filtering_value(filter.value)
# Compare the lexicographical values according to the operation.
if filter.operation == GenericFilterOps.EQUALS:
result = str_column_value == str_filter_value
elif filter.operation == GenericFilterOps.CONTAINS:
result = str_filter_value in str_column_value
elif filter.operation == GenericFilterOps.STARTSWITH:
result = str_column_value.startswith(str_filter_value)
elif filter.operation == GenericFilterOps.ENDSWITH:
result = str_column_value.endswith(str_filter_value)
elif filter.operation == GenericFilterOps.GT:
result = str_column_value > str_filter_value
elif filter.operation == GenericFilterOps.GTE:
result = str_column_value >= str_filter_value
elif filter.operation == GenericFilterOps.LT:
result = str_column_value < str_filter_value
elif filter.operation == GenericFilterOps.LTE:
result = str_column_value <= str_filter_value
# Exit early if the result is False for AND, and True for OR
if self.logical_operator == LogicalOperators.AND:
if not result:
return False
else:
if result:
return True
# If we get here, all filters have been checked and the result is
# True for AND, and False for OR
if self.logical_operator == LogicalOperators.AND:
return True
else:
return False
def sort_secrets(
self, secrets: List[SecretResponse]
) -> List[SecretResponse]:
"""Sorts a list of secrets according to the filter criteria.
Args:
secrets: The list of secrets to sort.
Returns:
The sorted list of secrets.
"""
column, sort_op = self.sorting_params
sorted_secrets = sorted(
secrets,
key=lambda secret: self._get_filtering_value(
getattr(secret, column)
),
reverse=sort_op == SorterOps.DESCENDING,
)
return sorted_secrets
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/secret.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
secret_matches(self, secret)
Checks if a secret matches the filter criteria.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
secret |
SecretResponse |
The secret to check. |
required |
Returns:
Type | Description |
---|---|
bool |
True if the secret matches the filter criteria, False otherwise. |
Source code in zenml/models/v2/core/secret.py
def secret_matches(self, secret: SecretResponse) -> bool:
"""Checks if a secret matches the filter criteria.
Args:
secret: The secret to check.
Returns:
True if the secret matches the filter criteria, False otherwise.
"""
for filter in self.list_of_filters:
column_value: Optional[Any] = None
if filter.column == "workspace_id":
column_value = secret.workspace.id
elif filter.column == "user_id":
column_value = secret.user.id if secret.user else None
else:
column_value = getattr(secret, filter.column)
# Convert the values to strings for lexicographical comparison.
str_column_value = self._get_filtering_value(column_value)
str_filter_value = self._get_filtering_value(filter.value)
# Compare the lexicographical values according to the operation.
if filter.operation == GenericFilterOps.EQUALS:
result = str_column_value == str_filter_value
elif filter.operation == GenericFilterOps.CONTAINS:
result = str_filter_value in str_column_value
elif filter.operation == GenericFilterOps.STARTSWITH:
result = str_column_value.startswith(str_filter_value)
elif filter.operation == GenericFilterOps.ENDSWITH:
result = str_column_value.endswith(str_filter_value)
elif filter.operation == GenericFilterOps.GT:
result = str_column_value > str_filter_value
elif filter.operation == GenericFilterOps.GTE:
result = str_column_value >= str_filter_value
elif filter.operation == GenericFilterOps.LT:
result = str_column_value < str_filter_value
elif filter.operation == GenericFilterOps.LTE:
result = str_column_value <= str_filter_value
# Exit early if the result is False for AND, and True for OR
if self.logical_operator == LogicalOperators.AND:
if not result:
return False
else:
if result:
return True
# If we get here, all filters have been checked and the result is
# True for AND, and False for OR
if self.logical_operator == LogicalOperators.AND:
return True
else:
return False
sort_secrets(self, secrets)
Sorts a list of secrets according to the filter criteria.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
secrets |
List[zenml.models.v2.core.secret.SecretResponse] |
The list of secrets to sort. |
required |
Returns:
Type | Description |
---|---|
List[zenml.models.v2.core.secret.SecretResponse] |
The sorted list of secrets. |
Source code in zenml/models/v2/core/secret.py
def sort_secrets(
self, secrets: List[SecretResponse]
) -> List[SecretResponse]:
"""Sorts a list of secrets according to the filter criteria.
Args:
secrets: The list of secrets to sort.
Returns:
The sorted list of secrets.
"""
column, sort_op = self.sorting_params
sorted_secrets = sorted(
secrets,
key=lambda secret: self._get_filtering_value(
getattr(secret, column)
),
reverse=sort_op == SorterOps.DESCENDING,
)
return sorted_secrets
SecretRequest (WorkspaceScopedRequest)
Request models for secrets.
Source code in zenml/models/v2/core/secret.py
class SecretRequest(WorkspaceScopedRequest):
"""Request models for secrets."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["scope"]
name: str = Field(
title="The name of the secret.",
max_length=STR_FIELD_MAX_LENGTH,
)
scope: SecretScope = Field(
SecretScope.WORKSPACE, title="The scope of the secret."
)
values: Dict[str, Optional[PlainSerializedSecretStr]] = Field(
default_factory=dict, title="The values stored in this secret."
)
@property
def secret_values(self) -> Dict[str, str]:
"""A dictionary with all un-obfuscated values stored in this secret.
The values are returned as strings, not SecretStr. If a value is
None, it is not included in the returned dictionary. This is to enable
the use of None values in the update model to indicate that a secret
value should be deleted.
Returns:
A dictionary containing the secret's values.
"""
return {
k: v.get_secret_value()
for k, v in self.values.items()
if v is not None
}
secret_values: Dict[str, str]
property
readonly
A dictionary with all un-obfuscated values stored in this secret.
The values are returned as strings, not SecretStr. If a value is None, it is not included in the returned dictionary. This is to enable the use of None values in the update model to indicate that a secret value should be deleted.
Returns:
Type | Description |
---|---|
Dict[str, str] |
A dictionary containing the secret's values. |
SecretResponse (WorkspaceScopedResponse[SecretResponseBody, SecretResponseMetadata, SecretResponseResources])
Response model for secrets.
Source code in zenml/models/v2/core/secret.py
class SecretResponse(
WorkspaceScopedResponse[
SecretResponseBody, SecretResponseMetadata, SecretResponseResources
]
):
"""Response model for secrets."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["scope"]
name: str = Field(
title="The name of the secret.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "SecretResponse":
"""Get the hydrated version of this workspace.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_secret(self.id)
# Body and metadata properties
@property
def scope(self) -> SecretScope:
"""The `scope` property.
Returns:
the value of the property.
"""
return self.get_body().scope
@property
def values(self) -> Dict[str, Optional[SecretStr]]:
"""The `values` property.
Returns:
the value of the property.
"""
return self.get_body().values
# Helper methods
@property
def secret_values(self) -> Dict[str, str]:
"""A dictionary with all un-obfuscated values stored in this secret.
The values are returned as strings, not SecretStr. If a value is
None, it is not included in the returned dictionary. This is to enable
the use of None values in the update model to indicate that a secret
value should be deleted.
Returns:
A dictionary containing the secret's values.
"""
return {
k: v.get_secret_value()
for k, v in self.values.items()
if v is not None
}
@property
def has_missing_values(self) -> bool:
"""Returns True if the secret has missing values (i.e. None).
Values can be missing from a secret for example if the user retrieves a
secret but does not have the permission to view the secret values.
Returns:
True if the secret has any values set to None.
"""
return any(v is None for v in self.values.values())
def add_secret(self, key: str, value: str) -> None:
"""Adds a secret value to the secret.
Args:
key: The key of the secret value.
value: The secret value.
"""
self.get_body().values[key] = SecretStr(value)
def remove_secret(self, key: str) -> None:
"""Removes a secret value from the secret.
Args:
key: The key of the secret value.
"""
del self.get_body().values[key]
def remove_secrets(self) -> None:
"""Removes all secret values from the secret but keep the keys."""
self.get_body().values = {k: None for k in self.values.keys()}
def set_secrets(self, values: Dict[str, str]) -> None:
"""Sets the secret values of the secret.
Args:
values: The secret values to set.
"""
self.get_body().values = {k: SecretStr(v) for k, v in values.items()}
has_missing_values: bool
property
readonly
Returns True if the secret has missing values (i.e. None).
Values can be missing from a secret for example if the user retrieves a secret but does not have the permission to view the secret values.
Returns:
Type | Description |
---|---|
bool |
True if the secret has any values set to None. |
scope: SecretScope
property
readonly
The scope
property.
Returns:
Type | Description |
---|---|
SecretScope |
the value of the property. |
secret_values: Dict[str, str]
property
readonly
A dictionary with all un-obfuscated values stored in this secret.
The values are returned as strings, not SecretStr. If a value is None, it is not included in the returned dictionary. This is to enable the use of None values in the update model to indicate that a secret value should be deleted.
Returns:
Type | Description |
---|---|
Dict[str, str] |
A dictionary containing the secret's values. |
values: Dict[str, Optional[pydantic.types.SecretStr]]
property
readonly
The values
property.
Returns:
Type | Description |
---|---|
Dict[str, Optional[pydantic.types.SecretStr]] |
the value of the property. |
add_secret(self, key, value)
Adds a secret value to the secret.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key |
str |
The key of the secret value. |
required |
value |
str |
The secret value. |
required |
Source code in zenml/models/v2/core/secret.py
def add_secret(self, key: str, value: str) -> None:
"""Adds a secret value to the secret.
Args:
key: The key of the secret value.
value: The secret value.
"""
self.get_body().values[key] = SecretStr(value)
get_hydrated_version(self)
Get the hydrated version of this workspace.
Returns:
Type | Description |
---|---|
SecretResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/secret.py
def get_hydrated_version(self) -> "SecretResponse":
"""Get the hydrated version of this workspace.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_secret(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/secret.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
remove_secret(self, key)
Removes a secret value from the secret.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
key |
str |
The key of the secret value. |
required |
Source code in zenml/models/v2/core/secret.py
def remove_secret(self, key: str) -> None:
"""Removes a secret value from the secret.
Args:
key: The key of the secret value.
"""
del self.get_body().values[key]
remove_secrets(self)
Removes all secret values from the secret but keep the keys.
Source code in zenml/models/v2/core/secret.py
def remove_secrets(self) -> None:
"""Removes all secret values from the secret but keep the keys."""
self.get_body().values = {k: None for k in self.values.keys()}
set_secrets(self, values)
Sets the secret values of the secret.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
values |
Dict[str, str] |
The secret values to set. |
required |
Source code in zenml/models/v2/core/secret.py
def set_secrets(self, values: Dict[str, str]) -> None:
"""Sets the secret values of the secret.
Args:
values: The secret values to set.
"""
self.get_body().values = {k: SecretStr(v) for k, v in values.items()}
SecretResponseBody (WorkspaceScopedResponseBody)
Response body for secrets.
Source code in zenml/models/v2/core/secret.py
class SecretResponseBody(WorkspaceScopedResponseBody):
"""Response body for secrets."""
scope: SecretScope = Field(
SecretScope.WORKSPACE, title="The scope of the secret."
)
values: Dict[str, Optional[PlainSerializedSecretStr]] = Field(
default_factory=dict, title="The values stored in this secret."
)
SecretResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for secrets.
Source code in zenml/models/v2/core/secret.py
class SecretResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for secrets."""
SecretResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the secret entity.
Source code in zenml/models/v2/core/secret.py
class SecretResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the secret entity."""
SecretUpdate (BaseUpdate)
Secret update model.
Source code in zenml/models/v2/core/secret.py
class SecretUpdate(BaseUpdate):
"""Secret update model."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["scope"]
name: Optional[str] = Field(
title="The name of the secret.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
scope: Optional[SecretScope] = Field(
default=None, title="The scope of the secret."
)
values: Optional[Dict[str, Optional[PlainSerializedSecretStr]]] = Field(
title="The values stored in this secret.",
default=None,
)
def get_secret_values_update(self) -> Dict[str, Optional[str]]:
"""Returns a dictionary with the secret values to update.
Returns:
A dictionary with the secret values to update.
"""
if self.values is not None:
return {
k: v.get_secret_value() if v is not None else None
for k, v in self.values.items()
}
return {}
get_secret_values_update(self)
Returns a dictionary with the secret values to update.
Returns:
Type | Description |
---|---|
Dict[str, Optional[str]] |
A dictionary with the secret values to update. |
Source code in zenml/models/v2/core/secret.py
def get_secret_values_update(self) -> Dict[str, Optional[str]]:
"""Returns a dictionary with the secret values to update.
Returns:
A dictionary with the secret values to update.
"""
if self.values is not None:
return {
k: v.get_secret_value() if v is not None else None
for k, v in self.values.items()
}
return {}
server_settings
Models representing server settings stored in the database.
ServerActivationRequest (ServerSettingsUpdate)
Model for activating the server.
Source code in zenml/models/v2/core/server_settings.py
class ServerActivationRequest(ServerSettingsUpdate):
"""Model for activating the server."""
admin_username: Optional[str] = Field(
default=None,
title="The username of the default admin account to create. Leave "
"empty to skip creating the default admin account.",
)
admin_password: Optional[str] = Field(
default=None,
title="The password of the default admin account to create. Leave "
"empty to skip creating the default admin account.",
)
ServerSettingsResponse (BaseResponse[ServerSettingsResponseBody, ServerSettingsResponseMetadata, ServerSettingsResponseResources])
Response model for server settings.
Source code in zenml/models/v2/core/server_settings.py
class ServerSettingsResponse(
BaseResponse[
ServerSettingsResponseBody,
ServerSettingsResponseMetadata,
ServerSettingsResponseResources,
]
):
"""Response model for server settings."""
def get_hydrated_version(self) -> "ServerSettingsResponse":
"""Get the hydrated version of the server settings.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_server_settings(hydrate=True)
# Body and metadata properties
@property
def server_id(self) -> UUID:
"""The `server_id` property.
Returns:
the value of the property.
"""
return self.get_body().server_id
@property
def server_name(self) -> str:
"""The `server_name` property.
Returns:
the value of the property.
"""
return self.get_body().server_name
@property
def logo_url(self) -> Optional[str]:
"""The `logo_url` property.
Returns:
the value of the property.
"""
return self.get_body().logo_url
@property
def enable_analytics(self) -> bool:
"""The `enable_analytics` property.
Returns:
the value of the property.
"""
return self.get_body().enable_analytics
@property
def display_announcements(self) -> Optional[bool]:
"""The `display_announcements` property.
Returns:
the value of the property.
"""
return self.get_body().display_announcements
@property
def display_updates(self) -> Optional[bool]:
"""The `display_updates` property.
Returns:
the value of the property.
"""
return self.get_body().display_updates
@property
def active(self) -> bool:
"""The `active` property.
Returns:
the value of the property.
"""
return self.get_body().active
@property
def last_user_activity(self) -> datetime:
"""The `last_user_activity` property.
Returns:
the value of the property.
"""
return self.get_body().last_user_activity
@property
def updated(self) -> datetime:
"""The `updated` property.
Returns:
the value of the property.
"""
return self.get_body().updated
active: bool
property
readonly
The active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
display_announcements: Optional[bool]
property
readonly
The display_announcements
property.
Returns:
Type | Description |
---|---|
Optional[bool] |
the value of the property. |
display_updates: Optional[bool]
property
readonly
The display_updates
property.
Returns:
Type | Description |
---|---|
Optional[bool] |
the value of the property. |
enable_analytics: bool
property
readonly
The enable_analytics
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
last_user_activity: datetime
property
readonly
The last_user_activity
property.
Returns:
Type | Description |
---|---|
datetime |
the value of the property. |
logo_url: Optional[str]
property
readonly
The logo_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
server_id: UUID
property
readonly
The server_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
server_name: str
property
readonly
The server_name
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
updated: datetime
property
readonly
The updated
property.
Returns:
Type | Description |
---|---|
datetime |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of the server settings.
Returns:
Type | Description |
---|---|
ServerSettingsResponse |
An instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/server_settings.py
def get_hydrated_version(self) -> "ServerSettingsResponse":
"""Get the hydrated version of the server settings.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_server_settings(hydrate=True)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/server_settings.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ServerSettingsResponseBody (BaseResponseBody)
Response body for server settings.
Source code in zenml/models/v2/core/server_settings.py
class ServerSettingsResponseBody(BaseResponseBody):
"""Response body for server settings."""
server_id: UUID = Field(
title="The unique server id.",
)
server_name: str = Field(title="The name of the server.")
logo_url: Optional[str] = Field(
default=None, title="The logo URL of the server."
)
active: bool = Field(
title="Whether the server has been activated or not.",
)
enable_analytics: bool = Field(
title="Whether analytics are enabled for the server.",
)
display_announcements: Optional[bool] = Field(
title="Whether to display announcements about ZenML in the dashboard.",
)
display_updates: Optional[bool] = Field(
title="Whether to display notifications about ZenML updates in the dashboard.",
)
last_user_activity: datetime = Field(
title="The timestamp when the last user activity was detected.",
)
updated: datetime = Field(
title="The timestamp when this resource was last updated."
)
ServerSettingsResponseMetadata (BaseResponseMetadata)
Response metadata for server settings.
Source code in zenml/models/v2/core/server_settings.py
class ServerSettingsResponseMetadata(BaseResponseMetadata):
"""Response metadata for server settings."""
ServerSettingsResponseResources (BaseResponseResources)
Response resources for server settings.
Source code in zenml/models/v2/core/server_settings.py
class ServerSettingsResponseResources(BaseResponseResources):
"""Response resources for server settings."""
ServerSettingsUpdate (BaseZenModel)
Model for updating server settings.
Source code in zenml/models/v2/core/server_settings.py
class ServerSettingsUpdate(BaseZenModel):
"""Model for updating server settings."""
server_name: Optional[str] = Field(
default=None, title="The name of the server."
)
logo_url: Optional[str] = Field(
default=None, title="The logo URL of the server."
)
enable_analytics: Optional[bool] = Field(
default=None,
title="Whether to enable analytics for the server.",
)
display_announcements: Optional[bool] = Field(
default=None,
title="Whether to display announcements about ZenML in the dashboard.",
)
display_updates: Optional[bool] = Field(
default=None,
title="Whether to display notifications about ZenML updates in the dashboard.",
)
service
Models representing Services.
ServiceFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of services.
The Service needs additional scoping. As such the _scope_user
field
can be set to the user that is doing the filtering. The
generate_filter()
method of the baseclass is overwritten to include the
scoping.
Source code in zenml/models/v2/core/service.py
class ServiceFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of services.
The Service needs additional scoping. As such the `_scope_user` field
can be set to the user that is doing the filtering. The
`generate_filter()` method of the baseclass is overwritten to include the
scoping.
"""
name: Optional[str] = Field(
default=None,
description="Name of the service. Use this to filter services by "
"their name.",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the service",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User of the service",
union_mode="left_to_right",
)
type: Optional[str] = Field(
default=None,
description="Type of the service. Filter services by their type.",
)
flavor: Optional[str] = Field(
default=None,
description="Flavor of the service. Use this to filter services by "
"their flavor.",
)
config: Optional[bytes] = Field(
default=None,
description="Config of the service. Use this to filter services by "
"their config.",
)
pipeline_name: Optional[str] = Field(
default=None,
description="Pipeline name responsible for deploying the service",
)
pipeline_step_name: Optional[str] = Field(
default=None,
description="Pipeline step name responsible for deploying the service",
)
running: Optional[bool] = Field(
default=None, description="Whether the service is running"
)
model_version_id: Optional[Union[UUID, str]] = Field(
default=None,
description="By the model version this service is attached to.",
union_mode="left_to_right",
)
pipeline_run_id: Optional[Union[UUID, str]] = Field(
default=None,
description="By the pipeline run this service is attached to.",
union_mode="left_to_right",
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
def set_type(self, type: str) -> None:
"""Set the type of the service.
Args:
type: The type of the service.
"""
self.type = type
def set_flavor(self, flavor: str) -> None:
"""Set the flavor of the service.
Args:
flavor: The flavor of the service.
"""
self.flavor = flavor
# Artifact name and type are not DB fields and need to be handled separately
FILTER_EXCLUDE_FIELDS = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"flavor",
"type",
"pipeline_step_name",
"running",
"pipeline_name",
"config",
]
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedTaggableFilter.CLI_EXCLUDE_FIELDS,
"workspace_id",
"user_id",
"flavor",
"type",
"pipeline_step_name",
"running",
"pipeline_name",
]
def generate_filter(
self, table: Type["SQLModel"]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Services can be scoped by type to narrow the search.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
"""
from sqlmodel import and_
base_filter = super().generate_filter(table)
if self.type:
type_filter = getattr(table, "type") == self.type
base_filter = and_(base_filter, type_filter)
if self.flavor:
flavor_filter = getattr(table, "flavor") == self.flavor
base_filter = and_(base_filter, flavor_filter)
if self.pipeline_name:
pipeline_name_filter = (
getattr(table, "pipeline_name") == self.pipeline_name
)
base_filter = and_(base_filter, pipeline_name_filter)
if self.pipeline_step_name:
pipeline_step_name_filter = (
getattr(table, "pipeline_step_name") == self.pipeline_step_name
)
base_filter = and_(base_filter, pipeline_step_name_filter)
return base_filter
generate_filter(self, table)
Generate the filter for the query.
Services can be scoped by type to narrow the search.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
table |
Type[SQLModel] |
The Table that is being queried from. |
required |
Returns:
Type | Description |
---|---|
ColumnElement[bool] |
The filter expression for the query. |
Source code in zenml/models/v2/core/service.py
def generate_filter(
self, table: Type["SQLModel"]
) -> Union["ColumnElement[bool]"]:
"""Generate the filter for the query.
Services can be scoped by type to narrow the search.
Args:
table: The Table that is being queried from.
Returns:
The filter expression for the query.
"""
from sqlmodel import and_
base_filter = super().generate_filter(table)
if self.type:
type_filter = getattr(table, "type") == self.type
base_filter = and_(base_filter, type_filter)
if self.flavor:
flavor_filter = getattr(table, "flavor") == self.flavor
base_filter = and_(base_filter, flavor_filter)
if self.pipeline_name:
pipeline_name_filter = (
getattr(table, "pipeline_name") == self.pipeline_name
)
base_filter = and_(base_filter, pipeline_name_filter)
if self.pipeline_step_name:
pipeline_step_name_filter = (
getattr(table, "pipeline_step_name") == self.pipeline_step_name
)
base_filter = and_(base_filter, pipeline_step_name_filter)
return base_filter
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/service.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_flavor(self, flavor)
Set the flavor of the service.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
flavor |
str |
The flavor of the service. |
required |
Source code in zenml/models/v2/core/service.py
def set_flavor(self, flavor: str) -> None:
"""Set the flavor of the service.
Args:
flavor: The flavor of the service.
"""
self.flavor = flavor
set_type(self, type)
Set the type of the service.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
type |
str |
The type of the service. |
required |
Source code in zenml/models/v2/core/service.py
def set_type(self, type: str) -> None:
"""Set the type of the service.
Args:
type: The type of the service.
"""
self.type = type
ServiceRequest (WorkspaceScopedRequest)
Request model for services.
Source code in zenml/models/v2/core/service.py
class ServiceRequest(WorkspaceScopedRequest):
"""Request model for services."""
name: str = Field(
title="The name of the service.",
max_length=STR_FIELD_MAX_LENGTH,
)
service_type: ServiceType = Field(
title="The type of the service.",
)
service_source: Optional[str] = Field(
title="The class of the service.",
description="The fully qualified class name of the service "
"implementation.",
default=None,
)
admin_state: Optional[ServiceState] = Field(
title="The admin state of the service.",
description="The administrative state of the service, e.g., ACTIVE, "
"INACTIVE.",
default=None,
)
config: Dict[str, Any] = Field(
title="The service config.",
description="A dictionary containing configuration parameters for the "
"service.",
)
labels: Optional[Dict[str, str]] = Field(
default=None,
title="The service labels.",
)
status: Optional[Dict[str, Any]] = Field(
default=None,
title="The status of the service.",
)
endpoint: Optional[Dict[str, Any]] = Field(
default=None,
title="The service endpoint.",
)
prediction_url: Optional[str] = Field(
default=None,
title="The service endpoint URL.",
)
health_check_url: Optional[str] = Field(
default=None,
title="The service health check URL.",
)
model_version_id: Optional[UUID] = Field(
default=None,
title="The model version id linked to the service.",
)
pipeline_run_id: Optional[Union[UUID, str]] = Field(
default=None,
description="By the event source this trigger is attached to.",
union_mode="left_to_right",
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
ServiceResponse (WorkspaceScopedResponse[ServiceResponseBody, ServiceResponseMetadata, ServiceResponseResources])
Response model for services.
Source code in zenml/models/v2/core/service.py
class ServiceResponse(
WorkspaceScopedResponse[
ServiceResponseBody, ServiceResponseMetadata, ServiceResponseResources
]
):
"""Response model for services."""
name: str = Field(
title="The name of the service.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "ServiceResponse":
"""Get the hydrated version of this artifact.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_service(self.id)
# Body and metadata properties
@property
def service_type(self) -> ServiceType:
"""The `service_type` property.
Returns:
the value of the property.
"""
return self.get_body().service_type
@property
def labels(self) -> Optional[Dict[str, str]]:
"""The `labels` property.
Returns:
the value of the property.
"""
return self.get_body().labels
@property
def service_source(self) -> Optional[str]:
"""The `service_source` property.
Returns:
the value of the property.
"""
return self.get_metadata().service_source
@property
def config(self) -> Dict[str, Any]:
"""The `config` property.
Returns:
the value of the property.
"""
return self.get_metadata().config
@property
def status(self) -> Optional[Dict[str, Any]]:
"""The `status` property.
Returns:
the value of the property.
"""
return self.get_metadata().status
@property
def endpoint(self) -> Optional[Dict[str, Any]]:
"""The `endpoint` property.
Returns:
the value of the property.
"""
return self.get_metadata().endpoint
@property
def created(self) -> datetime:
"""The `created` property.
Returns:
the value of the property.
"""
return self.get_body().created
@property
def updated(self) -> datetime:
"""The `updated` property.
Returns:
the value of the property.
"""
return self.get_body().updated
@property
def admin_state(self) -> Optional[ServiceState]:
"""The `admin_state` property.
Returns:
the value of the property.
"""
return self.get_metadata().admin_state
@property
def prediction_url(self) -> Optional[str]:
"""The `prediction_url` property.
Returns:
the value of the property.
"""
return self.get_metadata().prediction_url
@property
def health_check_url(self) -> Optional[str]:
"""The `health_check_url` property.
Returns:
the value of the property.
"""
return self.get_metadata().health_check_url
@property
def state(self) -> Optional[ServiceState]:
"""The `state` property.
Returns:
the value of the property.
"""
return self.get_body().state
admin_state: Optional[zenml.services.service_status.ServiceState]
property
readonly
The admin_state
property.
Returns:
Type | Description |
---|---|
Optional[zenml.services.service_status.ServiceState] |
the value of the property. |
config: Dict[str, Any]
property
readonly
The config
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
created: datetime
property
readonly
The created
property.
Returns:
Type | Description |
---|---|
datetime |
the value of the property. |
endpoint: Optional[Dict[str, Any]]
property
readonly
The endpoint
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
health_check_url: Optional[str]
property
readonly
The health_check_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
labels: Optional[Dict[str, str]]
property
readonly
The labels
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, str]] |
the value of the property. |
prediction_url: Optional[str]
property
readonly
The prediction_url
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
service_source: Optional[str]
property
readonly
The service_source
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
service_type: ServiceType
property
readonly
The service_type
property.
Returns:
Type | Description |
---|---|
ServiceType |
the value of the property. |
state: Optional[zenml.services.service_status.ServiceState]
property
readonly
The state
property.
Returns:
Type | Description |
---|---|
Optional[zenml.services.service_status.ServiceState] |
the value of the property. |
status: Optional[Dict[str, Any]]
property
readonly
The status
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
updated: datetime
property
readonly
The updated
property.
Returns:
Type | Description |
---|---|
datetime |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this artifact.
Returns:
Type | Description |
---|---|
ServiceResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/service.py
def get_hydrated_version(self) -> "ServiceResponse":
"""Get the hydrated version of this artifact.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_service(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/service.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ServiceResponseBody (WorkspaceScopedResponseBody)
Response body for services.
Source code in zenml/models/v2/core/service.py
class ServiceResponseBody(WorkspaceScopedResponseBody):
"""Response body for services."""
service_type: ServiceType = Field(
title="The type of the service.",
)
labels: Optional[Dict[str, str]] = Field(
default=None,
title="The service labels.",
)
created: datetime = Field(
title="The timestamp when this component was created."
)
updated: datetime = Field(
title="The timestamp when this component was last updated.",
)
state: Optional[ServiceState] = Field(
default=None,
title="The current state of the service.",
)
ServiceResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for services.
Source code in zenml/models/v2/core/service.py
class ServiceResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for services."""
service_source: Optional[str] = Field(
title="The class of the service.",
)
admin_state: Optional[ServiceState] = Field(
title="The admin state of the service.",
)
config: Dict[str, Any] = Field(
title="The service config.",
)
status: Optional[Dict[str, Any]] = Field(
title="The status of the service.",
)
endpoint: Optional[Dict[str, Any]] = Field(
default=None,
title="The service endpoint.",
)
prediction_url: Optional[str] = Field(
default=None,
title="The service endpoint URL.",
)
health_check_url: Optional[str] = Field(
default=None,
title="The service health check URL.",
)
ServiceResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the service entity.
Source code in zenml/models/v2/core/service.py
class ServiceResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the service entity."""
ServiceUpdate (BaseModel)
Update model for stack components.
Source code in zenml/models/v2/core/service.py
class ServiceUpdate(BaseModel):
"""Update model for stack components."""
name: Optional[str] = Field(
None,
title="The name of the service.",
max_length=STR_FIELD_MAX_LENGTH,
)
admin_state: Optional[ServiceState] = Field(
None,
title="The admin state of the service.",
description="The administrative state of the service, e.g., ACTIVE, "
"INACTIVE.",
)
service_source: Optional[str] = Field(
None,
title="The class of the service.",
description="The fully qualified class name of the service "
"implementation.",
)
status: Optional[Dict[str, Any]] = Field(
None,
title="The status of the service.",
)
endpoint: Optional[Dict[str, Any]] = Field(
None,
title="The service endpoint.",
)
prediction_url: Optional[str] = Field(
None,
title="The service endpoint URL.",
)
health_check_url: Optional[str] = Field(
None,
title="The service health check URL.",
)
labels: Optional[Dict[str, str]] = Field(
default=None,
title="The service labels.",
)
model_version_id: Optional[UUID] = Field(
default=None,
title="The model version id linked to the service.",
)
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
service_account
Models representing service accounts.
ServiceAccountFilter (BaseFilter)
Model to enable advanced filtering of service accounts.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountFilter(BaseFilter):
"""Model to enable advanced filtering of service accounts."""
name: Optional[str] = Field(
default=None,
description="Name of the user",
)
description: Optional[str] = Field(
default=None,
title="Filter by the service account description.",
)
active: Optional[Union[bool, str]] = Field(
default=None,
description="Whether the user is active",
union_mode="left_to_right",
)
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Override to filter out user accounts from the query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
query = query.where(
getattr(table, "is_service_account") == True # noqa: E712
)
return query
apply_filter(self, query, table)
Override to filter out user accounts from the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/core/service_account.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Override to filter out user accounts from the query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
query = query.where(
getattr(table, "is_service_account") == True # noqa: E712
)
return query
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/service_account.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
ServiceAccountRequest (BaseRequest)
Request model for service accounts.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountRequest(BaseRequest):
"""Request model for service accounts."""
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"name",
"active",
]
name: str = Field(
title="The unique name for the service account.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="A description of the service account.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
active: bool = Field(title="Whether the service account is active or not.")
model_config = ConfigDict(validate_assignment=True, extra="ignore")
ServiceAccountResponse (BaseIdentifiedResponse[ServiceAccountResponseBody, ServiceAccountResponseMetadata, ServiceAccountResponseResources])
Response model for service accounts.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountResponse(
BaseIdentifiedResponse[
ServiceAccountResponseBody,
ServiceAccountResponseMetadata,
ServiceAccountResponseResources,
]
):
"""Response model for service accounts."""
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"name",
"active",
]
name: str = Field(
title="The unique username for the account.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "ServiceAccountResponse":
"""Get the hydrated version of this service account.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_service_account(self.id)
def to_user_model(self) -> "UserResponse":
"""Converts the service account to a user model.
For now, a lot of code still relies on the active user and resource
owners being a UserResponse object, which is a superset of the
ServiceAccountResponse object. We need this method to convert the
service account to a user.
Returns:
The user model.
"""
from zenml.models.v2.core.user import (
UserResponse,
UserResponseBody,
UserResponseMetadata,
)
return UserResponse(
id=self.id,
name=self.name,
body=UserResponseBody(
active=self.active,
is_service_account=True,
email_opted_in=False,
created=self.created,
updated=self.updated,
is_admin=False,
),
metadata=UserResponseMetadata(
description=self.description,
),
)
# Body and metadata properties
@property
def active(self) -> bool:
"""The `active` property.
Returns:
the value of the property.
"""
return self.get_body().active
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
active: bool
property
readonly
The active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this service account.
Returns:
Type | Description |
---|---|
ServiceAccountResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/service_account.py
def get_hydrated_version(self) -> "ServiceAccountResponse":
"""Get the hydrated version of this service account.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_service_account(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/service_account.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
to_user_model(self)
Converts the service account to a user model.
For now, a lot of code still relies on the active user and resource owners being a UserResponse object, which is a superset of the ServiceAccountResponse object. We need this method to convert the service account to a user.
Returns:
Type | Description |
---|---|
UserResponse |
The user model. |
Source code in zenml/models/v2/core/service_account.py
def to_user_model(self) -> "UserResponse":
"""Converts the service account to a user model.
For now, a lot of code still relies on the active user and resource
owners being a UserResponse object, which is a superset of the
ServiceAccountResponse object. We need this method to convert the
service account to a user.
Returns:
The user model.
"""
from zenml.models.v2.core.user import (
UserResponse,
UserResponseBody,
UserResponseMetadata,
)
return UserResponse(
id=self.id,
name=self.name,
body=UserResponseBody(
active=self.active,
is_service_account=True,
email_opted_in=False,
created=self.created,
updated=self.updated,
is_admin=False,
),
metadata=UserResponseMetadata(
description=self.description,
),
)
ServiceAccountResponseBody (BaseDatedResponseBody)
Response body for service accounts.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountResponseBody(BaseDatedResponseBody):
"""Response body for service accounts."""
active: bool = Field(default=False, title="Whether the account is active.")
ServiceAccountResponseMetadata (BaseResponseMetadata)
Response metadata for service accounts.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountResponseMetadata(BaseResponseMetadata):
"""Response metadata for service accounts."""
description: str = Field(
default="",
title="A description of the service account.",
max_length=TEXT_FIELD_MAX_LENGTH,
)
ServiceAccountResponseResources (BaseResponseResources)
Class for all resource models associated with the service account entity.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountResponseResources(BaseResponseResources):
"""Class for all resource models associated with the service account entity."""
ServiceAccountUpdate (BaseUpdate)
Update model for service accounts.
Source code in zenml/models/v2/core/service_account.py
class ServiceAccountUpdate(BaseUpdate):
"""Update model for service accounts."""
ANALYTICS_FIELDS: ClassVar[List[str]] = ["name", "active"]
name: Optional[str] = Field(
title="The unique name for the service account.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
title="A description of the service account.",
max_length=TEXT_FIELD_MAX_LENGTH,
default=None,
)
active: Optional[bool] = Field(
title="Whether the service account is active or not.",
default=None,
)
model_config = ConfigDict(validate_assignment=True)
service_connector
Models representing service connectors.
ServiceConnectorFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of service connectors.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of service connectors."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"scope_type",
"resource_type",
"labels_str",
"labels",
]
CLI_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.CLI_EXCLUDE_FIELDS,
"scope_type",
"labels_str",
"labels",
]
scope_type: Optional[str] = Field(
default=None,
description="The type to scope this query to.",
)
name: Optional[str] = Field(
default=None,
description="The name to filter by",
)
connector_type: Optional[str] = Field(
default=None,
description="The type of service connector to filter by",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace to filter by",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User to filter by",
union_mode="left_to_right",
)
auth_method: Optional[str] = Field(
default=None,
title="Filter by the authentication method configured for the "
"connector",
)
resource_type: Optional[str] = Field(
default=None,
title="Filter by the type of resource that the connector can be used "
"to access",
)
resource_id: Optional[str] = Field(
default=None,
title="Filter by the ID of the resource instance that the connector "
"is configured to access",
)
labels_str: Optional[str] = Field(
default=None,
title="Filter by one or more labels. This field can be either a JSON "
"formatted dictionary of label names and values, where the values are "
'optional and can be set to None (e.g. `{"label1":"value1", "label2": '
"null}` ), or a comma-separated list of label names and values (e.g "
"`label1=value1,label2=`. If a label name is specified without a "
"value, the filter will match all service connectors that have that "
"label present, regardless of value.",
)
secret_id: Optional[Union[UUID, str]] = Field(
default=None,
title="Filter by the ID of the secret that contains the service "
"connector's credentials",
union_mode="left_to_right",
)
# Use this internally to configure and access the labels as a dictionary
labels: Optional[Dict[str, Optional[str]]] = Field(
default=None,
title="The labels to filter by, as a dictionary",
exclude=True,
)
@model_validator(mode="after")
def validate_labels(self) -> "ServiceConnectorFilter":
"""Parse the labels string into a label dictionary and vice-versa.
Returns:
The validated values.
"""
if self.labels_str is not None:
try:
self.labels = json.loads(self.labels_str)
except json.JSONDecodeError:
# Interpret as comma-separated values instead
self.labels = {
label.split("=", 1)[0]: label.split("=", 1)[1]
if "=" in label
else None
for label in self.labels_str.split(",")
}
elif self.labels is not None:
self.labels_str = json.dumps(self.labels)
return self
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/service_connector.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
validate_labels(self)
Parse the labels string into a label dictionary and vice-versa.
Returns:
Type | Description |
---|---|
ServiceConnectorFilter |
The validated values. |
Source code in zenml/models/v2/core/service_connector.py
@model_validator(mode="after")
def validate_labels(self) -> "ServiceConnectorFilter":
"""Parse the labels string into a label dictionary and vice-versa.
Returns:
The validated values.
"""
if self.labels_str is not None:
try:
self.labels = json.loads(self.labels_str)
except json.JSONDecodeError:
# Interpret as comma-separated values instead
self.labels = {
label.split("=", 1)[0]: label.split("=", 1)[1]
if "=" in label
else None
for label in self.labels_str.split(",")
}
elif self.labels is not None:
self.labels_str = json.dumps(self.labels)
return self
ServiceConnectorRequest (WorkspaceScopedRequest)
Request model for service connectors.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorRequest(WorkspaceScopedRequest):
"""Request model for service connectors."""
name: str = Field(
title="The service connector name.",
max_length=STR_FIELD_MAX_LENGTH,
)
connector_type: Union[str, "ServiceConnectorTypeModel"] = Field(
title="The type of service connector.",
union_mode="left_to_right",
)
description: str = Field(
default="",
title="The service connector instance description.",
)
auth_method: str = Field(
title="The authentication method that the connector instance uses to "
"access the resources.",
max_length=STR_FIELD_MAX_LENGTH,
)
resource_types: List[str] = Field(
default_factory=list,
title="The type(s) of resource that the connector instance can be used "
"to gain access to.",
)
resource_id: Optional[str] = Field(
default=None,
title="Uniquely identifies a specific resource instance that the "
"connector instance can be used to access. If omitted, the connector "
"instance can be used to access any and all resource instances that "
"the authentication method and resource type(s) allow.",
max_length=STR_FIELD_MAX_LENGTH,
)
supports_instances: bool = Field(
default=False,
title="Indicates whether the connector instance can be used to access "
"multiple instances of the configured resource type.",
)
expires_at: Optional[datetime] = Field(
default=None,
title="Time when the authentication credentials configured for the "
"connector expire. If omitted, the credentials do not expire.",
)
expires_skew_tolerance: Optional[int] = Field(
default=None,
title="The number of seconds of tolerance to apply when checking "
"whether the authentication credentials configured for the connector "
"have expired. If omitted, no tolerance is applied.",
)
expiration_seconds: Optional[int] = Field(
default=None,
title="The duration, in seconds, that the temporary credentials "
"generated by this connector should remain valid. Only applicable for "
"connectors and authentication methods that involve generating "
"temporary credentials from the ones configured in the connector.",
)
configuration: Dict[str, Any] = Field(
default_factory=dict,
title="The service connector configuration, not including secrets.",
)
secrets: Dict[str, Optional[PlainSerializedSecretStr]] = Field(
default_factory=dict,
title="The service connector secrets.",
)
labels: Dict[str, str] = Field(
default_factory=dict,
title="Service connector labels.",
)
# Analytics
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"connector_type",
"auth_method",
"resource_types",
]
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Format the resource types in the analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
if len(self.resource_types) == 1:
metadata["resource_types"] = self.resource_types[0]
else:
metadata["resource_types"] = ", ".join(self.resource_types)
metadata["connector_type"] = self.type
return metadata
# Helper methods
@property
def type(self) -> str:
"""Get the connector type.
Returns:
The connector type.
"""
if isinstance(self.connector_type, str):
return self.connector_type
return self.connector_type.connector_type
@property
def emojified_connector_type(self) -> str:
"""Get the emojified connector type.
Returns:
The emojified connector type.
"""
if not isinstance(self.connector_type, str):
return self.connector_type.emojified_connector_type
return self.connector_type
@property
def emojified_resource_types(self) -> List[str]:
"""Get the emojified connector type.
Returns:
The emojified connector type.
"""
if not isinstance(self.connector_type, str):
return [
self.connector_type.resource_type_dict[
resource_type
].emojified_resource_type
for resource_type in self.resource_types
]
return self.resource_types
def validate_and_configure_resources(
self,
connector_type: "ServiceConnectorTypeModel",
resource_types: Optional[Union[str, List[str]]] = None,
resource_id: Optional[str] = None,
configuration: Optional[Dict[str, Any]] = None,
secrets: Optional[Dict[str, Optional[SecretStr]]] = None,
) -> None:
"""Validate and configure the resources that the connector can be used to access.
Args:
connector_type: The connector type specification used to validate
the connector configuration.
resource_types: The type(s) of resource that the connector instance
can be used to access. If omitted, a multi-type connector is
configured.
resource_id: Uniquely identifies a specific resource instance that
the connector instance can be used to access.
configuration: The connector configuration.
secrets: The connector secrets.
"""
_validate_and_configure_resources(
connector=self,
connector_type=connector_type,
resource_types=resource_types,
resource_id=resource_id,
configuration=configuration,
secrets=secrets,
)
emojified_connector_type: str
property
readonly
Get the emojified connector type.
Returns:
Type | Description |
---|---|
str |
The emojified connector type. |
emojified_resource_types: List[str]
property
readonly
Get the emojified connector type.
Returns:
Type | Description |
---|---|
List[str] |
The emojified connector type. |
type: str
property
readonly
Get the connector type.
Returns:
Type | Description |
---|---|
str |
The connector type. |
get_analytics_metadata(self)
Format the resource types in the analytics metadata.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
Dict of analytics metadata. |
Source code in zenml/models/v2/core/service_connector.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Format the resource types in the analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
if len(self.resource_types) == 1:
metadata["resource_types"] = self.resource_types[0]
else:
metadata["resource_types"] = ", ".join(self.resource_types)
metadata["connector_type"] = self.type
return metadata
validate_and_configure_resources(self, connector_type, resource_types=None, resource_id=None, configuration=None, secrets=None)
Validate and configure the resources that the connector can be used to access.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
connector_type |
ServiceConnectorTypeModel |
The connector type specification used to validate the connector configuration. |
required |
resource_types |
Union[str, List[str]] |
The type(s) of resource that the connector instance can be used to access. If omitted, a multi-type connector is configured. |
None |
resource_id |
Optional[str] |
Uniquely identifies a specific resource instance that the connector instance can be used to access. |
None |
configuration |
Optional[Dict[str, Any]] |
The connector configuration. |
None |
secrets |
Optional[Dict[str, Optional[pydantic.types.SecretStr]]] |
The connector secrets. |
None |
Source code in zenml/models/v2/core/service_connector.py
def validate_and_configure_resources(
self,
connector_type: "ServiceConnectorTypeModel",
resource_types: Optional[Union[str, List[str]]] = None,
resource_id: Optional[str] = None,
configuration: Optional[Dict[str, Any]] = None,
secrets: Optional[Dict[str, Optional[SecretStr]]] = None,
) -> None:
"""Validate and configure the resources that the connector can be used to access.
Args:
connector_type: The connector type specification used to validate
the connector configuration.
resource_types: The type(s) of resource that the connector instance
can be used to access. If omitted, a multi-type connector is
configured.
resource_id: Uniquely identifies a specific resource instance that
the connector instance can be used to access.
configuration: The connector configuration.
secrets: The connector secrets.
"""
_validate_and_configure_resources(
connector=self,
connector_type=connector_type,
resource_types=resource_types,
resource_id=resource_id,
configuration=configuration,
secrets=secrets,
)
ServiceConnectorResponse (WorkspaceScopedResponse[ServiceConnectorResponseBody, ServiceConnectorResponseMetadata, ServiceConnectorResponseResources])
Response model for service connectors.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorResponse(
WorkspaceScopedResponse[
ServiceConnectorResponseBody,
ServiceConnectorResponseMetadata,
ServiceConnectorResponseResources,
]
):
"""Response model for service connectors."""
name: str = Field(
title="The service connector name.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Add the service connector labels to analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata.update(
{
label[6:]: value
for label, value in self.labels.items()
if label.startswith("zenml:")
}
)
return metadata
def get_hydrated_version(self) -> "ServiceConnectorResponse":
"""Get the hydrated version of this service connector.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_service_connector(self.id)
# Helper methods
@property
def type(self) -> str:
"""Get the connector type.
Returns:
The connector type.
"""
if isinstance(self.connector_type, str):
return self.connector_type
return self.connector_type.connector_type
@property
def emojified_connector_type(self) -> str:
"""Get the emojified connector type.
Returns:
The emojified connector type.
"""
if not isinstance(self.connector_type, str):
return self.connector_type.emojified_connector_type
return self.connector_type
@property
def emojified_resource_types(self) -> List[str]:
"""Get the emojified connector type.
Returns:
The emojified connector type.
"""
if not isinstance(self.connector_type, str):
return [
self.connector_type.resource_type_dict[
resource_type
].emojified_resource_type
for resource_type in self.resource_types
]
return self.resource_types
@property
def is_multi_type(self) -> bool:
"""Checks if the connector is multi-type.
A multi-type connector can be used to access multiple types of
resources.
Returns:
True if the connector is multi-type, False otherwise.
"""
return len(self.resource_types) > 1
@property
def is_multi_instance(self) -> bool:
"""Checks if the connector is multi-instance.
A multi-instance connector is configured to access multiple instances
of the configured resource type.
Returns:
True if the connector is multi-instance, False otherwise.
"""
return (
not self.is_multi_type
and self.supports_instances
and not self.resource_id
)
@property
def is_single_instance(self) -> bool:
"""Checks if the connector is single-instance.
A single-instance connector is configured to access only a single
instance of the configured resource type or does not support multiple
resource instances.
Returns:
True if the connector is single-instance, False otherwise.
"""
return not self.is_multi_type and not self.is_multi_instance
@property
def full_configuration(self) -> Dict[str, str]:
"""Get the full connector configuration, including secrets.
Returns:
The full connector configuration, including secrets.
"""
config = self.configuration.copy()
config.update(
{k: v.get_secret_value() for k, v in self.secrets.items() if v}
)
return config
def set_connector_type(
self, value: Union[str, "ServiceConnectorTypeModel"]
) -> None:
"""Auxiliary method to set the connector type.
Args:
value: the new value for the connector type.
"""
self.get_body().connector_type = value
def validate_and_configure_resources(
self,
connector_type: "ServiceConnectorTypeModel",
resource_types: Optional[Union[str, List[str]]] = None,
resource_id: Optional[str] = None,
configuration: Optional[Dict[str, Any]] = None,
secrets: Optional[Dict[str, Optional[SecretStr]]] = None,
) -> None:
"""Validate and configure the resources that the connector can be used to access.
Args:
connector_type: The connector type specification used to validate
the connector configuration.
resource_types: The type(s) of resource that the connector instance
can be used to access. If omitted, a multi-type connector is
configured.
resource_id: Uniquely identifies a specific resource instance that
the connector instance can be used to access.
configuration: The connector configuration.
secrets: The connector secrets.
"""
_validate_and_configure_resources(
connector=self,
connector_type=connector_type,
resource_types=resource_types,
resource_id=resource_id,
configuration=configuration,
secrets=secrets,
)
# Body and metadata properties
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_body().description
@property
def connector_type(self) -> Union[str, "ServiceConnectorTypeModel"]:
"""The `connector_type` property.
Returns:
the value of the property.
"""
return self.get_body().connector_type
@property
def auth_method(self) -> str:
"""The `auth_method` property.
Returns:
the value of the property.
"""
return self.get_body().auth_method
@property
def resource_types(self) -> List[str]:
"""The `resource_types` property.
Returns:
the value of the property.
"""
return self.get_body().resource_types
@property
def resource_id(self) -> Optional[str]:
"""The `resource_id` property.
Returns:
the value of the property.
"""
return self.get_body().resource_id
@property
def supports_instances(self) -> bool:
"""The `supports_instances` property.
Returns:
the value of the property.
"""
return self.get_body().supports_instances
@property
def expires_at(self) -> Optional[datetime]:
"""The `expires_at` property.
Returns:
the value of the property.
"""
return self.get_body().expires_at
@property
def expires_skew_tolerance(self) -> Optional[int]:
"""The `expires_skew_tolerance` property.
Returns:
the value of the property.
"""
return self.get_body().expires_skew_tolerance
@property
def configuration(self) -> Dict[str, Any]:
"""The `configuration` property.
Returns:
the value of the property.
"""
return self.get_metadata().configuration
@property
def secret_id(self) -> Optional[UUID]:
"""The `secret_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().secret_id
@property
def expiration_seconds(self) -> Optional[int]:
"""The `expiration_seconds` property.
Returns:
the value of the property.
"""
return self.get_metadata().expiration_seconds
@property
def secrets(self) -> Dict[str, Optional[SecretStr]]:
"""The `secrets` property.
Returns:
the value of the property.
"""
return self.get_metadata().secrets
@property
def labels(self) -> Dict[str, str]:
"""The `labels` property.
Returns:
the value of the property.
"""
return self.get_metadata().labels
auth_method: str
property
readonly
The auth_method
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
configuration: Dict[str, Any]
property
readonly
The configuration
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
connector_type: Union[str, ServiceConnectorTypeModel]
property
readonly
The connector_type
property.
Returns:
Type | Description |
---|---|
Union[str, ServiceConnectorTypeModel] |
the value of the property. |
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
emojified_connector_type: str
property
readonly
Get the emojified connector type.
Returns:
Type | Description |
---|---|
str |
The emojified connector type. |
emojified_resource_types: List[str]
property
readonly
Get the emojified connector type.
Returns:
Type | Description |
---|---|
List[str] |
The emojified connector type. |
expiration_seconds: Optional[int]
property
readonly
The expiration_seconds
property.
Returns:
Type | Description |
---|---|
Optional[int] |
the value of the property. |
expires_at: Optional[datetime.datetime]
property
readonly
The expires_at
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
expires_skew_tolerance: Optional[int]
property
readonly
The expires_skew_tolerance
property.
Returns:
Type | Description |
---|---|
Optional[int] |
the value of the property. |
full_configuration: Dict[str, str]
property
readonly
Get the full connector configuration, including secrets.
Returns:
Type | Description |
---|---|
Dict[str, str] |
The full connector configuration, including secrets. |
is_multi_instance: bool
property
readonly
Checks if the connector is multi-instance.
A multi-instance connector is configured to access multiple instances of the configured resource type.
Returns:
Type | Description |
---|---|
bool |
True if the connector is multi-instance, False otherwise. |
is_multi_type: bool
property
readonly
Checks if the connector is multi-type.
A multi-type connector can be used to access multiple types of resources.
Returns:
Type | Description |
---|---|
bool |
True if the connector is multi-type, False otherwise. |
is_single_instance: bool
property
readonly
Checks if the connector is single-instance.
A single-instance connector is configured to access only a single instance of the configured resource type or does not support multiple resource instances.
Returns:
Type | Description |
---|---|
bool |
True if the connector is single-instance, False otherwise. |
labels: Dict[str, str]
property
readonly
The labels
property.
Returns:
Type | Description |
---|---|
Dict[str, str] |
the value of the property. |
resource_id: Optional[str]
property
readonly
The resource_id
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
resource_types: List[str]
property
readonly
The resource_types
property.
Returns:
Type | Description |
---|---|
List[str] |
the value of the property. |
secret_id: Optional[uuid.UUID]
property
readonly
The secret_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
secrets: Dict[str, Optional[pydantic.types.SecretStr]]
property
readonly
The secrets
property.
Returns:
Type | Description |
---|---|
Dict[str, Optional[pydantic.types.SecretStr]] |
the value of the property. |
supports_instances: bool
property
readonly
The supports_instances
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
type: str
property
readonly
Get the connector type.
Returns:
Type | Description |
---|---|
str |
The connector type. |
get_analytics_metadata(self)
Add the service connector labels to analytics metadata.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
Dict of analytics metadata. |
Source code in zenml/models/v2/core/service_connector.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Add the service connector labels to analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata.update(
{
label[6:]: value
for label, value in self.labels.items()
if label.startswith("zenml:")
}
)
return metadata
get_hydrated_version(self)
Get the hydrated version of this service connector.
Returns:
Type | Description |
---|---|
ServiceConnectorResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/service_connector.py
def get_hydrated_version(self) -> "ServiceConnectorResponse":
"""Get the hydrated version of this service connector.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_service_connector(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/service_connector.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
set_connector_type(self, value)
Auxiliary method to set the connector type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
value |
Union[str, ServiceConnectorTypeModel] |
the new value for the connector type. |
required |
Source code in zenml/models/v2/core/service_connector.py
def set_connector_type(
self, value: Union[str, "ServiceConnectorTypeModel"]
) -> None:
"""Auxiliary method to set the connector type.
Args:
value: the new value for the connector type.
"""
self.get_body().connector_type = value
validate_and_configure_resources(self, connector_type, resource_types=None, resource_id=None, configuration=None, secrets=None)
Validate and configure the resources that the connector can be used to access.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
connector_type |
ServiceConnectorTypeModel |
The connector type specification used to validate the connector configuration. |
required |
resource_types |
Union[str, List[str]] |
The type(s) of resource that the connector instance can be used to access. If omitted, a multi-type connector is configured. |
None |
resource_id |
Optional[str] |
Uniquely identifies a specific resource instance that the connector instance can be used to access. |
None |
configuration |
Optional[Dict[str, Any]] |
The connector configuration. |
None |
secrets |
Optional[Dict[str, Optional[pydantic.types.SecretStr]]] |
The connector secrets. |
None |
Source code in zenml/models/v2/core/service_connector.py
def validate_and_configure_resources(
self,
connector_type: "ServiceConnectorTypeModel",
resource_types: Optional[Union[str, List[str]]] = None,
resource_id: Optional[str] = None,
configuration: Optional[Dict[str, Any]] = None,
secrets: Optional[Dict[str, Optional[SecretStr]]] = None,
) -> None:
"""Validate and configure the resources that the connector can be used to access.
Args:
connector_type: The connector type specification used to validate
the connector configuration.
resource_types: The type(s) of resource that the connector instance
can be used to access. If omitted, a multi-type connector is
configured.
resource_id: Uniquely identifies a specific resource instance that
the connector instance can be used to access.
configuration: The connector configuration.
secrets: The connector secrets.
"""
_validate_and_configure_resources(
connector=self,
connector_type=connector_type,
resource_types=resource_types,
resource_id=resource_id,
configuration=configuration,
secrets=secrets,
)
ServiceConnectorResponseBody (WorkspaceScopedResponseBody)
Response body for service connectors.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorResponseBody(WorkspaceScopedResponseBody):
"""Response body for service connectors."""
description: str = Field(
default="",
title="The service connector instance description.",
)
connector_type: Union[str, "ServiceConnectorTypeModel"] = Field(
title="The type of service connector.", union_mode="left_to_right"
)
auth_method: str = Field(
title="The authentication method that the connector instance uses to "
"access the resources.",
max_length=STR_FIELD_MAX_LENGTH,
)
resource_types: List[str] = Field(
default_factory=list,
title="The type(s) of resource that the connector instance can be used "
"to gain access to.",
)
resource_id: Optional[str] = Field(
default=None,
title="Uniquely identifies a specific resource instance that the "
"connector instance can be used to access. If omitted, the connector "
"instance can be used to access any and all resource instances that "
"the authentication method and resource type(s) allow.",
max_length=STR_FIELD_MAX_LENGTH,
)
supports_instances: bool = Field(
default=False,
title="Indicates whether the connector instance can be used to access "
"multiple instances of the configured resource type.",
)
expires_at: Optional[datetime] = Field(
default=None,
title="Time when the authentication credentials configured for the "
"connector expire. If omitted, the credentials do not expire.",
)
expires_skew_tolerance: Optional[int] = Field(
default=None,
title="The number of seconds of tolerance to apply when checking "
"whether the authentication credentials configured for the connector "
"have expired. If omitted, no tolerance is applied.",
)
ServiceConnectorResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for service connectors.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for service connectors."""
configuration: Dict[str, Any] = Field(
default_factory=dict,
title="The service connector configuration, not including secrets.",
)
secret_id: Optional[UUID] = Field(
default=None,
title="The ID of the secret that contains the service connector "
"secret configuration values.",
)
expiration_seconds: Optional[int] = Field(
default=None,
title="The duration, in seconds, that the temporary credentials "
"generated by this connector should remain valid. Only applicable for "
"connectors and authentication methods that involve generating "
"temporary credentials from the ones configured in the connector.",
)
secrets: Dict[str, Optional[PlainSerializedSecretStr]] = Field(
default_factory=dict,
title="The service connector secrets.",
)
labels: Dict[str, str] = Field(
default_factory=dict,
title="Service connector labels.",
)
ServiceConnectorResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the service connector entity.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the service connector entity."""
ServiceConnectorUpdate (BaseUpdate)
Model used for service connector updates.
Most fields in the update model are optional and will not be updated if omitted. However, the following fields are "special" and leaving them out will also cause the corresponding value to be removed from the service connector in the database:
- the
resource_id
field - the
expiration_seconds
field
In addition to the above exceptions, the following rules apply:
- the
configuration
andsecrets
fields together represent a full valid configuration update, not just a partial update. If either is set (i.e. not None) in the update, their values are merged together and will replace the existing configuration and secrets values. - the
secret_id
field value in the update is ignored, given that secrets are managed internally by the ZenML store. - the
labels
field is also a full labels update: if set (i.e. notNone
), all existing labels are removed and replaced by the new labels in the update.
NOTE: the attributes here override the ones in the base class, so they have a None default value.
Source code in zenml/models/v2/core/service_connector.py
class ServiceConnectorUpdate(BaseUpdate):
"""Model used for service connector updates.
Most fields in the update model are optional and will not be updated if
omitted. However, the following fields are "special" and leaving them out
will also cause the corresponding value to be removed from the service
connector in the database:
* the `resource_id` field
* the `expiration_seconds` field
In addition to the above exceptions, the following rules apply:
* the `configuration` and `secrets` fields together represent a full
valid configuration update, not just a partial update. If either is
set (i.e. not None) in the update, their values are merged together and
will replace the existing configuration and secrets values.
* the `secret_id` field value in the update is ignored, given that
secrets are managed internally by the ZenML store.
* the `labels` field is also a full labels update: if set (i.e. not
`None`), all existing labels are removed and replaced by the new labels
in the update.
NOTE: the attributes here override the ones in the base class, so they
have a None default value.
"""
name: Optional[str] = Field(
title="The service connector name.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
connector_type: Optional[Union[str, "ServiceConnectorTypeModel"]] = Field(
title="The type of service connector.",
default=None,
union_mode="left_to_right",
)
description: Optional[str] = Field(
title="The service connector instance description.",
default=None,
)
auth_method: Optional[str] = Field(
title="The authentication method that the connector instance uses to "
"access the resources.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
resource_types: Optional[List[str]] = Field(
title="The type(s) of resource that the connector instance can be used "
"to gain access to.",
default=None,
)
resource_id: Optional[str] = Field(
title="Uniquely identifies a specific resource instance that the "
"connector instance can be used to access. If omitted, the "
"connector instance can be used to access any and all resource "
"instances that the authentication method and resource type(s) "
"allow.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
supports_instances: Optional[bool] = Field(
title="Indicates whether the connector instance can be used to access "
"multiple instances of the configured resource type.",
default=None,
)
expires_at: Optional[datetime] = Field(
title="Time when the authentication credentials configured for the "
"connector expire. If omitted, the credentials do not expire.",
default=None,
)
expires_skew_tolerance: Optional[int] = Field(
title="The number of seconds of tolerance to apply when checking "
"whether the authentication credentials configured for the "
"connector have expired. If omitted, no tolerance is applied.",
default=None,
)
expiration_seconds: Optional[int] = Field(
title="The duration, in seconds, that the temporary credentials "
"generated by this connector should remain valid. Only "
"applicable for connectors and authentication methods that "
"involve generating temporary credentials from the ones "
"configured in the connector.",
default=None,
)
configuration: Optional[Dict[str, Any]] = Field(
title="The service connector configuration, not including secrets.",
default=None,
)
secrets: Optional[Dict[str, Optional[PlainSerializedSecretStr]]] = Field(
title="The service connector secrets.",
default=None,
)
labels: Optional[Dict[str, str]] = Field(
title="Service connector labels.",
default=None,
)
# Analytics
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"connector_type",
"auth_method",
"resource_types",
]
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Format the resource types in the analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
if self.resource_types is not None:
if len(self.resource_types) == 1:
metadata["resource_types"] = self.resource_types[0]
else:
metadata["resource_types"] = ", ".join(self.resource_types)
if self.connector_type is not None:
metadata["connector_type"] = self.type
return metadata
# Helper methods
@property
def type(self) -> Optional[str]:
"""Get the connector type.
Returns:
The connector type.
"""
if self.connector_type is not None:
if isinstance(self.connector_type, str):
return self.connector_type
return self.connector_type.connector_type
return None
def validate_and_configure_resources(
self,
connector_type: "ServiceConnectorTypeModel",
resource_types: Optional[Union[str, List[str]]] = None,
resource_id: Optional[str] = None,
configuration: Optional[Dict[str, Any]] = None,
secrets: Optional[Dict[str, Optional[SecretStr]]] = None,
) -> None:
"""Validate and configure the resources that the connector can be used to access.
Args:
connector_type: The connector type specification used to validate
the connector configuration.
resource_types: The type(s) of resource that the connector instance
can be used to access. If omitted, a multi-type connector is
configured.
resource_id: Uniquely identifies a specific resource instance that
the connector instance can be used to access.
configuration: The connector configuration.
secrets: The connector secrets.
"""
_validate_and_configure_resources(
connector=self,
connector_type=connector_type,
resource_types=resource_types,
resource_id=resource_id,
configuration=configuration,
secrets=secrets,
)
def convert_to_request(self) -> "ServiceConnectorRequest":
"""Method to generate a service connector request object from self.
For certain operations, the service connector update model need to
adhere to the limitations set by the request model. In order to use
update models in such situations, we need to be able to convert an
update model into a request model.
Returns:
The equivalent request model
Raises:
RuntimeError: if the model can not be converted to a request model.
"""
try:
return ServiceConnectorRequest.model_validate(self.model_dump())
except ValidationError as e:
raise RuntimeError(
"The service connector update model can not be converted into "
f"an equivalent request model: {e}"
)
type: Optional[str]
property
readonly
Get the connector type.
Returns:
Type | Description |
---|---|
Optional[str] |
The connector type. |
convert_to_request(self)
Method to generate a service connector request object from self.
For certain operations, the service connector update model need to adhere to the limitations set by the request model. In order to use update models in such situations, we need to be able to convert an update model into a request model.
Returns:
Type | Description |
---|---|
ServiceConnectorRequest |
The equivalent request model |
Exceptions:
Type | Description |
---|---|
RuntimeError |
if the model can not be converted to a request model. |
Source code in zenml/models/v2/core/service_connector.py
def convert_to_request(self) -> "ServiceConnectorRequest":
"""Method to generate a service connector request object from self.
For certain operations, the service connector update model need to
adhere to the limitations set by the request model. In order to use
update models in such situations, we need to be able to convert an
update model into a request model.
Returns:
The equivalent request model
Raises:
RuntimeError: if the model can not be converted to a request model.
"""
try:
return ServiceConnectorRequest.model_validate(self.model_dump())
except ValidationError as e:
raise RuntimeError(
"The service connector update model can not be converted into "
f"an equivalent request model: {e}"
)
get_analytics_metadata(self)
Format the resource types in the analytics metadata.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
Dict of analytics metadata. |
Source code in zenml/models/v2/core/service_connector.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Format the resource types in the analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
if self.resource_types is not None:
if len(self.resource_types) == 1:
metadata["resource_types"] = self.resource_types[0]
else:
metadata["resource_types"] = ", ".join(self.resource_types)
if self.connector_type is not None:
metadata["connector_type"] = self.type
return metadata
validate_and_configure_resources(self, connector_type, resource_types=None, resource_id=None, configuration=None, secrets=None)
Validate and configure the resources that the connector can be used to access.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
connector_type |
ServiceConnectorTypeModel |
The connector type specification used to validate the connector configuration. |
required |
resource_types |
Union[str, List[str]] |
The type(s) of resource that the connector instance can be used to access. If omitted, a multi-type connector is configured. |
None |
resource_id |
Optional[str] |
Uniquely identifies a specific resource instance that the connector instance can be used to access. |
None |
configuration |
Optional[Dict[str, Any]] |
The connector configuration. |
None |
secrets |
Optional[Dict[str, Optional[pydantic.types.SecretStr]]] |
The connector secrets. |
None |
Source code in zenml/models/v2/core/service_connector.py
def validate_and_configure_resources(
self,
connector_type: "ServiceConnectorTypeModel",
resource_types: Optional[Union[str, List[str]]] = None,
resource_id: Optional[str] = None,
configuration: Optional[Dict[str, Any]] = None,
secrets: Optional[Dict[str, Optional[SecretStr]]] = None,
) -> None:
"""Validate and configure the resources that the connector can be used to access.
Args:
connector_type: The connector type specification used to validate
the connector configuration.
resource_types: The type(s) of resource that the connector instance
can be used to access. If omitted, a multi-type connector is
configured.
resource_id: Uniquely identifies a specific resource instance that
the connector instance can be used to access.
configuration: The connector configuration.
secrets: The connector secrets.
"""
_validate_and_configure_resources(
connector=self,
connector_type=connector_type,
resource_types=resource_types,
resource_id=resource_id,
configuration=configuration,
secrets=secrets,
)
stack
Models representing stacks.
StackFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all StackModels.
The Stack Model needs additional scoping. As such the _scope_user
field
can be set to the user that is doing the filtering. The
generate_filter()
method of the baseclass is overwritten to include the
scoping.
Source code in zenml/models/v2/core/stack.py
class StackFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all StackModels.
The Stack Model needs additional scoping. As such the `_scope_user` field
can be set to the user that is doing the filtering. The
`generate_filter()` method of the baseclass is overwritten to include the
scoping.
"""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"component_id",
"user",
"component",
]
name: Optional[str] = Field(
default=None,
description="Name of the stack",
)
description: Optional[str] = Field(
default=None, description="Description of the stack"
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of the stack",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User of the stack",
union_mode="left_to_right",
)
component_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Component in the stack",
union_mode="left_to_right",
)
user: Optional[Union[UUID, str]] = Field(
default=None,
description="Name/ID of the user that created the stack.",
)
component: Optional[Union[UUID, str]] = Field(
default=None, description="Name/ID of a component in the stack."
)
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from zenml.zen_stores.schemas import (
StackComponentSchema,
StackCompositionSchema,
StackSchema,
UserSchema,
)
if self.component_id:
component_id_filter = and_(
StackCompositionSchema.stack_id == StackSchema.id,
StackCompositionSchema.component_id == self.component_id,
)
custom_filters.append(component_id_filter)
if self.user:
user_filter = and_(
StackSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.component:
component_filter = and_(
StackCompositionSchema.stack_id == StackSchema.id,
StackCompositionSchema.component_id == StackComponentSchema.id,
self.generate_name_or_id_query_conditions(
value=self.component,
table=StackComponentSchema,
),
)
custom_filters.append(component_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/stack.py
def get_custom_filters(self) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
custom_filters = super().get_custom_filters()
from zenml.zen_stores.schemas import (
StackComponentSchema,
StackCompositionSchema,
StackSchema,
UserSchema,
)
if self.component_id:
component_id_filter = and_(
StackCompositionSchema.stack_id == StackSchema.id,
StackCompositionSchema.component_id == self.component_id,
)
custom_filters.append(component_id_filter)
if self.user:
user_filter = and_(
StackSchema.user_id == UserSchema.id,
self.generate_name_or_id_query_conditions(
value=self.user, table=UserSchema
),
)
custom_filters.append(user_filter)
if self.component:
component_filter = and_(
StackCompositionSchema.stack_id == StackSchema.id,
StackCompositionSchema.component_id == StackComponentSchema.id,
self.generate_name_or_id_query_conditions(
value=self.component,
table=StackComponentSchema,
),
)
custom_filters.append(component_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/stack.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
StackRequest (BaseRequest)
Request model for a stack.
Source code in zenml/models/v2/core/stack.py
class StackRequest(BaseRequest):
"""Request model for a stack."""
user: Optional[UUID] = None
workspace: Optional[UUID] = None
name: str = Field(
title="The name of the stack.", max_length=STR_FIELD_MAX_LENGTH
)
description: str = Field(
default="",
title="The description of the stack",
max_length=STR_FIELD_MAX_LENGTH,
)
stack_spec_path: Optional[str] = Field(
default=None,
title="The path to the stack spec used for mlstacks deployments.",
)
components: Dict[StackComponentType, List[Union[UUID, ComponentInfo]]] = (
Field(
title="The mapping for the components of the full stack registration.",
description="The mapping from component types to either UUIDs of "
"existing components or request information for brand new "
"components.",
)
)
labels: Optional[Dict[str, Any]] = Field(
default=None,
title="The stack labels.",
)
service_connectors: List[Union[UUID, ServiceConnectorInfo]] = Field(
default=[],
title="The service connectors dictionary for the full stack "
"registration.",
description="The UUID of an already existing service connector or "
"request information to create a service connector from "
"scratch.",
)
@property
def is_valid(self) -> bool:
"""Check if the stack is valid.
Returns:
True if the stack is valid, False otherwise.
"""
if not self.components:
return False
return (
StackComponentType.ARTIFACT_STORE in self.components
and StackComponentType.ORCHESTRATOR in self.components
)
@model_validator(mode="after")
def _validate_indexes_in_components(self) -> "StackRequest":
for components in self.components.values():
for component in components:
if isinstance(component, ComponentInfo):
if component.service_connector_index is not None:
if (
component.service_connector_index < 0
or component.service_connector_index
>= len(self.service_connectors)
):
raise ValueError(
f"Service connector index "
f"{component.service_connector_index} "
"is out of range. Please provide a valid index "
"referring to the position in the list of service "
"connectors."
)
return self
is_valid: bool
property
readonly
Check if the stack is valid.
Returns:
Type | Description |
---|---|
bool |
True if the stack is valid, False otherwise. |
StackResponse (WorkspaceScopedResponse[StackResponseBody, StackResponseMetadata, StackResponseResources])
Response model for stacks.
Source code in zenml/models/v2/core/stack.py
class StackResponse(
WorkspaceScopedResponse[
StackResponseBody, StackResponseMetadata, StackResponseResources
]
):
"""Response model for stacks."""
name: str = Field(
title="The name of the stack.", max_length=STR_FIELD_MAX_LENGTH
)
def get_hydrated_version(self) -> "StackResponse":
"""Get the hydrated version of this stack.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_stack(self.id)
# Helper methods
@property
def is_valid(self) -> bool:
"""Check if the stack is valid.
Returns:
True if the stack is valid, False otherwise.
"""
return (
StackComponentType.ARTIFACT_STORE in self.components
and StackComponentType.ORCHESTRATOR in self.components
)
def to_yaml(self) -> Dict[str, Any]:
"""Create yaml representation of the Stack Model.
Returns:
The yaml representation of the Stack Model.
"""
component_data = {}
for component_type, components_list in self.components.items():
component = components_list[0]
component_dict = dict(
name=component.name,
type=str(component.type),
flavor=component.flavor,
)
configuration = json.loads(
component.get_metadata().model_dump_json(
include={"configuration"}
)
)
component_dict.update(configuration)
component_data[component_type.value] = component_dict
# write zenml version and stack dict to YAML
yaml_data = {
"stack_name": self.name,
"components": component_data,
}
return yaml_data
# Analytics
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Add the stack components to the stack analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata.update({ct: c[0].flavor for ct, c in self.components.items()})
if self.labels is not None:
metadata.update(
{
label[6:]: value
for label, value in self.labels.items()
if label.startswith("zenml:")
}
)
return metadata
@property
def description(self) -> Optional[str]:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def stack_spec_path(self) -> Optional[str]:
"""The `stack_spec_path` property.
Returns:
the value of the property.
"""
return self.get_metadata().stack_spec_path
@property
def components(
self,
) -> Dict[StackComponentType, List["ComponentResponse"]]:
"""The `components` property.
Returns:
the value of the property.
"""
return self.get_metadata().components
@property
def labels(self) -> Optional[Dict[str, Any]]:
"""The `labels` property.
Returns:
the value of the property.
"""
return self.get_metadata().labels
components: Dict[zenml.enums.StackComponentType, List[ComponentResponse]]
property
readonly
The components
property.
Returns:
Type | Description |
---|---|
Dict[zenml.enums.StackComponentType, List[ComponentResponse]] |
the value of the property. |
description: Optional[str]
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
is_valid: bool
property
readonly
Check if the stack is valid.
Returns:
Type | Description |
---|---|
bool |
True if the stack is valid, False otherwise. |
labels: Optional[Dict[str, Any]]
property
readonly
The labels
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
stack_spec_path: Optional[str]
property
readonly
The stack_spec_path
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
get_analytics_metadata(self)
Add the stack components to the stack analytics metadata.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
Dict of analytics metadata. |
Source code in zenml/models/v2/core/stack.py
def get_analytics_metadata(self) -> Dict[str, Any]:
"""Add the stack components to the stack analytics metadata.
Returns:
Dict of analytics metadata.
"""
metadata = super().get_analytics_metadata()
metadata.update({ct: c[0].flavor for ct, c in self.components.items()})
if self.labels is not None:
metadata.update(
{
label[6:]: value
for label, value in self.labels.items()
if label.startswith("zenml:")
}
)
return metadata
get_hydrated_version(self)
Get the hydrated version of this stack.
Returns:
Type | Description |
---|---|
StackResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/stack.py
def get_hydrated_version(self) -> "StackResponse":
"""Get the hydrated version of this stack.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_stack(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/stack.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
to_yaml(self)
Create yaml representation of the Stack Model.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
The yaml representation of the Stack Model. |
Source code in zenml/models/v2/core/stack.py
def to_yaml(self) -> Dict[str, Any]:
"""Create yaml representation of the Stack Model.
Returns:
The yaml representation of the Stack Model.
"""
component_data = {}
for component_type, components_list in self.components.items():
component = components_list[0]
component_dict = dict(
name=component.name,
type=str(component.type),
flavor=component.flavor,
)
configuration = json.loads(
component.get_metadata().model_dump_json(
include={"configuration"}
)
)
component_dict.update(configuration)
component_data[component_type.value] = component_dict
# write zenml version and stack dict to YAML
yaml_data = {
"stack_name": self.name,
"components": component_data,
}
return yaml_data
StackResponseBody (WorkspaceScopedResponseBody)
Response body for stacks.
Source code in zenml/models/v2/core/stack.py
class StackResponseBody(WorkspaceScopedResponseBody):
"""Response body for stacks."""
StackResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for stacks.
Source code in zenml/models/v2/core/stack.py
class StackResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for stacks."""
components: Dict[StackComponentType, List["ComponentResponse"]] = Field(
title="A mapping of stack component types to the actual"
"instances of components of this type."
)
description: Optional[str] = Field(
default="",
title="The description of the stack",
max_length=STR_FIELD_MAX_LENGTH,
)
stack_spec_path: Optional[str] = Field(
default=None,
title="The path to the stack spec used for mlstacks deployments.",
)
labels: Optional[Dict[str, Any]] = Field(
default=None,
title="The stack labels.",
)
StackResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the stack entity.
Source code in zenml/models/v2/core/stack.py
class StackResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the stack entity."""
StackUpdate (BaseUpdate)
Update model for stacks.
Source code in zenml/models/v2/core/stack.py
class StackUpdate(BaseUpdate):
"""Update model for stacks."""
name: Optional[str] = Field(
title="The name of the stack.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
title="The description of the stack",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
stack_spec_path: Optional[str] = Field(
title="The path to the stack spec used for mlstacks deployments.",
default=None,
)
components: Optional[Dict[StackComponentType, List[UUID]]] = Field(
title="A mapping of stack component types to the actual"
"instances of components of this type.",
default=None,
)
labels: Optional[Dict[str, Any]] = Field(
default=None,
title="The stack labels.",
)
step_run
Models representing steps runs.
StepRunFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of step runs.
Source code in zenml/models/v2/core/step_run.py
class StepRunFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of step runs."""
name: Optional[str] = Field(
default=None,
description="Name of the step run",
)
code_hash: Optional[str] = Field(
default=None,
description="Code hash for this step run",
)
cache_key: Optional[str] = Field(
default=None,
description="Cache key for this step run",
)
status: Optional[str] = Field(
default=None,
description="Status of the Step Run",
)
start_time: Optional[Union[datetime, str]] = Field(
default=None,
description="Start time for this run",
union_mode="left_to_right",
)
end_time: Optional[Union[datetime, str]] = Field(
default=None,
description="End time for this run",
union_mode="left_to_right",
)
pipeline_run_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Pipeline run of this step run",
union_mode="left_to_right",
)
original_step_run_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Original id for this step run",
union_mode="left_to_right",
)
user_id: Optional[Union[UUID, str]] = Field(
default=None,
description="User that produced this step run",
union_mode="left_to_right",
)
workspace_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Workspace of this step run",
union_mode="left_to_right",
)
model_version_id: Optional[Union[UUID, str]] = Field(
default=None,
description="Model version associated with the pipeline run.",
union_mode="left_to_right",
)
model_config = ConfigDict(protected_namespaces=())
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/step_run.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
StepRunRequest (WorkspaceScopedRequest)
Request model for step runs.
Source code in zenml/models/v2/core/step_run.py
class StepRunRequest(WorkspaceScopedRequest):
"""Request model for step runs."""
name: str = Field(
title="The name of the pipeline run step.",
max_length=STR_FIELD_MAX_LENGTH,
)
start_time: Optional[datetime] = Field(
title="The start time of the step run.",
default=None,
)
end_time: Optional[datetime] = Field(
title="The end time of the step run.",
default=None,
)
status: ExecutionStatus = Field(title="The status of the step.")
cache_key: Optional[str] = Field(
title="The cache key of the step run.",
default=None,
max_length=STR_FIELD_MAX_LENGTH,
)
code_hash: Optional[str] = Field(
title="The code hash of the step run.",
default=None,
max_length=STR_FIELD_MAX_LENGTH,
)
docstring: Optional[str] = Field(
title="The docstring of the step function or class.",
default=None,
max_length=TEXT_FIELD_MAX_LENGTH,
)
source_code: Optional[str] = Field(
title="The source code of the step function or class.",
default=None,
max_length=TEXT_FIELD_MAX_LENGTH,
)
pipeline_run_id: UUID = Field(
title="The ID of the pipeline run that this step run belongs to.",
)
original_step_run_id: Optional[UUID] = Field(
title="The ID of the original step run if this step was cached.",
default=None,
)
parent_step_ids: List[UUID] = Field(
title="The IDs of the parent steps of this step run.",
default_factory=list,
)
inputs: Dict[str, UUID] = Field(
title="The IDs of the input artifact versions of the step run.",
default={},
)
outputs: Dict[str, UUID] = Field(
title="The IDs of the output artifact versions of the step run.",
default={},
)
logs: Optional["LogsRequest"] = Field(
title="Logs associated with this step run.",
default=None,
)
deployment: UUID = Field(
title="The deployment associated with the step run."
)
model_version_id: Optional[UUID] = Field(
title="The ID of the model version that was "
"configured by this step run explicitly.",
default=None,
)
model_config = ConfigDict(protected_namespaces=())
StepRunResponse (WorkspaceScopedResponse[StepRunResponseBody, StepRunResponseMetadata, StepRunResponseResources])
Response model for step runs.
Source code in zenml/models/v2/core/step_run.py
class StepRunResponse(
WorkspaceScopedResponse[
StepRunResponseBody, StepRunResponseMetadata, StepRunResponseResources
]
):
"""Response model for step runs."""
name: str = Field(
title="The name of the pipeline run step.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "StepRunResponse":
"""Get the hydrated version of this step run.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_run_step(self.id)
# Helper properties
@property
def input(self) -> "ArtifactVersionResponse":
"""Returns the input artifact that was used to run this step.
Returns:
The input artifact.
Raises:
ValueError: If there were zero or multiple inputs to this step.
"""
if not self.inputs:
raise ValueError(f"Step {self.name} has no inputs.")
if len(self.inputs) > 1:
raise ValueError(
f"Step {self.name} has multiple inputs, so `Step.input` is "
"ambiguous. Please use `Step.inputs` instead."
)
return next(iter(self.inputs.values()))
@property
def output(self) -> "ArtifactVersionResponse":
"""Returns the output artifact that was written by this step.
Returns:
The output artifact.
Raises:
ValueError: If there were zero or multiple step outputs.
"""
if not self.outputs:
raise ValueError(f"Step {self.name} has no outputs.")
if len(self.outputs) > 1:
raise ValueError(
f"Step {self.name} has multiple outputs, so `Step.output` is "
"ambiguous. Please use `Step.outputs` instead."
)
return next(iter(self.outputs.values()))
# Body and metadata properties
@property
def status(self) -> ExecutionStatus:
"""The `status` property.
Returns:
the value of the property.
"""
return self.get_body().status
@property
def inputs(self) -> Dict[str, "ArtifactVersionResponse"]:
"""The `inputs` property.
Returns:
the value of the property.
"""
return self.get_body().inputs
@property
def outputs(self) -> Dict[str, "ArtifactVersionResponse"]:
"""The `outputs` property.
Returns:
the value of the property.
"""
return self.get_body().outputs
@property
def model_version_id(self) -> Optional[UUID]:
"""The `model_version_id` property.
Returns:
the value of the property.
"""
return self.get_body().model_version_id
@property
def config(self) -> "StepConfiguration":
"""The `config` property.
Returns:
the value of the property.
"""
return self.get_metadata().config
@property
def spec(self) -> "StepSpec":
"""The `spec` property.
Returns:
the value of the property.
"""
return self.get_metadata().spec
@property
def cache_key(self) -> Optional[str]:
"""The `cache_key` property.
Returns:
the value of the property.
"""
return self.get_metadata().cache_key
@property
def code_hash(self) -> Optional[str]:
"""The `code_hash` property.
Returns:
the value of the property.
"""
return self.get_metadata().code_hash
@property
def docstring(self) -> Optional[str]:
"""The `docstring` property.
Returns:
the value of the property.
"""
return self.get_metadata().docstring
@property
def source_code(self) -> Optional[str]:
"""The `source_code` property.
Returns:
the value of the property.
"""
return self.get_metadata().source_code
@property
def start_time(self) -> Optional[datetime]:
"""The `start_time` property.
Returns:
the value of the property.
"""
return self.get_metadata().start_time
@property
def end_time(self) -> Optional[datetime]:
"""The `end_time` property.
Returns:
the value of the property.
"""
return self.get_metadata().end_time
@property
def logs(self) -> Optional["LogsResponse"]:
"""The `logs` property.
Returns:
the value of the property.
"""
return self.get_metadata().logs
@property
def deployment_id(self) -> UUID:
"""The `deployment_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().deployment_id
@property
def pipeline_run_id(self) -> UUID:
"""The `pipeline_run_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().pipeline_run_id
@property
def original_step_run_id(self) -> Optional[UUID]:
"""The `original_step_run_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().original_step_run_id
@property
def parent_step_ids(self) -> List[UUID]:
"""The `parent_step_ids` property.
Returns:
the value of the property.
"""
return self.get_metadata().parent_step_ids
@property
def run_metadata(self) -> Dict[str, "RunMetadataResponse"]:
"""The `run_metadata` property.
Returns:
the value of the property.
"""
return self.get_metadata().run_metadata
@property
def model_version(self) -> Optional[ModelVersionResponse]:
"""The `model_version` property.
Returns:
the value of the property.
"""
return self.get_resources().model_version
cache_key: Optional[str]
property
readonly
The cache_key
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
code_hash: Optional[str]
property
readonly
The code_hash
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
config: StepConfiguration
property
readonly
The config
property.
Returns:
Type | Description |
---|---|
StepConfiguration |
the value of the property. |
deployment_id: UUID
property
readonly
The deployment_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
docstring: Optional[str]
property
readonly
The docstring
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
end_time: Optional[datetime.datetime]
property
readonly
The end_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
input: ArtifactVersionResponse
property
readonly
Returns the input artifact that was used to run this step.
Returns:
Type | Description |
---|---|
ArtifactVersionResponse |
The input artifact. |
Exceptions:
Type | Description |
---|---|
ValueError |
If there were zero or multiple inputs to this step. |
inputs: Dict[str, ArtifactVersionResponse]
property
readonly
The inputs
property.
Returns:
Type | Description |
---|---|
Dict[str, ArtifactVersionResponse] |
the value of the property. |
logs: Optional[LogsResponse]
property
readonly
The logs
property.
Returns:
Type | Description |
---|---|
Optional[LogsResponse] |
the value of the property. |
model_version: Optional[zenml.models.v2.core.model_version.ModelVersionResponse]
property
readonly
The model_version
property.
Returns:
Type | Description |
---|---|
Optional[zenml.models.v2.core.model_version.ModelVersionResponse] |
the value of the property. |
model_version_id: Optional[uuid.UUID]
property
readonly
The model_version_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
original_step_run_id: Optional[uuid.UUID]
property
readonly
The original_step_run_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
output: ArtifactVersionResponse
property
readonly
Returns the output artifact that was written by this step.
Returns:
Type | Description |
---|---|
ArtifactVersionResponse |
The output artifact. |
Exceptions:
Type | Description |
---|---|
ValueError |
If there were zero or multiple step outputs. |
outputs: Dict[str, ArtifactVersionResponse]
property
readonly
The outputs
property.
Returns:
Type | Description |
---|---|
Dict[str, ArtifactVersionResponse] |
the value of the property. |
parent_step_ids: List[uuid.UUID]
property
readonly
The parent_step_ids
property.
Returns:
Type | Description |
---|---|
List[uuid.UUID] |
the value of the property. |
pipeline_run_id: UUID
property
readonly
The pipeline_run_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
run_metadata: Dict[str, RunMetadataResponse]
property
readonly
The run_metadata
property.
Returns:
Type | Description |
---|---|
Dict[str, RunMetadataResponse] |
the value of the property. |
source_code: Optional[str]
property
readonly
The source_code
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
spec: StepSpec
property
readonly
The spec
property.
Returns:
Type | Description |
---|---|
StepSpec |
the value of the property. |
start_time: Optional[datetime.datetime]
property
readonly
The start_time
property.
Returns:
Type | Description |
---|---|
Optional[datetime.datetime] |
the value of the property. |
status: ExecutionStatus
property
readonly
The status
property.
Returns:
Type | Description |
---|---|
ExecutionStatus |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this step run.
Returns:
Type | Description |
---|---|
StepRunResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/step_run.py
def get_hydrated_version(self) -> "StepRunResponse":
"""Get the hydrated version of this step run.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_run_step(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/step_run.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
StepRunResponseBody (WorkspaceScopedResponseBody)
Response body for step runs.
Source code in zenml/models/v2/core/step_run.py
class StepRunResponseBody(WorkspaceScopedResponseBody):
"""Response body for step runs."""
status: ExecutionStatus = Field(title="The status of the step.")
inputs: Dict[str, "ArtifactVersionResponse"] = Field(
title="The input artifact versions of the step run.",
default={},
)
outputs: Dict[str, "ArtifactVersionResponse"] = Field(
title="The output artifact versions of the step run.",
default={},
)
model_version_id: Optional[UUID] = Field(
title="The ID of the model version that was "
"configured by this step run explicitly.",
default=None,
)
model_config = ConfigDict(protected_namespaces=())
StepRunResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for step runs.
Source code in zenml/models/v2/core/step_run.py
class StepRunResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for step runs."""
# Configuration
config: "StepConfiguration" = Field(title="The configuration of the step.")
spec: "StepSpec" = Field(title="The spec of the step.")
# Code related fields
cache_key: Optional[str] = Field(
title="The cache key of the step run.",
default=None,
max_length=STR_FIELD_MAX_LENGTH,
)
code_hash: Optional[str] = Field(
title="The code hash of the step run.",
default=None,
max_length=STR_FIELD_MAX_LENGTH,
)
docstring: Optional[str] = Field(
title="The docstring of the step function or class.",
default=None,
max_length=TEXT_FIELD_MAX_LENGTH,
)
source_code: Optional[str] = Field(
title="The source code of the step function or class.",
default=None,
max_length=TEXT_FIELD_MAX_LENGTH,
)
# Timestamps
start_time: Optional[datetime] = Field(
title="The start time of the step run.",
default=None,
)
end_time: Optional[datetime] = Field(
title="The end time of the step run.",
default=None,
)
# References
logs: Optional["LogsResponse"] = Field(
title="Logs associated with this step run.",
default=None,
)
deployment_id: UUID = Field(
title="The deployment associated with the step run."
)
pipeline_run_id: UUID = Field(
title="The ID of the pipeline run that this step run belongs to.",
)
original_step_run_id: Optional[UUID] = Field(
title="The ID of the original step run if this step was cached.",
default=None,
)
parent_step_ids: List[UUID] = Field(
title="The IDs of the parent steps of this step run.",
default_factory=list,
)
run_metadata: Dict[str, "RunMetadataResponse"] = Field(
title="Metadata associated with this step run.",
default={},
)
StepRunResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the step run entity.
Source code in zenml/models/v2/core/step_run.py
class StepRunResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the step run entity."""
model_version: Optional[ModelVersionResponse] = None
# TODO: In Pydantic v2, the `model_` is a protected namespaces for all
# fields defined under base models. If not handled, this raises a warning.
# It is possible to suppress this warning message with the following
# configuration, however the ultimate solution is to rename these fields.
# Even though they do not cause any problems right now, if we are not
# careful we might overwrite some fields protected by pydantic.
model_config = ConfigDict(protected_namespaces=())
StepRunUpdate (BaseModel)
Update model for step runs.
Source code in zenml/models/v2/core/step_run.py
class StepRunUpdate(BaseModel):
"""Update model for step runs."""
outputs: Dict[str, UUID] = Field(
title="The IDs of the output artifact versions of the step run.",
default={},
)
saved_artifact_versions: Dict[str, UUID] = Field(
title="The IDs of artifact versions that were saved by this step run.",
default={},
)
loaded_artifact_versions: Dict[str, UUID] = Field(
title="The IDs of artifact versions that were loaded by this step run.",
default={},
)
status: Optional[ExecutionStatus] = Field(
title="The status of the step.",
default=None,
)
end_time: Optional[datetime] = Field(
title="The end time of the step run.",
default=None,
)
model_version_id: Optional[UUID] = Field(
title="The ID of the model version that was "
"configured by this step run explicitly.",
default=None,
)
model_config = ConfigDict(protected_namespaces=())
tag
Models representing tags.
TagFilter (BaseFilter)
Model to enable advanced filtering of all tags.
Source code in zenml/models/v2/core/tag.py
class TagFilter(BaseFilter):
"""Model to enable advanced filtering of all tags."""
name: Optional[str] = Field(
description="The unique title of the tag.", default=None
)
color: Optional[ColorVariants] = Field(
description="The color variant assigned to the tag.", default=None
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/tag.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TagRequest (BaseRequest)
Request model for tags.
Source code in zenml/models/v2/core/tag.py
class TagRequest(BaseRequest):
"""Request model for tags."""
name: str = Field(
description="The unique title of the tag.",
max_length=STR_FIELD_MAX_LENGTH,
)
color: ColorVariants = Field(
description="The color variant assigned to the tag.",
default_factory=lambda: random.choice(list(ColorVariants)),
)
TagResponse (BaseIdentifiedResponse[TagResponseBody, BaseResponseMetadata, TagResponseResources])
Response model for tags.
Source code in zenml/models/v2/core/tag.py
class TagResponse(
BaseIdentifiedResponse[
TagResponseBody, BaseResponseMetadata, TagResponseResources
]
):
"""Response model for tags."""
name: str = Field(
description="The unique title of the tag.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "TagResponse":
"""Get the hydrated version of this tag.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_tag(self.id)
@property
def color(self) -> ColorVariants:
"""The `color` property.
Returns:
the value of the property.
"""
return self.get_body().color
@property
def tagged_count(self) -> int:
"""The `tagged_count` property.
Returns:
the value of the property.
"""
return self.get_body().tagged_count
color: ColorVariants
property
readonly
The color
property.
Returns:
Type | Description |
---|---|
ColorVariants |
the value of the property. |
tagged_count: int
property
readonly
The tagged_count
property.
Returns:
Type | Description |
---|---|
int |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this tag.
Returns:
Type | Description |
---|---|
TagResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/tag.py
def get_hydrated_version(self) -> "TagResponse":
"""Get the hydrated version of this tag.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_tag(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/tag.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TagResponseBody (BaseDatedResponseBody)
Response body for tags.
Source code in zenml/models/v2/core/tag.py
class TagResponseBody(BaseDatedResponseBody):
"""Response body for tags."""
color: ColorVariants = Field(
description="The color variant assigned to the tag.",
default_factory=lambda: random.choice(list(ColorVariants)),
)
tagged_count: int = Field(
description="The count of resources tagged with this tag."
)
TagResponseResources (BaseResponseResources)
Class for all resource models associated with the tag entity.
Source code in zenml/models/v2/core/tag.py
class TagResponseResources(BaseResponseResources):
"""Class for all resource models associated with the tag entity."""
TagUpdate (BaseModel)
Update model for tags.
Source code in zenml/models/v2/core/tag.py
class TagUpdate(BaseModel):
"""Update model for tags."""
name: Optional[str] = None
color: Optional[ColorVariants] = None
tag_resource
Models representing the link between tags and resources.
TagResourceRequest (BaseRequest)
Request model for links between tags and resources.
Source code in zenml/models/v2/core/tag_resource.py
class TagResourceRequest(BaseRequest):
"""Request model for links between tags and resources."""
tag_id: UUID
resource_id: UUID
resource_type: TaggableResourceTypes
TagResourceResponse (BaseIdentifiedResponse[TagResourceResponseBody, BaseResponseMetadata, TagResourceResponseResources])
Response model for the links between tags and resources.
Source code in zenml/models/v2/core/tag_resource.py
class TagResourceResponse(
BaseIdentifiedResponse[
TagResourceResponseBody,
BaseResponseMetadata,
TagResourceResponseResources,
]
):
"""Response model for the links between tags and resources."""
@property
def tag_id(self) -> UUID:
"""The `tag_id` property.
Returns:
the value of the property.
"""
return self.get_body().tag_id
@property
def resource_id(self) -> UUID:
"""The `resource_id` property.
Returns:
the value of the property.
"""
return self.get_body().resource_id
@property
def resource_type(self) -> TaggableResourceTypes:
"""The `resource_type` property.
Returns:
the value of the property.
"""
return self.get_body().resource_type
resource_id: UUID
property
readonly
The resource_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
resource_type: TaggableResourceTypes
property
readonly
The resource_type
property.
Returns:
Type | Description |
---|---|
TaggableResourceTypes |
the value of the property. |
tag_id: UUID
property
readonly
The tag_id
property.
Returns:
Type | Description |
---|---|
UUID |
the value of the property. |
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/tag_resource.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TagResourceResponseBody (BaseDatedResponseBody)
Response body for the links between tags and resources.
Source code in zenml/models/v2/core/tag_resource.py
class TagResourceResponseBody(BaseDatedResponseBody):
"""Response body for the links between tags and resources."""
tag_id: UUID
resource_id: UUID
resource_type: TaggableResourceTypes
TagResourceResponseResources (BaseResponseResources)
Class for all resource models associated with the tag resource entity.
Source code in zenml/models/v2/core/tag_resource.py
class TagResourceResponseResources(BaseResponseResources):
"""Class for all resource models associated with the tag resource entity."""
trigger
Collection of all models concerning triggers.
TriggerFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all triggers.
Source code in zenml/models/v2/core/trigger.py
class TriggerFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all triggers."""
FILTER_EXCLUDE_FIELDS: ClassVar[List[str]] = [
*WorkspaceScopedFilter.FILTER_EXCLUDE_FIELDS,
"action_flavor",
"action_subtype",
"event_source_flavor",
"event_source_subtype",
]
name: Optional[str] = Field(
default=None,
description="Name of the trigger.",
)
event_source_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The event source this trigger is attached to.",
union_mode="left_to_right",
)
action_id: Optional[Union[UUID, str]] = Field(
default=None,
description="The action this trigger is attached to.",
union_mode="left_to_right",
)
is_active: Optional[bool] = Field(
default=None,
description="Whether the trigger is active.",
)
action_flavor: Optional[str] = Field(
default=None,
title="The flavor of the action that is executed by this trigger.",
)
action_subtype: Optional[str] = Field(
default=None,
title="The subtype of the action that is executed by this trigger.",
)
event_source_flavor: Optional[str] = Field(
default=None,
title="The flavor of the event source that activates this trigger.",
)
event_source_subtype: Optional[str] = Field(
default=None,
title="The subtype of the event source that activates this trigger.",
)
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ActionSchema,
EventSourceSchema,
TriggerSchema,
)
custom_filters = super().get_custom_filters()
if self.event_source_flavor:
event_source_flavor_filter = and_(
EventSourceSchema.id == TriggerSchema.event_source_id,
EventSourceSchema.flavor == self.event_source_flavor,
)
custom_filters.append(event_source_flavor_filter)
if self.event_source_subtype:
event_source_subtype_filter = and_(
EventSourceSchema.id == TriggerSchema.event_source_id,
EventSourceSchema.plugin_subtype == self.event_source_subtype,
)
custom_filters.append(event_source_subtype_filter)
if self.action_flavor:
action_flavor_filter = and_(
ActionSchema.id == TriggerSchema.action_id,
ActionSchema.flavor == self.action_flavor,
)
custom_filters.append(action_flavor_filter)
if self.action_subtype:
action_subtype_filter = and_(
ActionSchema.id == TriggerSchema.action_id,
ActionSchema.plugin_subtype == self.action_subtype,
)
custom_filters.append(action_subtype_filter)
return custom_filters
get_custom_filters(self)
Get custom filters.
Returns:
Type | Description |
---|---|
List[ColumnElement[bool]] |
A list of custom filters. |
Source code in zenml/models/v2/core/trigger.py
def get_custom_filters(
self,
) -> List["ColumnElement[bool]"]:
"""Get custom filters.
Returns:
A list of custom filters.
"""
from sqlmodel import and_
from zenml.zen_stores.schemas import (
ActionSchema,
EventSourceSchema,
TriggerSchema,
)
custom_filters = super().get_custom_filters()
if self.event_source_flavor:
event_source_flavor_filter = and_(
EventSourceSchema.id == TriggerSchema.event_source_id,
EventSourceSchema.flavor == self.event_source_flavor,
)
custom_filters.append(event_source_flavor_filter)
if self.event_source_subtype:
event_source_subtype_filter = and_(
EventSourceSchema.id == TriggerSchema.event_source_id,
EventSourceSchema.plugin_subtype == self.event_source_subtype,
)
custom_filters.append(event_source_subtype_filter)
if self.action_flavor:
action_flavor_filter = and_(
ActionSchema.id == TriggerSchema.action_id,
ActionSchema.flavor == self.action_flavor,
)
custom_filters.append(action_flavor_filter)
if self.action_subtype:
action_subtype_filter = and_(
ActionSchema.id == TriggerSchema.action_id,
ActionSchema.plugin_subtype == self.action_subtype,
)
custom_filters.append(action_subtype_filter)
return custom_filters
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/trigger.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TriggerRequest (WorkspaceScopedRequest)
Model for creating a new trigger.
Source code in zenml/models/v2/core/trigger.py
class TriggerRequest(WorkspaceScopedRequest):
"""Model for creating a new trigger."""
name: str = Field(
title="The name of the trigger.", max_length=STR_FIELD_MAX_LENGTH
)
description: str = Field(
default="",
title="The description of the trigger",
max_length=STR_FIELD_MAX_LENGTH,
)
action_id: UUID = Field(
title="The action that is executed by this trigger.",
)
schedule: Optional[Schedule] = Field(
default=None,
title="The schedule for the trigger. Either a schedule or an event "
"source is required.",
)
event_source_id: Optional[UUID] = Field(
default=None,
title="The event source that activates this trigger. Either a schedule "
"or an event source is required.",
)
event_filter: Optional[Dict[str, Any]] = Field(
default=None,
title="Filter applied to events that activate this trigger. Only "
"set if the trigger is activated by an event source.",
)
@model_validator(mode="after")
def _validate_schedule_or_event_source(self) -> "TriggerRequest":
"""Validate that either a schedule or an event source is provided.
Returns:
The validated request.
Raises:
ValueError: If neither a schedule nor an event source is provided,
or if both are provided.
"""
if not self.schedule and not self.event_source_id:
raise ValueError(
"Either a schedule or an event source is required."
)
if self.schedule and self.event_source_id:
raise ValueError("Only a schedule or an event source is allowed.")
return self
TriggerResponse (WorkspaceScopedResponse[TriggerResponseBody, TriggerResponseMetadata, TriggerResponseResources])
Response model for models.
Source code in zenml/models/v2/core/trigger.py
class TriggerResponse(
WorkspaceScopedResponse[
TriggerResponseBody, TriggerResponseMetadata, TriggerResponseResources
]
):
"""Response model for models."""
name: str = Field(
title="The name of the trigger",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "TriggerResponse":
"""Get the hydrated version of this trigger.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_trigger(self.id)
@property
def action_flavor(self) -> str:
"""The `action_flavor` property.
Returns:
the value of the property.
"""
return self.get_body().action_flavor
@property
def action_subtype(self) -> str:
"""The `action_subtype` property.
Returns:
the value of the property.
"""
return self.get_body().action_subtype
@property
def event_source_flavor(self) -> Optional[str]:
"""The `event_source_flavor` property.
Returns:
the value of the property.
"""
return self.get_body().event_source_flavor
@property
def event_source_subtype(self) -> Optional[str]:
"""The `event_source_subtype` property.
Returns:
the value of the property.
"""
return self.get_body().event_source_subtype
@property
def is_active(self) -> bool:
"""The `is_active` property.
Returns:
the value of the property.
"""
return self.get_body().is_active
@property
def event_filter(self) -> Optional[Dict[str, Any]]:
"""The `event_filter` property.
Returns:
the value of the property.
"""
return self.get_metadata().event_filter
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
@property
def action(self) -> "ActionResponse":
"""The `action` property.
Returns:
the value of the property.
"""
return self.get_resources().action
@property
def event_source(self) -> Optional["EventSourceResponse"]:
"""The `event_source` property.
Returns:
the value of the property.
"""
return self.get_resources().event_source
@property
def executions(self) -> Page[TriggerExecutionResponse]:
"""The `event_source` property.
Returns:
the value of the property.
"""
return self.get_resources().executions
action: ActionResponse
property
readonly
The action
property.
Returns:
Type | Description |
---|---|
ActionResponse |
the value of the property. |
action_flavor: str
property
readonly
The action_flavor
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
action_subtype: str
property
readonly
The action_subtype
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
event_filter: Optional[Dict[str, Any]]
property
readonly
The event_filter
property.
Returns:
Type | Description |
---|---|
Optional[Dict[str, Any]] |
the value of the property. |
event_source: Optional[EventSourceResponse]
property
readonly
The event_source
property.
Returns:
Type | Description |
---|---|
Optional[EventSourceResponse] |
the value of the property. |
event_source_flavor: Optional[str]
property
readonly
The event_source_flavor
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
event_source_subtype: Optional[str]
property
readonly
The event_source_subtype
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
executions: Page[TriggerExecutionResponse]
property
readonly
The event_source
property.
Returns:
Type | Description |
---|---|
Page[TriggerExecutionResponse] |
the value of the property. |
is_active: bool
property
readonly
The is_active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this trigger.
Returns:
Type | Description |
---|---|
TriggerResponse |
An instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/trigger.py
def get_hydrated_version(self) -> "TriggerResponse":
"""Get the hydrated version of this trigger.
Returns:
An instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_trigger(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/trigger.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TriggerResponseBody (WorkspaceScopedResponseBody)
Response body for triggers.
Source code in zenml/models/v2/core/trigger.py
class TriggerResponseBody(WorkspaceScopedResponseBody):
"""Response body for triggers."""
action_flavor: str = Field(
title="The flavor of the action that is executed by this trigger.",
max_length=STR_FIELD_MAX_LENGTH,
)
action_subtype: str = Field(
title="The subtype of the action that is executed by this trigger.",
)
event_source_flavor: Optional[str] = Field(
default=None,
title="The flavor of the event source that activates this trigger. Not "
"set if the trigger is activated by a schedule.",
max_length=STR_FIELD_MAX_LENGTH,
)
event_source_subtype: Optional[str] = Field(
default=None,
title="The subtype of the event source that activates this trigger. "
"Not set if the trigger is activated by a schedule.",
max_length=STR_FIELD_MAX_LENGTH,
)
is_active: bool = Field(
title="Whether the trigger is active.",
)
TriggerResponseMetadata (WorkspaceScopedResponseMetadata)
Response metadata for triggers.
Source code in zenml/models/v2/core/trigger.py
class TriggerResponseMetadata(WorkspaceScopedResponseMetadata):
"""Response metadata for triggers."""
description: str = Field(
default="",
title="The description of the trigger.",
max_length=STR_FIELD_MAX_LENGTH,
)
event_filter: Optional[Dict[str, Any]] = Field(
default=None,
title="The event that activates this trigger. Not set if the trigger "
"is activated by a schedule.",
)
schedule: Optional[Schedule] = Field(
default=None,
title="The schedule that activates this trigger. Not set if the "
"trigger is activated by an event source.",
)
TriggerResponseResources (WorkspaceScopedResponseResources)
Class for all resource models associated with the trigger entity.
Source code in zenml/models/v2/core/trigger.py
class TriggerResponseResources(WorkspaceScopedResponseResources):
"""Class for all resource models associated with the trigger entity."""
action: "ActionResponse" = Field(
title="The action that is executed by this trigger.",
)
event_source: Optional["EventSourceResponse"] = Field(
default=None,
title="The event source that activates this trigger. Not set if the "
"trigger is activated by a schedule.",
)
executions: Page[TriggerExecutionResponse] = Field(
title="The executions of this trigger.",
)
TriggerUpdate (BaseUpdate)
Update model for triggers.
Source code in zenml/models/v2/core/trigger.py
class TriggerUpdate(BaseUpdate):
"""Update model for triggers."""
name: Optional[str] = Field(
default=None,
title="The new name for the trigger.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: Optional[str] = Field(
default=None,
title="The new description for the trigger.",
max_length=STR_FIELD_MAX_LENGTH,
)
event_filter: Optional[Dict[str, Any]] = Field(
default=None,
title="New filter applied to events that activate this trigger. Only "
"valid if the trigger is already configured to be activated by an "
"event source.",
)
schedule: Optional[Schedule] = Field(
default=None,
title="The updated schedule for the trigger. Only valid if the trigger "
"is already configured to be activated by a schedule.",
)
is_active: Optional[bool] = Field(
default=None,
title="The new status of the trigger.",
)
trigger_execution
Collection of all models concerning trigger executions.
TriggerExecutionFilter (WorkspaceScopedFilter)
Model to enable advanced filtering of all trigger executions.
Source code in zenml/models/v2/core/trigger_execution.py
class TriggerExecutionFilter(WorkspaceScopedFilter):
"""Model to enable advanced filtering of all trigger executions."""
trigger_id: Optional[Union[UUID, str]] = Field(
default=None,
description="ID of the trigger of the execution.",
union_mode="left_to_right",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/trigger_execution.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TriggerExecutionRequest (BaseRequest)
Model for creating a new Trigger execution.
Source code in zenml/models/v2/core/trigger_execution.py
class TriggerExecutionRequest(BaseRequest):
"""Model for creating a new Trigger execution."""
trigger: UUID
event_metadata: Dict[str, Any] = {}
TriggerExecutionResponse (BaseIdentifiedResponse[TriggerExecutionResponseBody, TriggerExecutionResponseMetadata, TriggerExecutionResponseResources])
Response model for trigger executions.
Source code in zenml/models/v2/core/trigger_execution.py
class TriggerExecutionResponse(
BaseIdentifiedResponse[
TriggerExecutionResponseBody,
TriggerExecutionResponseMetadata,
TriggerExecutionResponseResources,
]
):
"""Response model for trigger executions."""
def get_hydrated_version(self) -> "TriggerExecutionResponse":
"""Get the hydrated version of this trigger execution.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_trigger_execution(self.id)
# Body and metadata properties
@property
def trigger(self) -> "TriggerResponse":
"""The `trigger` property.
Returns:
the value of the property.
"""
return self.get_resources().trigger
@property
def event_metadata(self) -> Dict[str, Any]:
"""The `event_metadata` property.
Returns:
the value of the property.
"""
return self.get_metadata().event_metadata
event_metadata: Dict[str, Any]
property
readonly
The event_metadata
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
trigger: TriggerResponse
property
readonly
The trigger
property.
Returns:
Type | Description |
---|---|
TriggerResponse |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this trigger execution.
Returns:
Type | Description |
---|---|
TriggerExecutionResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/trigger_execution.py
def get_hydrated_version(self) -> "TriggerExecutionResponse":
"""Get the hydrated version of this trigger execution.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_trigger_execution(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/trigger_execution.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
TriggerExecutionResponseBody (BaseDatedResponseBody)
Response body for trigger executions.
Source code in zenml/models/v2/core/trigger_execution.py
class TriggerExecutionResponseBody(BaseDatedResponseBody):
"""Response body for trigger executions."""
TriggerExecutionResponseMetadata (BaseResponseMetadata)
Response metadata for trigger executions.
Source code in zenml/models/v2/core/trigger_execution.py
class TriggerExecutionResponseMetadata(BaseResponseMetadata):
"""Response metadata for trigger executions."""
event_metadata: Dict[str, Any] = {}
TriggerExecutionResponseResources (BaseResponseResources)
Class for all resource models associated with the trigger entity.
Source code in zenml/models/v2/core/trigger_execution.py
class TriggerExecutionResponseResources(BaseResponseResources):
"""Class for all resource models associated with the trigger entity."""
trigger: "TriggerResponse" = Field(
title="The event source that activates this trigger.",
)
user
Models representing users.
UserBase (BaseModel)
Base model for users.
Source code in zenml/models/v2/core/user.py
class UserBase(BaseModel):
"""Base model for users."""
# Fields
email: Optional[str] = Field(
default=None,
title="The email address associated with the account.",
max_length=STR_FIELD_MAX_LENGTH,
)
email_opted_in: Optional[bool] = Field(
default=None,
title="Whether the user agreed to share their email. Only relevant for "
"user accounts",
description="`null` if not answered, `true` if agreed, "
"`false` if skipped.",
)
password: Optional[str] = Field(
default=None,
title="A password for the user.",
max_length=STR_FIELD_MAX_LENGTH,
)
activation_token: Optional[str] = Field(
default=None, max_length=STR_FIELD_MAX_LENGTH
)
external_user_id: Optional[UUID] = Field(
default=None,
title="The external user ID associated with the account.",
)
user_metadata: Optional[Dict[str, Any]] = Field(
default=None,
title="The metadata associated with the user.",
)
@classmethod
def _get_crypt_context(cls) -> "CryptContext":
"""Returns the password encryption context.
Returns:
The password encryption context.
"""
from passlib.context import CryptContext
return CryptContext(schemes=["bcrypt"], deprecated="auto")
@classmethod
def _create_hashed_secret(cls, secret: Optional[str]) -> Optional[str]:
"""Hashes the input secret and returns the hash value.
Only applied if supplied and if not already hashed.
Args:
secret: The secret value to hash.
Returns:
The secret hash value, or None if no secret was supplied.
"""
if secret is None:
return None
pwd_context = cls._get_crypt_context()
return pwd_context.hash(secret)
def create_hashed_password(self) -> Optional[str]:
"""Hashes the password.
Returns:
The hashed password.
"""
return self._create_hashed_secret(self.password)
def create_hashed_activation_token(self) -> Optional[str]:
"""Hashes the activation token.
Returns:
The hashed activation token.
"""
return self._create_hashed_secret(self.activation_token)
def generate_activation_token(self) -> str:
"""Generates and stores a new activation token.
Returns:
The generated activation token.
"""
self.activation_token = token_hex(32)
return self.activation_token
create_hashed_activation_token(self)
Hashes the activation token.
Returns:
Type | Description |
---|---|
Optional[str] |
The hashed activation token. |
Source code in zenml/models/v2/core/user.py
def create_hashed_activation_token(self) -> Optional[str]:
"""Hashes the activation token.
Returns:
The hashed activation token.
"""
return self._create_hashed_secret(self.activation_token)
create_hashed_password(self)
Hashes the password.
Returns:
Type | Description |
---|---|
Optional[str] |
The hashed password. |
Source code in zenml/models/v2/core/user.py
def create_hashed_password(self) -> Optional[str]:
"""Hashes the password.
Returns:
The hashed password.
"""
return self._create_hashed_secret(self.password)
generate_activation_token(self)
Generates and stores a new activation token.
Returns:
Type | Description |
---|---|
str |
The generated activation token. |
Source code in zenml/models/v2/core/user.py
def generate_activation_token(self) -> str:
"""Generates and stores a new activation token.
Returns:
The generated activation token.
"""
self.activation_token = token_hex(32)
return self.activation_token
UserFilter (BaseFilter)
Model to enable advanced filtering of all Users.
Source code in zenml/models/v2/core/user.py
class UserFilter(BaseFilter):
"""Model to enable advanced filtering of all Users."""
name: Optional[str] = Field(
default=None,
description="Name of the user",
)
full_name: Optional[str] = Field(
default=None,
description="Full Name of the user",
)
email: Optional[str] = Field(
default=None,
description="Email of the user",
)
active: Optional[Union[bool, str]] = Field(
default=None,
description="Whether the user is active",
union_mode="left_to_right",
)
email_opted_in: Optional[Union[bool, str]] = Field(
default=None,
description="Whether the user has opted in to emails",
union_mode="left_to_right",
)
external_user_id: Optional[Union[UUID, str]] = Field(
default=None,
title="The external user ID associated with the account.",
union_mode="left_to_right",
)
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Override to filter out service accounts from the query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
query = query.where(
getattr(table, "is_service_account") != True # noqa: E712
)
return query
apply_filter(self, query, table)
Override to filter out service accounts from the query.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
query |
~AnyQuery |
The query to which to apply the filter. |
required |
table |
Type[AnySchema] |
The query table. |
required |
Returns:
Type | Description |
---|---|
~AnyQuery |
The query with filter applied. |
Source code in zenml/models/v2/core/user.py
def apply_filter(
self,
query: AnyQuery,
table: Type["AnySchema"],
) -> AnyQuery:
"""Override to filter out service accounts from the query.
Args:
query: The query to which to apply the filter.
table: The query table.
Returns:
The query with filter applied.
"""
query = super().apply_filter(query=query, table=table)
query = query.where(
getattr(table, "is_service_account") != True # noqa: E712
)
return query
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/user.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
UserRequest (UserBase, BaseRequest)
Request model for users.
Source code in zenml/models/v2/core/user.py
class UserRequest(UserBase, BaseRequest):
"""Request model for users."""
# Analytics fields for user request models
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"name",
"full_name",
"active",
"email_opted_in",
]
name: str = Field(
title="The unique username for the account.",
max_length=STR_FIELD_MAX_LENGTH,
)
full_name: str = Field(
default="",
title="The full name for the account owner. Only relevant for user "
"accounts.",
max_length=STR_FIELD_MAX_LENGTH,
)
is_admin: bool = Field(
title="Whether the account is an administrator.",
)
active: bool = Field(default=False, title="Whether the account is active.")
model_config = ConfigDict(
# Validate attributes when assigning them
validate_assignment=True,
# Forbid extra attributes to prevent unexpected behavior
extra="forbid",
)
UserResponse (BaseIdentifiedResponse[UserResponseBody, UserResponseMetadata, UserResponseResources])
Response model for user and service accounts.
This returns the activation_token that is required for the user-invitation-flow of the frontend. The email is returned optionally as well for use by the analytics on the client-side.
Source code in zenml/models/v2/core/user.py
class UserResponse(
BaseIdentifiedResponse[
UserResponseBody, UserResponseMetadata, UserResponseResources
]
):
"""Response model for user and service accounts.
This returns the activation_token that is required for the
user-invitation-flow of the frontend. The email is returned optionally as
well for use by the analytics on the client-side.
"""
ANALYTICS_FIELDS: ClassVar[List[str]] = [
"name",
"full_name",
"active",
"email_opted_in",
"is_service_account",
]
name: str = Field(
title="The unique username for the account.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "UserResponse":
"""Get the hydrated version of this user.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_user(self.id)
# Body and metadata properties
@property
def active(self) -> bool:
"""The `active` property.
Returns:
the value of the property.
"""
return self.get_body().active
@property
def activation_token(self) -> Optional[str]:
"""The `activation_token` property.
Returns:
the value of the property.
"""
return self.get_body().activation_token
@property
def full_name(self) -> str:
"""The `full_name` property.
Returns:
the value of the property.
"""
return self.get_body().full_name
@property
def email_opted_in(self) -> Optional[bool]:
"""The `email_opted_in` property.
Returns:
the value of the property.
"""
return self.get_body().email_opted_in
@property
def is_service_account(self) -> bool:
"""The `is_service_account` property.
Returns:
the value of the property.
"""
return self.get_body().is_service_account
@property
def is_admin(self) -> bool:
"""The `is_admin` property.
Returns:
Whether the user is an admin.
"""
return self.get_body().is_admin
@property
def email(self) -> Optional[str]:
"""The `email` property.
Returns:
the value of the property.
"""
return self.get_metadata().email
@property
def external_user_id(self) -> Optional[UUID]:
"""The `external_user_id` property.
Returns:
the value of the property.
"""
return self.get_metadata().external_user_id
@property
def user_metadata(self) -> Dict[str, Any]:
"""The `user_metadata` property.
Returns:
the value of the property.
"""
return self.get_metadata().user_metadata
# Helper methods
@classmethod
def _get_crypt_context(cls) -> "CryptContext":
"""Returns the password encryption context.
Returns:
The password encryption context.
"""
from passlib.context import CryptContext
return CryptContext(schemes=["bcrypt"], deprecated="auto")
activation_token: Optional[str]
property
readonly
The activation_token
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
active: bool
property
readonly
The active
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
email: Optional[str]
property
readonly
The email
property.
Returns:
Type | Description |
---|---|
Optional[str] |
the value of the property. |
email_opted_in: Optional[bool]
property
readonly
The email_opted_in
property.
Returns:
Type | Description |
---|---|
Optional[bool] |
the value of the property. |
external_user_id: Optional[uuid.UUID]
property
readonly
The external_user_id
property.
Returns:
Type | Description |
---|---|
Optional[uuid.UUID] |
the value of the property. |
full_name: str
property
readonly
The full_name
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
is_admin: bool
property
readonly
The is_admin
property.
Returns:
Type | Description |
---|---|
bool |
Whether the user is an admin. |
is_service_account: bool
property
readonly
The is_service_account
property.
Returns:
Type | Description |
---|---|
bool |
the value of the property. |
user_metadata: Dict[str, Any]
property
readonly
The user_metadata
property.
Returns:
Type | Description |
---|---|
Dict[str, Any] |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this user.
Returns:
Type | Description |
---|---|
UserResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/user.py
def get_hydrated_version(self) -> "UserResponse":
"""Get the hydrated version of this user.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_user(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/user.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
UserResponseBody (BaseDatedResponseBody)
Response body for users.
Source code in zenml/models/v2/core/user.py
class UserResponseBody(BaseDatedResponseBody):
"""Response body for users."""
active: bool = Field(default=False, title="Whether the account is active.")
activation_token: Optional[str] = Field(
default=None,
max_length=STR_FIELD_MAX_LENGTH,
title="The activation token for the user. Only relevant for user "
"accounts.",
)
full_name: str = Field(
default="",
title="The full name for the account owner. Only relevant for user "
"accounts.",
max_length=STR_FIELD_MAX_LENGTH,
)
email_opted_in: Optional[bool] = Field(
default=None,
title="Whether the user agreed to share their email. Only relevant for "
"user accounts",
description="`null` if not answered, `true` if agreed, "
"`false` if skipped.",
)
is_service_account: bool = Field(
title="Indicates whether this is a service account or a user account."
)
is_admin: bool = Field(
title="Whether the account is an administrator.",
)
UserResponseMetadata (BaseResponseMetadata)
Response metadata for users.
Source code in zenml/models/v2/core/user.py
class UserResponseMetadata(BaseResponseMetadata):
"""Response metadata for users."""
email: Optional[str] = Field(
default="",
title="The email address associated with the account. Only relevant "
"for user accounts.",
max_length=STR_FIELD_MAX_LENGTH,
)
external_user_id: Optional[UUID] = Field(
default=None,
title="The external user ID associated with the account. Only relevant "
"for user accounts.",
)
user_metadata: Dict[str, Any] = Field(
default={},
title="The metadata associated with the user.",
)
UserResponseResources (BaseResponseResources)
Class for all resource models associated with the user entity.
Source code in zenml/models/v2/core/user.py
class UserResponseResources(BaseResponseResources):
"""Class for all resource models associated with the user entity."""
UserUpdate (UserBase, BaseZenModel)
Update model for users.
Source code in zenml/models/v2/core/user.py
class UserUpdate(UserBase, BaseZenModel):
"""Update model for users."""
name: Optional[str] = Field(
title="The unique username for the account.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
full_name: Optional[str] = Field(
default=None,
title="The full name for the account owner. Only relevant for user "
"accounts.",
max_length=STR_FIELD_MAX_LENGTH,
)
is_admin: Optional[bool] = Field(
default=None,
title="Whether the account is an administrator.",
)
active: Optional[bool] = Field(
default=None, title="Whether the account is active."
)
old_password: Optional[str] = Field(
default=None,
title="The previous password for the user. Only relevant for user "
"accounts. Required when updating the password.",
max_length=STR_FIELD_MAX_LENGTH,
)
@model_validator(mode="after")
def user_email_updates(self) -> "UserUpdate":
"""Validate that the UserUpdateModel conforms to the email-opt-in-flow.
Returns:
The validated values.
Raises:
ValueError: If the email was not provided when the email_opted_in
field was set to True.
"""
# When someone sets the email, or updates the email and hasn't
# before explicitly opted out, they are opted in
if self.email is not None:
if self.email_opted_in is None:
self.email_opted_in = True
# It should not be possible to do opt in without an email
if self.email_opted_in is True:
if self.email is None:
raise ValueError(
"Please provide an email, when you are opting-in with "
"your email."
)
return self
def create_copy(self, exclude: AbstractSet[str]) -> "UserUpdate":
"""Create a copy of the current instance.
Args:
exclude: Fields to exclude from the copy.
Returns:
A copy of the current instance.
"""
return UserUpdate(
**self.model_dump(
exclude=set(exclude),
exclude_unset=True,
)
)
create_copy(self, exclude)
Create a copy of the current instance.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
exclude |
AbstractSet[str] |
Fields to exclude from the copy. |
required |
Returns:
Type | Description |
---|---|
UserUpdate |
A copy of the current instance. |
Source code in zenml/models/v2/core/user.py
def create_copy(self, exclude: AbstractSet[str]) -> "UserUpdate":
"""Create a copy of the current instance.
Args:
exclude: Fields to exclude from the copy.
Returns:
A copy of the current instance.
"""
return UserUpdate(
**self.model_dump(
exclude=set(exclude),
exclude_unset=True,
)
)
user_email_updates(self)
Validate that the UserUpdateModel conforms to the email-opt-in-flow.
Returns:
Type | Description |
---|---|
UserUpdate |
The validated values. |
Exceptions:
Type | Description |
---|---|
ValueError |
If the email was not provided when the email_opted_in field was set to True. |
Source code in zenml/models/v2/core/user.py
@model_validator(mode="after")
def user_email_updates(self) -> "UserUpdate":
"""Validate that the UserUpdateModel conforms to the email-opt-in-flow.
Returns:
The validated values.
Raises:
ValueError: If the email was not provided when the email_opted_in
field was set to True.
"""
# When someone sets the email, or updates the email and hasn't
# before explicitly opted out, they are opted in
if self.email is not None:
if self.email_opted_in is None:
self.email_opted_in = True
# It should not be possible to do opt in without an email
if self.email_opted_in is True:
if self.email is None:
raise ValueError(
"Please provide an email, when you are opting-in with "
"your email."
)
return self
workspace
Models representing workspaces.
WorkspaceFilter (BaseFilter)
Model to enable advanced filtering of all Workspaces.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceFilter(BaseFilter):
"""Model to enable advanced filtering of all Workspaces."""
name: Optional[str] = Field(
default=None,
description="Name of the workspace",
)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/workspace.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceRequest (BaseRequest)
Request model for workspaces.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceRequest(BaseRequest):
"""Request model for workspaces."""
name: str = Field(
title="The unique name of the workspace.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: str = Field(
default="",
title="The description of the workspace.",
max_length=STR_FIELD_MAX_LENGTH,
)
WorkspaceResponse (BaseIdentifiedResponse[WorkspaceResponseBody, WorkspaceResponseMetadata, WorkspaceResponseResources])
Response model for workspaces.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceResponse(
BaseIdentifiedResponse[
WorkspaceResponseBody,
WorkspaceResponseMetadata,
WorkspaceResponseResources,
]
):
"""Response model for workspaces."""
name: str = Field(
title="The unique name of the workspace.",
max_length=STR_FIELD_MAX_LENGTH,
)
def get_hydrated_version(self) -> "WorkspaceResponse":
"""Get the hydrated version of this workspace.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_workspace(self.id)
# Body and metadata properties
@property
def description(self) -> str:
"""The `description` property.
Returns:
the value of the property.
"""
return self.get_metadata().description
description: str
property
readonly
The description
property.
Returns:
Type | Description |
---|---|
str |
the value of the property. |
get_hydrated_version(self)
Get the hydrated version of this workspace.
Returns:
Type | Description |
---|---|
WorkspaceResponse |
an instance of the same entity with the metadata field attached. |
Source code in zenml/models/v2/core/workspace.py
def get_hydrated_version(self) -> "WorkspaceResponse":
"""Get the hydrated version of this workspace.
Returns:
an instance of the same entity with the metadata field attached.
"""
from zenml.client import Client
return Client().zen_store.get_workspace(self.id)
model_post_init(/, self, context)
We need to both initialize private attributes and call the user-defined model_post_init method.
Source code in zenml/models/v2/core/workspace.py
def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
"""We need to both initialize private attributes and call the user-defined model_post_init
method.
"""
init_private_attributes(self, context)
original_model_post_init(self, context)
WorkspaceResponseBody (BaseDatedResponseBody)
Response body for workspaces.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceResponseBody(BaseDatedResponseBody):
"""Response body for workspaces."""
WorkspaceResponseMetadata (BaseResponseMetadata)
Response metadata for workspaces.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceResponseMetadata(BaseResponseMetadata):
"""Response metadata for workspaces."""
description: str = Field(
default="",
title="The description of the workspace.",
max_length=STR_FIELD_MAX_LENGTH,
)
WorkspaceResponseResources (BaseResponseResources)
Class for all resource models associated with the workspace entity.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceResponseResources(BaseResponseResources):
"""Class for all resource models associated with the workspace entity."""
WorkspaceUpdate (BaseUpdate)
Update model for workspaces.
Source code in zenml/models/v2/core/workspace.py
class WorkspaceUpdate(BaseUpdate):
"""Update model for workspaces."""
name: Optional[str] = Field(
title="The unique name of the workspace.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
description: Optional[str] = Field(
title="The description of the workspace.",
max_length=STR_FIELD_MAX_LENGTH,
default=None,
)
misc
special
auth_models
Models representing OAuth2 requests and responses.
OAuthDeviceAuthorizationRequest (BaseModel)
OAuth2 device authorization grant request.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthDeviceAuthorizationRequest(BaseModel):
"""OAuth2 device authorization grant request."""
client_id: UUID
OAuthDeviceAuthorizationResponse (BaseModel)
OAuth2 device authorization grant response.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthDeviceAuthorizationResponse(BaseModel):
"""OAuth2 device authorization grant response."""
device_code: str
user_code: str
verification_uri: str
verification_uri_complete: Optional[str] = None
expires_in: int
interval: int
OAuthDeviceTokenRequest (BaseModel)
OAuth2 device authorization grant request.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthDeviceTokenRequest(BaseModel):
"""OAuth2 device authorization grant request."""
grant_type: str = OAuthGrantTypes.OAUTH_DEVICE_CODE
client_id: UUID
device_code: str
OAuthDeviceUserAgentHeader (BaseModel)
OAuth2 device user agent header.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthDeviceUserAgentHeader(BaseModel):
"""OAuth2 device user agent header."""
hostname: Optional[str] = None
os: Optional[str] = None
python_version: Optional[str] = None
zenml_version: Optional[str] = None
@classmethod
def decode(cls, header_str: str) -> "OAuthDeviceUserAgentHeader":
"""Decode the user agent header.
Args:
header_str: The user agent header string value.
Returns:
The decoded user agent header.
"""
header = cls()
properties = header_str.strip().split(" ")
for property in properties:
try:
key, value = property.split("/", maxsplit=1)
except ValueError:
continue
if key == "Host":
header.hostname = value
elif key == "ZenML":
header.zenml_version = value
elif key == "Python":
header.python_version = value
elif key == "OS":
header.os = value
return header
def encode(self) -> str:
"""Encode the user agent header.
Returns:
The encoded user agent header.
"""
return (
f"Host/{self.hostname} "
f"ZenML/{self.zenml_version} "
f"Python/{self.python_version} "
f"OS/{self.os}"
)
decode(header_str)
classmethod
Decode the user agent header.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
header_str |
str |
The user agent header string value. |
required |
Returns:
Type | Description |
---|---|
OAuthDeviceUserAgentHeader |
The decoded user agent header. |
Source code in zenml/models/v2/misc/auth_models.py
@classmethod
def decode(cls, header_str: str) -> "OAuthDeviceUserAgentHeader":
"""Decode the user agent header.
Args:
header_str: The user agent header string value.
Returns:
The decoded user agent header.
"""
header = cls()
properties = header_str.strip().split(" ")
for property in properties:
try:
key, value = property.split("/", maxsplit=1)
except ValueError:
continue
if key == "Host":
header.hostname = value
elif key == "ZenML":
header.zenml_version = value
elif key == "Python":
header.python_version = value
elif key == "OS":
header.os = value
return header
encode(self)
Encode the user agent header.
Returns:
Type | Description |
---|---|
str |
The encoded user agent header. |
Source code in zenml/models/v2/misc/auth_models.py
def encode(self) -> str:
"""Encode the user agent header.
Returns:
The encoded user agent header.
"""
return (
f"Host/{self.hostname} "
f"ZenML/{self.zenml_version} "
f"Python/{self.python_version} "
f"OS/{self.os}"
)
OAuthDeviceVerificationRequest (BaseModel)
OAuth2 device authorization verification request.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthDeviceVerificationRequest(BaseModel):
"""OAuth2 device authorization verification request."""
user_code: str
trusted_device: bool = False
OAuthRedirectResponse (BaseModel)
Redirect response.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthRedirectResponse(BaseModel):
"""Redirect response."""
authorization_url: str
OAuthTokenResponse (BaseModel)
OAuth2 device authorization token response.
Source code in zenml/models/v2/misc/auth_models.py
class OAuthTokenResponse(BaseModel):
"""OAuth2 device authorization token response."""
access_token: str
token_type: str
expires_in: Optional[int] = None
refresh_token: Optional[str] = None
scope: Optional[str] = None
build_item
Model definition for pipeline build item.
BuildItem (BaseModel)
Pipeline build item.
Attributes:
Name | Type | Description |
---|---|---|
image |
str |
The image name or digest. |
dockerfile |
Optional[str] |
The contents of the Dockerfile used to build the image. |
requirements |
Optional[str] |
The pip requirements installed in the image. This is a string consisting of multiple concatenated requirements.txt files. |
settings_checksum |
Optional[str] |
Checksum of the settings used for the build. |
contains_code |
bool |
Whether the image contains user files. |
requires_code_download |
bool |
Whether the image needs to download files. |
Source code in zenml/models/v2/misc/build_item.py
class BuildItem(BaseModel):
"""Pipeline build item.
Attributes:
image: The image name or digest.
dockerfile: The contents of the Dockerfile used to build the image.
requirements: The pip requirements installed in the image. This is a
string consisting of multiple concatenated requirements.txt files.
settings_checksum: Checksum of the settings used for the build.
contains_code: Whether the image contains user files.
requires_code_download: Whether the image needs to download files.
"""
image: str = Field(title="The image name or digest.")
dockerfile: Optional[str] = Field(
default=None, title="The dockerfile used to build the image."
)
requirements: Optional[str] = Field(
default=None, title="The pip requirements installed in the image."
)
settings_checksum: Optional[str] = Field(
default=None, title="The checksum of the build settings."
)
contains_code: bool = Field(
default=True, title="Whether the image contains user files."
)
requires_code_download: bool = Field(
default=False, title="Whether the image needs to download files."
)
external_user
Models representing users.
ExternalUserModel (BaseModel)
External user model.
Source code in zenml/models/v2/misc/external_user.py
class ExternalUserModel(BaseModel):
"""External user model."""
id: UUID
email: str
name: Optional[str] = None
is_admin: bool = False
model_config = ConfigDict(extra="ignore")
info_models
Models representing full stack requests.
ComponentInfo (BaseModel)
Information about each stack components when creating a full stack.
Source code in zenml/models/v2/misc/info_models.py
class ComponentInfo(BaseModel):
"""Information about each stack components when creating a full stack."""
flavor: str
service_connector_index: Optional[int] = Field(
default=None,
title="The id of the service connector from the list "
"`service_connectors`.",
description="The id of the service connector from the list "
"`service_connectors` from `FullStackRequest`.",
)
service_connector_resource_id: Optional[str] = None
configuration: Dict[str, Any] = {}
ResourcesInfo (BaseModel)
Information about the resources needed for CLI and UI.
Source code in zenml/models/v2/misc/info_models.py
class ResourcesInfo(BaseModel):
"""Information about the resources needed for CLI and UI."""
flavor: str
flavor_display_name: str
required_configuration: Dict[str, str] = {}
use_resource_value_as_fixed_config: bool = False
accessible_by_service_connector: List[str]
connected_through_service_connector: List["ComponentResponse"]
@model_validator(mode="after")
def _validate_resource_info(self) -> "ResourcesInfo":
if (
self.use_resource_value_as_fixed_config
and len(self.required_configuration) > 1
):
raise ValueError(
"Cannot use resource value as fixed config if more than "
"one required configuration key is provided."
)
return self
ServiceConnectorInfo (BaseModel)
Information about the service connector when creating a full stack.
Source code in zenml/models/v2/misc/info_models.py
class ServiceConnectorInfo(BaseModel):
"""Information about the service connector when creating a full stack."""
type: str
auth_method: str
configuration: Dict[str, Any] = {}
ServiceConnectorResourcesInfo (BaseModel)
Information about the service connector resources needed for CLI and UI.
Source code in zenml/models/v2/misc/info_models.py
class ServiceConnectorResourcesInfo(BaseModel):
"""Information about the service connector resources needed for CLI and UI."""
connector_type: str
components_resources_info: Dict[StackComponentType, List[ResourcesInfo]]
loaded_visualization
Model representing loaded visualizations.
LoadedVisualization (BaseModel)
Model for loaded visualizations.
Source code in zenml/models/v2/misc/loaded_visualization.py
class LoadedVisualization(BaseModel):
"""Model for loaded visualizations."""
type: VisualizationType
value: Union[str, bytes] = Field(union_mode="left_to_right")
server_models
Model definitions for ZenML servers.
ServerDatabaseType (StrEnum)
Enum for server database types.
Source code in zenml/models/v2/misc/server_models.py
class ServerDatabaseType(StrEnum):
"""Enum for server database types."""
SQLITE = "sqlite"
MYSQL = "mysql"
OTHER = "other"
ServerDeploymentType (StrEnum)
Enum for server deployment types.
Source code in zenml/models/v2/misc/server_models.py
class ServerDeploymentType(StrEnum):
"""Enum for server deployment types."""
LOCAL = "local"
DOCKER = "docker"
KUBERNETES = "kubernetes"
AWS = "aws"
GCP = "gcp"
AZURE = "azure"
ALPHA = "alpha"
OTHER = "other"
HF_SPACES = "hf_spaces"
SANDBOX = "sandbox"
CLOUD = "cloud"
ServerModel (BaseModel)
Domain model for ZenML servers.
Source code in zenml/models/v2/misc/server_models.py
class ServerModel(BaseModel):
"""Domain model for ZenML servers."""
id: UUID = Field(default_factory=uuid4, title="The unique server id.")
version: str = Field(
title="The ZenML version that the server is running.",
)
active: bool = Field(
True, title="Flag to indicate whether the server is active."
)
debug: bool = Field(
False, title="Flag to indicate whether ZenML is running on debug mode."
)
deployment_type: ServerDeploymentType = Field(
ServerDeploymentType.OTHER,
title="The ZenML server deployment type.",
)
database_type: ServerDatabaseType = Field(
ServerDatabaseType.OTHER,
title="The database type that the server is using.",
)
secrets_store_type: SecretsStoreType = Field(
SecretsStoreType.NONE,
title="The type of secrets store that the server is using.",
)
auth_scheme: AuthScheme = Field(
title="The authentication scheme that the server is using.",
)
server_url: str = Field(
"",
title="The URL where the ZenML server API is reachable. If not "
"specified, the clients will use the same URL used to connect them to "
"the ZenML server.",
)
dashboard_url: str = Field(
"",
title="The URL where the ZenML dashboard is reachable. If "
"not specified, the `server_url` value will be used instead.",
)
analytics_enabled: bool = Field(
default=True, # We set a default for migrations from < 0.57.0
title="Enable server-side analytics.",
)
metadata: Dict[str, str] = Field(
{},
title="The metadata associated with the server.",
)
use_legacy_dashboard: bool = Field(
False,
title="Flag to indicate whether the server is using the legacy dashboard.",
)
last_user_activity: Optional[datetime] = Field(
None,
title="Timestamp of latest user activity traced on the server.",
)
def is_local(self) -> bool:
"""Return whether the server is running locally.
Returns:
True if the server is running locally, False otherwise.
"""
from zenml.config.global_config import GlobalConfiguration
# Local ZenML servers are identifiable by the fact that their
# server ID is the same as the local client (user) ID.
return self.id == GlobalConfiguration().user_id
is_local(self)
Return whether the server is running locally.
Returns:
Type | Description |
---|---|
bool |
True if the server is running locally, False otherwise. |
Source code in zenml/models/v2/misc/server_models.py
def is_local(self) -> bool:
"""Return whether the server is running locally.
Returns:
True if the server is running locally, False otherwise.
"""
from zenml.config.global_config import GlobalConfiguration
# Local ZenML servers are identifiable by the fact that their
# server ID is the same as the local client (user) ID.
return self.id == GlobalConfiguration().user_id
service_connector_type
Model definitions for ZenML service connectors.
AuthenticationMethodModel (BaseModel)
Authentication method specification.
Describes the schema for the configuration and secrets that need to be provided to configure an authentication method.
Source code in zenml/models/v2/misc/service_connector_type.py
class AuthenticationMethodModel(BaseModel):
"""Authentication method specification.
Describes the schema for the configuration and secrets that need to be
provided to configure an authentication method.
"""
name: str = Field(
title="User readable name for the authentication method.",
)
auth_method: str = Field(
title="The name of the authentication method.",
max_length=STR_FIELD_MAX_LENGTH,
)
description: str = Field(
default="",
title="A description of the authentication method.",
)
config_schema: Dict[str, Any] = Field(
default_factory=dict,
title="The JSON schema of the configuration for this authentication "
"method.",
)
min_expiration_seconds: Optional[int] = Field(
default=None,
title="The minimum number of seconds that the authentication "
"session can be configured to be valid for. Set to None for "
"authentication sessions and long-lived credentials that don't expire.",
)
max_expiration_seconds: Optional[int] = Field(
default=None,
title="The maximum number of seconds that the authentication "
"session can be configured to be valid for. Set to None for "
"authentication sessions and long-lived credentials that don't expire.",
)
default_expiration_seconds: Optional[int] = Field(
default=None,
title="The default number of seconds that the authentication "
"session is valid for. Set to None for authentication sessions and "
"long-lived credentials that don't expire.",
)
_config_class: Optional[Type[BaseModel]] = None
def __init__(
self, config_class: Optional[Type[BaseModel]] = None, **values: Any
):
"""Initialize the authentication method.
Args:
config_class: The configuration class for the authentication
method.
**values: The data to initialize the authentication method with.
"""
if config_class:
values["config_schema"] = config_class.model_json_schema()
super().__init__(**values)
self._config_class = config_class
@property
def config_class(self) -> Optional[Type[BaseModel]]:
"""Get the configuration class for the authentication method.
Returns:
The configuration class for the authentication method.
"""
return self._config_class
def supports_temporary_credentials(self) -> bool:
"""Check if the authentication method supports temporary credentials.
Returns:
True if the authentication method supports temporary credentials,
False otherwise.
"""
return (
self.min_expiration_seconds is not None
or self.max_expiration_seconds is not None
or self.default_expiration_seconds is not None
)
def validate_expiration(
self, expiration_seconds: Optional[int]
) -> Optional[int]:
"""Validate the expiration time.
Args:
expiration_seconds: The expiration time in seconds. If None, the
default expiration time is used, if applicable.
Returns:
The expiration time in seconds or None if not applicable.
Raises:
ValueError: If the expiration time is not valid.
"""
if not self.supports_temporary_credentials():
if expiration_seconds is not None:
# Expiration is not supported
raise ValueError(
"Expiration time is not supported for this authentication "
f"method but a value was provided: {expiration_seconds}"
)
return None
expiration_seconds = (
expiration_seconds or self.default_expiration_seconds
)
if expiration_seconds is None:
return None
if self.min_expiration_seconds is not None:
if expiration_seconds < self.min_expiration_seconds:
raise ValueError(
f"Expiration time must be at least "
f"{self.min_expiration_seconds} seconds."
)
if self.max_expiration_seconds is not None:
if expiration_seconds > self.max_expiration_seconds:
raise ValueError(
f"Expiration time must be at most "
f"{self.max_expiration_seconds} seconds."
)
return expiration_seconds
config_class: Optional[Type[pydantic.main.BaseModel]]
property
readonly
Get the configuration class for the authentication method.
Returns:
Type | Description |
---|---|
Optional[Type[pydantic.main.BaseModel]] |
The configuration class for the authentication method. |
__init__(self, config_class=None, **values)
special
Initialize the authentication method.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
config_class |
Optional[Type[pydantic.main.BaseModel]] |
The configuration class for the authentication method. |
None |
**values |
Any |
The data to initialize the authentication method with. |
{} |
Source code in zenml/models/v2/misc/service_connector_type.py
def __init__(
self, config_class: Optional[Type[BaseModel]] = None, **values: Any
):
"""Initialize the authentication method.
Args:
config_class: The configuration class for the authentication
method.
**values: The data to initialize the authentication method with.
"""
if config_class:
values["config_schema"] = config_class.model_json_schema()
super().__init__(**values)
self._config_class = config_class
model_post_init(/, self, context)
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
self |
BaseModel |
The BaseModel instance. |
required |
context |
Any |
The context. |
required |
Source code in zenml/models/v2/misc/service_connector_type.py
def init_private_attributes(self: BaseModel, context: Any, /) -> None:
"""This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args:
self: The BaseModel instance.
context: The context.
"""
if getattr(self, '__pydantic_private__', None) is None:
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)
supports_temporary_credentials(self)
Check if the authentication method supports temporary credentials.
Returns:
Type | Description |
---|---|
bool |
True if the authentication method supports temporary credentials, False otherwise. |
Source code in zenml/models/v2/misc/service_connector_type.py
def supports_temporary_credentials(self) -> bool:
"""Check if the authentication method supports temporary credentials.
Returns:
True if the authentication method supports temporary credentials,
False otherwise.
"""
return (
self.min_expiration_seconds is not None
or self.max_expiration_seconds is not None
or self.default_expiration_seconds is not None
)
validate_expiration(self, expiration_seconds)
Validate the expiration time.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
expiration_seconds |
Optional[int] |
The expiration time in seconds. If None, the default expiration time is used, if applicable. |
required |
Returns:
Type | Description |
---|---|
Optional[int] |
The expiration time in seconds or None if not applicable. |
Exceptions:
Type | Description |
---|---|
ValueError |
If the expiration time is not valid. |
Source code in zenml/models/v2/misc/service_connector_type.py
def validate_expiration(
self, expiration_seconds: Optional[int]
) -> Optional[int]:
"""Validate the expiration time.
Args:
expiration_seconds: The expiration time in seconds. If None, the
default expiration time is used, if applicable.
Returns:
The expiration time in seconds or None if not applicable.
Raises:
ValueError: If the expiration time is not valid.
"""
if not self.supports_temporary_credentials():
if expiration_seconds is not None:
# Expiration is not supported
raise ValueError(
"Expiration time is not supported for this authentication "
f"method but a value was provided: {expiration_seconds}"
)
return None
expiration_seconds = (
expiration_seconds or self.default_expiration_seconds
)
if expiration_seconds is None:
return None
if self.min_expiration_seconds is not None:
if expiration_seconds < self.min_expiration_seconds:
raise ValueError(
f"Expiration time must be at least "
f"{self.min_expiration_seconds} seconds."
)
if self.max_expiration_seconds is not None:
if expiration_seconds > self.max_expiration_seconds:
raise ValueError(
f"Expiration time must be at most "
f"{self.max_expiration_seconds} seconds."
)
return expiration_seconds
ResourceTypeModel (BaseModel)
Resource type specification.
Describes the authentication methods and resource instantiation model for one or more resource types.
Source code in zenml/models/v2/misc/service_connector_type.py
class ResourceTypeModel(BaseModel):
"""Resource type specification.
Describes the authentication methods and resource instantiation model for
one or more resource types.
"""
name: str = Field(
title="User readable name for the resource type.",
)
resource_type: str = Field(
title="Resource type identifier.",
)
description: str = Field(
default="",
title="A description of the resource type.",
)
auth_methods: List[str] = Field(
title="The list of authentication methods that can be used to access "
"resources of this type.",
)
supports_instances: bool = Field(
default=False,
title="Specifies if a single connector instance can be used to access "
"multiple instances of this resource type. If set to True, the "
"connector is able to provide a list of resource IDs identifying all "
"the resources that it can access and a resource ID needs to be "
"explicitly configured or supplied when access to a resource is "
"requested. If set to False, a connector instance is only able to "
"access a single resource and a resource ID is not required to access "
"the resource.",
)
logo_url: Optional[str] = Field(
default=None,
title="Optionally, a URL pointing to a png,"
"svg or jpg file can be attached.",
)
emoji: Optional[str] = Field(
default=None,
title="Optionally, a python-rich emoji can be attached.",
)
@property
def emojified_resource_type(self) -> str:
"""Get the emojified resource type.
Returns:
The emojified resource type.
"""
if not self.emoji:
return self.resource_type
return f"{self.emoji} {self.resource_type}"
emojified_resource_type: str
property
readonly
Get the emojified resource type.
Returns:
Type | Description |
---|---|
str |
The emojified resource type. |
ServiceConnectorRequirements (BaseModel)
Service connector requirements.
Describes requirements that a service connector consumer has for a service connector instance that it needs in order to access a resource.
Attributes:
Name | Type | Description |
---|---|---|
connector_type |
Optional[str] |
The type of service connector that is required. If omitted, any service connector type can be used. |
resource_type |
str |
The type of resource that the service connector instance must be able to access. |
resource_id_attr |
Optional[str] |
The name of an attribute in the stack component configuration that contains the resource ID of the resource that the service connector instance must be able to access. |
Source code in zenml/models/v2/misc/service_connector_type.py
class ServiceConnectorRequirements(BaseModel):
"""Service connector requirements.
Describes requirements that a service connector consumer has for a
service connector instance that it needs in order to access a resource.
Attributes:
connector_type: The type of service connector that is required. If
omitted, any service connector type can be used.
resource_type: The type of resource that the service connector instance
must be able to access.
resource_id_attr: The name of an attribute in the stack component
configuration that contains the resource ID of the resource that
the service connector instance must be able to access.
"""
connector_type: Optional[str] = None
resource_type: str
resource_id_attr: Optional[str] = None
def is_satisfied_by(
self,
connector: Union[
"ServiceConnectorResponse", "ServiceConnectorRequest"
],
component: Union["ComponentResponse", "ComponentBase"],
) -> Tuple[bool, str]:
"""Check if the requirements are satisfied by a connector.
Args:
connector: The connector to check.
component: The stack component that the connector is associated
with.
Returns:
True if the requirements are satisfied, False otherwise, and a
message describing the reason for the failure.
"""
if self.connector_type and self.connector_type != connector.type:
return (
False,
f"connector type '{connector.type}' does not match the "
f"'{self.connector_type}' connector type specified in the "
"stack component requirements",
)
if self.resource_type not in connector.resource_types:
return False, (
f"connector does not provide the '{self.resource_type}' "
"resource type specified in the stack component requirements. "
"Only the following resource types are supported: "
f"{', '.join(connector.resource_types)}"
)
if self.resource_id_attr:
resource_id = component.configuration.get(self.resource_id_attr)
if not resource_id:
return (
False,
f"the '{self.resource_id_attr}' stack component "
f"configuration attribute plays the role of resource "
f"identifier, but the stack component does not contain a "
f"'{self.resource_id_attr}' attribute. Please add the "
f"'{self.resource_id_attr}' attribute to the stack "
"component configuration and try again.",
)
return True, ""
is_satisfied_by(self, connector, component)
Check if the requirements are satisfied by a connector.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
connector |
Union[ServiceConnectorResponse, ServiceConnectorRequest] |
The connector to check. |
required |
component |
Union[ComponentResponse, ComponentBase] |
The stack component that the connector is associated with. |
required |
Returns:
Type | Description |
---|---|
Tuple[bool, str] |
True if the requirements are satisfied, False otherwise, and a message describing the reason for the failure. |
Source code in zenml/models/v2/misc/service_connector_type.py
def is_satisfied_by(
self,
connector: Union[
"ServiceConnectorResponse", "ServiceConnectorRequest"
],
component: Union["ComponentResponse", "ComponentBase"],
) -> Tuple[bool, str]:
"""Check if the requirements are satisfied by a connector.
Args:
connector: The connector to check.
component: The stack component that the connector is associated
with.
Returns:
True if the requirements are satisfied, False otherwise, and a
message describing the reason for the failure.
"""
if self.connector_type and self.connector_type != connector.type:
return (
False,
f"connector type '{connector.type}' does not match the "
f"'{self.connector_type}' connector type specified in the "
"stack component requirements",
)
if self.resource_type not in connector.resource_types:
return False, (
f"connector does not provide the '{self.resource_type}' "
"resource type specified in the stack component requirements. "
"Only the following resource types are supported: "
f"{', '.join(connector.resource_types)}"
)
if self.resource_id_attr:
resource_id = component.configuration.get(self.resource_id_attr)
if not resource_id:
return (
False,
f"the '{self.resource_id_attr}' stack component "
f"configuration attribute plays the role of resource "
f"identifier, but the stack component does not contain a "
f"'{self.resource_id_attr}' attribute. Please add the "
f"'{self.resource_id_attr}' attribute to the stack "
"component configuration and try again.",
)
return True, ""
ServiceConnectorResourcesModel (BaseModel)
Service connector resources list.
Lists the resource types and resource instances that a service connector can provide access to.
Source code in zenml/models/v2/misc/service_connector_type.py
class ServiceConnectorResourcesModel(BaseModel):
"""Service connector resources list.
Lists the resource types and resource instances that a service connector
can provide access to.
"""
id: Optional[UUID] = Field(
default=None,
title="The ID of the service connector instance providing this "
"resource.",
)
name: Optional[str] = Field(
default=None,
title="The name of the service connector instance providing this "
"resource.",
max_length=STR_FIELD_MAX_LENGTH,
)
connector_type: Union[str, "ServiceConnectorTypeModel"] = Field(
title="The type of service connector.", union_mode="left_to_right"
)
resources: List[ServiceConnectorTypedResourcesModel] = Field(
default_factory=list,
title="The list of resources that the service connector instance can "
"give access to. Contains one entry for every resource type "
"that the connector is configured for.",
)
error: Optional[str] = Field(
default=None,
title="A global error message describing why the service connector "
"instance could not authenticate to the remote service.",
)
@property
def resources_dict(self) -> Dict[str, ServiceConnectorTypedResourcesModel]:
"""Get the resources as a dictionary indexed by resource type.
Returns:
The resources as a dictionary indexed by resource type.
"""
return {
resource.resource_type: resource for resource in self.resources
}
@property
def resource_types(self) -> List[str]:
"""Get the resource types.
Returns:
The resource types.
"""
return [resource.resource_type for resource in self.resources]
def set_error(
self, error: str, resource_type: Optional[str] = None
) -> None:
"""Set a global error message or an error for a single resource type.
Args:
error: The error message.
resource_type: The resource type to set the error message for. If
omitted, or if there is only one resource type involved, the
error message is (also) set globally.
Raises:
KeyError: If the resource type is not found in the resources list.
"""
if resource_type:
resource = self.resources_dict.get(resource_type)
if not resource:
raise KeyError(
f"resource type '{resource_type}' not found in "
"service connector resources list"
)
resource.error = error
resource.resource_ids = None
if len(self.resources) == 1:
# If there is only one resource type involved, set the global
# error message as well.
self.error = error
else:
self.error = error
for resource in self.resources:
resource.error = error
resource.resource_ids = None
def set_resource_ids(
self, resource_type: str, resource_ids: List[str]
) -> None:
"""Set the resource IDs for a resource type.
Args:
resource_type: The resource type to set the resource IDs for.
resource_ids: The resource IDs to set.
Raises:
KeyError: If the resource type is not found in the resources list.
"""
resource = self.resources_dict.get(resource_type)
if not resource:
raise KeyError(
f"resource type '{resource_type}' not found in "
"service connector resources list"
)
resource.resource_ids = resource_ids
resource.error = None
@property
def type(self) -> str:
"""Get the connector type.
Returns:
The connector type.
"""
if isinstance(self.connector_type, str):
return self.connector_type
return self.connector_type.connector_type
@property
def emojified_connector_type(self) -> str:
"""Get the emojified connector type.
Returns:
The emojified connector type.
"""
if not isinstance(self.connector_type, str):
return self.connector_type.emojified_connector_type
return self.connector_type
def get_emojified_resource_types(
self, resource_type: Optional[str] = None
) -> List[str]:
"""Get the emojified resource type.
Args:
resource_type: The resource type to get the emojified resource type
for. If omitted, the emojified resource type for all resource
types is returned.
Returns:
The list of emojified resource types.
"""
if not isinstance(self.connector_type, str):
if resource_type:
return [
self.connector_type.resource_type_dict[
resource_type
].emojified_resource_type
]
return [
self.connector_type.resource_type_dict[
resource_type
].emojified_resource_type
for resource_type in self.resources_dict.keys()
]
if resource_type:
return [resource_type]
return list(self.resources_dict.keys())
def get_default_resource_id(self) -> Optional[str]:
"""Get the default resource ID, if included in the resource list.
The default resource ID is a resource ID supplied by the connector
implementation only for resource types that do not support multiple
instances.
Returns:
The default resource ID, or None if no resource ID is set.
"""
if len(self.resources) != 1:
# multi-type connectors do not have a default resource ID
return None
if isinstance(self.connector_type, str):
# can't determine default resource ID for unknown connector types
return None
resource_type_spec = self.connector_type.resource_type_dict[
self.resources[0].resource_type
]
if resource_type_spec.supports_instances:
# resource types that support multiple instances do not have a
# default resource ID
return None
resource_ids = self.resources[0].resource_ids
if not resource_ids or len(resource_ids) != 1:
return None
return resource_ids[0]
@classmethod
def from_connector_model(
cls,
connector_model: "ServiceConnectorResponse",
resource_type: Optional[str] = None,
) -> "ServiceConnectorResourcesModel":
"""Initialize a resource model from a connector model.
Args:
connector_model: The connector model.
resource_type: The resource type to set on the resource model. If
omitted, the resource type is set according to the connector
model.
Returns:
A resource list model instance.
"""
resources = cls(
id=connector_model.id,
name=connector_model.name,
connector_type=connector_model.type,
)
resource_types = resource_type or connector_model.resource_types
for resource_type in resource_types:
resources.resources.append(
ServiceConnectorTypedResourcesModel(
resource_type=resource_type,
resource_ids=[connector_model.resource_id]
if connector_model.resource_id
else None,
)
)
return resources
emojified_connector_type: str
property
readonly
Get the emojified connector type.
Returns:
Type | Description |
---|---|
str |
The emojified connector type. |
resource_types: List[str]
property
readonly
Get the resource types.
Returns:
Type | Description |
---|---|
List[str] |
The resource types. |
resources_dict: Dict[str, zenml.models.v2.misc.service_connector_type.ServiceConnectorTypedResourcesModel]
property
readonly
Get the resources as a dictionary indexed by resource type.
Returns:
Type | Description |
---|---|
Dict[str, zenml.models.v2.misc.service_connector_type.ServiceConnectorTypedResourcesModel] |
The resources as a dictionary indexed by resource type. |
type: str
property
readonly
Get the connector type.
Returns:
Type | Description |
---|---|
str |
The connector type. |
from_connector_model(connector_model, resource_type=None)
classmethod
Initialize a resource model from a connector model.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
connector_model |
ServiceConnectorResponse |
The connector model. |
required |
resource_type |
Optional[str] |
The resource type to set on the resource model. If omitted, the resource type is set according to the connector model. |
None |
Returns:
Type | Description |
---|---|
ServiceConnectorResourcesModel |
A resource list model instance. |
Source code in zenml/models/v2/misc/service_connector_type.py
@classmethod
def from_connector_model(
cls,
connector_model: "ServiceConnectorResponse",
resource_type: Optional[str] = None,
) -> "ServiceConnectorResourcesModel":
"""Initialize a resource model from a connector model.
Args:
connector_model: The connector model.
resource_type: The resource type to set on the resource model. If
omitted, the resource type is set according to the connector
model.
Returns:
A resource list model instance.
"""
resources = cls(
id=connector_model.id,
name=connector_model.name,
connector_type=connector_model.type,
)
resource_types = resource_type or connector_model.resource_types
for resource_type in resource_types:
resources.resources.append(
ServiceConnectorTypedResourcesModel(
resource_type=resource_type,
resource_ids=[connector_model.resource_id]
if connector_model.resource_id
else None,
)
)
return resources
get_default_resource_id(self)
Get the default resource ID, if included in the resource list.
The default resource ID is a resource ID supplied by the connector implementation only for resource types that do not support multiple instances.
Returns:
Type | Description |
---|---|
Optional[str] |
The default resource ID, or None if no resource ID is set. |
Source code in zenml/models/v2/misc/service_connector_type.py
def get_default_resource_id(self) -> Optional[str]:
"""Get the default resource ID, if included in the resource list.
The default resource ID is a resource ID supplied by the connector
implementation only for resource types that do not support multiple
instances.
Returns:
The default resource ID, or None if no resource ID is set.
"""
if len(self.resources) != 1:
# multi-type connectors do not have a default resource ID
return None
if isinstance(self.connector_type, str):
# can't determine default resource ID for unknown connector types
return None
resource_type_spec = self.connector_type.resource_type_dict[
self.resources[0].resource_type
]
if resource_type_spec.supports_instances:
# resource types that support multiple instances do not have a
# default resource ID
return None
resource_ids = self.resources[0].resource_ids
if not resource_ids or len(resource_ids) != 1:
return None
return resource_ids[0]
get_emojified_resource_types(self, resource_type=None)
Get the emojified resource type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource_type |
Optional[str] |
The resource type to get the emojified resource type for. If omitted, the emojified resource type for all resource types is returned. |
None |
Returns:
Type | Description |
---|---|
List[str] |
The list of emojified resource types. |
Source code in zenml/models/v2/misc/service_connector_type.py
def get_emojified_resource_types(
self, resource_type: Optional[str] = None
) -> List[str]:
"""Get the emojified resource type.
Args:
resource_type: The resource type to get the emojified resource type
for. If omitted, the emojified resource type for all resource
types is returned.
Returns:
The list of emojified resource types.
"""
if not isinstance(self.connector_type, str):
if resource_type:
return [
self.connector_type.resource_type_dict[
resource_type
].emojified_resource_type
]
return [
self.connector_type.resource_type_dict[
resource_type
].emojified_resource_type
for resource_type in self.resources_dict.keys()
]
if resource_type:
return [resource_type]
return list(self.resources_dict.keys())
set_error(self, error, resource_type=None)
Set a global error message or an error for a single resource type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
error |
str |
The error message. |
required |
resource_type |
Optional[str] |
The resource type to set the error message for. If omitted, or if there is only one resource type involved, the error message is (also) set globally. |
None |
Exceptions:
Type | Description |
---|---|
KeyError |
If the resource type is not found in the resources list. |
Source code in zenml/models/v2/misc/service_connector_type.py
def set_error(
self, error: str, resource_type: Optional[str] = None
) -> None:
"""Set a global error message or an error for a single resource type.
Args:
error: The error message.
resource_type: The resource type to set the error message for. If
omitted, or if there is only one resource type involved, the
error message is (also) set globally.
Raises:
KeyError: If the resource type is not found in the resources list.
"""
if resource_type:
resource = self.resources_dict.get(resource_type)
if not resource:
raise KeyError(
f"resource type '{resource_type}' not found in "
"service connector resources list"
)
resource.error = error
resource.resource_ids = None
if len(self.resources) == 1:
# If there is only one resource type involved, set the global
# error message as well.
self.error = error
else:
self.error = error
for resource in self.resources:
resource.error = error
resource.resource_ids = None
set_resource_ids(self, resource_type, resource_ids)
Set the resource IDs for a resource type.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
resource_type |
str |
The resource type to set the resource IDs for. |
required |
resource_ids |
List[str] |
The resource IDs to set. |
required |
Exceptions:
Type | Description |
---|---|
KeyError |
If the resource type is not found in the resources list. |
Source code in zenml/models/v2/misc/service_connector_type.py
def set_resource_ids(
self, resource_type: str, resource_ids: List[str]
) -> None:
"""Set the resource IDs for a resource type.
Args:
resource_type: The resource type to set the resource IDs for.
resource_ids: The resource IDs to set.
Raises:
KeyError: If the resource type is not found in the resources list.
"""
resource = self.resources_dict.get(resource_type)
if not resource:
raise KeyError(
f"resource type '{resource_type}' not found in "
"service connector resources list"
)
resource.resource_ids = resource_ids
resource.error = None
ServiceConnectorTypeModel (BaseModel)
Service connector type specification.
Describes the types of resources to which the service connector can be used to gain access and the authentication methods that are supported by the service connector.
The connector type, resource types, resource IDs and authentication methods can all be used as search criteria to lookup and filter service connector instances that are compatible with the requirements of a consumer (e.g. a stack component).
Source code in zenml/models/v2/misc/service_connector_type.py
class ServiceConnectorTypeModel(BaseModel):
"""Service connector type specification.
Describes the types of resources to which the service connector can be used
to gain access and the authentication methods that are supported by the
service connector.
The connector type, resource types, resource IDs and authentication
methods can all be used as search criteria to lookup and filter service
connector instances that are compatible with the requirements of a consumer
(e.g. a stack component).
"""
name: str = Field(
title="User readable name for the service connector type.",
)
connector_type: str = Field(
title="The type of service connector. It can be used to represent a "
"generic resource (e.g. Docker, Kubernetes) or a group of different "
"resources accessible through a common interface or point of access "
"and authentication (e.g. a cloud provider or a platform).",
max_length=STR_FIELD_MAX_LENGTH,
)
description: str = Field(
default="",
title="A description of the service connector.",
)
resource_types: List[ResourceTypeModel] = Field(
title="A list of resource types that the connector can be used to "
"access.",
)
auth_methods: List[AuthenticationMethodModel] = Field(
title="A list of specifications describing the authentication "
"methods that are supported by the service connector, along with the "
"configuration and secrets attributes that need to be configured for "
"them.",
)
supports_auto_configuration: bool = Field(
default=False,
title="Models if the connector can be configured automatically based "
"on information extracted from a local environment.",
)
logo_url: Optional[str] = Field(
default=None,
title="Optionally, a URL pointing to a png,"
"svg or jpg can be attached.",
)
emoji: Optional[str] = Field(
default=None,
title="Optionally, a python-rich emoji can be attached.",
)
docs_url: Optional[str] = Field(
default=None,
title="Optionally, a URL pointing to docs, within docs.zenml.io.",
)
sdk_docs_url: Optional[str] = Field(
default=None,
title="Optionally, a URL pointing to SDK docs,"
"within sdkdocs.zenml.io.",
)
local: bool = Field(
default=True,
title="If True, the service connector is available locally.",
)
remote: bool = Field(
default=False,
title="If True, the service connector is available remotely.",
)
_connector_class: Optional[Type["ServiceConnector"]] = None
@property
def connector_class(self) -> Optional[Type["ServiceConnector"]]:
"""Get the service connector class.
Returns:
The service connector class.
"""
return self._connector_class
@property
def emojified_connector_type(self) -> str:
"""Get the emojified connector type.
Returns:
The emojified connector type.
"""
if not self.emoji:
return self.connector_type
return f"{self.emoji} {self.connector_type}"
@property
def emojified_resource_types(self) -> List[str]:
"""Get the emojified connector types.
Returns:
The emojified connector types.
"""
return [
resource_type.emojified_resource_type
for resource_type in self.resource_types
]
def set_connector_class(
self, connector_class: Type["ServiceConnector"]
) -> None:
"""Set the service connector class.
Args:
connector_class: The service connector class.
"""
self._connector_class = connector_class
@field_validator("resource_types")
@classmethod
def validate_resource_types(
cls, values: List[ResourceTypeModel]
) -> List[ResourceTypeModel]:
"""Validate that the resource types are unique.
Args:
values: The list of resource types.
Returns:
The list of resource types.
Raises:
ValueError: If two or more resource type specifications list the
same resource type.
"""
# Gather all resource types from the list of resource type
# specifications.
resource_types = [r.resource_type for r in values]
if len(resource_types) != len(set(resource_types)):
raise ValueError(
"Two or more resource type specifications must not list "
"the same resource type."
)
return values
@field_validator("auth_methods")
@classmethod
def validate_auth_methods(
cls, values: List[AuthenticationMethodModel]
) -> List[AuthenticationMethodModel]:
"""Validate that the authentication methods are unique.
Args:
values: The list of authentication methods.
Returns:
The list of authentication methods.
Raises:
ValueError: If two or more authentication method specifications
share the same authentication method value.
"""
# Gather all auth methods from the list of auth method
# specifications.
auth_methods = [a.auth_method for a in values]
if len(auth_methods) != len(set(auth_methods)):
raise ValueError(
"Two or more authentication method specifications must not "
"share the same authentication method value."
)
return values
@property
def resource_type_dict(
self,
) -> Dict[str, ResourceTypeModel]:
"""Returns a map of resource types to resource type specifications.
Returns:
A map of resource types to resource type specifications.
"""
return {r.resource_type: r for r in self.resource_types}
@property
def auth_method_dict(
self,
) -> Dict[str, AuthenticationMethodModel]:
"""Returns a map of authentication methods to authentication method specifications.
Returns:
A map of authentication methods to authentication method
specifications.
"""
return {a.auth_method: a for a in self.auth_methods}
def find_resource_specifications(
self,
auth_method: str,
resource_type: Optional[str] = None,
) -> Tuple[AuthenticationMethodModel, Optional[ResourceTypeModel]]:
"""Find the specifications for a configurable resource.
Validate the supplied connector configuration parameters against the
connector specification and return the matching authentication method
specification and resource specification.
Args:
auth_method: The name of the authentication method.
resource_type: The type of resource being configured.
Returns:
The authentication method specification and resource specification
for the specified authentication method and resource type.
Raises:
KeyError: If the authentication method is not supported by the
connector for the specified resource type and ID.
"""
# Verify the authentication method
auth_method_dict = self.auth_method_dict
if auth_method in auth_method_dict:
# A match was found for the authentication method
auth_method_spec = auth_method_dict[auth_method]
else:
# No match was found for the authentication method
raise KeyError(
f"connector type '{self.connector_type}' does not support the "
f"'{auth_method}' authentication method. Supported "
f"authentication methods are: {list(auth_method_dict.keys())}."
)
if resource_type is None:
# No resource type was specified, so no resource type
# specification can be returned.
return auth_method_spec, None
# Verify the resource type
resource_type_dict = self.resource_type_dict
if resource_type in resource_type_dict:
resource_type_spec = resource_type_dict[resource_type]
else:
raise KeyError(
f"connector type '{self.connector_type}' does not support "
f"resource type '{resource_type}'. Supported resource types "
f"are: {list(resource_type_dict.keys())}."
)
if auth_method not in resource_type_spec.auth_methods:
raise KeyError(
f"the '{self.connector_type}' connector type does not support "
f"the '{auth_method}' authentication method for the "
f"'{resource_type}' resource type. Supported authentication "
f"methods are: {resource_type_spec.auth_methods}."
)
return auth_method_spec, resource_type_spec
auth_method_dict: Dict[str, zenml.models.v2.misc.service_connector_type.AuthenticationMethodModel]
property
readonly
Returns a map of authentication methods to authentication method specifications.
Returns:
Type | Description |
---|---|
Dict[str, zenml.models.v2.misc.service_connector_type.AuthenticationMethodModel] |
A map of authentication methods to authentication method specifications. |
connector_class: Optional[Type[ServiceConnector]]
property
readonly
Get the service connector class.
Returns:
Type | Description |
---|---|
Optional[Type[ServiceConnector]] |
The service connector class. |
emojified_connector_type: str
property
readonly
Get the emojified connector type.
Returns:
Type | Description |
---|---|
str |
The emojified connector type. |
emojified_resource_types: List[str]
property
readonly
Get the emojified connector types.
Returns:
Type | Description |
---|---|
List[str] |
The emojified connector types. |
resource_type_dict: Dict[str, zenml.models.v2.misc.service_connector_type.ResourceTypeModel]
property
readonly
Returns a map of resource types to resource type specifications.
Returns:
Type | Description |
---|---|
Dict[str, zenml.models.v2.misc.service_connector_type.ResourceTypeModel] |
A map of resource types to resource type specifications. |
find_resource_specifications(self, auth_method, resource_type=None)
Find the specifications for a configurable resource.
Validate the supplied connector configuration parameters against the connector specification and return the matching authentication method specification and resource specification.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
auth_method |
str |
The name of the authentication method. |
required |
resource_type |
Optional[str] |
The type of resource being configured. |
None |
Returns:
Type | Description |
---|---|
Tuple[zenml.models.v2.misc.service_connector_type.AuthenticationMethodModel, Optional[zenml.models.v2.misc.service_connector_type.ResourceTypeModel]] |
The authentication method specification and resource specification for the specified authentication method and resource type. |
Exceptions:
Type | Description |
---|---|
KeyError |
If the authentication method is not supported by the connector for the specified resource type and ID. |
Source code in zenml/models/v2/misc/service_connector_type.py
def find_resource_specifications(
self,
auth_method: str,
resource_type: Optional[str] = None,
) -> Tuple[AuthenticationMethodModel, Optional[ResourceTypeModel]]:
"""Find the specifications for a configurable resource.
Validate the supplied connector configuration parameters against the
connector specification and return the matching authentication method
specification and resource specification.
Args:
auth_method: The name of the authentication method.
resource_type: The type of resource being configured.
Returns:
The authentication method specification and resource specification
for the specified authentication method and resource type.
Raises:
KeyError: If the authentication method is not supported by the
connector for the specified resource type and ID.
"""
# Verify the authentication method
auth_method_dict = self.auth_method_dict
if auth_method in auth_method_dict:
# A match was found for the authentication method
auth_method_spec = auth_method_dict[auth_method]
else:
# No match was found for the authentication method
raise KeyError(
f"connector type '{self.connector_type}' does not support the "
f"'{auth_method}' authentication method. Supported "
f"authentication methods are: {list(auth_method_dict.keys())}."
)
if resource_type is None:
# No resource type was specified, so no resource type
# specification can be returned.
return auth_method_spec, None
# Verify the resource type
resource_type_dict = self.resource_type_dict
if resource_type in resource_type_dict:
resource_type_spec = resource_type_dict[resource_type]
else:
raise KeyError(
f"connector type '{self.connector_type}' does not support "
f"resource type '{resource_type}'. Supported resource types "
f"are: {list(resource_type_dict.keys())}."
)
if auth_method not in resource_type_spec.auth_methods:
raise KeyError(
f"the '{self.connector_type}' connector type does not support "
f"the '{auth_method}' authentication method for the "
f"'{resource_type}' resource type. Supported authentication "
f"methods are: {resource_type_spec.auth_methods}."
)
return auth_method_spec, resource_type_spec
model_post_init(/, self, context)
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
self |
BaseModel |
The BaseModel instance. |
required |
context |
Any |
The context. |
required |
Source code in zenml/models/v2/misc/service_connector_type.py
def init_private_attributes(self: BaseModel, context: Any, /) -> None:
"""This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Args:
self: The BaseModel instance.
context: The context.
"""
if getattr(self, '__pydantic_private__', None) is None:
pydantic_private = {}
for name, private_attr in self.__private_attributes__.items():
default = private_attr.get_default()
if default is not PydanticUndefined:
pydantic_private[name] = default
object_setattr(self, '__pydantic_private__', pydantic_private)
set_connector_class(self, connector_class)
Set the service connector class.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
connector_class |
Type[ServiceConnector] |
The service connector class. |
required |
Source code in zenml/models/v2/misc/service_connector_type.py
def set_connector_class(
self, connector_class: Type["ServiceConnector"]
) -> None:
"""Set the service connector class.
Args:
connector_class: The service connector class.
"""
self._connector_class = connector_class
validate_auth_methods(values)
classmethod
Validate that the authentication methods are unique.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
values |
List[zenml.models.v2.misc.service_connector_type.AuthenticationMethodModel] |
The list of authentication methods. |
required |
Returns:
Type | Description |
---|---|
List[zenml.models.v2.misc.service_connector_type.AuthenticationMethodModel] |
The list of authentication methods. |
Exceptions:
Type | Description |
---|---|
ValueError |
If two or more authentication method specifications share the same authentication method value. |
Source code in zenml/models/v2/misc/service_connector_type.py
@field_validator("auth_methods")
@classmethod
def validate_auth_methods(
cls, values: List[AuthenticationMethodModel]
) -> List[AuthenticationMethodModel]:
"""Validate that the authentication methods are unique.
Args:
values: The list of authentication methods.
Returns:
The list of authentication methods.
Raises:
ValueError: If two or more authentication method specifications
share the same authentication method value.
"""
# Gather all auth methods from the list of auth method
# specifications.
auth_methods = [a.auth_method for a in values]
if len(auth_methods) != len(set(auth_methods)):
raise ValueError(
"Two or more authentication method specifications must not "
"share the same authentication method value."
)
return values
validate_resource_types(values)
classmethod
Validate that the resource types are unique.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
values |
List[zenml.models.v2.misc.service_connector_type.ResourceTypeModel] |
The list of resource types. |
required |
Returns:
Type | Description |
---|---|
List[zenml.models.v2.misc.service_connector_type.ResourceTypeModel] |
The list of resource types. |
Exceptions:
Type | Description |
---|---|
ValueError |
If two or more resource type specifications list the same resource type. |
Source code in zenml/models/v2/misc/service_connector_type.py
@field_validator("resource_types")
@classmethod
def validate_resource_types(
cls, values: List[ResourceTypeModel]
) -> List[ResourceTypeModel]:
"""Validate that the resource types are unique.
Args:
values: The list of resource types.
Returns:
The list of resource types.
Raises:
ValueError: If two or more resource type specifications list the
same resource type.
"""
# Gather all resource types from the list of resource type
# specifications.
resource_types = [r.resource_type for r in values]
if len(resource_types) != len(set(resource_types)):
raise ValueError(
"Two or more resource type specifications must not list "
"the same resource type."
)
return values
ServiceConnectorTypedResourcesModel (BaseModel)
Service connector typed resources list.
Lists the resource instances that a service connector can provide access to.
Source code in zenml/models/v2/misc/service_connector_type.py
class ServiceConnectorTypedResourcesModel(BaseModel):
"""Service connector typed resources list.
Lists the resource instances that a service connector can provide
access to.
"""
resource_type: str = Field(
title="The type of resource that the service connector instance can "
"be used to access.",
max_length=STR_FIELD_MAX_LENGTH,
)
resource_ids: Optional[List[str]] = Field(
default=None,
title="The resource IDs of all resource instances that the service "
"connector instance can be used to access. Omitted (set to None) for "
"multi-type service connectors that didn't explicitly request to "
"fetch resources for all resource types. Also omitted if an error "
"occurred while listing the resource instances or if no resources are "
"listed due to authorization issues or lack of permissions (in both "
"cases the 'error' field is set to an error message). For resource "
"types that do not support multiple instances, a single resource ID is "
"listed.",
)
error: Optional[str] = Field(
default=None,
title="An error message describing why the service connector instance "
"could not list the resources that it is configured to access.",
)
stack_deployment
Models related to cloud stack deployments.
DeployedStack (BaseModel)
Information about a deployed stack.
Source code in zenml/models/v2/misc/stack_deployment.py
class DeployedStack(BaseModel):
"""Information about a deployed stack."""
stack: StackResponse = Field(
title="The stack that was deployed.",
description="The stack that was deployed.",
)
service_connector: Optional[ServiceConnectorResponse] = Field(
default=None,
title="The service connector for the deployed stack.",
description="The service connector for the deployed stack.",
)
StackDeploymentConfig (BaseModel)
Configuration about a stack deployment.
Source code in zenml/models/v2/misc/stack_deployment.py
class StackDeploymentConfig(BaseModel):
"""Configuration about a stack deployment."""
deployment_url: str = Field(
title="The cloud provider console URL where the stack will be deployed.",
)
deployment_url_text: str = Field(
title="A textual description for the cloud provider console URL.",
)
configuration: Optional[str] = Field(
default=None,
title="Configuration for the stack deployment that the user must "
"manually configure into the cloud provider console.",
)
instructions: Optional[str] = Field(
default=None,
title="Instructions for deploying the stack.",
)
StackDeploymentInfo (BaseModel)
Information about a stack deployment.
Source code in zenml/models/v2/misc/stack_deployment.py
class StackDeploymentInfo(BaseModel):
"""Information about a stack deployment."""
provider: StackDeploymentProvider = Field(
title="The provider of the stack deployment."
)
description: str = Field(
title="The description of the stack deployment.",
description="The description of the stack deployment.",
)
instructions: str = Field(
title="The instructions for deploying the stack.",
description="The instructions for deploying the stack.",
)
post_deploy_instructions: str = Field(
title="The instructions for post-deployment.",
description="The instructions for post-deployment.",
)
integrations: List[str] = Field(
title="ZenML integrations required for the stack.",
description="The list of ZenML integrations that need to be installed "
"for the stack to be usable.",
)
permissions: Dict[str, List[str]] = Field(
title="The permissions granted to ZenML to access the cloud resources.",
description="The permissions granted to ZenML to access the cloud "
"resources, as a dictionary grouping permissions by resource.",
)
locations: Dict[str, str] = Field(
title="The locations where the stack can be deployed.",
description="The locations where the stack can be deployed, as a "
"dictionary mapping location names to descriptions.",
)
skypilot_default_regions: Dict[str, str] = Field(
title="The locations where the Skypilot clusters can be deployed by default.",
description="The locations where the Skypilot clusters can be deployed by default, as a "
"dictionary mapping location names to descriptions.",
)
user_auth
Model definition for auth users.
UserAuthModel (BaseZenModel)
Authentication Model for the User.
This model is only used server-side. The server endpoints can use this model to authenticate the user credentials (Token, Password).
Source code in zenml/models/v2/misc/user_auth.py
class UserAuthModel(BaseZenModel):
"""Authentication Model for the User.
This model is only used server-side. The server endpoints can use this model
to authenticate the user credentials (Token, Password).
"""
id: UUID = Field(title="The unique resource id.")
created: datetime = Field(title="Time when this resource was created.")
updated: datetime = Field(
title="Time when this resource was last updated."
)
active: bool = Field(default=False, title="Active account.")
is_service_account: bool = Field(
title="Indicates whether this is a service account or a regular user "
"account."
)
activation_token: Optional[PlainSerializedSecretStr] = Field(
default=None, exclude=True
)
password: Optional[PlainSerializedSecretStr] = Field(
default=None, exclude=True
)
name: str = Field(
title="The unique username for the account.",
max_length=STR_FIELD_MAX_LENGTH,
)
full_name: str = Field(
default="",
title="The full name for the account owner. Only relevant for user "
"accounts.",
max_length=STR_FIELD_MAX_LENGTH,
)
email_opted_in: Optional[bool] = Field(
default=None,
title="Whether the user agreed to share their email. Only relevant for "
"user accounts",
description="`null` if not answered, `true` if agreed, "
"`false` if skipped.",
)
@classmethod
def _get_crypt_context(cls) -> "CryptContext":
"""Returns the password encryption context.
Returns:
The password encryption context.
"""
from passlib.context import CryptContext
return CryptContext(schemes=["bcrypt"], deprecated="auto")
@classmethod
def _is_hashed_secret(cls, secret: SecretStr) -> bool:
"""Checks if a secret value is already hashed.
Args:
secret: The secret value to check.
Returns:
True if the secret value is hashed, otherwise False.
"""
return (
re.match(r"^\$2[ayb]\$.{56}$", secret.get_secret_value())
is not None
)
@classmethod
def _get_hashed_secret(cls, secret: Optional[SecretStr]) -> Optional[str]:
"""Hashes the input secret and returns the hash value.
Only applied if supplied and if not already hashed.
Args:
secret: The secret value to hash.
Returns:
The secret hash value, or None if no secret was supplied.
"""
if secret is None:
return None
if cls._is_hashed_secret(secret):
return secret.get_secret_value()
pwd_context = cls._get_crypt_context()
return pwd_context.hash(secret.get_secret_value())
def get_password(self) -> Optional[str]:
"""Get the password.
Returns:
The password as a plain string, if it exists.
"""
if self.password is None:
return None
return self.password.get_secret_value()
def get_hashed_password(self) -> Optional[str]:
"""Returns the hashed password, if configured.
Returns:
The hashed password.
"""
return self._get_hashed_secret(self.password)
def get_hashed_activation_token(self) -> Optional[str]:
"""Returns the hashed activation token, if configured.
Returns:
The hashed activation token.
"""
return self._get_hashed_secret(self.activation_token)
@classmethod
def verify_password(
cls, plain_password: str, user: Optional["UserAuthModel"] = None
) -> bool:
"""Verifies a given plain password against the stored password.
Args:
plain_password: Input password to be verified.
user: User for which the password is to be verified.
Returns:
True if the passwords match.
"""
# even when the user or password is not set, we still want to execute
# the password hash verification to protect against response discrepancy
# attacks (https://cwe.mitre.org/data/definitions/204.html)
password_hash: Optional[str] = None
if (
user is not None
# Disable password verification for service accounts as an extra
# security measure. Service accounts should only be used with API
# keys.
and not user.is_service_account
and user.password is not None
): # and user.active:
password_hash = user.get_hashed_password()
pwd_context = cls._get_crypt_context()
return pwd_context.verify(plain_password, password_hash)
@classmethod
def verify_activation_token(
cls, activation_token: str, user: Optional["UserAuthModel"] = None
) -> bool:
"""Verifies a given activation token against the stored token.
Args:
activation_token: Input activation token to be verified.
user: User for which the activation token is to be verified.
Returns:
True if the token is valid.
"""
# even when the user or token is not set, we still want to execute the
# token hash verification to protect against response discrepancy
# attacks (https://cwe.mitre.org/data/definitions/204.html)
token_hash: str = ""
if (
user is not None
# Disable activation tokens for service accounts as an extra
# security measure. Service accounts should only be used with API
# keys.
and not user.is_service_account
and user.activation_token is not None
and not user.active
):
token_hash = user.get_hashed_activation_token() or ""
pwd_context = cls._get_crypt_context()
return pwd_context.verify(activation_token, token_hash)
get_hashed_activation_token(self)
Returns the hashed activation token, if configured.
Returns:
Type | Description |
---|---|
Optional[str] |
The hashed activation token. |
Source code in zenml/models/v2/misc/user_auth.py
def get_hashed_activation_token(self) -> Optional[str]:
"""Returns the hashed activation token, if configured.
Returns:
The hashed activation token.
"""
return self._get_hashed_secret(self.activation_token)
get_hashed_password(self)
Returns the hashed password, if configured.
Returns:
Type | Description |
---|---|
Optional[str] |
The hashed password. |
Source code in zenml/models/v2/misc/user_auth.py
def get_hashed_password(self) -> Optional[str]:
"""Returns the hashed password, if configured.
Returns:
The hashed password.
"""
return self._get_hashed_secret(self.password)
get_password(self)
Get the password.
Returns:
Type | Description |
---|---|
Optional[str] |
The password as a plain string, if it exists. |
Source code in zenml/models/v2/misc/user_auth.py
def get_password(self) -> Optional[str]:
"""Get the password.
Returns:
The password as a plain string, if it exists.
"""
if self.password is None:
return None
return self.password.get_secret_value()
verify_activation_token(activation_token, user=None)
classmethod
Verifies a given activation token against the stored token.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
activation_token |
str |
Input activation token to be verified. |
required |
user |
Optional[UserAuthModel] |
User for which the activation token is to be verified. |
None |
Returns:
Type | Description |
---|---|
bool |
True if the token is valid. |
Source code in zenml/models/v2/misc/user_auth.py
@classmethod
def verify_activation_token(
cls, activation_token: str, user: Optional["UserAuthModel"] = None
) -> bool:
"""Verifies a given activation token against the stored token.
Args:
activation_token: Input activation token to be verified.
user: User for which the activation token is to be verified.
Returns:
True if the token is valid.
"""
# even when the user or token is not set, we still want to execute the
# token hash verification to protect against response discrepancy
# attacks (https://cwe.mitre.org/data/definitions/204.html)
token_hash: str = ""
if (
user is not None
# Disable activation tokens for service accounts as an extra
# security measure. Service accounts should only be used with API
# keys.
and not user.is_service_account
and user.activation_token is not None
and not user.active
):
token_hash = user.get_hashed_activation_token() or ""
pwd_context = cls._get_crypt_context()
return pwd_context.verify(activation_token, token_hash)
verify_password(plain_password, user=None)
classmethod
Verifies a given plain password against the stored password.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
plain_password |
str |
Input password to be verified. |
required |
user |
Optional[UserAuthModel] |
User for which the password is to be verified. |
None |
Returns:
Type | Description |
---|---|
bool |
True if the passwords match. |
Source code in zenml/models/v2/misc/user_auth.py
@classmethod
def verify_password(
cls, plain_password: str, user: Optional["UserAuthModel"] = None
) -> bool:
"""Verifies a given plain password against the stored password.
Args:
plain_password: Input password to be verified.
user: User for which the password is to be verified.
Returns:
True if the passwords match.
"""
# even when the user or password is not set, we still want to execute
# the password hash verification to protect against response discrepancy
# attacks (https://cwe.mitre.org/data/definitions/204.html)
password_hash: Optional[str] = None
if (
user is not None
# Disable password verification for service accounts as an extra
# security measure. Service accounts should only be used with API
# keys.
and not user.is_service_account
and user.password is not None
): # and user.active:
password_hash = user.get_hashed_password()
pwd_context = cls._get_crypt_context()
return pwd_context.verify(plain_password, password_hash)