Source code for pyobo.struct.reference

# -*- coding: utf-8 -*-

"""Data structures for OBO."""

from typing import Optional, Tuple

import bioregistry
import curies
from pydantic import Field, validator

from .utils import obo_escape
from ..identifier_utils import normalize_curie

__all__ = [
    "Reference",
    "Referenced",
]


[docs]class Reference(curies.Reference): """A namespace, identifier, and label.""" name: Optional[str] = Field(description="the name of the reference")
[docs] @validator("prefix") def validate_prefix(cls, v): # noqa """Validate the prefix for this reference.""" norm_prefix = bioregistry.normalize_prefix(v) if norm_prefix is None: raise ValueError(f"Unknown prefix: {v}") return norm_prefix
[docs] @classmethod def auto(cls, prefix: str, identifier: str) -> "Reference": """Create a reference and auto-populate its name.""" from ..api import get_name name = get_name(prefix, identifier) return cls(prefix=prefix, identifier=identifier, name=name)
@property def bioregistry_link(self) -> str: """Get the bioregistry link.""" return f"https://bioregistry.io/{self.curie}"
[docs] @classmethod def from_curie( cls, curie: str, name: Optional[str] = None, *, strict: bool = True, auto: bool = False, ) -> Optional["Reference"]: """Get a reference from a CURIE. :param curie: The compact URI (CURIE) to parse in the form of `<prefix>:<identifier>` :param name: The name associated with the CURIE :param strict: If true, raises an error if the CURIE can not be parsed. :param auto: Automatically look up name """ prefix, identifier = normalize_curie(curie, strict=strict) return cls._materialize(prefix=prefix, identifier=identifier, name=name, auto=auto)
[docs] @classmethod def from_iri( cls, iri: str, name: Optional[str] = None, *, auto: bool = False, ) -> Optional["Reference"]: """Get a reference from an IRI using the Bioregistry. :param iri: The IRI to parse :param name: The name associated with the CURIE :param auto: Automatically look up name """ prefix, identifier = bioregistry.parse_iri(iri) return cls._materialize(prefix=prefix, identifier=identifier, name=name, auto=auto)
@classmethod def _materialize( cls, prefix: Optional[str], identifier: Optional[str], name: Optional[str] = None, *, auto: bool = False, ) -> Optional["Reference"]: if prefix is None or identifier is None: return None if name is None and auto: return cls.auto(prefix=prefix, identifier=identifier) return cls(prefix=prefix, identifier=identifier, name=name) @property def _escaped_identifier(self): return obo_escape(self.identifier) def __str__(self): # noqa: D105 identifier_lower = self.identifier.lower() if identifier_lower.startswith(f"{self.prefix.lower()}:"): rv = identifier_lower else: rv = f"{self.prefix}:{self._escaped_identifier}" if self.name: rv = f"{rv} ! {self.name}" return rv def __hash__(self): # noqa: D105 return hash((self.__class__, self.prefix, self.identifier))
class Referenced: """A class that contains a reference.""" reference: Reference @property def prefix(self): """The prefix of the typedef.""" # noqa: D401 return self.reference.prefix @property def name(self): """The name of the typedef.""" # noqa: D401 return self.reference.name @property def identifier(self) -> str: """The local unique identifier for this typedef.""" # noqa: D401 return self.reference.identifier @property def curie(self) -> str: """The CURIE for this typedef.""" # noqa: D401 return self.reference.curie @property def pair(self) -> Tuple[str, str]: """The pair of namespace/identifier.""" # noqa: D401 return self.reference.pair @property def bioregistry_link(self) -> str: """Get the bioregistry link.""" return self.reference.bioregistry_link