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 schema for embed API requests #117

Merged
merged 15 commits into from
Jan 17, 2024
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -107,3 +107,6 @@ tests/testcontent/
# Pycharm project settings
.idea/
*.iml

# pytest
.pytest_cache/
96 changes: 96 additions & 0 deletions js/EmbedRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// -*- coding: utf-8 -*-
// Generated by scripts/generate_from_specs.py
// RecommendationsRequest


export const SCHEMA = {
"$id": "/schemas/embed_request",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "Schema for embed requests received by RayServe",
"additionalProperties": false,
"definitions": {
"ancestors": {
"type": "array",
"description": "The ancestors of the topic, in order, from the parent to the root",
"items": {"$ref": "#/definitions/topic"},
},
"language": {
"type": "string",
"description": "Language code from https://github.com/learningequality/le-utils/blob/main/le_utils/resources/languagelookup.json",
"pattern": "^[a-z]{2,3}(?:-[a-zA-Z]+)?$",
},
"topic": {
"type": "object",
"description": "A topic in the tree structure",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"description": "The ID of the topic content node on Studio",
},
"title": {"type": "string", "description": "The title of the topic"},
"description": {
"type": "string",
"description": "The description of the topic",
},
"language": {"$ref": "#/definitions/language"},
"ancestors": {"$ref": "#/definitions/ancestors"},
},
"required": ["id", "title", "description"],
},
"resource": {
"type": "object",
"description": "The key textual metadata and data for a content resource",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"description": "The ID of the content resource",
},
"title": {
"type": "string",
"description": "The title of the content resource",
},
"description": {
"type": "string",
"description": "The description of the content resource",
},
"text": {
"type": "string",
"description": "The cleaned up text extracted from the content resource (in markdown or plaintext format)",
},
"language": {"$ref": "#/definitions/language"},
},
"required": ["id", "title", "description", "text"],
},
},
"properties": {
"topics": {
"type": "array",
"description": "A list of topics to embed",
"items": {"$ref": "#/definitions/topic"},
},
"resources": {
"type": "array",
"description": "A list of content resources to embed",
"items": {"$ref": "#/definitions/resource"},
},
"metadata": {
"type": "object",
"description": "The metadata of the channel for logging purposes",
"properties": {
"channel_id": {
"type": "string",
"description": "The ID of the channel",
},
"channel_title": {
"type": "string",
"description": "The title of the channel",
},
},
"required": ["channel_id", "channel_title"],
},
},
"required": ["topics", "resources"],
};
105 changes: 105 additions & 0 deletions le_utils/constants/embed_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
# Generated by scripts/generate_from_specs.py
from __future__ import unicode_literals

# RecommendationsRequest


choices = ()

RECOMMENDATIONSREQUESTLIST = []

SCHEMA = {
"$id": "/schemas/embed_request",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "Schema for embed requests received by RayServe",
"additionalProperties": False,
"definitions": {
"ancestors": {
"type": "array",
"description": "The ancestors of the topic, in order, from the parent to the root",
"items": {"$ref": "#/definitions/topic"},
},
"language": {
"type": "string",
"description": "Language code from "
"https://github.com/learningequality/le-utils/blob/main/le_utils/resources/languagelookup"
".json",
"pattern": "^[a-z]{2,3}(?:-[a-zA-Z]+)?$",
},
"topic": {
"type": "object",
"description": "A topic in the tree structure",
"additionalProperties": False,
"properties": {
"id": {
"type": "string",
"description": "The ID of the topic content node on Studio",
},
"title": {"type": "string", "description": "The title of the topic"},
"description": {
"type": "string",
"description": "The description of the topic",
},
"language": {"$ref": "#/definitions/language"},
"ancestors": {"$ref": "#/definitions/ancestors"},
},
"required": ["id", "title", "description"],
},
"resource": {
"type": "object",
"description": "The key textual metadata and data for a content resource",
"additionalProperties": False,
"properties": {
"id": {
"type": "string",
"description": "The ID of the content resource",
},
"title": {
"type": "string",
"description": "The title of the content resource",
},
"description": {
"type": "string",
"description": "The description of the content resource",
},
"text": {
"type": "string",
"description": "The cleaned up text extracted from the content resource (in markdown or plaintext "
"format)",
},
"language": {"$ref": "#/definitions/language"},
},
"required": ["id", "title", "description", "text"],
},
},
"properties": {
"topics": {
"type": "array",
"description": "A list of topics to embed",
"items": {"$ref": "#/definitions/topic"},
},
"resources": {
"type": "array",
"description": "A list of content resources to embed",
"items": {"$ref": "#/definitions/resource"},
},
"metadata": {
"type": "object",
"description": "The metadata of the channel for logging purposes",
"properties": {
"channel_id": {
"type": "string",
"description": "The ID of the channel",
},
"channel_title": {
"type": "string",
"description": "The title of the channel",
},
},
"required": ["channel_id", "channel_title"],
},
},
"required": ["topics", "resources"],
}
11 changes: 11 additions & 0 deletions le_utils/validators/embed_request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import jsonschema

