"""Annotatitons resources."""
import logging
from typing import TYPE_CHECKING, Optional, Union
from .base import BaseResource
from .sample import Sample
if TYPE_CHECKING:
from resdk.resolwe import Resolwe
[docs]class AnnotationGroup(BaseResource):
"""Resolwe AnnotationGroup resource."""
# There is currently no endpoint for AnnotationGroup object, but it might be
# created in the future. The objects are created when AnnotationField is
# initialized.
endpoint = "annotation_group"
READ_ONLY_FIELDS = BaseResource.READ_ONLY_FIELDS + ("name", "sort_order", "label")
def __init__(self, resolwe: "Resolwe", **model_data):
"""Initialize the instance.
:param resolwe: Resolwe instance
:param model_data: Resource model data
"""
self.logger = logging.getLogger(__name__)
super().__init__(resolwe, **model_data)
def __repr__(self):
"""Return user friendly string representation."""
return f"AnnotationGroup <name: {self.name}>"
[docs]class AnnotationField(BaseResource):
"""Resolwe AnnotationField resource."""
endpoint = "annotation_field"
READ_ONLY_FIELDS = BaseResource.READ_ONLY_FIELDS + (
"description",
"group",
"label",
"name",
"sort_order",
"type",
"validator_regex",
"vocabulary",
"required",
)
def __init__(self, resolwe: "Resolwe", **model_data):
"""Initialize the instance.
:param resolwe: Resolwe instance
:param model_data: Resource model data
"""
self.logger = logging.getLogger(__name__)
#: annotation group
self._group = None
super().__init__(resolwe, **model_data)
@property
def group(self) -> AnnotationGroup:
"""Get annotation group."""
assert (
self._group is not None
), "AnnotationGroup must be set before it can be used."
return self._group
@group.setter
def group(self, payload: dict):
"""Set annotation group."""
if self._group is None:
self._resource_setter(payload, AnnotationGroup, "_group")
else:
raise AttributeError("AnnotationGroup is read-only.")
def __repr__(self):
"""Return user friendly string representation."""
return f"AnnotationField <path: {self.group.name}.{self.name}>"
def __str__(self):
"""Return full path of the annotation field."""
return f"{self.group.name}.{self.name}"
[docs]class AnnotationValue(BaseResource):
"""Resolwe AnnotationValue resource."""
endpoint = "annotation_value"
READ_ONLY_FIELDS = BaseResource.READ_ONLY_FIELDS + ("label", "modified")
UPDATE_PROTECTED_FIELDS = BaseResource.UPDATE_PROTECTED_FIELDS + ("field", "sample")
WRITABLE_FIELDS = BaseResource.WRITABLE_FIELDS + ("value",)
def __init__(self, resolwe: "Resolwe", **model_data):
"""Initialize the instance.
:param resolwe: Resolwe instance
:param model_data: Resource model data
"""
self.logger = logging.getLogger(__name__)
#: annotation field
self._field: Optional[AnnotationField] = None
self.field_id: Optional[int] = None
#: sample
self.sample_id: Optional[int] = None
self._sample: Optional[Sample] = None
super().__init__(resolwe, **model_data)
@property
def sample(self):
"""Get sample."""
if self._sample is None:
if self.sample_id is None:
self.sample_id = self._original_values["entity"]
self._sample = Sample(resolwe=self.resolwe, id=self.sample_id)
# Without this save will fail due to change in read-only field.
self._original_values["sample"] = {"id": self.sample_id}
return self._sample
@sample.setter
def sample(self, payload):
"""Set the sample."""
# Update fields sets sample to None.
if payload is None:
return
if self.sample_id is not None:
raise AttributeError("Sample is read-only.")
if isinstance(payload, Sample):
self.sample_id = payload.id
elif isinstance(payload, dict):
self.sample_id = payload["id"]
else:
self.sample_id = payload
@property
def field(self) -> AnnotationField:
"""Get annotation field."""
if self._field is None:
assert (
self.field_id is not None
), "AnnotationField must be set before it can be used."
self._field = self.resolwe.annotation_field.get(id=self.field_id)
# The field is read-only but we have to modify original values here so save
# can detect there were no changes.
self._original_values["field"] = self._field._original_values
return self._field
@field.setter
def field(self, payload: Union[int, AnnotationField, dict]):
"""Set annotation field."""
field_id = None
if isinstance(payload, int):
field_id = payload
elif isinstance(payload, dict):
field_id = payload["id"]
elif isinstance(payload, AnnotationField):
field_id = payload.id
if field_id != self.field_id:
self._field = None
self.field_id = field_id
def __repr__(self):
"""Format resource name."""
return f"AnnotationValue <path: {self.field.group.name}.{self.field.name}, value: '{self.value}'>"