-
Couldn't load subscription status.
- Fork 0
Add backend for population management #56
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
base: main
Are you sure you want to change the base?
Changes from 32 commits
1f421da
125a8e0
f88b56b
51a7038
dba14b2
bdd615a
5ca9d81
18d7990
3100850
e3f158d
158709a
13d3b9b
33d48cd
5c248ca
c669028
6139bf0
00c43f5
eb36aa2
cf1db27
121becd
512f4d4
93304fa
cedc27f
dad0ef3
38a6ee4
ed2ca6a
f50ab52
09fa0a5
8c4faea
ac488e6
0278738
2bf9654
5f15c71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| """Statements Management API Resource.""" | ||
|
|
||
| from typing import Dict, Tuple | ||
|
|
||
| from flask import request | ||
| from flask_restful import Resource | ||
|
|
||
| from pkg_api.server.utils import ( | ||
| open_pkg, | ||
| parse_query_statement_population_data, | ||
| ) | ||
|
|
||
|
|
||
| class StatementsManagementResource(Resource): | ||
| def post(self) -> Tuple[Dict[str, str], int]: | ||
| """Adds a statement to the PKG. | ||
| Returns: | ||
| A dictionary containing a message, and the status code. | ||
NoB0 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """ | ||
| data = request.json | ||
| try: | ||
| pkg = open_pkg(data) | ||
| except Exception as e: | ||
| return {"message": str(e)}, 400 | ||
|
|
||
| try: | ||
| pkg_data = parse_query_statement_population_data(data) | ||
| pkg.add_statement(pkg_data) | ||
| pkg.close() | ||
| except Exception as e: | ||
| return {"message": str(e)}, 400 | ||
|
|
||
| return {"message": "Statement added successfully"}, 200 | ||
|
|
||
| def delete(self) -> Tuple[Dict[str, str], int]: | ||
| """Deletes a statement from the PKG. | ||
NoB0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Returns: | ||
| A dictionary containing a message, and the status code. | ||
NoB0 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| """ | ||
| data = request.json | ||
| try: | ||
| pkg = open_pkg(data) | ||
| except Exception as e: | ||
| return {"message": str(e)}, 400 | ||
|
|
||
| try: | ||
| pkg_data = parse_query_statement_population_data(data) | ||
| pkg.remove_statement(pkg_data) | ||
| pkg.close() | ||
| except Exception as e: | ||
| return {"message": str(e)}, 400 | ||
|
|
||
| return {"message": "Statement removed successfully"}, 200 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,19 @@ | ||
| """Utility functions for the server.""" | ||
| from typing import Any, Dict | ||
|
|
||
| import uuid | ||
| from typing import Any, Dict, Union | ||
|
|
||
| from flask import current_app | ||
|
|
||
| from pkg_api.connector import RDFStore | ||
| from pkg_api.core.pkg_types import URI | ||
| from pkg_api.core.pkg_types import ( | ||
| URI, | ||
| Concept, | ||
| PKGData, | ||
| Preference, | ||
| Triple, | ||
| TripleElement, | ||
| ) | ||
| from pkg_api.pkg import PKG | ||
|
|
||
|
|
||
|
|
@@ -14,6 +23,9 @@ def open_pkg(data: Dict[str, str]) -> PKG: | |
| Args: | ||
| data: Request data. | ||
|
|
||
| Raises: | ||
| Exception: If the owner URI is missing. | ||
|
|
||
| Returns: | ||
| A PKG instance. | ||
| """ | ||
|
|
@@ -43,3 +55,64 @@ def parse_query_request_data(data: Dict[str, Any]) -> str: | |
| A string containing SPARQL query. | ||
| """ | ||
| return data.get("sparql_query", None) | ||
|
|
||
|
|
||
| def _parse_triple_element( | ||
| element_data: Union[Dict[str, Any], str] | ||
| ) -> TripleElement: | ||
| """Parses a triple element received from HTTP request. | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Raises block missing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method does not raise any exception. |
||
| Args: | ||
| element_data: Data sent with HTTP request. | ||
|
|
||
| Returns: | ||
| Triple element. | ||
| """ | ||
| if element_data is not None: | ||
| value = ( | ||
| element_data | ||
| if isinstance(element_data, str) | ||
| else element_data.get("value") | ||
| ) | ||
| if isinstance(value, dict): | ||
| return TripleElement(value.get("description"), Concept(**value)) | ||
| elif isinstance(value, str): | ||
| try: | ||
| return TripleElement(value, URI(value)) | ||
| except Exception: | ||
| return TripleElement(value, None) | ||
|
|
||
| return None | ||
|
|
||
|
|
||
| def parse_query_statement_population_data(data: Dict[str, Any]) -> PKGData: | ||
| """Parses the request data to execute SPARQL query. | ||
|
|
||
NoB0 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Args: | ||
| data: Request data. | ||
|
|
||
| Returns: | ||
| Associated PKGData. | ||
| """ | ||
| description = data.get("description", None) | ||
| if description is None: | ||
| raise Exception("Missing description") | ||
|
|
||
| # Parse triple elements | ||
| subject = _parse_triple_element(data.get("subject", None)) | ||
| predicate = _parse_triple_element(data.get("predicate", None)) | ||
| statement_object = _parse_triple_element(data.get("object", None)) | ||
|
|
||
| # Parse preference | ||
| preference = data.get("preference", None) | ||
| if preference and -1.0 <= preference <= 1.0: | ||
| preference = Preference(statement_object, preference) | ||
| else: | ||
| preference = None | ||
|
|
||
| return PKGData( | ||
| id=uuid.uuid1(), | ||
| statement=description, | ||
| triple=Triple(subject, predicate, statement_object), | ||
| preference=preference, | ||
| ) | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| """Tests for the population endpoint.""" | ||
|
|
||
| from typing import Any, Dict | ||
|
|
||
| import pytest | ||
| from flask import Flask | ||
|
|
||
| from pkg_api.core.pkg_types import URI, PKGData, Triple, TripleElement | ||
| from pkg_api.server.utils import open_pkg | ||
|
|
||
|
|
||
| def test_statement_management_with_errors(client: Flask) -> None: | ||
| """Tests /statements endpoint with errors.""" | ||
| response = client.post("/statements", json={}) | ||
| assert response.status_code == 400 | ||
| assert response.get_json() == {"message": "Missing owner URI"} | ||
|
|
||
| response = client.delete("/statements", json={}) | ||
| assert response.status_code == 400 | ||
| assert response.get_json() == {"message": "Missing owner URI"} | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def request_data() -> Dict[str, Any]: | ||
| """Returns request data.""" | ||
| return { | ||
| "owner_uri": "http://example.org/pkg#test", | ||
| "owner_username": "test", | ||
| "description": "I like Tom Cruise", | ||
| "subject": "http://example.org/pkg#test", | ||
| "predicate": {"value": {"description": "like"}}, | ||
| "object": "https://en.wikipedia.org/wiki/Tom_Cruise", | ||
| } | ||
|
|
||
|
|
||
| def test_statement_management_post( | ||
| client: Flask, request_data: Dict[str, Any] | ||
| ) -> None: | ||
| """Tests POST /statements endpoint.""" | ||
| response = client.post("/statements", json=request_data) | ||
| assert response.status_code == 200 | ||
| assert response.get_json() == {"message": "Statement added successfully"} | ||
|
|
||
| with client.application.app_context(): | ||
| pkg = open_pkg(request_data) | ||
| statements = pkg.get_statements( | ||
| PKGData( | ||
| id=None, | ||
| statement="I like Tom Cruise", | ||
| triple=Triple( | ||
| None, | ||
| None, | ||
| TripleElement( | ||
| "Tom Cruise", | ||
| URI("https://en.wikipedia.org/wiki/Tom_Cruise"), | ||
| ), | ||
| ), | ||
| ) | ||
| ) | ||
| assert "I like Tom Cruise" in [ | ||
| statement.statement for statement in statements | ||
| ] | ||
| pkg.close() | ||
|
|
||
|
|
||
| def test_statement_management_delete( | ||
| client: Flask, request_data: Dict[str, Any] | ||
| ) -> None: | ||
| """Tests DELETE /statements endpoint.""" | ||
| response = client.delete("/statements", json=request_data) | ||
| assert response.status_code == 200 | ||
| assert response.get_json() == {"message": "Statement removed successfully"} | ||
|
|
||
| with client.application.app_context(): | ||
| pkg = open_pkg(request_data) | ||
| statements = pkg.get_statements( | ||
| PKGData( | ||
| id=None, | ||
| statement="I like Tom Cruise", | ||
| triple=Triple( | ||
| None, | ||
| None, | ||
| TripleElement( | ||
| "Tom Cruise", | ||
| URI("https://en.wikipedia.org/wiki/Tom_Cruise"), | ||
| ), | ||
| ), | ||
| ) | ||
| ) | ||
| assert "I like Tom Cruise" not in [ | ||
| statement.statement for statement in statements | ||
| ] | ||
| pkg.close() |
Uh oh!
There was an error while loading. Please reload this page.