Skip to content

Commit

Permalink
Merge pull request #649 from NatLibFi/issue644-openapi-3
Browse files Browse the repository at this point in the history
Upgrade REST API spec to OpenAPI 3
  • Loading branch information
osma authored Nov 25, 2022
2 parents 05bb64d + b8f6b8c commit 26a405c
Show file tree
Hide file tree
Showing 6 changed files with 297 additions and 283 deletions.
2 changes: 1 addition & 1 deletion annif/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def create_app(config_name=None):
# 'cxapp' here is the Connexion application that has a normal Flask app
# as a property (cxapp.app)

specdir = os.path.join(os.path.dirname(__file__), "swagger")
specdir = os.path.join(os.path.dirname(__file__), "openapi")
cxapp = connexion.App(__name__, specification_dir=specdir)
if config_name is None:
config_name = os.environ.get("ANNIF_CONFIG")
Expand Down
277 changes: 277 additions & 0 deletions annif/openapi/annif.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
openapi: 3.0.1
info:
title: Annif REST API
version: v1
servers:
- url: /v1
paths:
/projects:
get:
tags:
- Project administration
summary: get a list of projects
operationId: annif.rest.list_projects
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectList'
/projects/{project_id}:
get:
tags:
- Project administration
summary: show project information
operationId: annif.rest.show_project
parameters:
- $ref: '#/components/parameters/project_id'
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/Project'
404:
description: Project not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/projects/{project_id}/suggest:
post:
tags:
- Automatic subject indexing
summary: suggest subjects for a given text
operationId: annif.rest.suggest
parameters:
- $ref: '#/components/parameters/project_id'
requestBody:
content:
application/x-www-form-urlencoded:
schema:
type: object
required:
- text
properties:
text:
type: string
description: input text
limit:
type: integer
description: maximum number of results to return
format: int32
default: 10
minimum: 0
threshold:
type: number
description: minimum score threshold, below which results will not
be returned
default: 0.0
minimum: 0.0
maximum: 1.0
language:
type: string
description: language of subject labels
required: true
responses:
200:
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/SuggestionResultList'
400:
description: Bad Request
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
404:
description: Project not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
503:
description: Service Unavailable
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
/projects/{project_id}/learn:
post:
tags:
- Learning from feedback
summary: learn from manually indexed documents
operationId: annif.rest.learn
parameters:
- $ref: '#/components/parameters/project_id'
requestBody:
description: documents to learn from
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/IndexedDocument'
required: true
responses:
204:
description: successful operation
content: {}
404:
description: Project not found
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
503:
description: Service Unavailable
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
x-codegen-request-body-name: documents
components:
schemas:
ProjectBackend:
required:
- backend_id
type: object
properties:
backend_id:
type: string
example: my-backend
description: A backend of a project
Project:
required:
- backend
- language
- name
- project_id
type: object
properties:
project_id:
type: string
example: my-project
name:
type: string
example: My Project
language:
type: string
example: en
backend:
$ref: '#/components/schemas/ProjectBackend'
is_trained:
type: boolean
example: true
modification_time:
type: string
format: date-time
example: 2020-05-19T16:42:42Z
description: A project definition
ProjectList:
type: object
properties:
projects:
type: array
items:
$ref: '#/components/schemas/Project'
description: A list of projects
SuggestionResult:
required:
- label
- score
- uri
type: object
properties:
uri:
type: string
example: http://example.org/subject1
label:
type: string
example: Archaeology
notation:
type: string
example: "42.42"
score:
type: number
example: 0.85
description: A single candidate subject for a document
SuggestionResultList:
type: object
properties:
results:
type: array
items:
$ref: '#/components/schemas/SuggestionResult'
description: A list of analysis results
IndexedDocument:
type: object
properties:
text:
type: string
example: A quick brown fox jumped over the lazy dog.
subjects:
type: array
items:
type: object
properties:
uri:
type: string
example: http://example.org/subject1
label:
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
parameters:
project_id:
name: project_id
in: path
description: project identifier
required: true
schema:
type: string
example: dummy-fi
13 changes: 8 additions & 5 deletions annif/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _suggestion_to_dict(suggestion, subject_index, language):
}


def suggest(project_id, text, limit, threshold, language=None):
def suggest(project_id, body):
"""suggest subjects for the given text and return a dict with results
formatted according to Swagger spec"""

Expand All @@ -70,7 +70,7 @@ def suggest(project_id, text, limit, threshold, language=None):
return project_not_found_error(project_id)

try:
lang = language or project.vocab_lang
lang = body.get("language") or project.vocab_lang
except AnnifException as err:
return server_error(err)

Expand All @@ -81,9 +81,12 @@ def suggest(project_id, text, limit, threshold, language=None):
detail=f'language "{lang}" not supported by vocabulary',
)

limit = body.get("limit", 10)
threshold = body.get("threshold", 0.0)

try:
hit_filter = SuggestionFilter(project.subjects, limit, threshold)
result = project.suggest(text)
result = project.suggest(body["text"])
except AnnifException as err:
return server_error(err)

Expand All @@ -107,7 +110,7 @@ def _documents_to_corpus(documents, subject_index):
return DocumentList(corpus)


def learn(project_id, documents):
def learn(project_id, body):
"""learn from documents and return an empty 204 response if succesful"""

try:
Expand All @@ -116,7 +119,7 @@ def learn(project_id, documents):
return project_not_found_error(project_id)

try:
corpus = _documents_to_corpus(documents, project.subjects)
corpus = _documents_to_corpus(body, project.subjects)
project.learn(corpus)
except AnnifException as err:
return server_error(err)
Expand Down
Loading

0 comments on commit 26a405c

Please sign in to comment.