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 reconciliation API endpoint to REST API #734

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Fix queries parameter in reconciliation GET request
  • Loading branch information
UnniKohonen committed Sep 8, 2023
commit de054db16f9052919a42491aee455580e0f389b8
191 changes: 127 additions & 64 deletions annif/openapi/annif.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -184,26 +184,38 @@ paths:
get:
tags:
- Reconciliation
summary: reconcile against a project
summary: get reconciliation service manifest or reconcile against a project
operationId: annif.rest.reconcile_metadata
parameters:
- $ref: '#/components/parameters/project_id'
# queries parameter doesn't work for some reason
- in: query
description: A call to the reconciliation service API
name: queries
required: false
schema:
type: object
type: string
additionalProperties:
type: object
required:
- query
- query
properties:
query:
type: string
description: query string
example:
{"q0": {"query": "query"}}
required: false
description: Query string to search for
limit:
type: integer
description: Maximum number of results to return
example:
'{
"q0": {
"query": "example query",
"limit": 10
},
"q1": {
"query": "another example",
"limit": 15
}
}'
responses:
"200":
description: successful operation
Expand All @@ -212,7 +224,53 @@ paths:
schema:
oneOf:
- $ref: '#/components/schemas/ReconcileMetadata'
- $ref: '#/components/schemas/Reconcile'
- $ref: '#/components/schemas/ReconciliationResult'
examples:
ReconcileMetadata:
summary: Reconciliation service manifest
value:
{
"defaultTypes": [
{
"id": "default-type",
"name": "Default type"
}
],
"identifierSpace": "",
"name": "Annif Reconciliation Service for Dummy Finnish",
"schemaSpace": "https://www.w3.org/2004/02/skos/core#Concept",
"versions": [
"0.2"
],
"view": {
"url": "{{id}}"
}
}
ReconciliationResult:
summary: Reconciliation result
value:
{
"q0": {
"result": [
{
"id": "example-id",
"name": "example name",
"score": 0.5,
"match": true
}
]
},
"q1": {
"result": [
{
"id": "another-id",
"name": "another name",
"score": 0.5,
"match": false
}
]
}
}
"404":
$ref: '#/components/responses/NotFound'
post:
Expand All @@ -235,26 +293,27 @@ paths:
properties:
queries:
type: object
description: A call to the reconciliation service API
additionalProperties:
type: object
required:
- query
properties:
query:
type: string
description: query string
description: Query string to search for
limit:
type: integer
description: maximum number of results to return
description: Maximum number of results to return
example:
{
"q0": {
"query": "cat",
"query": "example query",
"limit": 10
},
"q1": {
"query": "dog",
"limit": 10
"query": "another example",
"limit": 15
}
}
required: true
Expand All @@ -264,7 +323,7 @@ paths:
content:
application/json:
schema:
$ref: '#/components/schemas/Reconcile'
$ref: '#/components/schemas/ReconciliationResult'
"404":
$ref: '#/components/responses/NotFound'
components:
Expand Down Expand Up @@ -401,46 +460,6 @@ components:
type: string
example: Vulpes vulpes
description: A document with attached, known good subjects
Problem:
type: object
properties:
type:
type: string
description: |
An absolute URI that identifies the problem type. When dereferenced,
it SHOULD provide human-readable documentation for the problem type
(e.g., using HTML).
format: uri
example: https://zalando.github.io/problem/constraint-violation
default: about:blank
title:
type: string
description: |
A short, summary of the problem type. Written in english and readable
for engineers (usually not suited for non technical stakeholders and
not localized); example: Service Unavailable
status:
maximum: 600
exclusiveMaximum: true
minimum: 100
type: integer
description: |
The HTTP status code generated by the origin server for this occurrence
of the problem.
format: int32
example: 503
detail:
type: string
description: |
A human readable explanation specific to this occurrence of the
problem.
example: Connection to database timed out
instance:
type: string
description: |
An absolute URI that identifies the specific occurrence of the problem.
It may or may not yield further information if dereferenced.
format: uri
ReconcileMetadata:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could be better to call this type ReconciliationServiceManifest (although it's pretty long...) so that it matches the reconciliation API spec.

required:
- name
Expand All @@ -459,7 +478,7 @@ components:
example: ""
schemaSpace:
type: string
example: ""
example: "https://www.w3.org/2004/02/skos/core#Concept"
defaultTypes:
type: array
items:
Expand All @@ -470,25 +489,25 @@ components:
properties:
id:
type: string
example: type_id
example: type-id
name:
type: string
example: type_name
example: type name
view:
type: object
required:
- url
properties:
url:
type: string
example: '{{id}}'
example: "{{id}}"
versions:
type: array
items:
type: string
example: 0.2
description: Reconciliation service information
Reconcile:
ReconciliationResult:
type: object
additionalProperties:
type: object
Expand All @@ -507,19 +526,23 @@ components:
properties:
id:
type: string
example: example-id
name:
type: string
example: example name
score:
type: number
example: 0.5
match:
type: boolean
example: true
example:
{
"q0": {
"result": [
{
"id": "id0",
"name": "name0",
"id": "example-id",
"name": "example name",
"score": 0.5,
"match": true
}
Expand All @@ -528,14 +551,54 @@ components:
"q1": {
"result": [
{
"id": "id1",
"name": "name1",
"id": "another-id",
"name": "another name",
"score": 0.5,
"match": false
}
]
}
}
Problem:
type: object
properties:
type:
type: string
description: |
An absolute URI that identifies the problem type. When dereferenced,
it SHOULD provide human-readable documentation for the problem type
(e.g., using HTML).
format: uri
example: https://zalando.github.io/problem/constraint-violation
default: about:blank
title:
type: string
description: |
A short, summary of the problem type. Written in english and readable
for engineers (usually not suited for non technical stakeholders and
not localized); example: Service Unavailable
status:
maximum: 600
exclusiveMaximum: true
minimum: 100
type: integer
description: |
The HTTP status code generated by the origin server for this occurrence
of the problem.
format: int32
example: 503
detail:
type: string
description: |
A human readable explanation specific to this occurrence of the
problem.
example: Connection to database timed out
instance:
type: string
description: |
An absolute URI that identifies the specific occurrence of the problem.
It may or may not yield further information if dereferenced.
format: uri
parameters:
project_id:
name: project_id
Expand Down
14 changes: 12 additions & 2 deletions annif/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import importlib
import json
from typing import TYPE_CHECKING, Any

import connexion
Expand Down Expand Up @@ -252,11 +253,20 @@ def reconcile_metadata(
"versions": ["0.2"],
"name": "Annif Reconciliation Service for " + project.name,
"identifierSpace": "",
"schemaSpace": "",
"schemaSpace": "https://www.w3.org/2004/02/skos/core#Concept",
"view": {"url": "{{id}}"},
"defaultTypes": [{"id": "default-type", "name": "Default type"}],
}
else:
return {}
queries = json.loads(query_parameters["queries"])
results = {}
for key, query in queries.items():
data = _reconcile(project_id, query)
if _is_error(data):
return data
results[key] = {"result": data}

return results


def reconcile(
Expand Down
18 changes: 17 additions & 1 deletion tests/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,22 @@ def test_rest_reocncile_metadata_nonexistent(app):
assert result.status_code == 404


def test_rest_reconcile_metadata_queries(app):
with app.app_context():
results = annif.rest.reconcile_metadata(
"dummy-fi", queries='{"q0": {"query": "example text"}}'
)
assert "result" in results["q0"]


def test_rest_reconcile_metadata_queries_nonexistent(app):
with app.app_context():
result = annif.rest.reconcile_metadata(
"nonexistent", queries='{"q0": {"query": "example text"}}'
)
assert result.status_code == 404


def test_rest_reconcile(app):
with app.app_context():
results = annif.rest.reconcile(
Expand All @@ -255,7 +271,7 @@ def test_rest_reconcile(app):
assert "result" in results["q0"]


def test_test_reconcile_nonexistent(app):
def test_rest_reconcile_nonexistent(app):

Check warning

Code scanning / CodeQL

Variable defined multiple times Warning test

This assignment to 'test_rest_reconcile_nonexistent' is unnecessary as it is
redefined
before this value is used.
with app.app_context():
result = annif.rest.reconcile(
"nonexistent", {"queries": {"q0": {"query": "example text"}}}
Expand Down
Loading