1# =====================================================
2# Imports
3# =====================================================
4from typing import Annotated
5
6from pydantic import Field, field_validator, HttpUrl
7
8from mt_metadata.base import MetadataBase
9from mt_metadata.transfer_functions.io.emtfxml.metadata import helpers
10
11
12# =====================================================
13class ExternalUrl(MetadataBase):
14 description: Annotated[
15 str,
16 Field(
17 default="",
18 description="description of where the external URL points towards",
19 alias=None,
20 json_schema_extra={
21 "units": None,
22 "required": True,
23 "examples": ["IRIS DMC Metadata"],
24 },
25 ),
26 ]
27
28 url: Annotated[
29 HttpUrl | str,
30 Field(
31 default="",
32 description="full URL of where the data is stored",
33 alias=None,
34 json_schema_extra={
35 "units": None,
36 "required": True,
37 "examples": ["http://www.iris.edu/mda/EM/NVS11"],
38 },
39 ),
40 ]
41
42 @field_validator("url", mode="before")
43 @classmethod
44 def validate_url(cls, value: HttpUrl | str | None, info=None) -> HttpUrl | str:
45 # Normalize None to empty string
46 if value is None:
47 value = ""
48
49 # If setting to empty string after a non-empty value, disallow
50 try:
51 existing = None
52 if info is not None and hasattr(info, "data") and info.data is not None:
53 existing = info.data.get("url")
54 except Exception:
55 existing = None
56
57 if value == "":
58 if existing not in [None, ""]:
59 raise ValueError("Cannot assign empty URL after it has been set")
60 return ""
61
62 # If already a HttpUrl, return it
63 if isinstance(value, HttpUrl):
64 return value
65
66 # Validate string URL via HttpUrl
67 return HttpUrl(value)
68
69 def read_dict(self, input_dict: dict) -> None:
70 """
71
72 :param input_dict: input dictionary containing external URL data
73 :type input_dict: dict
74 :return: None
75 :rtype: None
76
77 """
78 helpers._read_element(self, input_dict, "external_url")