Source code for tdw_catalog.metadata.field
from datetime import date, datetime
import json
from typing import Generic, List, Optional, TypeVar
import uuid
from tdw_catalog.errors import CatalogFailedPreconditionException, CatalogPermissionDeniedException
import tdw_catalog.metadata_template.contract_owner as template_contract_owner
import tdw_catalog.metadata_template.currency as template_currency
import tdw_catalog.metadata_template.data_cost as template_data_cost
import tdw_catalog.metadata_template.date_field as template_date
import tdw_catalog.metadata_template.decimal as template_decimal
import tdw_catalog.metadata_template.license_expiry as template_license_expiry
import tdw_catalog.metadata_template.link as template_link
import tdw_catalog.metadata_template.field as field
import tdw_catalog.metadata_template.number as template_number
import tdw_catalog.metadata_template.organization_member as template_organization_member
import tdw_catalog.metadata_template.organization_team as template_organization_team
import tdw_catalog.metadata_template.point_in_time as template_point_in_time
import tdw_catalog.metadata_template.point_of_contact as template_point_of_contact
import tdw_catalog.metadata_template.text as template_text
import tdw_catalog.metadata_template.alias as template_alias
import tdw_catalog.metadata_template.list_field as template_list
from tdw_catalog.utils import MetadataFieldType
T = TypeVar('T')
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import tdw_catalog.dataset as dataset
[docs]class MetadataField(Generic[T]):
"""
The base type for all custom metadata fields which can be added to a :class:`.Dataset`
Attributes
----------
key : str
A key for this field, which must be unique among all metadata fields in a :class:`.Dataset`
value : Optional[T]
An optional value for :class:`.MetadataField`\\ s produced from this :class:`.MetadataField`.
"""
_key: str
_value: Optional[T]
def __init__(
self,
key: str,
value: Optional[T],
) -> None:
self._key = key
self._value = value
@property
def key(self):
return self._key
@key.setter
def key(self, key: str):
self._key = key
@property
def value(self):
return self._value
@value.setter
def value(self, value: Optional[T]):
self._value = value
@property
def is_recommended(self) -> bool:
return False
def serialize(self) -> dict:
res = {
"key": self._key,
}
return res
def __getitem__(self, item):
return getattr(self, item)
@classmethod
def deserialize(cls, data: dict, dataset: 'dataset.Dataset') -> None:
# if field_type is missing, assume string
if "field_type" not in data:
data["field_type"] = MetadataFieldType.FT_STRING
if "value" not in data:
data["value"] = ""
# if field_type comes back as a string, convert to int enum
if isinstance(data["field_type"], str):
data["field_type"] = MetadataFieldType[data["field_type"]]
if "recommended_type" in data and data["recommended_type"] == "cost":
currencyDict = json.loads(
data["value"]) if "value" in data else {}
import tdw_catalog.metadata.data_cost as data_cost
return data_cost.Field(
key=data["key"],
currency=currencyDict["currency"] if "currency" in currencyDict else "",
amount=currencyDict["value"] if "value" in currencyDict else 0,
)
elif "recommended_type" in data and data["recommended_type"] == "poc":
import tdw_catalog.metadata.point_of_contact as point_of_contact
try:
return point_of_contact.Field(
key=data["key"],
value=dataset.organization.get_member(
user_id=data["value"]),
)
except:
return point_of_contact.Field(
key=data["key"],
value=None,
)
elif "recommended_type" in data and data[
"recommended_type"] == "expiryDate":
import tdw_catalog.metadata.license_expiry as license_expiry
return license_expiry.Field(
key=data["key"],
value=datetime.strptime(data["value"][0:10], "%Y-%m-%d").date() if "value" in data and len(data["value"]) == 10 else None,
)
elif "recommended_type" in data and data[
"recommended_type"] == "contractOwner":
import tdw_catalog.metadata.contract_owner as contract_owner
try:
return contract_owner.Field(
key=data["key"],
value=dataset.organization.get_team(team_id=data["value"]),
)
except:
return contract_owner.Field(
key=data["key"],
value=None,
)
# determine field type and instantiate appropriate class
elif data["field_type"] == MetadataFieldType.FT_STRING:
import tdw_catalog.metadata.text as text
return text.Field(
key=data["key"],
value=data["value"],
)
elif data["field_type"] == MetadataFieldType.FT_INTEGER:
import tdw_catalog.metadata.number as number
return number.Field(
key=data["key"],
value=int(data["value"]),
)
elif data["field_type"] == MetadataFieldType.FT_DECIMAL:
import tdw_catalog.metadata.decimal as decimal
return decimal.Field(
key=data["key"],
value=float(data["value"]),
)
elif data["field_type"] == MetadataFieldType.FT_DATE:
import tdw_catalog.metadata.date_field as date_field
try:
d = datetime.strptime(data["value"][0:10], "%Y-%m-%d").date()
return date_field.Field(
key=data["key"],
value=d,
)
except ValueError:
return date_field.Field(
key=data["key"],
value=None,
)
elif data["field_type"] == MetadataFieldType.FT_DATETIME:
import tdw_catalog.metadata.point_in_time as point_in_time
try:
dt = datetime.fromisoformat(data["value"])
return point_in_time.Field(
key=data["key"],
value=dt,
)
except ValueError:
return point_in_time.Field(
key=data["key"],
value=None,
)
elif data["field_type"] == MetadataFieldType.FT_DATASET:
import tdw_catalog.metadata.linked_dataset as linked_dataset
try:
return linked_dataset.Field(
key=data["key"],
value=dataset.organization.get_dataset(id=data["value"]),
)
except:
return linked_dataset.Field(
key=data["key"],
value=None,
)
elif data["field_type"] == MetadataFieldType.FT_URL:
import tdw_catalog.metadata.link as link
return link.Field(
key=data["key"],
value=data["value"],
)
elif data["field_type"] == MetadataFieldType.FT_USER:
import tdw_catalog.metadata.organization_member as organization_member
try:
return organization_member.Field(
key=data["key"],
value=dataset.organization.get_member(
user_id=data["value"]),
)
except:
return organization_member.Field(
key=data["key"],
value=None,
)
elif data["field_type"] == MetadataFieldType.FT_ATTACHMENT:
import tdw_catalog.metadata.attachment as attachment
return attachment.Field(key=data["key"], value=data["value"])
elif data["field_type"] == MetadataFieldType.FT_LIST:
import tdw_catalog.metadata.list_field as list_field
return list_field.Field(
key=data["key"],
value=data["value"],
list_items=data["listValueList"]
if "listValueList" in data else None,
)
elif data["field_type"] == MetadataFieldType.FT_CURRENCY:
currencyDict = json.loads(data["value"])
import tdw_catalog.metadata.currency as currency
return currency.Field(
key=data["key"],
currency=currencyDict["currency"],
amount=currencyDict["value"],
)
elif data["field_type"] == MetadataFieldType.FT_TEAM:
import tdw_catalog.metadata.organization_team as organization_team
try:
return organization_team.Field(
key=data["key"],
value=dataset.organization.get_team(team_id=data["value"]),
)
except:
return organization_team.Field(
key=data["key"],
value=None,
)
elif data["field_type"] == MetadataFieldType.FT_ALIAS:
import tdw_catalog.metadata.alias as alias
return alias.Field(
key=data["key"],
value=data["value"],
)
[docs]class TemplatedMetadataField(Generic[T]):
"""
A wrapper class for :class:`.MetadataField`\\ s that come from an attached :class:`.MetadataTemplate`. :class:`.TemplatedMetadataField`\\ s `key`\\ s can not be changed on a :class:`.Dataset`.
"""
_field: MetadataField[T]
def __init__(self, field: MetadataField[T]):
self._field = field
@property
def key(self):
return self._field._key
@key.setter
def key(self, key: str):
raise CatalogPermissionDeniedException(
message=
"Keys of fields on a MetadataTemplate can only be changed on the MetadataTemplate directly"
)
@property
def value(self):
return self._field._value
@value.setter
def value(self, value: Optional[T]):
self._field._value = value
[docs]class RecommendedMetadataField(MetadataField[T]):
"""
A subclass of :class:`.MetadataField` representing one of `license expiry`\\ , `point of contact`\\ , `data cost`\\ , or `contract owner`. The `key` of a :class:`.RecommendedMetadataField` cannot be changed
"""
def __init__(self, key: str, value: T):
super().__init__(key, value)
@property
def key(self):
return super().key
@key.setter
def key(self, key: str):
raise CatalogPermissionDeniedException(
message="Keys of recommended metadata fields may not be changed")
@property
def is_recommended() -> bool:
return True
def _deserialize_metadata_fields(
data: List[dict],
dataset: 'dataset.Dataset') -> Optional[List[MetadataField]]:
if data is None:
return None
return list(map(lambda d: MetadataField.deserialize(d, dataset), data))
def _convert_template_field(
field: field.MetadataTemplateField[T]) -> MetadataField[T]:
if isinstance(field, template_contract_owner.Field):
import tdw_catalog.metadata.contract_owner as contract_owner
return contract_owner.Field(key=field.key, value=field.default_value)
if isinstance(field, template_point_of_contact.Field):
import tdw_catalog.metadata.point_of_contact as point_of_contact
return point_of_contact.Field(key=field.key, value=field.default_value)
if isinstance(field, template_license_expiry.Field):
import tdw_catalog.metadata.license_expiry as license_expiry
return license_expiry.Field(key=field.key, value=field.default_value)
if isinstance(field, template_data_cost.Field):
currencyDict = field["default_value"] if field[
"default_value"] is not None else None
import tdw_catalog.metadata.currency as currency
import tdw_catalog.metadata.data_cost as data_cost
currency = currencyDict.currency if currencyDict is not None else ""
amount = currencyDict.value if currencyDict is not None else 0
return data_cost.Field(key=field.key, currency=currency, amount=amount)
if isinstance(field, template_text.Field):
import tdw_catalog.metadata.text as text
return text.Field(key=field.key, value=field.default_value)
if isinstance(field, template_number.Field):
import tdw_catalog.metadata.number as number
return number.Field(key=field.key, value=field.default_value)
if isinstance(field, template_decimal.Field):
import tdw_catalog.metadata.decimal as decimal
return decimal.Field(key=field.key, value=field.default_value)
if isinstance(field, template_link.Field):
import tdw_catalog.metadata.link as link
return link.Field(key=field.key, value=field.default_value)
import tdw_catalog.metadata_template.linked_dataset as template_linked_dataset
if isinstance(field, template_linked_dataset.Field):
import tdw_catalog.metadata.linked_dataset as linked_dataset
return linked_dataset.Field(key=field.key, value=field.default_value)
if isinstance(field, template_date.Field):
import tdw_catalog.metadata.date_field as date_field
return date_field.Field(key=field.key, value=field.default_value)
if isinstance(field, template_point_in_time.Field):
import tdw_catalog.metadata.point_in_time as point_in_time
return point_in_time.Field(key=field.key, value=field.default_value)
if isinstance(field, template_organization_member.Field):
import tdw_catalog.metadata.organization_member as organization_member
return organization_member.Field(key=field.key,
value=field.default_value)
if isinstance(field, template_organization_team.Field):
import tdw_catalog.metadata.organization_team as organization_team
return organization_team.Field(key=field.key,
value=field.default_value)
if isinstance(field, template_alias.Field):
import tdw_catalog.metadata.alias as alias
return alias.Field(key=field.key, value=field.default_value)
if isinstance(field, template_list.Field):
import tdw_catalog.metadata.list_field as list_field
return list_field.Field(key=field.key,
value=field.default_value,
list_items=field.list_items)
def _check_field_match(field: MetadataField,
templated_field: 'field.MetadataTemplateField') -> bool:
if isinstance(templated_field, template_contract_owner.Field):
import tdw_catalog.metadata.contract_owner as contract_owner
return isinstance(field, contract_owner.Field)
if isinstance(field, template_point_of_contact.Field):
import tdw_catalog.metadata.point_of_contact as point_of_contact
return isinstance(field, point_of_contact.Field)
if isinstance(field, template_license_expiry.Field):
import tdw_catalog.metadata.license_expiry as license_expiry
return isinstance(field, license_expiry.Field)
if isinstance(field, template_data_cost.Field):
import tdw_catalog.metadata.data_cost as data_cost
return isinstance(field, data_cost.Field)
if isinstance(field, template_text.Field):
import tdw_catalog.metadata.text as text
return isinstance(field, text.Field)
if isinstance(field, template_number.Field):
import tdw_catalog.metadata.number as number
return isinstance(field, number.Field)
if isinstance(field, template_decimal.Field):
import tdw_catalog.metadata.decimal as decimal
return isinstance(field, decimal.Field)
if isinstance(field, template_link.Field):
import tdw_catalog.metadata.link as link
return isinstance(field, link.Field)
import tdw_catalog.metadata_template.linked_dataset as template_linked_dataset
if isinstance(field, template_linked_dataset.Field):
import tdw_catalog.metadata.linked_dataset as linked_dataset
return isinstance(field, linked_dataset.Field)
if isinstance(field, template_date.Field):
import tdw_catalog.metadata.date_field as date_field
return isinstance(field, date_field.Field)
if isinstance(field, template_point_in_time.Field):
import tdw_catalog.metadata.point_in_time as point_in_time
return isinstance(field, point_in_time.Field)
if isinstance(field, template_organization_member.Field):
import tdw_catalog.metadata.organization_member as organization_member
return isinstance(field, organization_member.Field)
if isinstance(field, template_organization_team.Field):
import tdw_catalog.metadata.organization_team as organization_team
return isinstance(field, organization_team.Field)
if isinstance(field, template_currency.Field):
import tdw_catalog.metadata.currency as currency
return isinstance(field, currency.Field)
if isinstance(field, template_alias.Field):
import tdw_catalog.metadata.alias as alias
return isinstance(field, alias.Field)
if isinstance(field, template_list.Field):
import tdw_catalog.metadata.list_field as list_field
return isinstance(field, list_field.Field)