from le_utils.constants.embed_request import SCHEMA


def validate(data):
"""
:param data: Dictionary of data to validate
:raises: jsonschema.ValidationError: When invalid
"""
jsonschema.validate(instance=data, schema=SCHEMA)
25 changes: 15 additions & 10 deletions scripts/generate_from_specs.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,11 @@ def write_js_file(output_file, name, ordered_output, schema=None):
write_js_header(f)
f.write("// {}\n".format(name))
f.write("\n")
f.write("export default {\n")
for key, value in ordered_output.items():
f.write(' {key}: "{value}",\n'.format(key=key, value=value))
f.write("};\n")
if ordered_output:
f.write("export default {\n")
for key, value in ordered_output.items():
f.write(' {key}: "{value}",\n'.format(key=key, value=value))
f.write("};\n")
if schema:
f.write("\n")
f.write("export const SCHEMA = {};\n".format(schema))
Expand All @@ -255,16 +256,20 @@ def write_labels_src_files(label_outputs):

def write_constants_src_files(constants_outputs, schemas):
output_files = []
for constant_type, ordered_output in constants_outputs.items():
keys = set(list(constants_outputs.keys()) + list(schemas.keys()))

for key in keys:
constant_outputs = constants_outputs.get(key, {})
schema = schemas.get(key, None)

py_output_file = os.path.join(
py_output_dir, "{}.py".format(pascal_to_snake(constant_type))
py_output_dir, "{}.py".format(pascal_to_snake(key))
)
schema = schemas.get(constant_type)
write_python_file(py_output_file, constant_type, ordered_output, schema=schema)
write_python_file(py_output_file, key, constant_outputs, schema=schema)
output_files.append(py_output_file)

js_output_file = os.path.join(js_output_dir, "{}.js".format(constant_type))
write_js_file(js_output_file, constant_type, ordered_output, schema=schema)
js_output_file = os.path.join(js_output_dir, "{}.js".format(key))
write_js_file(js_output_file, key, constant_outputs, schema=schema)
output_files.append(js_output_file)
return output_files

Expand Down
77 changes: 77 additions & 0 deletions spec/schema-recommendations_request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"$id": "/schemas/recommendations_request",
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"description": "Schema for recommendations API requests received by RayServe",
"additionalProperties": false,
"definitions": {
"language": {
"type": "string",
"description": "The language code of the topic or channel",
"pattern": "^[a-z]{2,3}(?:-[A-Z]{2})?$"
},
"topic": {
"type": "object",
"description": "A topic in the tree structure for which to generate recommendations",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"description": "The ID of the topic content node on Studio"
},
"title": {
"type": "string",
"description": "The title of the topic"
},
"description": {
"type": "string",
"description": "The description of the topic"
},
"language": {
"$ref": "#/definitions/language"
},
"ancestors": {
"type": "array",
"description": "The ancestors of the channel",
"items": {
"$ref": "#/definitions/topic"
}
}
},
"required": ["id", "title", "description", "language"]
}
},
"properties": {
"target": {
"type": "string",
"description": "The target topic of the channel"
},
"ancestors": {
"type": "array",
"description": "The ancestors of the channel's target topic",
"items": {
"$ref": "#/definitions/topic"
}
},
"metadata": {
"type": "object",
"description": "The metadata of the channel for which to generate recommendations",
"additionalProperties": false,
"properties": {
"id": {
"type": "string",
"description": "The ID of the channel"
},
"title": {
"type": "string",
"description": "The title of the channel"
},
"language": {
"$ref": "#/definitions/language"
}
},
"required": ["id", "title", "language"]
}
},
"required": ["target", "metadata"]
}
Loading
Loading