Source code for kif_lib.model.value.property

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

from __future__ import annotations

from typing import TYPE_CHECKING

from typing_extensions import overload

from ...typing import Any, ClassVar, Iterable, override, TypeAlias, Union
from ..term import OpenTerm, Variable
from .datatype import Datatype, DatatypeVariable, VDatatype, VTDatatype
from .entity import Entity, EntityTemplate, EntityVariable, VTEntity
from .iri import IRI_Template, T_IRI, VT_IRI
from .value import VTValue

if TYPE_CHECKING:               # pragma: no cover
    from ..snak import (
        NoValueSnak,
        NoValueSnakTemplate,
        SomeValueSnak,
        SomeValueSnakTemplate,
        ValueSnak,
        ValueSnakTemplate,
    )
    from ..statement import Statement, StatementTemplate

TProperty: TypeAlias = Union['Property', T_IRI]
VProperty: TypeAlias =\
    Union['PropertyTemplate', 'PropertyVariable', 'Property']
VTProperty: TypeAlias = Union[Variable, VProperty, TProperty]
VTPropertyContent: TypeAlias = Union[Variable, IRI_Template, TProperty]


[docs] class PropertyTemplate(EntityTemplate): """Property template. Parameters: iri: IRI, IRI template, or IRI variable. range: Datatype or datatype variable. """ object_class: ClassVar[type[Property]] # pyright: ignore
[docs] def __init__(self, iri: VT_IRI, range: VTDatatype | None = None) -> None: super().__init__(iri, range)
@override def _preprocess_arg(self, arg: Any, i: int) -> Any: if i == 1: # iri if isinstance(arg, OpenTerm): return super()._preprocess_arg(arg, i) else: return Property._static_preprocess_arg(self, arg, i) elif i == 2: # range if isinstance(arg, Variable): return DatatypeVariable.check(arg, type(self), None, i) else: return Property._static_preprocess_arg(self, arg, i) else: raise self._should_not_get_here() @overload def __call__(self, v1: VTEntity, v2: VTValue) -> StatementTemplate: ... # pragma: no cover @overload def __call__(self, v1: VTValue) -> ValueSnakTemplate: ... # pragma: no cover def __call__( self, v1: VTEntity | VTValue, v2: VTValue | None = None ) -> StatementTemplate | ValueSnakTemplate: if v2 is not None: from ..snak import ValueSnak from ..statement import StatementTemplate return StatementTemplate(v1, ValueSnak(self, v2)) # type: ignore else: from ..snak import ValueSnakTemplate return ValueSnakTemplate(self, v1) @property def range(self) -> VDatatype | None: """The range of property template.""" return self.get_range()
[docs] def get_range(self, default: VDatatype | None = None) -> VDatatype | None: """Gets the range of property template. If range is ``None``, returns `default`. Parameters: default: Default range. Returns: Datatype or datatype variable. """ return self.get(1, default)
[docs] def no_value(self) -> NoValueSnakTemplate: """Constructs a no-value snak template from property template. Returns: No-value snak template. """ from ..snak import NoValueSnakTemplate return NoValueSnakTemplate(self)
[docs] def some_value(self) -> SomeValueSnakTemplate: """Constructs a some-value snak template from property template. Returns: Some-value snak template. """ from ..snak import SomeValueSnakTemplate return SomeValueSnakTemplate(self)
[docs] class PropertyVariable(EntityVariable): """Property variable. Parameters: name: Name. """ object_class: ClassVar[type[Property]] # pyright: ignore @overload def __call__(self, v1: VTEntity, v2: VTValue) -> StatementTemplate: ... # pragma: no cover @overload def __call__(self, v1: VTValue) -> ValueSnakTemplate: ... # pragma: no cover def __call__( self, v1: VTEntity | VTValue, v2: VTValue | None = None ) -> StatementTemplate | ValueSnakTemplate: if v2 is not None: from ..snak import ValueSnak from ..statement import StatementTemplate return StatementTemplate(v1, ValueSnak(self, v2)) # type: ignore else: from ..snak import ValueSnakTemplate return ValueSnakTemplate(self, v1)
[docs] def no_value(self) -> NoValueSnakTemplate: """Constructs a no-value snak template from property variable. Returns: No-value snak template. """ from ..snak import NoValueSnakTemplate return NoValueSnakTemplate(self)
[docs] def some_value(self) -> SomeValueSnakTemplate: """Constructs a some-value snak template from property variable. Returns: Some-value snak template. """ from ..snak import SomeValueSnakTemplate return SomeValueSnakTemplate(self)
class PropertyDatatype(Datatype): """Property datatype.""" value_class: ClassVar[type[Property]] # pyright: ignore
[docs] class Property( Entity, datatype_class=PropertyDatatype, template_class=PropertyTemplate, variable_class=PropertyVariable ): """Binary relationship. Parameters: iri: IRI. range: Datatype. """ datatype_class: ClassVar[type[PropertyDatatype]] # pyright: ignore datatype: ClassVar[PropertyDatatype] # pyright: ignore template_class: ClassVar[type[PropertyTemplate]] # pyright: ignore variable_class: ClassVar[type[PropertyVariable]] # pyright: ignore
[docs] def __init__( self, iri: VTPropertyContent, range: VTDatatype | None = None ) -> None: super().__init__(iri, range)
@staticmethod @override def _static_preprocess_arg(self_, arg: Any, i: int) -> Any: if i == 1: # iri return Entity._static_preprocess_arg(self_, arg, i) elif i == 2: # range return Datatype.check_optional(arg, None, type(self_), None, i) else: raise self_._should_not_get_here() @overload def __call__(self, v1: VTEntity, v2: VTValue) -> Statement: ... # pragma: no cover @overload def __call__(self, v1: VTValue) -> ValueSnak: ... # pragma: no cover def __call__( self, v1: VTEntity | VTValue, v2: VTValue | None = None ) -> Statement | ValueSnak: if v2 is not None: from ..snak import ValueSnak from ..statement import Statement return Statement(v1, ValueSnak(self, v2)) # type: ignore else: from ..snak import ValueSnak return ValueSnak(self, v1) @property def range(self) -> Datatype | None: """The range of property.""" return self.get_range()
[docs] def get_range(self, default: Datatype | None = None) -> Datatype | None: """Gets the range of property. If range is ``None``, returns `default`. Parameters: default: Default range. Returns: Datatype. """ return self.get(1, default)
[docs] def no_value(self) -> NoValueSnak: """Constructs a no-value snak from property. Returns: No-value snak. """ from ..snak import NoValueSnak return NoValueSnak(self)
[docs] def some_value(self) -> SomeValueSnak: """Constructs a some-value snak from property. Returns: Some-value snak. """ from ..snak import SomeValueSnak return SomeValueSnak(self)
def Properties( iri: VTPropertyContent, *iris: VTPropertyContent ) -> Iterable[Property]: """Constructs one or more properties. Parameters: iri: IRI. iris: IRIs. Returns: The resulting properties. """ from ... import itertools return map(Property, itertools.chain((iri,), iris))