"""VOResource Simple Types"""importrefromdatetimeimportdatetimefromenumimportEnumfromtypingimportTYPE_CHECKING,AnnotatedfrompydanticimportField,GetCoreSchemaHandlerfrompydantic_coreimportCoreSchema,core_schema# pylint: disable=too-few-public-methodsifTYPE_CHECKING:UTCTimestamp=Annotated[datetime,...]else:classUTCTimestamp(datetime):"""A subclass of datetime to allow expanded handling of ISO formatted datetimes, and enforce the use of a Z identifier for UTC timezone in outputs """# This is the strict regex definition for VO datetimes from:# https://www.ivoa.net/documents/VOResource/20180625/REC-VOResource-1.1.html#tth_sEc2.2.4# vodt_regex = r"\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?Z?"# Expanded regex to accept Zulu but also +00:00 offset UTC timesexp_utc_regex=r"(\d{4}-\d\d-\d\d(T|\s)\d\d:\d\d:\d\d(\.\d+)?)(Z|\+\d\d:\d\d)?"# Will match:# 2023-03-15T18:27:18.758 (UTC assumed - T separator)# 2023-03-15 18:27:18.758 (UTC assumed - space separator)# 2023-03-15T18:27:18.758Z (Zulu UTC - T separator)# 2023-03-15 18:27:18.758Z (Zulu UTC - space separator)# 2023-03-15T18:27:18.758+00:00 (UTC w/ offset - T separator)# 2023-03-15 18:27:18.758+00:00 (UTC w/ offset - space separator)# TODO: Python 3.11 datetime.fromisoformat() does accept a 'Z' indicated UTC time. Revisit this when upgrading.utc_regex_match=re.compile(exp_utc_regex)def__str__(self)->str:returnself.isoformat(sep="T",timespec="milliseconds")def_serialize(self)->str:returnself.isoformat(sep="T",timespec="milliseconds")# pylint: disable=unused-argument@classmethoddef__get_pydantic_core_schema__(cls,source_type,handler:GetCoreSchemaHandler)->CoreSchema:returncore_schema.no_info_after_validator_function(cls._validate,core_schema.datetime_schema(),serialization=core_schema.plain_serializer_function_ser_schema(cls._serialize,info_arg=False,return_schema=core_schema.str_schema(),),)@classmethoddef_validate(cls,value:str):"""Validator that expands the pydantic datetime model to include Z UTC identifiers Args: value: datetime string. Comes from either a user's POST (destruction) or from the cache Returns: UTCTimestamp: VO-compliant datetime subclass """ifisinstance(value,UTCTimestamp):returnvalueifisinstance(value,datetime):returncls._validate(value.isoformat())ifnotisinstance(value,str):raiseTypeError("String datetime required")value=value.upper()valid_utc=cls.utc_regex_match.fullmatch(value)ifnotvalid_utc:# If there was no full match, reject itraiseValueError("Invalid VOResource ISO-8601 date format")# Grab only the date/time match and manually add a UTC offset for an aware python datetime objectvalue=valid_utc.group(1)+"+00:00"returnsuper().fromisoformat(value)@classmethoddeffromisoformat(cls,date_string):returncls._validate(date_string)defisoformat(self,sep:str="T",timespec:str="milliseconds")->str:"""Overwrites the datetime isoformat output to use a Z UTC indicator Parameters: sep: Separator between date and time (default: 'T') timespec: Resolution of time to include (default: 'milliseconds') Returns: str: VO-compliant ISO-8601 datetime string """iso_dt=super().isoformat(sep=sep,timespec=timespec)returniso_dt.replace("+00:00","Z")
[docs]classUTCDateTime(str):"""A date stamp that can be given to a precision of either a day (type xs:date) or seconds (type xs:dateTime). Where only a date is given, it is to be interpreted as the span of the day on the UTC timezone if such distinctions are relevant."""
[docs]classValidationLevel(Enum):""" The allowed values for describing the resource descriptions and interfaces. """VALUE_0=0""" The resource has a description that is stored in a registry. This level does not imply a compliant description. """VALUE_1=1""" In addition to meeting the level 0 definition, the resource description conforms syntactically to this standard and to the encoding scheme used. """VALUE_2=2""" In addition to meeting the level 1 definition, the resource description refers to an existing resource that has demonstrated to be functionally compliant. """VALUE_3=3""" In addition to meeting the level 2 definition, the resource description has been inspected by a human and judged to comply semantically to this standard as well as meeting any additional minimum quality criteria (e.g., providing values for important but non-required metadata) set by the human inspector. """VALUE_4=4""" In addition to meeting the level 3 definition, the resource description meets additional quality criteria set by the human inspector and is therefore considered an excellent description of the resource. Consequently, the resource is expected to operate well as part of a VO application or research study. """
AuthorityID=Annotated[str,Field(pattern=r"[\w\d][\w\d\-_\.!~\*'\(\)\+=]{2,}",description="The authority identifier for the resource.")]ResourceKey=Annotated[str,Field(pattern=r"[\w\d\-_\.!~\*'\(\)\+=]+(/[\w\d\-_\.!~\*'\(\)\+=]+)*",description="The resource key for the resource.",),]IdentifierURI=Annotated[str,Field(pattern=r"ivo://[\w\d][\w\d\-_\.!~\*'\(\)\+=]{2,}(/[\w\d\-_\.!~\*'\(\)\+=]+(/[\w\d\-_\.!~\*'\(\)\+=]+)*)?",description="A reference to a registry record.",),]