From 7a006a6907b342187a928cd45c6d3b637b15e7df Mon Sep 17 00:00:00 2001 From: Roman Kalyakin Date: Wed, 20 Nov 2024 10:04:50 +0100 Subject: [PATCH] wikidata in entities (#17) * wikidata in entities * updated url --- examples/notebooks/entities.ipynb | 287 +++++++++++++++++- .../api_client/api/entities/find_entities.py | 15 + impresso/api_client/models/__init__.py | 18 ++ impresso/api_client/models/entity_details.py | 44 ++- .../api_client/models/wikidata_location.py | 108 +++++++ .../models/wikidata_location_coordinates.py | 47 +++ .../models/wikidata_location_descriptions.py | 43 +++ .../models/wikidata_location_labels.py | 43 +++ .../models/wikidata_location_type.py | 12 + impresso/api_client/models/wikidata_person.py | 158 ++++++++++ .../models/wikidata_person_descriptions.py | 43 +++ .../models/wikidata_person_labels.py | 43 +++ .../api_client/models/wikidata_person_type.py | 12 + impresso/api_models.py | 116 +++++-- impresso/config_file.py | 2 +- impresso/resources/entities.py | 2 + pyproject.toml | 2 +- 17 files changed, 965 insertions(+), 30 deletions(-) create mode 100644 impresso/api_client/models/wikidata_location.py create mode 100644 impresso/api_client/models/wikidata_location_coordinates.py create mode 100644 impresso/api_client/models/wikidata_location_descriptions.py create mode 100644 impresso/api_client/models/wikidata_location_labels.py create mode 100644 impresso/api_client/models/wikidata_location_type.py create mode 100644 impresso/api_client/models/wikidata_person.py create mode 100644 impresso/api_client/models/wikidata_person_descriptions.py create mode 100644 impresso/api_client/models/wikidata_person_labels.py create mode 100644 impresso/api_client/models/wikidata_person_type.py diff --git a/examples/notebooks/entities.ipynb b/examples/notebooks/entities.ipynb index 80acdd9..6fd1c41 100644 --- a/examples/notebooks/entities.ipynb +++ b/examples/notebooks/entities.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -31,7 +31,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -109,10 +109,10 @@ "" ], "text/plain": [ - "" + "" ] }, - "execution_count": 3, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -597,6 +597,285 @@ "from impresso import AND\n", "impresso.entities.find(wikidata_id=AND(\"Q2\", \"Q4\", \"Q42\"))" ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Get wikidata details" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "
\n", + "

FindEntities result

\n", + "
Contains 3 items of 3 total items.
\n", + "
\n", + "See this result in the Impresso App.\n", + "
\n", + "
\n", + "

Data preview:

\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
labeltypewikidataIdtotalMentionstotalContentItemswikidataDetails.idwikidataDetails.typewikidataDetails.descriptions.enwikidataDetails.descriptions.frwikidataDetails.descriptions.itwikidataDetails.descriptions.dewikidataDetails.birthDatewikidataDetails.deathDatewikidataDetails.birthPlace.idwikidataDetails.birthPlace.typewikidataDetails.birthPlace.labels.enwikidataDetails.birthPlace.labels.frwikidataDetails.birthPlace.labels.itwikidataDetails.birthPlace.labels.dewikidataDetails.birthPlace.descriptions.enwikidataDetails.birthPlace.descriptions.frwikidataDetails.birthPlace.descriptions.itwikidataDetails.birthPlace.descriptions.dewikidataDetails.birthPlace.coordinates.latitudewikidataDetails.birthPlace.coordinates.longitudewikidataDetails.deathPlace.idwikidataDetails.deathPlace.typewikidataDetails.deathPlace.labels.frwikidataDetails.deathPlace.labels.itwikidataDetails.deathPlace.labels.dewikidataDetails.deathPlace.labels.enwikidataDetails.deathPlace.descriptions.dewikidataDetails.deathPlace.descriptions.enwikidataDetails.deathPlace.descriptions.frwikidataDetails.deathPlace.descriptions.itwikidataDetails.deathPlace.coordinates.latitudewikidataDetails.deathPlace.coordinates.longitudewikidataDetails.labels.dewikidataDetails.labels.enwikidataDetails.labels.itwikidataDetails.labels.fr
uid
aida-0001-50-Douglas_AdamsDouglas AdamspersonQ429494Q42humanEnglish science fiction writer and humorist (1...écrivain et humoriste anglais (1952–2001)scrittore e umorista britannico (1952–2001)britischer Science-Fiction-Autor und Humorist1952-03-11T00:00:00+00:002001-05-11T00:00:00+00:00Q350locationCambridgeCambridgeCambridgeCambridgecity in Cambridgeshire, Englandville britanniquecittà della Gran Bretagnaenglische Universitätsstadt, Hauptort von Camb...52.2080560.1225Q159288locationSanta BarbaraSanta BarbaraSanta BarbaraSanta BarbaraStadt in Kalifornien, Vereinigte Staatencity in and county seat of Santa Barbara Count...municipalité de Californiecittà della California34.425833-119.714167NaNNaNNaNNaN
aida-0001-50-Douglas_Q._AdamsDouglas Q. AdamspersonQ9328693030Q932869humanAmerican professor of EnglishNaNlinguista statunitenseUS-amerikanischer Sprachwissenschaftler2000-01-01T00:00:00+00:00NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNDouglas Quentin AdamsDouglas Q. AdamsDouglas Q. AdamsDouglas Q. Adams
aida-0001-54-Douglas_AdamsDouglas AdamslocationQ422424Q42humanEnglish science fiction writer and humorist (1...écrivain et humoriste anglais (1952–2001)scrittore e umorista britannico (1952–2001)britischer Science-Fiction-Autor und Humorist1952-03-11T00:00:00+00:002001-05-11T00:00:00+00:00Q350locationCambridgeCambridgeCambridgeCambridgecity in Cambridgeshire, Englandville britanniquecittà della Gran Bretagnaenglische Universitätsstadt, Hauptort von Camb...52.2080560.1225Q159288locationSanta BarbaraSanta BarbaraSanta BarbaraSanta BarbaraStadt in Kalifornien, Vereinigte Staatencity in and county seat of Santa Barbara Count...municipalité de Californiecittà della California34.425833-119.714167NaNNaNNaNNaN
\n", + "
" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "impresso.entities.find(term=\"Douglas Adams\", resolve=True)" + ] } ], "metadata": { diff --git a/impresso/api_client/api/entities/find_entities.py b/impresso/api_client/api/entities/find_entities.py index c0f5c51..0380c92 100644 --- a/impresso/api_client/api/entities/find_entities.py +++ b/impresso/api_client/api/entities/find_entities.py @@ -15,6 +15,7 @@ def _get_kwargs( *, term: Union[Unset, str] = UNSET, + resolve: Union[Unset, bool] = False, order_by: Union[Unset, FindEntitiesOrderBy] = UNSET, filters: Union[List["Filter"], Unset, str] = UNSET, limit: Union[Unset, int] = UNSET, @@ -24,6 +25,8 @@ def _get_kwargs( params["term"] = term + params["resolve"] = resolve + json_order_by: Union[Unset, str] = UNSET if not isinstance(order_by, Unset): json_order_by = order_by.value @@ -110,6 +113,7 @@ def sync_detailed( *, client: AuthenticatedClient, term: Union[Unset, str] = UNSET, + resolve: Union[Unset, bool] = False, order_by: Union[Unset, FindEntitiesOrderBy] = UNSET, filters: Union[List["Filter"], Unset, str] = UNSET, limit: Union[Unset, int] = UNSET, @@ -119,6 +123,7 @@ def sync_detailed( Args: term (Union[Unset, str]): + resolve (Union[Unset, bool]): Default: False. order_by (Union[Unset, FindEntitiesOrderBy]): filters (Union[List['Filter'], Unset, str]): limit (Union[Unset, int]): @@ -134,6 +139,7 @@ def sync_detailed( kwargs = _get_kwargs( term=term, + resolve=resolve, order_by=order_by, filters=filters, limit=limit, @@ -151,6 +157,7 @@ def sync( *, client: AuthenticatedClient, term: Union[Unset, str] = UNSET, + resolve: Union[Unset, bool] = False, order_by: Union[Unset, FindEntitiesOrderBy] = UNSET, filters: Union[List["Filter"], Unset, str] = UNSET, limit: Union[Unset, int] = UNSET, @@ -160,6 +167,7 @@ def sync( Args: term (Union[Unset, str]): + resolve (Union[Unset, bool]): Default: False. order_by (Union[Unset, FindEntitiesOrderBy]): filters (Union[List['Filter'], Unset, str]): limit (Union[Unset, int]): @@ -176,6 +184,7 @@ def sync( return sync_detailed( client=client, term=term, + resolve=resolve, order_by=order_by, filters=filters, limit=limit, @@ -187,6 +196,7 @@ async def asyncio_detailed( *, client: AuthenticatedClient, term: Union[Unset, str] = UNSET, + resolve: Union[Unset, bool] = False, order_by: Union[Unset, FindEntitiesOrderBy] = UNSET, filters: Union[List["Filter"], Unset, str] = UNSET, limit: Union[Unset, int] = UNSET, @@ -196,6 +206,7 @@ async def asyncio_detailed( Args: term (Union[Unset, str]): + resolve (Union[Unset, bool]): Default: False. order_by (Union[Unset, FindEntitiesOrderBy]): filters (Union[List['Filter'], Unset, str]): limit (Union[Unset, int]): @@ -211,6 +222,7 @@ async def asyncio_detailed( kwargs = _get_kwargs( term=term, + resolve=resolve, order_by=order_by, filters=filters, limit=limit, @@ -226,6 +238,7 @@ async def asyncio( *, client: AuthenticatedClient, term: Union[Unset, str] = UNSET, + resolve: Union[Unset, bool] = False, order_by: Union[Unset, FindEntitiesOrderBy] = UNSET, filters: Union[List["Filter"], Unset, str] = UNSET, limit: Union[Unset, int] = UNSET, @@ -235,6 +248,7 @@ async def asyncio( Args: term (Union[Unset, str]): + resolve (Union[Unset, bool]): Default: False. order_by (Union[Unset, FindEntitiesOrderBy]): filters (Union[List['Filter'], Unset, str]): limit (Union[Unset, int]): @@ -252,6 +266,7 @@ async def asyncio( await asyncio_detailed( client=client, term=term, + resolve=resolve, order_by=order_by, filters=filters, limit=limit, diff --git a/impresso/api_client/models/__init__.py b/impresso/api_client/models/__init__.py index 99bf889..c4a9cae 100644 --- a/impresso/api_client/models/__init__.py +++ b/impresso/api_client/models/__init__.py @@ -74,6 +74,15 @@ from .topic_mention import TopicMention from .update_collectable_items_request import UpdateCollectableItemsRequest from .version_details import VersionDetails +from .wikidata_location import WikidataLocation +from .wikidata_location_coordinates import WikidataLocationCoordinates +from .wikidata_location_descriptions import WikidataLocationDescriptions +from .wikidata_location_labels import WikidataLocationLabels +from .wikidata_location_type import WikidataLocationType +from .wikidata_person import WikidataPerson +from .wikidata_person_descriptions import WikidataPersonDescriptions +from .wikidata_person_labels import WikidataPersonLabels +from .wikidata_person_type import WikidataPersonType __all__ = ( "AuthenticationCreateRequest", @@ -150,4 +159,13 @@ "TopicMention", "UpdateCollectableItemsRequest", "VersionDetails", + "WikidataLocation", + "WikidataLocationCoordinates", + "WikidataLocationDescriptions", + "WikidataLocationLabels", + "WikidataLocationType", + "WikidataPerson", + "WikidataPersonDescriptions", + "WikidataPersonLabels", + "WikidataPersonType", ) diff --git a/impresso/api_client/models/entity_details.py b/impresso/api_client/models/entity_details.py index e8bf581..1a22bd4 100644 --- a/impresso/api_client/models/entity_details.py +++ b/impresso/api_client/models/entity_details.py @@ -1,10 +1,15 @@ -from typing import Any, Dict, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union from attrs import define as _attrs_define from ..models.entity_details_type import EntityDetailsType from ..types import UNSET, Unset +if TYPE_CHECKING: + from ..models.wikidata_location import WikidataLocation + from ..models.wikidata_person import WikidataPerson + + T = TypeVar("T", bound="EntityDetails") @@ -19,6 +24,7 @@ class EntityDetails: wikidata_id (Union[Unset, str]): Wikidata identifier of the entity. total_mentions (Union[Unset, int]): Total number of mentions of the entity. total_content_items (Union[Unset, int]): Total number of content items the entity is mentioned in. + wikidata_details (Union['WikidataLocation', 'WikidataPerson', Unset]): """ uid: str @@ -27,8 +33,11 @@ class EntityDetails: wikidata_id: Union[Unset, str] = UNSET total_mentions: Union[Unset, int] = UNSET total_content_items: Union[Unset, int] = UNSET + wikidata_details: Union["WikidataLocation", "WikidataPerson", Unset] = UNSET def to_dict(self) -> Dict[str, Any]: + from ..models.wikidata_person import WikidataPerson + uid = self.uid label = self.label @@ -43,6 +52,14 @@ def to_dict(self) -> Dict[str, Any]: total_content_items = self.total_content_items + wikidata_details: Union[Dict[str, Any], Unset] + if isinstance(self.wikidata_details, Unset): + wikidata_details = UNSET + elif isinstance(self.wikidata_details, WikidataPerson): + wikidata_details = self.wikidata_details.to_dict() + else: + wikidata_details = self.wikidata_details.to_dict() + field_dict: Dict[str, Any] = {} field_dict.update( { @@ -59,11 +76,16 @@ def to_dict(self) -> Dict[str, Any]: field_dict["totalMentions"] = total_mentions if total_content_items is not UNSET: field_dict["totalContentItems"] = total_content_items + if wikidata_details is not UNSET: + field_dict["wikidataDetails"] = wikidata_details return field_dict @classmethod def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + from ..models.wikidata_location import WikidataLocation + from ..models.wikidata_person import WikidataPerson + d = src_dict.copy() uid = d.pop("uid") @@ -82,6 +104,25 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: total_content_items = d.pop("totalContentItems", UNSET) + def _parse_wikidata_details(data: object) -> Union["WikidataLocation", "WikidataPerson", Unset]: + if isinstance(data, Unset): + return data + try: + if not isinstance(data, dict): + raise TypeError() + wikidata_details_type_0 = WikidataPerson.from_dict(data) + + return wikidata_details_type_0 + except: # noqa: E722 + pass + if not isinstance(data, dict): + raise TypeError() + wikidata_details_type_1 = WikidataLocation.from_dict(data) + + return wikidata_details_type_1 + + wikidata_details = _parse_wikidata_details(d.pop("wikidataDetails", UNSET)) + entity_details = cls( uid=uid, label=label, @@ -89,6 +130,7 @@ def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: wikidata_id=wikidata_id, total_mentions=total_mentions, total_content_items=total_content_items, + wikidata_details=wikidata_details, ) return entity_details diff --git a/impresso/api_client/models/wikidata_location.py b/impresso/api_client/models/wikidata_location.py new file mode 100644 index 0000000..59a7c55 --- /dev/null +++ b/impresso/api_client/models/wikidata_location.py @@ -0,0 +1,108 @@ +from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union + +from attrs import define as _attrs_define + +from ..models.wikidata_location_type import WikidataLocationType +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.wikidata_location_coordinates import WikidataLocationCoordinates + from ..models.wikidata_location_descriptions import WikidataLocationDescriptions + from ..models.wikidata_location_labels import WikidataLocationLabels + + +T = TypeVar("T", bound="WikidataLocation") + + +@_attrs_define +class WikidataLocation: + """Wikidata location schema. Based on https://schema.org/Place + + Attributes: + id (str): The Q Wikidata ID of the location (https://www.wikidata.org/wiki/Wikidata:Identifiers) + type (WikidataLocationType): The type of the entity + labels (Union[Unset, WikidataLocationLabels]): Labels of the location in different languages + descriptions (Union[Unset, WikidataLocationDescriptions]): Descriptions of the location in different languages + coordinates (Union[Unset, WikidataLocationCoordinates]): + """ + + id: str + type: WikidataLocationType + labels: Union[Unset, "WikidataLocationLabels"] = UNSET + descriptions: Union[Unset, "WikidataLocationDescriptions"] = UNSET + coordinates: Union[Unset, "WikidataLocationCoordinates"] = UNSET + + def to_dict(self) -> Dict[str, Any]: + id = self.id + + type = self.type.value + + labels: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.labels, Unset): + labels = self.labels.to_dict() + + descriptions: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.descriptions, Unset): + descriptions = self.descriptions.to_dict() + + coordinates: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.coordinates, Unset): + coordinates = self.coordinates.to_dict() + + field_dict: Dict[str, Any] = {} + field_dict.update( + { + "id": id, + "type": type, + } + ) + if labels is not UNSET: + field_dict["labels"] = labels + if descriptions is not UNSET: + field_dict["descriptions"] = descriptions + if coordinates is not UNSET: + field_dict["coordinates"] = coordinates + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + from ..models.wikidata_location_coordinates import WikidataLocationCoordinates + from ..models.wikidata_location_descriptions import WikidataLocationDescriptions + from ..models.wikidata_location_labels import WikidataLocationLabels + + d = src_dict.copy() + id = d.pop("id") + + type = WikidataLocationType(d.pop("type")) + + _labels = d.pop("labels", UNSET) + labels: Union[Unset, WikidataLocationLabels] + if isinstance(_labels, Unset): + labels = UNSET + else: + labels = WikidataLocationLabels.from_dict(_labels) + + _descriptions = d.pop("descriptions", UNSET) + descriptions: Union[Unset, WikidataLocationDescriptions] + if isinstance(_descriptions, Unset): + descriptions = UNSET + else: + descriptions = WikidataLocationDescriptions.from_dict(_descriptions) + + _coordinates = d.pop("coordinates", UNSET) + coordinates: Union[Unset, WikidataLocationCoordinates] + if isinstance(_coordinates, Unset): + coordinates = UNSET + else: + coordinates = WikidataLocationCoordinates.from_dict(_coordinates) + + wikidata_location = cls( + id=id, + type=type, + labels=labels, + descriptions=descriptions, + coordinates=coordinates, + ) + + return wikidata_location diff --git a/impresso/api_client/models/wikidata_location_coordinates.py b/impresso/api_client/models/wikidata_location_coordinates.py new file mode 100644 index 0000000..af4f1f9 --- /dev/null +++ b/impresso/api_client/models/wikidata_location_coordinates.py @@ -0,0 +1,47 @@ +from typing import Any, Dict, Type, TypeVar, Union + +from attrs import define as _attrs_define + +from ..types import UNSET, Unset + +T = TypeVar("T", bound="WikidataLocationCoordinates") + + +@_attrs_define +class WikidataLocationCoordinates: + """ + Attributes: + latitude (Union[Unset, float]): The latitude of the location + longitude (Union[Unset, float]): The longitude of the location + """ + + latitude: Union[Unset, float] = UNSET + longitude: Union[Unset, float] = UNSET + + def to_dict(self) -> Dict[str, Any]: + latitude = self.latitude + + longitude = self.longitude + + field_dict: Dict[str, Any] = {} + field_dict.update({}) + if latitude is not UNSET: + field_dict["latitude"] = latitude + if longitude is not UNSET: + field_dict["longitude"] = longitude + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + latitude = d.pop("latitude", UNSET) + + longitude = d.pop("longitude", UNSET) + + wikidata_location_coordinates = cls( + latitude=latitude, + longitude=longitude, + ) + + return wikidata_location_coordinates diff --git a/impresso/api_client/models/wikidata_location_descriptions.py b/impresso/api_client/models/wikidata_location_descriptions.py new file mode 100644 index 0000000..621b936 --- /dev/null +++ b/impresso/api_client/models/wikidata_location_descriptions.py @@ -0,0 +1,43 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WikidataLocationDescriptions") + + +@_attrs_define +class WikidataLocationDescriptions: + """Descriptions of the location in different languages""" + + additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + wikidata_location_descriptions = cls() + + wikidata_location_descriptions.additional_properties = d + return wikidata_location_descriptions + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> str: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: str) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/impresso/api_client/models/wikidata_location_labels.py b/impresso/api_client/models/wikidata_location_labels.py new file mode 100644 index 0000000..9dd403a --- /dev/null +++ b/impresso/api_client/models/wikidata_location_labels.py @@ -0,0 +1,43 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WikidataLocationLabels") + + +@_attrs_define +class WikidataLocationLabels: + """Labels of the location in different languages""" + + additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + wikidata_location_labels = cls() + + wikidata_location_labels.additional_properties = d + return wikidata_location_labels + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> str: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: str) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/impresso/api_client/models/wikidata_location_type.py b/impresso/api_client/models/wikidata_location_type.py new file mode 100644 index 0000000..052e6db --- /dev/null +++ b/impresso/api_client/models/wikidata_location_type.py @@ -0,0 +1,12 @@ +from enum import Enum +from typing import Literal + + +class WikidataLocationType(str, Enum): + LOCATION = "location" + + def __str__(self) -> str: + return str(self.value) + + +WikidataLocationTypeLiteral = Literal["location",] diff --git a/impresso/api_client/models/wikidata_person.py b/impresso/api_client/models/wikidata_person.py new file mode 100644 index 0000000..c56e5d1 --- /dev/null +++ b/impresso/api_client/models/wikidata_person.py @@ -0,0 +1,158 @@ +import datetime +from typing import TYPE_CHECKING, Any, Dict, Type, TypeVar, Union + +from attrs import define as _attrs_define +from dateutil.parser import isoparse + +from ..models.wikidata_person_type import WikidataPersonType +from ..types import UNSET, Unset + +if TYPE_CHECKING: + from ..models.wikidata_location import WikidataLocation + from ..models.wikidata_person_descriptions import WikidataPersonDescriptions + from ..models.wikidata_person_labels import WikidataPersonLabels + + +T = TypeVar("T", bound="WikidataPerson") + + +@_attrs_define +class WikidataPerson: + """Wikidata person schema. Based on https://schema.org/Person + + Attributes: + id (str): The Q Wikidata ID of the person (https://www.wikidata.org/wiki/Wikidata:Identifiers) + type (WikidataPersonType): The type of the entity + labels (Union[Unset, WikidataPersonLabels]): Labels of the person in different languages + descriptions (Union[Unset, WikidataPersonDescriptions]): Descriptions of the person in different languages + birth_date (Union[Unset, datetime.datetime]): The birth date of the person + death_date (Union[Unset, datetime.datetime]): The death date of the person + birth_place (Union[Unset, WikidataLocation]): Wikidata location schema. Based on https://schema.org/Place + death_place (Union[Unset, WikidataLocation]): Wikidata location schema. Based on https://schema.org/Place + """ + + id: str + type: WikidataPersonType + labels: Union[Unset, "WikidataPersonLabels"] = UNSET + descriptions: Union[Unset, "WikidataPersonDescriptions"] = UNSET + birth_date: Union[Unset, datetime.datetime] = UNSET + death_date: Union[Unset, datetime.datetime] = UNSET + birth_place: Union[Unset, "WikidataLocation"] = UNSET + death_place: Union[Unset, "WikidataLocation"] = UNSET + + def to_dict(self) -> Dict[str, Any]: + id = self.id + + type = self.type.value + + labels: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.labels, Unset): + labels = self.labels.to_dict() + + descriptions: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.descriptions, Unset): + descriptions = self.descriptions.to_dict() + + birth_date: Union[Unset, str] = UNSET + if not isinstance(self.birth_date, Unset): + birth_date = self.birth_date.isoformat() + + death_date: Union[Unset, str] = UNSET + if not isinstance(self.death_date, Unset): + death_date = self.death_date.isoformat() + + birth_place: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.birth_place, Unset): + birth_place = self.birth_place.to_dict() + + death_place: Union[Unset, Dict[str, Any]] = UNSET + if not isinstance(self.death_place, Unset): + death_place = self.death_place.to_dict() + + field_dict: Dict[str, Any] = {} + field_dict.update( + { + "id": id, + "type": type, + } + ) + if labels is not UNSET: + field_dict["labels"] = labels + if descriptions is not UNSET: + field_dict["descriptions"] = descriptions + if birth_date is not UNSET: + field_dict["birthDate"] = birth_date + if death_date is not UNSET: + field_dict["deathDate"] = death_date + if birth_place is not UNSET: + field_dict["birthPlace"] = birth_place + if death_place is not UNSET: + field_dict["deathPlace"] = death_place + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + from ..models.wikidata_location import WikidataLocation + from ..models.wikidata_person_descriptions import WikidataPersonDescriptions + from ..models.wikidata_person_labels import WikidataPersonLabels + + d = src_dict.copy() + id = d.pop("id") + + type = WikidataPersonType(d.pop("type")) + + _labels = d.pop("labels", UNSET) + labels: Union[Unset, WikidataPersonLabels] + if isinstance(_labels, Unset): + labels = UNSET + else: + labels = WikidataPersonLabels.from_dict(_labels) + + _descriptions = d.pop("descriptions", UNSET) + descriptions: Union[Unset, WikidataPersonDescriptions] + if isinstance(_descriptions, Unset): + descriptions = UNSET + else: + descriptions = WikidataPersonDescriptions.from_dict(_descriptions) + + _birth_date = d.pop("birthDate", UNSET) + birth_date: Union[Unset, datetime.datetime] + if isinstance(_birth_date, Unset): + birth_date = UNSET + else: + birth_date = isoparse(_birth_date) + + _death_date = d.pop("deathDate", UNSET) + death_date: Union[Unset, datetime.datetime] + if isinstance(_death_date, Unset): + death_date = UNSET + else: + death_date = isoparse(_death_date) + + _birth_place = d.pop("birthPlace", UNSET) + birth_place: Union[Unset, WikidataLocation] + if isinstance(_birth_place, Unset): + birth_place = UNSET + else: + birth_place = WikidataLocation.from_dict(_birth_place) + + _death_place = d.pop("deathPlace", UNSET) + death_place: Union[Unset, WikidataLocation] + if isinstance(_death_place, Unset): + death_place = UNSET + else: + death_place = WikidataLocation.from_dict(_death_place) + + wikidata_person = cls( + id=id, + type=type, + labels=labels, + descriptions=descriptions, + birth_date=birth_date, + death_date=death_date, + birth_place=birth_place, + death_place=death_place, + ) + + return wikidata_person diff --git a/impresso/api_client/models/wikidata_person_descriptions.py b/impresso/api_client/models/wikidata_person_descriptions.py new file mode 100644 index 0000000..c26ddae --- /dev/null +++ b/impresso/api_client/models/wikidata_person_descriptions.py @@ -0,0 +1,43 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WikidataPersonDescriptions") + + +@_attrs_define +class WikidataPersonDescriptions: + """Descriptions of the person in different languages""" + + additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + wikidata_person_descriptions = cls() + + wikidata_person_descriptions.additional_properties = d + return wikidata_person_descriptions + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> str: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: str) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/impresso/api_client/models/wikidata_person_labels.py b/impresso/api_client/models/wikidata_person_labels.py new file mode 100644 index 0000000..7c50a27 --- /dev/null +++ b/impresso/api_client/models/wikidata_person_labels.py @@ -0,0 +1,43 @@ +from typing import Any, Dict, List, Type, TypeVar + +from attrs import define as _attrs_define +from attrs import field as _attrs_field + +T = TypeVar("T", bound="WikidataPersonLabels") + + +@_attrs_define +class WikidataPersonLabels: + """Labels of the person in different languages""" + + additional_properties: Dict[str, str] = _attrs_field(init=False, factory=dict) + + def to_dict(self) -> Dict[str, Any]: + field_dict: Dict[str, Any] = {} + field_dict.update(self.additional_properties) + + return field_dict + + @classmethod + def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T: + d = src_dict.copy() + wikidata_person_labels = cls() + + wikidata_person_labels.additional_properties = d + return wikidata_person_labels + + @property + def additional_keys(self) -> List[str]: + return list(self.additional_properties.keys()) + + def __getitem__(self, key: str) -> str: + return self.additional_properties[key] + + def __setitem__(self, key: str, value: str) -> None: + self.additional_properties[key] = value + + def __delitem__(self, key: str) -> None: + del self.additional_properties[key] + + def __contains__(self, key: str) -> bool: + return key in self.additional_properties diff --git a/impresso/api_client/models/wikidata_person_type.py b/impresso/api_client/models/wikidata_person_type.py new file mode 100644 index 0000000..bc00c4f --- /dev/null +++ b/impresso/api_client/models/wikidata_person_type.py @@ -0,0 +1,12 @@ +from enum import Enum +from typing import Literal + + +class WikidataPersonType(str, Enum): + HUMAN = "human" + + def __str__(self) -> str: + return str(self.value) + + +WikidataPersonTypeLiteral = Literal["human",] diff --git a/impresso/api_models.py b/impresso/api_models.py index 619d1d3..3f56def 100644 --- a/impresso/api_models.py +++ b/impresso/api_models.py @@ -371,29 +371,6 @@ class Collection(BaseModel): ] -class EntityDetails(BaseModel): - model_config = ConfigDict( - extra='forbid', - ) - uid: Annotated[str, Field(description='Unique identifier of the entity')] - label: Annotated[Optional[str], Field(None, description='Entity label')] - type: Optional[Literal['person', 'location']] = None - wikidataId: Annotated[ - Optional[str], Field(None, description='Wikidata identifier of the entity.') - ] - totalMentions: Annotated[ - Optional[int], - Field(None, description='Total number of mentions of the entity.'), - ] - totalContentItems: Annotated[ - Optional[int], - Field( - None, - description='Total number of content items the entity is mentioned in.', - ), - ] - - class EntityMention(BaseModel): model_config = ConfigDict( extra='forbid', @@ -564,6 +541,40 @@ class VersionDetails(BaseModel): version: Annotated[str, Field(description='Version of the API.')] +class Coordinates(BaseModel): + model_config = ConfigDict( + extra='forbid', + ) + latitude: Annotated[ + Optional[float], Field(None, description='The latitude of the location') + ] + longitude: Annotated[ + Optional[float], Field(None, description='The longitude of the location') + ] + + +class WikidataLocation(BaseModel): + model_config = ConfigDict( + extra='forbid', + ) + id: Annotated[ + str, + Field( + description='The Q Wikidata ID of the location (https://www.wikidata.org/wiki/Wikidata:Identifiers)' + ), + ] + type: Annotated[Literal['location'], Field(description='The type of the entity')] + labels: Annotated[ + Optional[Mapping[str, Sequence[str]]], + Field(None, description='Labels of the location in different languages'), + ] + descriptions: Annotated[ + Optional[Mapping[str, Sequence[str]]], + Field(None, description='Descriptions of the location in different languages'), + ] + coordinates: Optional[Coordinates] = None + + class ContentItem(BaseModel): model_config = ConfigDict( extra='forbid', @@ -638,3 +649,62 @@ class ContentItem(BaseModel): Optional[Literal['newspaper']], Field(None, description='The type of the media the content item belongs to.'), ] + + +class WikidataHuman(BaseModel): + model_config = ConfigDict( + extra='forbid', + ) + id: Annotated[ + str, + Field( + description='The Q Wikidata ID of the person (https://www.wikidata.org/wiki/Wikidata:Identifiers)' + ), + ] + type: Annotated[Literal['human'], Field(description='The type of the entity')] + labels: Annotated[ + Optional[Mapping[str, Sequence[str]]], + Field(None, description='Labels of the person in different languages'), + ] + descriptions: Annotated[ + Optional[Mapping[str, Sequence[str]]], + Field(None, description='Descriptions of the person in different languages'), + ] + birthDate: Annotated[ + Optional[AwareDatetime], Field(None, description='The birth date of the person') + ] + deathDate: Annotated[ + Optional[AwareDatetime], Field(None, description='The death date of the person') + ] + birthPlace: Annotated[ + Optional[WikidataLocation], + Field(None, description='The birth place of the person'), + ] + deathPlace: Annotated[ + Optional[WikidataLocation], + Field(None, description='The death place of the person'), + ] + + +class EntityDetails(BaseModel): + model_config = ConfigDict( + extra='forbid', + ) + uid: Annotated[str, Field(description='Unique identifier of the entity')] + label: Annotated[Optional[str], Field(None, description='Entity label')] + type: Optional[Literal['person', 'location']] = None + wikidataId: Annotated[ + Optional[str], Field(None, description='Wikidata identifier of the entity.') + ] + totalMentions: Annotated[ + Optional[int], + Field(None, description='Total number of mentions of the entity.'), + ] + totalContentItems: Annotated[ + Optional[int], + Field( + None, + description='Total number of content items the entity is mentioned in.', + ), + ] + wikidataDetails: Optional[Union[WikidataHuman, WikidataLocation]] = None diff --git a/impresso/config_file.py b/impresso/config_file.py index 8cdf257..19541df 100644 --- a/impresso/config_file.py +++ b/impresso/config_file.py @@ -5,7 +5,7 @@ from impresso.util.token import get_jwt_status -DEFAULT_API_URL = "https://impresso-project.ch/public-api" +DEFAULT_API_URL = "https://impresso-project.ch/public-api/v1" class ImpressoApiToken(BaseModel): diff --git a/impresso/resources/entities.py b/impresso/resources/entities.py index 393b01a..6a9536b 100644 --- a/impresso/resources/entities.py +++ b/impresso/resources/entities.py @@ -62,6 +62,7 @@ def find( entity_id: str | AND[str] | OR[str] | None = None, entity_type: EntityType | AND[EntityType] | OR[EntityType] | None = None, order_by: FindEntitiesOrderByLiteral | None = None, + resolve: bool = False, limit: int | None = None, offset: int | None = None, ) -> FindEntitiesContainer: @@ -88,6 +89,7 @@ def find( limit=limit if limit is not None else UNSET, offset=offset if offset is not None else UNSET, filters=filters_pb if filters_pb else UNSET, + resolve=resolve, ) raise_for_error(result) return FindEntitiesContainer( diff --git a/pyproject.toml b/pyproject.toml index a07cf1c..c941935 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -25,7 +25,7 @@ repository = "https://github.com/impresso/impresso-py" version = "0.9.9" [tool.poetry.urls] -Endpoint = "https://impresso-project.ch/public-api" +Endpoint = "https://impresso-project.ch/public-api/v1" Issues = "https://github.com/impresso/impresso-py/issues" [build-system]