Skip to content

Commit 853afd2

Browse files
authored
Merge pull request #197 from WikiMovimentoBrasil/2025-02-update-code-documentation
docs: update code documentation about the Wikibase REST API
2 parents d124e68 + a7bf13a commit 853afd2

File tree

3 files changed

+36
-39
lines changed

3 files changed

+36
-39
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ Now that everything is set up, we can start **Quickstatements**. We have 2 ways
5050

5151
Now **Quickstatements** is available at http://localhost:8765/
5252

53+
## Wikibase server
54+
55+
QuickStatements 3.0 uses the Wikibase REST API to interact with a Wikibase server. To define which server it is pointing to, define the `BASE_REST_URL` environment variable, pointing to the `rest.php` endpoint, as in `BASE_REST_URL=https://test.wikidata.org/w/rest.php`.
56+
57+
It uses the Wikibase REST API provided in `/wikibase/v1` and the profile endpoint for the Oauth2 API, provided in `/oauth2` to check autoconfirmation status and authorize users.
58+
59+
Currently it's only possible to point at one Wikibase instance.
60+
5361
## OAuth
5462

5563
This application uses OAuth2 with the Mediawiki provider.

src/core/client.py

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
import requests
32
import logging
43

@@ -93,10 +92,20 @@ def from_username(cls, username: str):
9392
# OAuth Token
9493
# ---
9594
def refresh_token_if_needed(self):
95+
"""
96+
The OAuth access token token can expire.
97+
98+
This will check if it's near expiration and
99+
make a call for a new one with the refresh token
100+
if necessary.
101+
"""
96102
if self.token.is_expired() and self.token.refresh_token:
97103
self.refresh_token()
98104

99105
def refresh_token(self):
106+
"""
107+
Refreshes the current `Token` using its refresh token.
108+
"""
100109
logger.debug(f"[{self.token}] Refreshing OAuth token...")
101110

102111
try:
@@ -179,6 +188,10 @@ def wikibase_entity_url(self, entity_id, entity_endpoint):
179188
return self.wikibase_url(endpoint)
180189

181190
def wikibase_request_wrapper(self, method, endpoint, body):
191+
"""
192+
Sends a request to the Wikibase REST API, using the provided
193+
endpoint, method and json body.
194+
"""
182195
kwargs = {
183196
"json": body,
184197
"headers": self.headers(),
@@ -196,12 +209,10 @@ def wikibase_request_wrapper(self, method, endpoint, body):
196209
self.raise_for_status(res)
197210
return res.json()
198211

199-
def wikibase_post(self, endpoint, body):
200-
return self.wikibase_request_wrapper("POST", endpoint, body)
201-
202212
# ---
203213
# Wikibase GET/reading
204214
# ---
215+
205216
@cache_with_first_arg("value_type_cache")
206217
def get_property_value_type(self, property_id):
207218
"""
@@ -279,26 +290,9 @@ def get_labels(self, entity_id):
279290
url = self.wikibase_entity_url(entity_id, "/labels")
280291
return self.get(url).json()
281292

282-
def get_statements(self, entity_id):
283-
"""
284-
Returns all statements for an entity in the form of a dictionary.
285-
286-
The key is the property id, and the value is an array with
287-
the statement objects.
288-
"""
289-
url = self.wikibase_entity_url(entity_id, "/statements")
290-
return self.get(url).json()
291-
292293
def get_entity(self, entity_id):
293294
"""
294295
Returns the entire entity json document.
295296
"""
296297
url = self.wikibase_entity_url(entity_id, "")
297298
return self.get(url).json()
298-
299-
# ---
300-
# Wikibase POST/editing
301-
# ---
302-
def add_statement(self, entity_id, body):
303-
endpoint = self.wikibase_entity_endpoint(entity_id, "/statements")
304-
return self.wikibase_post(endpoint, body)

src/core/models.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ def update_last_id(self, last_id=None):
697697

698698
def run(self, client: Client):
699699
"""
700-
Sends the command to the Wikidata API. This method should not raise exceptions.
700+
Sends the command to the Wikibase API. This method should not raise exceptions.
701701
"""
702702
# If we alredy have an error, just propagate backwards
703703
if self.status == BatchCommand.STATUS_ERROR:
@@ -1008,14 +1008,18 @@ def entity_patch(self, client: Client):
10081008
but the patch needs to be calculated using the original
10091009
entity json, since that's what exists in the wikibase server.
10101010
1011-
TODO: maybe cache that original as well to not make
1012-
two requests?
1011+
The json patch is a series of operations that tell the API
1012+
how to modify the entity's json.
10131013
"""
10141014
original = self.get_original_entity_json(client)
10151015
entity = self.get_previous_entity_json(client)
10161016
self.update_entity_json(entity)
10171017
return jsonpatch.JsonPatch.from_diff(original, entity).patch
10181018

1019+
# ----------------
1020+
# REST API methods
1021+
# ----------------
1022+
10191023
def api_payload(self, client: Client):
10201024
"""
10211025
Returns the data that is sent to the Wikibase API through the body.
@@ -1042,19 +1046,18 @@ def api_body(self, client: Client):
10421046

10431047
def send_to_api(self, client: Client) -> dict:
10441048
"""
1045-
Sends the operation to the Wikibase API.
1049+
Sends the operation to the Wikibase REST API.
10461050
10471051
# Raises
10481052
10491053
- `NotImplementedError` if the operation
10501054
is not implemented.
10511055
"""
1052-
match self.operation:
1053-
case self.Operation.CREATE_PROPERTY:
1054-
raise NotImplementedError()
1055-
case _:
1056-
return self.send_basic(client)
1057-
return {}
1056+
if self.operation == self.Operation.CREATE_PROPERTY:
1057+
raise NotImplementedError()
1058+
method, endpoint = self.operation_method_and_endpoint(client)
1059+
body = self.api_body(client)
1060+
return client.wikibase_request_wrapper(method, endpoint, body)
10581061

10591062
# -----------------
10601063
# Auxiliary methods for Wikibase API interaction
@@ -1075,14 +1078,6 @@ def operation_method_and_endpoint(self, client: Client):
10751078
statement_id = self.json["id"]
10761079
return ("DELETE", f"/statements/{statement_id}")
10771080

1078-
def send_basic(self, client: Client):
1079-
"""
1080-
Sends the request
1081-
"""
1082-
method, endpoint = self.operation_method_and_endpoint(client)
1083-
body = self.api_body(client)
1084-
return client.wikibase_request_wrapper(method, endpoint, body)
1085-
10861081
# -----------------
10871082
# Visualization/label methods
10881083
# -----------------

0 commit comments

Comments
 (0)