Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for parsing globecoordinate data type #28

Merged
merged 10 commits into from
Jul 30, 2020
2 changes: 2 additions & 0 deletions docs/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ To be released.
- Fixed a bug that raised :exc:`~urllib.error.HTTPError` when
non-existent `Entity` was requested. [:pr:`11`]
- Added support for `time` datatypes with precision `9` (year-only). [:pr:`26`]
- Added support for decoding the ``globe-coordinate`` datatype. [:pr:`28`]


Version 0.6.1
-------------
Expand Down
1 change: 1 addition & 0 deletions docs/wikidata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
wikidata/commonsmedia
wikidata/datavalue
wikidata/entity
wikidata/globecoordinate
wikidata/multilingual
3 changes: 3 additions & 0 deletions docs/wikidata/globecoordinate.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

.. automodule:: wikidata.globecoordinate
:members:
21 changes: 20 additions & 1 deletion tests/datavalue_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from wikidata.client import Client
from wikidata.commonsmedia import File
from wikidata.datavalue import DatavalueError, Decoder
from wikidata.entity import Entity
from wikidata.entity import Entity, EntityId
from wikidata.globecoordinate import GlobeCoordinate
from wikidata.multilingual import MonolingualText


Expand Down Expand Up @@ -152,3 +153,21 @@ def test_decoder_commonsMedia__string(fx_client: Client):
{'value': 'The Fabs.JPG', 'type': 'string'})
assert isinstance(f, File)
assert f.title == 'File:The Fabs.JPG'


def test_decoder_globecoordinate(fx_client: Client):
d = Decoder()
decoded = d(fx_client, 'globe-coordinate', {
'value': {
"latitude": 70.1525,
"longitude": 70.1525,
"precision": 0.0002777777777777778,
"globe": "http://www.wikidata.org/entity/Q111"
},
'type': 'globecoordinate'
})
gold = GlobeCoordinate(70.1525,
70.1525,
fx_client.get(EntityId("Q111")),
0.0002777777777777778,)
assert decoded == gold
29 changes: 29 additions & 0 deletions tests/globecoordinate_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from pytest import fixture

from wikidata.client import Client
from wikidata.entity import Entity, EntityId
from wikidata.globecoordinate import GlobeCoordinate


@fixture
def fx_globecoordinate() -> GlobeCoordinate:
client = Client()
return GlobeCoordinate(
latitude=70.1525,
longitude=70.1525,
precision=0.0002777777777777778,
globe=client.get(EntityId("Q111")))


def test_globecoordinate_value(fx_globecoordinate: GlobeCoordinate):
assert fx_globecoordinate.latitude == 70.1525
assert fx_globecoordinate.longitude == 70.1525
assert fx_globecoordinate.precision == 0.0002777777777777778
assert isinstance(fx_globecoordinate.globe, Entity)
assert fx_globecoordinate.globe.id == "Q111"


def test_globecoordinate_repr(fx_globecoordinate: GlobeCoordinate):
assert (repr(fx_globecoordinate) ==
("wikidata.globecoordinate.GlobeCoordinate(70.1525, 70.1525, "
"<wikidata.entity.Entity Q111>, 0.0002777777777777778)"))
19 changes: 18 additions & 1 deletion wikidata/datavalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@
"""
import collections.abc
import datetime
from typing import TYPE_CHECKING, Mapping, Union
from typing import TYPE_CHECKING, Any, Mapping, Union

from .client import Client
from .commonsmedia import File
from .globecoordinate import GlobeCoordinate
from .multilingual import MonolingualText
if TYPE_CHECKING:
from .entity import Entity # noqa: F401
Expand Down Expand Up @@ -220,6 +221,22 @@ def monolingualtext(self,
pair = datavalue['value']
return MonolingualText(pair['text'], pair['language']) # type: ignore

def globecoordinate(self,
client: Client,
datavalue: Mapping[str, Any]) -> GlobeCoordinate:
pair = datavalue['value']
# Try to split out the entity from the globe string.
globe_entity = pair["globe"].split("http://www.wikidata.org/entity/")
if len(globe_entity) != 2:
raise DatavalueError(
"Globe string {} does not appear to be a "
"valid WikiData entity URL".format(pair["globe"]))
entity_id = globe_entity[1]
return GlobeCoordinate(pair['latitude'],
pair['longitude'],
client.get(entity_id),
pair['precision'])

def commonsMedia__string(self,
client: Client,
datavalue: Mapping[str, object]) -> File:
Expand Down
56 changes: 56 additions & 0 deletions wikidata/globecoordinate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
""":mod:`wikidata.globecoordinate` --- Globe coordinate
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

"""
from .entity import Entity
nelson-liu marked this conversation as resolved.
Show resolved Hide resolved

__all__ = 'GlobeCoordinate',


class GlobeCoordinate:
"""
Literal data for a geographical position given as a latitude-longitude pair
in gms or decimal degrees for the given stellar body.
"""

latitude = None # type: float
longitude = None # type: float
globe = None # type: Entity
precision = None # type: float

def __init__(self,
latitude: float,
longitude: float,
globe: Entity,
precision: float) -> None:
self.latitude = latitude
self.longitude = longitude
self.globe = globe
self.precision = precision

def __eq__(self, other) -> bool:
if not isinstance(other, type(self)):
raise TypeError(
'expected an instance of {0.__module__}.{0.__qualname__}, '
'not {1!r}'.format(type(self), other)
)
return (other.latitude == self.latitude and
other.longitude == self.longitude and
other.globe == self.globe and
other.precision == self.precision)

def __hash__(self):
return hash((self.longitude,
self.latitude,
self.globe,
self.precision))
nelson-liu marked this conversation as resolved.
Show resolved Hide resolved

def __repr__(self) -> str:
return ('{0.__module__}.{0.__qualname__}({1!r}, '
'{2!r}, {3!r}, {4!r})').format(
type(self),
self.latitude,
self.longitude,
self.globe,
self.precision
)