Source code for qwikidata.snak

# Copyright 2019 Kensho Technologies, LLC.
"""Module for Wikidata Snaks."""

from typing import Union

from qwikidata import typedefs
from qwikidata.datavalue import WikidataDatavalue, get_datavalue_from_snak_dict


[docs]class WikidataSnak: """A Wikidata snak. Parameters ---------- snak_dict: dict A dictionary representing a Wikidata snak. See `the wikibase JSON data model docs`_ for a description of the format. Attributes ---------- snaktype: str One of ["value", "somevalue", "novalue"]. "value" indicates that a known value exists, "somevalue" indicates that an unknown value exists, and "novalue" indicates that no value exists. property_id: str A Wikidata property id (e.g. "P551") snak_datatype: str or `None` The snak data type (SDT). Must be one of ["commonsMedia", "external-id", "geo-shape", "globe-coordinate", "math", "monolingualtext", "quantity", "string", "tabular-data", "time", "url", "wikibase-item", "wikibase-property", `None`]. Will be `None` if `snaktype` is not "value". value_datatype: str or `None` The value data type (VDT). Must be one of ["globecoordinate", "monolingualtext", "quantity", "string", "time", "wikibase-entityid", `None`]. Will be `None` if `snaktype` is not "value". datavalue: :py:class:`WikidataDataValue` or `None` The datavalue object for this snak. Has `datatype` and `value` attributes. (this data type is the same as VDT above). .. note:: There are two related data types here, the snak data type (SDT) and the value data type (VDT). The SDT is derived from the data type of the property referenced by `property_id` and is stored in the `snak_datatype` attribute. The VDT defines the structure of the `value` attribute of :py:class:`WikidataDataValue`. The VDT does not allow for interpretation of the datavalue, only for processing of the raw structure. As an example, a link to a web page may have SDT="url", but have VDT="string". .. _the wikibase JSON data model docs: https://www.mediawiki.org/wiki/Wikibase/DataModel/JSON """ def __init__(self, snak_dict: typedefs.SnakDict) -> None: self._validate_snak_dict(snak_dict) self._snak_dict = snak_dict def _validate_snak_dict(self, snak_dict: typedefs.SnakDict) -> None: """Raise excpetions if snak_dict is not valid.""" _REQUIRED_KEYS = ["snaktype", "property"] for req_key in _REQUIRED_KEYS: if req_key not in snak_dict: raise ValueError( "required snak_dict keys are {} but only found {}".format( _REQUIRED_KEYS, list(snak_dict.keys()) ) ) self.snaktype = snak_dict["snaktype"] self.property_id = snak_dict["property"] self.snak_datatype = None # type: Union[str, None] self.value_datatype = None # type: Union[str, None] self.datavalue = None # type: Union[WikidataDatavalue, None] if self.snaktype == "value": _REQUIRED_KEYS = ["datavalue", "datatype"] for req_key in _REQUIRED_KEYS: if req_key not in snak_dict: raise ValueError( "required snak_dict keys are {} but only found {}".format( _REQUIRED_KEYS, list(snak_dict.keys()) ) ) self.snak_datatype = snak_dict["datatype"] self.value_datatype = str(snak_dict["datavalue"]["type"]) self.datavalue = get_datavalue_from_snak_dict(snak_dict) elif self.snaktype == "somevalue" or self.snaktype == "novalue": self.snak_datatype = None self.value_datatype = None self.datavalue = None else: raise ValueError( 'snaktype must be one of ["value", "somevalue", "novalue"] but got {}'.format( self.snaktype ) ) def __str__(self) -> str: return ( "WikidataSnak(snaktype={}, property_id={}, " "snak_datatype={}, value_datatype={}, " "datavalue={})".format( self.snaktype, self.property_id, self.snak_datatype, self.value_datatype, self.datavalue, ) ) def __repr__(self) -> str: return self.__str__()