Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 16 additions & 27 deletions src/pyobo/struct/functional/dsl.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@
from collections.abc import Iterable, Sequence
from typing import ClassVar, TypeAlias

import curies
import rdflib.namespace
from curies import Converter, Reference
from bioregistry import NormalizedReference, StandardReference
from curies import Converter
from rdflib import OWL, RDF, RDFS, XSD, Graph, collection, term

from pyobo.struct.functional.utils import list_to_funowl
from pyobo.struct.reference import OBOLiteral, Referenced, get_preferred_prefix
from pyobo.struct.reference import Reference as PyOBOReference

from .utils import FunctionalOWLSerializable, RDFNodeSerializable
from .utils import FunctionalOWLSerializable, RDFNodeSerializable, list_to_funowl

__all__ = [
"Annotation",
Expand Down Expand Up @@ -104,44 +102,37 @@

#: A partial hint for something that can be turned into an :class:`IdentifierBox`.
#: Here, a string gets interpreted into a CURIE using :meth:`curies.Reference.from_curie`
IdentifierHint = term.URIRef | Reference | Referenced | str
IdentifierHint = term.URIRef | curies.Reference | str


class Box(FunctionalOWLSerializable, RDFNodeSerializable):
"""A model for objects that can be represented as nodes in RDF and Functional OWL."""


def obo_literal_to_rdflib(obo_literal: OBOLiteral, converter: Converter) -> rdflib.Literal:
"""Expand the OBO literal."""
iri = converter.expand(obo_literal.datatype.curie, strict=True)
return rdflib.Literal(obo_literal.value, datatype=rdflib.URIRef(iri))
def _upgrade_ref(reference: NormalizedReference | curies.Reference) -> curies.Reference:
if isinstance(reference, NormalizedReference):
# this upgrades from using Bioregistry normalized prefixes into preferred prefixes
return StandardReference.from_reference(reference)
return reference


class IdentifierBox(Box):
"""A simple wrapper around CURIEs and IRIs."""

identifier: term.URIRef | Reference
identifier: term.URIRef | curies.Reference

def __init__(self, identifier: IdentifierBoxOrHint) -> None:
"""Initialize the identifier box with a URIRef, Reference, or string representing a CURIE."""
if isinstance(identifier, Referenced):
identifier = identifier.reference
if isinstance(identifier, IdentifierBox):
self.identifier = identifier.identifier
# make sure to check for URIRef first,
# since it's also a subclass of str
elif isinstance(identifier, term.URIRef):
self.identifier = identifier
elif isinstance(identifier, str):
self.identifier = Reference.from_curie(identifier)
elif isinstance(identifier, PyOBOReference):
# it doesn't matter we're potentially throwing away the name,
# since this annotation gets put in OFN in a different place
self.identifier = Reference(
prefix=get_preferred_prefix(identifier), identifier=identifier.identifier
)
elif isinstance(identifier, Reference):
self.identifier = identifier
self.identifier = curies.Reference.from_curie(identifier)
elif isinstance(identifier, curies.Reference):
self.identifier = _upgrade_ref(identifier)
else:
raise TypeError(f"can not make an identifier box from: {identifier}")

Expand Down Expand Up @@ -193,8 +184,6 @@ def __init__(self, literal: LiteralBoxOrHint, language: str | None = None) -> No
self.literal = term.Literal(literal, datatype=XSD.date)
elif isinstance(literal, datetime.datetime):
self.literal = term.Literal(literal, datatype=XSD.dateTime)
elif isinstance(literal, OBOLiteral):
self.literal = obo_literal_to_rdflib(literal, self._converter)
else:
raise TypeError(f"Unhandled type for literal: {literal}")

Expand All @@ -221,7 +210,7 @@ def to_funowl_args(self) -> str: # pragma: no cover


IdentifierBoxOrHint: TypeAlias = IdentifierHint | IdentifierBox
LiteralBoxOrHint: TypeAlias = LiteralBox | term.Literal | SupportedLiterals | OBOLiteral
LiteralBoxOrHint: TypeAlias = LiteralBox | term.Literal | SupportedLiterals
PrimitiveHint: TypeAlias = IdentifierBoxOrHint | LiteralBoxOrHint
PrimitiveBox: TypeAlias = LiteralBox | IdentifierBox

Expand All @@ -239,7 +228,7 @@ def _safe_primitive_box(value: PrimitiveHint) -> PrimitiveBox:
# through, wrap it with rdflib.Literal
if isinstance(value, str):
return IdentifierBox(value)
if isinstance(value, SupportedLiterals | OBOLiteral):
if isinstance(value, SupportedLiterals):
return LiteralBox(value)
# everything else (e.g., URIRef, Reference) are for identifier boxes
return IdentifierBox(value)
Expand Down
Loading
Loading