1# =====================================================
2# Imports
3# =====================================================
4from typing import Annotated
5from xml.etree import cElementTree as et
6
7from loguru import logger
8from pydantic import Field, field_validator, ValidationInfo
9
10from mt_metadata.base import MetadataBase
11from mt_metadata.transfer_functions.io.emtfxml.metadata import helpers
12
13from . import DataType
14
15
16# =====================================================
17class DataTypes(MetadataBase):
18 data_types_list: Annotated[
19 list[DataType | dict],
20 Field(
21 default_factory=list,
22 description="list of data types",
23 alias=None,
24 json_schema_extra={
25 "units": None,
26 "required": True,
27 "examples": ["[Z T]"],
28 },
29 ),
30 ]
31
32 @field_validator("data_types_list", mode="before")
33 @classmethod
34 def validate_data_types_list(
35 cls, value: list[DataType | dict], info: ValidationInfo
36 ) -> list[DataType]:
37 if not isinstance(value, list):
38 value = [value]
39 dt_list = []
40 for item in value:
41 if isinstance(item, dict):
42 dt = DataType() # type: ignore
43 dt.from_dict(item)
44 dt_list.append(dt)
45 elif isinstance(item, DataType):
46 dt_list.append(item)
47 else:
48 raise TypeError(
49 f"data_types_list must be a list of DataType instances or dictionaries, got {type(item)}"
50 )
51 return dt_list
52
53 def read_dict(self, input_dict: dict) -> None:
54 """
55 Read in statistical estimate descriptions
56
57 :param input_dict: input dictionary containing data types
58 :type input_dict: dict
59 :return: None
60 :rtype: None
61
62 """
63 try:
64 self.data_types_list = input_dict["data_types"]["data_type"]
65 except KeyError:
66 logger.warning("Could not read Data Types")
67
68 def to_xml(self, string: bool = False, required: bool = True) -> str | et.Element:
69 """
70
71 :param string: return XML string, defaults to False
72 :type string: bool, optional
73 :param required: include required fields, defaults to True
74 :type required: bool, optional
75 :return: XML representation of the object
76 :rtype: str | et.Element
77 :raises TypeError: if data_types_list is not a list of DataType instances or dictionaries
78 :raises ValueError: if data_types_list is empty
79
80 """
81
82 root = et.Element(self.__class__.__name__)
83
84 for dtype in self.data_types_list:
85 root.append(dtype.to_xml(required=required)) # type: ignore return-value
86
87 if string:
88 return helpers.element_to_string(root)
89 return root