Commit 2b910b9d authored by Konstantin Schulz's avatar Konstantin Schulz

documentation for the REST API is now complete

parent 2e0e4b74
Pipeline #11833 failed with stages
in 2 minutes and 43 seconds
import rapidjson as json
from mcserver.app.models import AnnisResponse, TextComplexity from mcserver.app.models import AnnisResponse, TextComplexity
from mcserver.app.services import NetworkService, CorpusService, TextComplexityService from mcserver.app.services import NetworkService, CorpusService, TextComplexityService
from openapi.openapi_server.models import TextComplexityForm from openapi.openapi_server.models import TextComplexityForm
...@@ -5,7 +6,7 @@ from openapi.openapi_server.models import TextComplexityForm ...@@ -5,7 +6,7 @@ from openapi.openapi_server.models import TextComplexityForm
def post(complexity_data: dict): def post(complexity_data: dict):
tcf: TextComplexityForm = TextComplexityForm.from_dict(complexity_data) tcf: TextComplexityForm = TextComplexityForm.from_dict(complexity_data)
ar: AnnisResponse = AnnisResponse.from_dict( ar: AnnisResponse = AnnisResponse.from_dict(json.loads(tcf.annis_response)) if tcf.annis_response \
tcf.annis_response.to_dict()) if tcf.annis_response else CorpusService.get_corpus(tcf.urn, is_csm=True) else CorpusService.get_corpus(tcf.urn, is_csm=True)
tc: TextComplexity = TextComplexityService.text_complexity(tcf.measure, tcf.urn, True, ar.graph_data) tc: TextComplexity = TextComplexityService.text_complexity(tcf.measure, tcf.urn, True, ar.graph_data)
return NetworkService.make_json_response(tc.to_dict()) return NetworkService.make_json_response(tc.to_dict())
...@@ -39,4 +39,4 @@ paths: ...@@ -39,4 +39,4 @@ paths:
content: content:
application/x-www-form-urlencoded: application/x-www-form-urlencoded:
schema: schema:
$ref: '../openapi_models.yaml#/components/schemas/TextComplexityFormBase' $ref: '../openapi_models.yaml#/components/schemas/TextComplexityForm'
...@@ -7,6 +7,7 @@ from mcserver.app import db ...@@ -7,6 +7,7 @@ from mcserver.app import db
from mcserver.app.models import Language, VocabularyCorpus, ResourceType from mcserver.app.models import Language, VocabularyCorpus, ResourceType
from mcserver.app.services import NetworkService, FileService from mcserver.app.services import NetworkService, FileService
from mcserver.models_auto import Exercise, UpdateInfo from mcserver.models_auto import Exercise, UpdateInfo
from openapi.openapi_server.models import MatchingExercise
def get(lang: str, frequency_upper_bound: int, last_update_time: int, vocabulary: str = ""): def get(lang: str, frequency_upper_bound: int, last_update_time: int, vocabulary: str = ""):
...@@ -29,13 +30,11 @@ def get(lang: str, frequency_upper_bound: int, last_update_time: int, vocabulary ...@@ -29,13 +30,11 @@ def get(lang: str, frequency_upper_bound: int, last_update_time: int, vocabulary
lang = Language.English lang = Language.English
exercises: List[Exercise] = db.session.query(Exercise).filter_by(language=lang.value) exercises: List[Exercise] = db.session.query(Exercise).filter_by(language=lang.value)
db.session.commit() db.session.commit()
ret_val: List[dict] = [NetworkService.serialize_exercise(x, compress=True) for x in exercises] matching_exercises: List[MatchingExercise] = [MatchingExercise.from_dict(x.to_dict()) for x in exercises]
matching_degrees: List[float] = []
if len(vocabulary_set): if len(vocabulary_set):
for exercise in exercises: for exercise in matching_exercises:
conll: List[TokenList] = conllu.parse(exercise.conll) conll: List[TokenList] = conllu.parse(exercise.conll)
lemmata: List[str] = [tok["lemma"] for sent in conll for tok in sent.tokens] lemmata: List[str] = [tok["lemma"] for sent in conll for tok in sent.tokens]
matching_degrees.append(sum((1 if x in vocabulary_set else 0) for x in lemmata) / len(lemmata) * 100) exercise.matching_degree = sum((1 if x in vocabulary_set else 0) for x in lemmata) / len(lemmata) * 100
for i in range(len(ret_val)): ret_val: List[dict] = [NetworkService.serialize_exercise(x, compress=True) for x in matching_exercises]
ret_val[i]["matching_degree"] = matching_degrees[i]
return NetworkService.make_json_response(ret_val) return NetworkService.make_json_response(ret_val)
...@@ -4,15 +4,10 @@ import os ...@@ -4,15 +4,10 @@ import os
import uuid import uuid
from datetime import datetime from datetime import datetime
from typing import List, Union from typing import List, Union
import connexion import connexion
import flask
from connexion.lifecycle import ConnexionResponse from connexion.lifecycle import ConnexionResponse
from flask import send_from_directory, Response from flask import send_from_directory, Response
from flask_restful import Resource, abort
from flask_restful.reqparse import RequestParser
from werkzeug.wrappers import ETagResponseMixin from werkzeug.wrappers import ETagResponseMixin
from mcserver.app import db from mcserver.app import db
from mcserver.app.models import FileType, ResourceType, DownloadableFile, MimeType, XapiStatement, LearningResultMC from mcserver.app.models import FileType, ResourceType, DownloadableFile, MimeType, XapiStatement, LearningResultMC
from mcserver.app.services import FileService, NetworkService from mcserver.app.services import FileService, NetworkService
......
...@@ -2,15 +2,17 @@ from typing import List, Union ...@@ -2,15 +2,17 @@ from typing import List, Union
import connexion import connexion
from connexion.lifecycle import ConnexionResponse from connexion.lifecycle import ConnexionResponse
from flask import Response from flask import Response
from mcserver import Config from mcserver import Config
from mcserver.app.services import CorpusService, NetworkService, CustomCorpusService from mcserver.app.services import CorpusService, NetworkService, CustomCorpusService
def get(urn: str) -> Union[Response, ConnexionResponse]: def get(urn: str) -> Union[Response, ConnexionResponse]:
"""The GET method for the valid references REST API. It provides references for the desired text.""" """The GET method for the valid references REST API. It provides references for the desired text."""
reff: List[str] = CustomCorpusService.get_custom_corpus_reff(urn) if CustomCorpusService.is_custom_corpus_urn( try:
urn) else CorpusService.get_standard_corpus_reff(urn) reff: List[str] = CustomCorpusService.get_custom_corpus_reff(urn) if CustomCorpusService.is_custom_corpus_urn(
urn) else CorpusService.get_standard_corpus_reff(urn)
except ValueError:
return connexion.problem(400, Config.ERROR_TITLE_BAD_REQUEST, Config.ERROR_MESSAGE_BAD_REQUEST)
if not reff: if not reff:
return connexion.problem(404, Config.ERROR_TITLE_NOT_FOUND, Config.ERROR_MESSAGE_CORPUS_NOT_FOUND) return connexion.problem(404, Config.ERROR_TITLE_NOT_FOUND, Config.ERROR_MESSAGE_CORPUS_NOT_FOUND)
return NetworkService.make_json_response(reff) return NetworkService.make_json_response(reff)
...@@ -2,12 +2,9 @@ import ntpath ...@@ -2,12 +2,9 @@ import ntpath
import os import os
from collections import OrderedDict from collections import OrderedDict
from typing import List, Tuple, Set, Dict from typing import List, Tuple, Set, Dict
import conllu import conllu
import rapidjson as json import rapidjson as json
from conllu import TokenList from conllu import TokenList
from flask_restful import abort
from mcserver import Config from mcserver import Config
from mcserver.app.models import CustomCorpus, CitationLevel, TextPart, Citation, CorpusMC from mcserver.app.models import CustomCorpus, CitationLevel, TextPart, Citation, CorpusMC
from mcserver.app.services import AnnotationService, FileService from mcserver.app.services import AnnotationService, FileService
...@@ -132,7 +129,10 @@ class CustomCorpusService: ...@@ -132,7 +129,10 @@ class CustomCorpusService:
if cts_urn == target_corpus.corpus.source_urn: if cts_urn == target_corpus.corpus.source_urn:
disk_reff = [(":".join([cts_urn, str(x.citation.value)])) for x in target_corpus.text_parts] disk_reff = [(":".join([cts_urn, str(x.citation.value)])) for x in target_corpus.text_parts]
else: else:
disk_reff = CustomCorpusService.get_custom_corpus_sub_reff(cts_urn, target_corpus) try:
disk_reff = CustomCorpusService.get_custom_corpus_sub_reff(cts_urn, target_corpus)
except ValueError:
raise
with open(os.path.join(Config.REFF_CACHE_DIRECTORY, disk_urn), "w+") as f: with open(os.path.join(Config.REFF_CACHE_DIRECTORY, disk_urn), "w+") as f:
f.write(json.dumps(disk_reff)) f.write(json.dumps(disk_reff))
return disk_reff return disk_reff
...@@ -145,7 +145,7 @@ class CustomCorpusService: ...@@ -145,7 +145,7 @@ class CustomCorpusService:
try: try:
citation_parts = [int(x) for x in urn_parts[-1].split(".")] citation_parts = [int(x) for x in urn_parts[-1].split(".")]
except ValueError: except ValueError:
abort(400) raise
target_text_parts: List[TextPart] = target_corpus.text_parts target_text_parts: List[TextPart] = target_corpus.text_parts
if len(citation_parts) > 1: if len(citation_parts) > 1:
target_text_parts = next( target_text_parts = next(
......
...@@ -9,7 +9,8 @@ from flask_restful.reqparse import RequestParser ...@@ -9,7 +9,8 @@ from flask_restful.reqparse import RequestParser
from mcserver import Config from mcserver import Config
from mcserver.app.models import StaticExercise from mcserver.app.models import StaticExercise
from mcserver.models_auto import Exercise, TExercise from mcserver.models_auto import Exercise
from openapi.openapi_server.models import MatchingExercise
class NetworkService: class NetworkService:
...@@ -33,12 +34,12 @@ class NetworkService: ...@@ -33,12 +34,12 @@ class NetworkService:
return response return response
@staticmethod @staticmethod
def serialize_exercise(exercise: TExercise, compress: bool) -> dict: def serialize_exercise(exercise: MatchingExercise, compress: bool) -> dict:
""" Serializes an exercise to JSON format. """ """ Serializes an exercise to JSON format. """
ret_val: dict = exercise.to_dict() exercise.conll = "" if compress else exercise.conll
ret_val["conll"] = "" if compress else exercise.conll
# convert the POSIX timestamp to JSON / Javascript, i.e. from seconds to milliseconds # convert the POSIX timestamp to JSON / Javascript, i.e. from seconds to milliseconds
ret_val["last_access_time"] = exercise.last_access_time * 1000 exercise.last_access_time = exercise.last_access_time * 1000
ret_val: dict = exercise.to_dict()
ret_val["search_values"] = json.loads(exercise.search_values) ret_val["search_values"] = json.loads(exercise.search_values)
ret_val["solutions"] = "[]" if compress else json.loads(exercise.solutions) ret_val["solutions"] = [] if compress else json.loads(exercise.solutions)
return ret_val return ret_val
...@@ -5,6 +5,7 @@ import requests ...@@ -5,6 +5,7 @@ import requests
from mcserver import Config from mcserver import Config
from mcserver.app.models import GraphData, TextComplexity, TextComplexityMeasure, AnnisResponse from mcserver.app.models import GraphData, TextComplexity, TextComplexityMeasure, AnnisResponse
from mcserver.app.services import TextService, AnnotationService, CorpusService from mcserver.app.services import TextService, AnnotationService, CorpusService
from openapi.openapi_server.models import TextComplexityForm
class TextComplexityService: class TextComplexityService:
...@@ -183,6 +184,7 @@ class TextComplexityService: ...@@ -183,6 +184,7 @@ class TextComplexityService:
url: str = f"{Config.INTERNET_PROTOCOL}{Config.HOST_IP_CSM}:" + \ url: str = f"{Config.INTERNET_PROTOCOL}{Config.HOST_IP_CSM}:" + \
f"{Config.CORPUS_STORAGE_MANAGER_PORT}{Config.SERVER_URI_TEXT_COMPLEXITY}" f"{Config.CORPUS_STORAGE_MANAGER_PORT}{Config.SERVER_URI_TEXT_COMPLEXITY}"
ar: AnnisResponse = AnnisResponse(graph_data=gd) ar: AnnisResponse = AnnisResponse(graph_data=gd)
response: requests.Response = requests.post(url, data=json.dumps( tcf: TextComplexityForm = TextComplexityForm(urn=urn, measure=TextComplexityMeasure.all.name,
dict(urn=urn, measure=TextComplexityMeasure.all.name, annis_response=ar.to_dict()))) annis_response=json.dumps(ar.to_dict()))
response: requests.Response = requests.post(url, data=tcf.to_dict())
return TextComplexity.from_dict(json.loads(response.text)) return TextComplexity.from_dict(json.loads(response.text))
...@@ -73,6 +73,9 @@ class Config(object): ...@@ -73,6 +73,9 @@ class Config(object):
DEBUG = False DEBUG = False
DOCKER_SERVICE_NAME_CSM = "csm" DOCKER_SERVICE_NAME_CSM = "csm"
DOCKER_SERVICE_NAME_MCSERVER = "mcserver" DOCKER_SERVICE_NAME_MCSERVER = "mcserver"
ERROR_MESSAGE_BAD_REQUEST = \
"The server cannot or will not process the request due to something that is perceived to be a client " \
"error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing)."
ERROR_MESSAGE_CORPUS_NOT_FOUND = "A corpus with the specified ID was not found!" ERROR_MESSAGE_CORPUS_NOT_FOUND = "A corpus with the specified ID was not found!"
ERROR_MESSAGE_EXERCISE_NOT_FOUND = "An exercise with the specified ID was not found!" ERROR_MESSAGE_EXERCISE_NOT_FOUND = "An exercise with the specified ID was not found!"
ERROR_MESSAGE_INTERNAL_SERVER_ERROR = \ ERROR_MESSAGE_INTERNAL_SERVER_ERROR = \
...@@ -83,6 +86,7 @@ class Config(object): ...@@ -83,6 +86,7 @@ class Config(object):
ERROR_MESSAGE_UNPROCESSABLE_ENTITY = \ ERROR_MESSAGE_UNPROCESSABLE_ENTITY = \
"The server understands the content type of the request entity, and the syntax of the request entity is " \ "The server understands the content type of the request entity, and the syntax of the request entity is " \
"correct, but it was unable to process the contained instructions." "correct, but it was unable to process the contained instructions."
ERROR_TITLE_BAD_REQUEST = "Bad Request"
ERROR_TITLE_INTERNAL_SERVER_ERROR = "Internal Server Error" ERROR_TITLE_INTERNAL_SERVER_ERROR = "Internal Server Error"
ERROR_TITLE_NOT_FOUND = "Not found" ERROR_TITLE_NOT_FOUND = "Not found"
ERROR_TITLE_SERVICE_UNAVAILABLE = "Service Unavailable" ERROR_TITLE_SERVICE_UNAVAILABLE = "Service Unavailable"
......
...@@ -12,7 +12,7 @@ paths: ...@@ -12,7 +12,7 @@ paths:
summary: Returns a list of corpora. summary: Returns a list of corpora.
operationId: mcserver.app.api.corpusListAPI.get operationId: mcserver.app.api.corpusListAPI.get
responses: responses:
200: "200":
description: Corpus list description: Corpus list
content: content:
application/json: application/json:
...@@ -39,7 +39,7 @@ paths: ...@@ -39,7 +39,7 @@ paths:
summary: Deletes a single corpus by ID. summary: Deletes a single corpus by ID.
operationId: mcserver.app.api.corpusAPI.delete operationId: mcserver.app.api.corpusAPI.delete
responses: responses:
200: "200":
description: Indication of success description: Indication of success
content: content:
application/json: application/json:
...@@ -50,7 +50,7 @@ paths: ...@@ -50,7 +50,7 @@ paths:
summary: Returns a single corpus by ID. summary: Returns a single corpus by ID.
operationId: mcserver.app.api.corpusAPI.get operationId: mcserver.app.api.corpusAPI.get
responses: responses:
200: "200":
description: Corpus object description: Corpus object
content: content:
application/json: application/json:
...@@ -60,7 +60,7 @@ paths: ...@@ -60,7 +60,7 @@ paths:
summary: Updates a single corpus by ID. summary: Updates a single corpus by ID.
operationId: mcserver.app.api.corpusAPI.patch operationId: mcserver.app.api.corpusAPI.patch
responses: responses:
200: "200":
description: Corpus object description: Corpus object
content: content:
application/json: application/json:
...@@ -93,7 +93,7 @@ paths: ...@@ -93,7 +93,7 @@ paths:
summary: Returns exercise data by ID. summary: Returns exercise data by ID.
operationId: mcserver.app.api.exerciseAPI.get operationId: mcserver.app.api.exerciseAPI.get
responses: responses:
200: "200":
description: Exercise data object, including a graph model for linguistic annotations. description: Exercise data object, including a graph model for linguistic annotations.
content: content:
application/json: application/json:
...@@ -105,7 +105,7 @@ paths: ...@@ -105,7 +105,7 @@ paths:
summary: Creates a new exercise. summary: Creates a new exercise.
operationId: mcserver.app.api.exerciseAPI.post operationId: mcserver.app.api.exerciseAPI.post
responses: responses:
200: "200":
description: Exercise data object description: Exercise data object
content: content:
application/json: application/json:
...@@ -122,12 +122,14 @@ paths: ...@@ -122,12 +122,14 @@ paths:
summary: Provides metadata for all available exercises. summary: Provides metadata for all available exercises.
operationId: mcserver.app.api.exerciseListAPI.get operationId: mcserver.app.api.exerciseListAPI.get
responses: responses:
200: "200":
description: Data for interactive exercises, excluding the linguistic details. description: Data for interactive exercises, excluding the linguistic details.
content: content:
application/json: application/json:
schema: schema:
$ref: '../openapi_models.yaml#/components/schemas/Exercise' type: array
items:
$ref: '../openapi_models.yaml#/components/schemas/MatchingExercise'
parameters: parameters:
- $ref: '../openapi_models.yaml#/components/parameters/LangParam' - $ref: '../openapi_models.yaml#/components/parameters/LangParam'
- name: frequency_upper_bound - name: frequency_upper_bound
...@@ -157,12 +159,18 @@ paths: ...@@ -157,12 +159,18 @@ paths:
summary: Provides the URL to download a specific file. summary: Provides the URL to download a specific file.
operationId: mcserver.app.api.fileAPI.get operationId: mcserver.app.api.fileAPI.get
responses: responses:
200: "200":
description: Data for interactive exercises, excluding the linguistic details. description: Data for interactive exercises, excluding the linguistic details.
content: content:
application/json: application/pdf:
schema:
type: object
application/vnd.openxmlformats-officedocument.wordprocessingml.document:
schema:
type: object
application/xml:
schema: schema:
$ref: '../openapi_models.yaml#/components/schemas/Exercise' type: object
parameters: parameters:
- name: id - name: id
in: query in: query
...@@ -182,7 +190,7 @@ paths: ...@@ -182,7 +190,7 @@ paths:
summary: Serializes and persists learning results or HTML content for later access. summary: Serializes and persists learning results or HTML content for later access.
operationId: mcserver.app.api.fileAPI.post operationId: mcserver.app.api.fileAPI.post
responses: responses:
200: "200":
description: Indication of success, possibly a reference to the resulting file. description: Indication of success, possibly a reference to the resulting file.
content: content:
application/json: application/json:
...@@ -218,7 +226,7 @@ paths: ...@@ -218,7 +226,7 @@ paths:
summary: Returns results for a frequency query from ANNIS for a given CTS URN. summary: Returns results for a frequency query from ANNIS for a given CTS URN.
operationId: mcserver.app.api.frequencyAPI.get operationId: mcserver.app.api.frequencyAPI.get
responses: responses:
200: "200":
description: Frequency analysis, i.e. a list of frequency items. description: Frequency analysis, i.e. a list of frequency items.
content: content:
application/json: application/json:
...@@ -234,7 +242,7 @@ paths: ...@@ -234,7 +242,7 @@ paths:
summary: Provides JSON templates for client-side H5P exercise layouts. summary: Provides JSON templates for client-side H5P exercise layouts.
operationId: mcserver.app.api.h5pAPI.get operationId: mcserver.app.api.h5pAPI.get
responses: responses:
200: "200":
description: JSON template for an interactive H5P exercise. description: JSON template for an interactive H5P exercise.
content: content:
application/json: application/json:
...@@ -251,7 +259,7 @@ paths: ...@@ -251,7 +259,7 @@ paths:
summary: Provides example contexts for a given phenomenon in a given corpus. summary: Provides example contexts for a given phenomenon in a given corpus.
operationId: mcserver.app.api.kwicAPI.post operationId: mcserver.app.api.kwicAPI.post
responses: responses:
200: "200":
description: HTML strings with SVG elements for rendering KWIC images. description: HTML strings with SVG elements for rendering KWIC images.
content: content:
application/json: application/json:
...@@ -268,7 +276,7 @@ paths: ...@@ -268,7 +276,7 @@ paths:
summary: Provides the raw text for a requested text passage. summary: Provides the raw text for a requested text passage.
operationId: mcserver.app.api.rawTextAPI.get operationId: mcserver.app.api.rawTextAPI.get
responses: responses:
200: "200":
description: Graph data for the text passage, including raw text and annotations. description: Graph data for the text passage, including raw text and annotations.
content: content:
application/json: application/json:
...@@ -281,7 +289,7 @@ paths: ...@@ -281,7 +289,7 @@ paths:
summary: Returns metadata for static exercises. summary: Returns metadata for static exercises.
operationId: mcserver.app.api.staticExercisesAPI.get operationId: mcserver.app.api.staticExercisesAPI.get
responses: responses:
200: "200":
description: Metadata for static exercises, mapped to their respective URIs in the frontend. description: Metadata for static exercises, mapped to their respective URIs in the frontend.
content: content:
application/json: application/json:
...@@ -294,7 +302,7 @@ paths: ...@@ -294,7 +302,7 @@ paths:
summary: Gives users measures of text complexity for a given text. summary: Gives users measures of text complexity for a given text.
operationId: mcserver.app.api.textcomplexityAPI.get operationId: mcserver.app.api.textcomplexityAPI.get
responses: responses:
200: "200":
description: Text complexity measures for a given text. description: Text complexity measures for a given text.
content: content:
application/json: application/json:
...@@ -314,7 +322,7 @@ paths: ...@@ -314,7 +322,7 @@ paths:
summary: Gives users all the citable text references for a corpus. summary: Gives users all the citable text references for a corpus.
operationId: mcserver.app.api.validReffAPI.get operationId: mcserver.app.api.validReffAPI.get
responses: responses:
200: "200":
description: Valid references for the desired text. description: Valid references for the desired text.
content: content:
application/json: application/json:
...@@ -330,7 +338,7 @@ paths: ...@@ -330,7 +338,7 @@ paths:
summary: Provides network data for the vectors in an AI model. summary: Provides network data for the vectors in an AI model.
operationId: mcserver.app.api.vectorNetworkAPI.get operationId: mcserver.app.api.vectorNetworkAPI.get
responses: responses:
200: "200":
description: HTML string with SVG elements for rendering the network graph. description: HTML string with SVG elements for rendering the network graph.
content: content:
application/json: application/json:
...@@ -369,7 +377,7 @@ paths: ...@@ -369,7 +377,7 @@ paths:
summary: Provides network data for the vectors in an AI model. summary: Provides network data for the vectors in an AI model.
operationId: mcserver.app.api.vectorNetworkAPI.post operationId: mcserver.app.api.vectorNetworkAPI.post
responses: responses:
200: "200":
description: Sentences whose content is similar to a given word. description: Sentences whose content is similar to a given word.
content: content:
application/json: application/json:
...@@ -395,7 +403,7 @@ paths: ...@@ -395,7 +403,7 @@ paths:
summary: Shows how well the vocabulary of a text matches a predefined reference vocabulary. summary: Shows how well the vocabulary of a text matches a predefined reference vocabulary.
operationId: mcserver.app.api.vocabularyAPI.get operationId: mcserver.app.api.vocabularyAPI.get
responses: responses:
200: "200":
description: Retrieves sentence ID and matching degree for each sentence in the query text. description: Retrieves sentence ID and matching degree for each sentence in the query text.
content: content:
application/json: application/json:
...@@ -428,7 +436,7 @@ paths: ...@@ -428,7 +436,7 @@ paths:
summary: Shows how well the vocabulary of a text matches a predefined reference vocabulary. summary: Shows how well the vocabulary of a text matches a predefined reference vocabulary.
operationId: mcserver.app.api.vocabularyAPI.post operationId: mcserver.app.api.vocabularyAPI.post
responses: responses:
200: "200":
description: Indicates for each token of a corpus whether it is covered by a reference vocabulary. description: Indicates for each token of a corpus whether it is covered by a reference vocabulary.
content: content:
application/json: application/json:
...@@ -443,7 +451,7 @@ paths: ...@@ -443,7 +451,7 @@ paths:
# include this here so the data model gets generated correctly # include this here so the data model gets generated correctly
components: components:
schemas: schemas:
TextComplexityForm: TextComplexityFormExtension:
type: object type: object
allOf: allOf: