Source code for kif_lib.model.value.value

# Copyright (C) 2024 IBM Corp.
# SPDX-License-Identifier: Apache-2.0

from __future__ import annotations

import datetime
import decimal
from typing import TYPE_CHECKING

from ... import namespace as NS
from ...rdflib import Literal, URIRef
from ...typing import (
    Any,
    cast,
    ClassVar,
    Collection,
    Location,
    override,
    Self,
    TypeAlias,
    Union,
)
from ..term import ClosedTerm, Template, Variable
from .datatype import Datatype

if TYPE_CHECKING:  # pragma: no cover
    from ..fingerprint import AndFingerprint, OrFingerprint, TFingerprint
    from .quantity import TDecimal  # noqa: F401
    from .time import TDatetime  # noqa: F401

TValue: TypeAlias = Union['Value', 'TDatetime', 'TDecimal', str]
VTValue: TypeAlias = Union[Variable, 'VValue', TValue]
VValue: TypeAlias = Union['ValueTemplate', 'ValueVariable', 'Value']


[docs] class ValueTemplate(Template): """Abstract base class for value templates.""" object_class: ClassVar[type[Value]] # pyright: ignore
[docs] class ValueVariable(Variable): """Value variable. Parameters: name: Name. """ object_class: ClassVar[type[Value]] # pyright: ignore
[docs] class Value( ClosedTerm, template_class=ValueTemplate, variable_class=ValueVariable ): """Abstract base class for values.""" template_class: ClassVar[type[ValueTemplate]] # pyright: ignore variable_class: ClassVar[type[ValueVariable]] # pyright: ignore #: Datatype class associated with this value class. datatype_class: ClassVar[type[Datatype]] #: Datatype associated with this value class. datatype: ClassVar[Datatype] @classmethod def __init_subclass__(cls, **kwargs: Any) -> None: super().__init_subclass__(**kwargs) if 'datatype_class' in kwargs: cls.datatype_class = kwargs['datatype_class'] assert issubclass(cls.datatype_class, Datatype) cls.datatype = cls.datatype_class() cls.datatype_class.value_class = cls
[docs] @classmethod @override def check( cls, arg: Any, function: Location | None = None, name: str | None = None, position: int | None = None ) -> Self: if isinstance(arg, cls): return arg if isinstance(arg, str): from .string import String arg = String.check(arg, function, name, position) elif isinstance(arg, datetime.datetime): from .time import Time arg = Time.check(arg, function, name, position) elif isinstance(arg, (decimal.Decimal, float, int)): from .quantity import Quantity arg = Quantity.check(arg, function, name, position) return super().check(arg, function, name, position)
def __and__(self, other: TFingerprint) -> AndFingerprint: from ..fingerprint import AndFingerprint return AndFingerprint(self, other) def __rand__(self, other: TFingerprint) -> AndFingerprint: from ..fingerprint import AndFingerprint return AndFingerprint(other, self) def __or__(self, other: TFingerprint) -> OrFingerprint: from ..fingerprint import OrFingerprint return OrFingerprint(self, other) def __ror__(self, other: TFingerprint) -> OrFingerprint: from ..fingerprint import OrFingerprint return OrFingerprint(self, other)
[docs] def n3(self) -> str: """Gets the simple value of value in N3 format. Returns: Simple value in N3 format. """ return self._to_rdflib().n3()
@classmethod def _from_rdflib( cls, node: Literal | URIRef | str, item_prefixes: Collection[NS.T_NS] | None = None, property_prefixes: Collection[NS.T_NS] | None = None, lexeme_prefixes: Collection[NS.T_NS] | None = None ) -> Self: from ...rdflib import _NUMERIC_LITERAL_TYPES from .external_id import ExternalId from .iri import IRI from .item import Item from .lexeme import Lexeme from .property import Property from .quantity import Quantity from .string import String from .text import Text from .time import Time assert isinstance(node, (Literal, URIRef)) res: Value if isinstance(node, URIRef): if not item_prefixes: item_prefixes = NS.Wikidata.default_item_prefixes if not property_prefixes: property_prefixes = NS.Wikidata.default_property_prefixes if not lexeme_prefixes: lexeme_prefixes = NS.Wikidata.default_lexeme_prefixes uri = cast(URIRef, node) if NS.Wikidata.is_wd_item(uri, item_prefixes): if item_prefixes == NS.Wikidata.default_item_prefixes: res = Item(uri) else: res = Item(NS.WD[NS.Wikidata.get_wikidata_name(uri)]) elif NS.Wikidata.is_wd_property(uri, property_prefixes): if property_prefixes == NS.Wikidata.default_property_prefixes: res = Property(uri) else: res = Property(NS.WD[NS.Wikidata.get_wikidata_name(uri)]) elif NS.Wikidata.is_wd_lexeme(uri, lexeme_prefixes): if lexeme_prefixes == NS.Wikidata.default_lexeme_prefixes: res = Lexeme(uri) else: res = Lexeme(NS.WD[NS.Wikidata.get_wikidata_name(uri)]) else: res = IRI(uri) elif isinstance(node, Literal): literal = cast(Literal, node) if literal.datatype in _NUMERIC_LITERAL_TYPES: res = Quantity(str(literal)) elif (literal.datatype == NS.XSD.dateTime or literal.datatype == NS.XSD.date): res = Time(str(literal)) elif literal.datatype is None and literal.language: res = Text(literal, literal.language) else: if issubclass(cls, ExternalId): res = ExternalId(literal) else: res = String(literal) else: raise cls._should_not_get_here() return cls.check(res, cls._from_rdflib, 'node', 1) def _to_rdflib(self) -> Literal | URIRef: from .entity import Entity from .iri import IRI from .quantity import Quantity from .string import String from .text import Text from .time import Time if isinstance(self, Entity): return URIRef(self.iri.content) elif isinstance(self, IRI): return URIRef(self.content) elif isinstance(self, Quantity): return Literal(str(self.amount), datatype=NS.XSD.decimal) elif isinstance(self, Time): return Literal(self.time.isoformat(), datatype=NS.XSD.dateTime) elif isinstance(self, Text): return Literal(self.content, self.language) elif isinstance(self, String): return Literal(self.content) else: raise self._should_not_get_here()