From 4472c124dd76869be7bcd2ffb26b2b7ec426c073 Mon Sep 17 00:00:00 2001 From: Blaine Jester Date: Thu, 2 Nov 2023 11:03:18 -0700 Subject: [PATCH 01/15] Add schema for recommendations API requests Co-authored-by: Samson Akol --- spec/recommendations-v1.json | 80 ++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 spec/recommendations-v1.json diff --git a/spec/recommendations-v1.json b/spec/recommendations-v1.json new file mode 100644 index 0000000..5212777 --- /dev/null +++ b/spec/recommendations-v1.json @@ -0,0 +1,80 @@ +{ + "$id": "/schemas/recommendations_request", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "description": "Schema for recommendations API requests received by TorchServe", + "additionalProperties": false, + "definitions": { + "language": { + "type": "string", + "description": "The language code of the topic", + "pattern": "^[a-z]{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", + "format": "uuid", + "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" + }, + "subtopics": { + "type": "array", + "description": "The subtopics of the topic", + "items": { + "$ref": "#/definitions/topic" + } + } + }, + "required": ["id", "title", "description", "language", "subtopics"] + } + }, + "properties": { + "category": { + "type": "string", + "description": "The category of the model", + "enum": ["aligned"] + }, + "channel": { + "type": "object", + "description": "The channel and topic tree for which to generate recommendations", + "additionalProperties": false, + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "The ID of the channel" + }, + "title": { + "type": "string", + "description": "The title of the channel" + }, + "language": { + "$ref": "#/definitions/language" + }, + "subtopics": { + "type": "array", + "description": "The subtopics of the channel", + "items": { + "$ref": "#/definitions/topic" + } + } + }, + "required": ["id", "title", "language", "subtopics"] + } + }, + "required": ["category", "channel"] +} \ No newline at end of file From 87b5cd14ee5ee0439b959114fdfd4f21908b9f6e Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Thu, 11 Jan 2024 00:19:09 +0300 Subject: [PATCH 02/15] flattens schema and updates annotations --- spec/recommendations-v1.json | 38 +++++++++++++++++------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/spec/recommendations-v1.json b/spec/recommendations-v1.json index 5212777..1b861a5 100644 --- a/spec/recommendations-v1.json +++ b/spec/recommendations-v1.json @@ -2,12 +2,12 @@ "$id": "/schemas/recommendations_request", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", - "description": "Schema for recommendations API requests received by TorchServe", + "description": "Schema for recommendations API requests received by RayServe", "additionalProperties": false, "definitions": { "language": { "type": "string", - "description": "The language code of the topic", + "description": "The language code of the topic or channel", "pattern": "^[a-z]{3}(?:-[A-Z]{2})?$" }, "topic": { @@ -31,31 +31,36 @@ "language": { "$ref": "#/definitions/language" }, - "subtopics": { + "ancestors": { "type": "array", - "description": "The subtopics of the topic", + "description": "The ancestors of the channel", "items": { "$ref": "#/definitions/topic" } } }, - "required": ["id", "title", "description", "language", "subtopics"] + "required": ["id", "title", "description", "language"] } }, "properties": { - "category": { + "target": { "type": "string", - "description": "The category of the model", - "enum": ["aligned"] + "description": "The target topic of the channel" }, - "channel": { + "ancestors": { + "type": "array", + "description": "The ancestors of the channel's target topic", + "items": { + "$ref": "#/definitions/topic" + } + }, + "metadata": { "type": "object", - "description": "The channel and topic tree for which to generate recommendations", + "description": "The metadata of the channel for which to generate recommendations", "additionalProperties": false, "properties": { "id": { "type": "string", - "format": "uuid", "description": "The ID of the channel" }, "title": { @@ -64,17 +69,10 @@ }, "language": { "$ref": "#/definitions/language" - }, - "subtopics": { - "type": "array", - "description": "The subtopics of the channel", - "items": { - "$ref": "#/definitions/topic" - } } }, - "required": ["id", "title", "language", "subtopics"] + "required": ["id", "title", "language"] } }, - "required": ["category", "channel"] + "required": ["target", "metadata"] } \ No newline at end of file From 2bc82874bf8861fe9329e990282f9f52faf26b72 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Thu, 11 Jan 2024 00:23:58 +0300 Subject: [PATCH 03/15] Removes uuid validation from id --- spec/recommendations-v1.json | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/recommendations-v1.json b/spec/recommendations-v1.json index 1b861a5..3212c8c 100644 --- a/spec/recommendations-v1.json +++ b/spec/recommendations-v1.json @@ -17,7 +17,6 @@ "properties": { "id": { "type": "string", - "format": "uuid", "description": "The ID of the topic content node on Studio" }, "title": { From f29bcfe0e8ab91bb5f592dc48d88ac0f0a8e7a8c Mon Sep 17 00:00:00 2001 From: Blaine Jester Date: Thu, 11 Jan 2024 10:29:11 -0800 Subject: [PATCH 04/15] Enable building with generate script, add test --- js/RecommendationsRequest.js | 82 +++++++++++++++++ le_utils/constants/recommendations_request.py | 68 ++++++++++++++ .../validators/recommendations_request.py | 11 +++ scripts/generate_from_specs.py | 25 +++-- ...on => schema-recommendations_request.json} | 2 +- tests/test_schemas.py | 91 +++++++++++++------ 6 files changed, 241 insertions(+), 38 deletions(-) create mode 100644 js/RecommendationsRequest.js create mode 100644 le_utils/constants/recommendations_request.py create mode 100644 le_utils/validators/recommendations_request.py rename spec/{recommendations-v1.json => schema-recommendations_request.json} (97%) diff --git a/js/RecommendationsRequest.js b/js/RecommendationsRequest.js new file mode 100644 index 0000000..a34ec42 --- /dev/null +++ b/js/RecommendationsRequest.js @@ -0,0 +1,82 @@ +// -*- coding: utf-8 -*- +// Generated by scripts/generate_from_specs.py +// RecommendationsRequest + + +export const SCHEMA = { + "$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"] +}; diff --git a/le_utils/constants/recommendations_request.py b/le_utils/constants/recommendations_request.py new file mode 100644 index 0000000..0e24a87 --- /dev/null +++ b/le_utils/constants/recommendations_request.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +# Generated by scripts/generate_from_specs.py +from __future__ import unicode_literals + +# RecommendationsRequest + + +choices = () + +RECOMMENDATIONSREQUESTLIST = [] + +SCHEMA = { + "$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"], +} diff --git a/le_utils/validators/recommendations_request.py b/le_utils/validators/recommendations_request.py new file mode 100644 index 0000000..2c69744 --- /dev/null +++ b/le_utils/validators/recommendations_request.py @@ -0,0 +1,11 @@ +import jsonschema + +from le_utils.constants.recommendations_request import SCHEMA + + +def validate(data): + """ + :param data: Dictionary of data to validate + :raises: jsonschema.ValidationError: When invalid + """ + jsonschema.validate(instance=data, schema=SCHEMA) diff --git a/scripts/generate_from_specs.py b/scripts/generate_from_specs.py index 8032f58..cbcadcf 100644 --- a/scripts/generate_from_specs.py +++ b/scripts/generate_from_specs.py @@ -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)) @@ -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 diff --git a/spec/recommendations-v1.json b/spec/schema-recommendations_request.json similarity index 97% rename from spec/recommendations-v1.json rename to spec/schema-recommendations_request.json index 3212c8c..f1d545c 100644 --- a/spec/recommendations-v1.json +++ b/spec/schema-recommendations_request.json @@ -8,7 +8,7 @@ "language": { "type": "string", "description": "The language code of the topic or channel", - "pattern": "^[a-z]{3}(?:-[A-Z]{2})?$" + "pattern": "^[a-z]{2,3}(?:-[A-Z]{2})?$" }, "topic": { "type": "object", diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 4553173..ef41211 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -7,6 +7,9 @@ from le_utils.constants import completion_criteria from le_utils.constants import mastery_criteria +from le_utils.validators.recommendations_request import ( + validate as validate_recommendations_request, +) try: @@ -26,7 +29,7 @@ ) -def _validate(data): +def _validate_completion_criteria(data): """ :param data: Dictionary of data to validate :raises: jsonschema.ValidationError: When invalid @@ -51,8 +54,10 @@ def _assert_not_raises(not_expected): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__time_model__valid(): with _assert_not_raises(jsonschema.ValidationError): - _validate({"model": "time", "threshold": 2, "learner_managed": False}) - _validate( + _validate_completion_criteria( + {"model": "time", "threshold": 2, "learner_managed": False} + ) + _validate_completion_criteria( { "model": "time", "threshold": 1200123, @@ -63,7 +68,7 @@ def test_completion_criteria__time_model__valid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__time_model__invalid(): with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "time", "threshold": {"mastery_model": "not_real"}, @@ -71,7 +76,7 @@ def test_completion_criteria__time_model__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "time", "threshold": -1, @@ -82,8 +87,10 @@ def test_completion_criteria__time_model__invalid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__approx_time_model__valid(): with _assert_not_raises(jsonschema.ValidationError): - _validate({"model": "approx_time", "threshold": 2, "learner_managed": False}) - _validate( + _validate_completion_criteria( + {"model": "approx_time", "threshold": 2, "learner_managed": False} + ) + _validate_completion_criteria( { "model": "approx_time", "threshold": 1200123, @@ -94,7 +101,7 @@ def test_completion_criteria__approx_time_model__valid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__approx_time_model__invalid(): with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "approx_time", "threshold": {"mastery_model": "not_real"}, @@ -102,7 +109,7 @@ def test_completion_criteria__approx_time_model__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "approx_time", "threshold": -1, @@ -113,8 +120,10 @@ def test_completion_criteria__approx_time_model__invalid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__pages_model__valid(): with _assert_not_raises(jsonschema.ValidationError): - _validate({"model": "pages", "threshold": 2, "learner_managed": False}) - _validate( + _validate_completion_criteria( + {"model": "pages", "threshold": 2, "learner_managed": False} + ) + _validate_completion_criteria( { "model": "pages", "threshold": 1200123, @@ -125,13 +134,13 @@ def test_completion_criteria__pages_model__valid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__pages_model__percentage__valid(): with _assert_not_raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "pages", "threshold": "99%", } ) - _validate( + _validate_completion_criteria( { "model": "pages", "threshold": "1%", @@ -142,7 +151,7 @@ def test_completion_criteria__pages_model__percentage__valid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__pages_model__invalid(): with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "pages", "threshold": {"mastery_model": "not_real"}, @@ -150,7 +159,7 @@ def test_completion_criteria__pages_model__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "pages", "threshold": -1, @@ -161,7 +170,7 @@ def test_completion_criteria__pages_model__invalid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__pages_model__percentage__invalid(): with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "pages", "threshold": "0%", @@ -169,7 +178,7 @@ def test_completion_criteria__pages_model__percentage__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "pages", "threshold": "101%", @@ -180,14 +189,14 @@ def test_completion_criteria__pages_model__percentage__invalid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__mastery_model__valid(): with _assert_not_raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "mastery", "threshold": {"mastery_model": "do_all"}, "learner_managed": False, } ) - _validate( + _validate_completion_criteria( { "model": "mastery", "threshold": {"mastery_model": "m_of_n", "m": 1, "n": 2}, @@ -198,7 +207,7 @@ def test_completion_criteria__mastery_model__valid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__mastery_model__invalid(): with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "mastery", "threshold": {"mastery_model": "m_of_n"}, @@ -206,7 +215,7 @@ def test_completion_criteria__mastery_model__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "mastery", "threshold": {"mastery_model": "do_all", "m": 1}, @@ -214,7 +223,7 @@ def test_completion_criteria__mastery_model__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "mastery", "threshold": {"mastery_model": "not_real"}, @@ -222,7 +231,7 @@ def test_completion_criteria__mastery_model__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "mastery", "threshold": -1, @@ -233,8 +242,8 @@ def test_completion_criteria__mastery_model__invalid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__reference__valid(): with _assert_not_raises(jsonschema.ValidationError): - _validate({"model": "reference", "learner_managed": False}) - _validate( + _validate_completion_criteria({"model": "reference", "learner_managed": False}) + _validate_completion_criteria( { "model": "reference", } @@ -244,7 +253,7 @@ def test_completion_criteria__reference__valid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_completion_criteria__reference__invalid(): with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "reference", "threshold": 1, @@ -252,10 +261,38 @@ def test_completion_criteria__reference__invalid(): } ) with pytest.raises(jsonschema.ValidationError): - _validate( + _validate_completion_criteria( { "model": "reference", "threshold": {"mastery_model": "do_all"}, "learner_managed": False, } ) + + +@pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") +def test_recommendations__topic__valid(): + with _assert_not_raises(jsonschema.ValidationError): + validate_recommendations_request( + { + "target": { + "id": "456", + "title": "Target topic", + "description": "Target description", + "language": "en", + }, + "ancestors": [ + { + "id": "123", + "title": "Parent title", + "description": "Parent description", + "language": "en", + }, + ], + "metadata": { + "id": "000", + "title": "Channel title", + "language": "en", + }, + } + ) From eb0a7263b4df3f530e1d82e3eadde51adc221bb7 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 15:25:22 +0300 Subject: [PATCH 05/15] Adds feedback and fixes failing validation test --- .gitignore | 3 + le_utils/constants/recommendations_request.py | 72 +++++++++++-------- tests/test_schemas.py | 31 ++++---- 3 files changed, 64 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 0e78518..05f4cb8 100644 --- a/.gitignore +++ b/.gitignore @@ -107,3 +107,6 @@ tests/testcontent/ # Pycharm project settings .idea/ *.iml + +# pytest +.pytest_cache/ diff --git a/le_utils/constants/recommendations_request.py b/le_utils/constants/recommendations_request.py index 0e24a87..1f6393b 100644 --- a/le_utils/constants/recommendations_request.py +++ b/le_utils/constants/recommendations_request.py @@ -10,59 +10,75 @@ RECOMMENDATIONSREQUESTLIST = [] SCHEMA = { - "$id": "/schemas/recommendations_request", + "$id": "/schemas/embed_request", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", - "description": "Schema for recommendations API requests received by RayServe", + "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": "The language code of the topic or channel", - "pattern": "^[a-z]{2,3}(?:-[A-Z]{2})?$", + "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 for which to generate recommendations", + "description": "A topic in the tree structure", "additionalProperties": False, "properties": { - "id": { - "type": "string", - "description": "The ID of the topic content node on Studio", - }, + "id": {"type": "string", "description": "The ID of the topic content node on Studio"}, "title": {"type": "string", "description": "The title of the topic"}, - "description": { + "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 description of the topic", + "description": "The cleaned up text extracted from the content resource (in markdown or plaintext " + "format)" }, "language": {"$ref": "#/definitions/language"}, - "ancestors": { - "type": "array", - "description": "The ancestors of the channel", - "items": {"$ref": "#/definitions/topic"}, - }, }, - "required": ["id", "title", "description", "language"], + "required": ["id", "title", "description", "text"] }, }, "properties": { - "target": {"type": "string", "description": "The target topic of the channel"}, - "ancestors": { + "topics": { "type": "array", - "description": "The ancestors of the channel's target topic", - "items": {"$ref": "#/definitions/topic"}, + "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 which to generate recommendations", - "additionalProperties": False, + "description": "The metadata of the channel for logging purposes", "properties": { - "id": {"type": "string", "description": "The ID of the channel"}, - "title": {"type": "string", "description": "The title of the channel"}, - "language": {"$ref": "#/definitions/language"}, + "channel_id": {"type": "string", "description": "The ID of the channel"}, + "channel_title": {"type": "string", "description": "The title of the channel"} }, - "required": ["id", "title", "language"], + "required": ["channel_id", "channel_title"] }, }, - "required": ["target", "metadata"], + "required": ["topics", "resources"] } diff --git a/tests/test_schemas.py b/tests/test_schemas.py index ef41211..af7d297 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -275,24 +275,27 @@ def test_recommendations__topic__valid(): with _assert_not_raises(jsonschema.ValidationError): validate_recommendations_request( { - "target": { - "id": "456", - "title": "Target topic", - "description": "Target description", - "language": "en", - }, - "ancestors": [ + "topics": [ + { + "id": "456", + "title": "Target topic", + "description": "Target description", + "language": "en" + } + ], + "resources": [ { "id": "123", - "title": "Parent title", - "description": "Parent description", - "language": "en", + "title": "Resource title", + "description": "Resource description", + "text": "Resource text", + "language": "en" }, ], "metadata": { - "id": "000", - "title": "Channel title", - "language": "en", - }, + "channel_id": "000", + "channel_title": "Channel title", + "some_additional_field": "some_random_value" + } } ) From 30fe07f4d2fe2aa19439cb5d4c263ebb3506e6d2 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 15:34:02 +0300 Subject: [PATCH 06/15] Fixes linting noise --- tests/test_schemas.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index af7d297..65f3853 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -280,7 +280,7 @@ def test_recommendations__topic__valid(): "id": "456", "title": "Target topic", "description": "Target description", - "language": "en" + "language": "en", } ], "resources": [ @@ -289,13 +289,13 @@ def test_recommendations__topic__valid(): "title": "Resource title", "description": "Resource description", "text": "Resource text", - "language": "en" + "language": "en", }, ], "metadata": { "channel_id": "000", "channel_title": "Channel title", - "some_additional_field": "some_random_value" - } + "some_additional_field": "some_random_value", + }, } ) From aea321e62af9777d5cd4d8256cd4df196856f904 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 15:41:15 +0300 Subject: [PATCH 07/15] Fixes more linting noise --- le_utils/constants/recommendations_request.py | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/le_utils/constants/recommendations_request.py b/le_utils/constants/recommendations_request.py index 1f6393b..4422897 100644 --- a/le_utils/constants/recommendations_request.py +++ b/le_utils/constants/recommendations_request.py @@ -24,8 +24,8 @@ "language": { "type": "string", "description": "Language code from " - "https://github.com/learningequality/le-utils/blob/main/le_utils/resources/languagelookup" - ".json", + "https://github.com/learningequality/le-utils/blob/main/le_utils/resources/languagelookup" + ".json", "pattern": "^[a-z]{2,3}(?:-[a-zA-Z]+)?$", }, "topic": { @@ -33,11 +33,17 @@ "description": "A topic in the tree structure", "additionalProperties": False, "properties": { - "id": {"type": "string", "description": "The ID of the topic content node on Studio"}, + "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"}, + "description": { + "type": "string", + "description": "The description of the topic", + }, "language": {"$ref": "#/definitions/language"}, - "ancestors": {"$ref": "#/definitions/ancestors"} + "ancestors": {"$ref": "#/definitions/ancestors"}, }, "required": ["id", "title", "description"], }, @@ -46,39 +52,54 @@ "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"}, + "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)" + "format)", }, "language": {"$ref": "#/definitions/language"}, }, - "required": ["id", "title", "description", "text"] + "required": ["id", "title", "description", "text"], }, }, "properties": { "topics": { "type": "array", "description": "A list of topics to embed", - "items": {"$ref": "#/definitions/topic"} + "items": {"$ref": "#/definitions/topic"}, }, "resources": { "type": "array", "description": "A list of content resources to embed", - "items": {"$ref": "#/definitions/resource"} + "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"} + "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": ["channel_id", "channel_title"], }, }, - "required": ["topics", "resources"] + "required": ["topics", "resources"], } From d43090dff0d31b37ab4803735535405e0692f049 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 15:48:09 +0300 Subject: [PATCH 08/15] updates js version of schema --- js/RecommendationsRequest.js | 150 +++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 68 deletions(-) diff --git a/js/RecommendationsRequest.js b/js/RecommendationsRequest.js index a34ec42..2e37169 100644 --- a/js/RecommendationsRequest.js +++ b/js/RecommendationsRequest.js @@ -4,79 +4,93 @@ export const SCHEMA = { - "$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" + "$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"}, }, - "title": { - "type": "string", - "description": "The title of the 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]+)?$", }, - "description": { - "type": "string", - "description": "The description of the topic" + "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"], }, - "language": { - "$ref": "#/definitions/language" + "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"], }, - "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" + "properties": { + "topics": { + "type": "array", + "description": "A list of topics to embed", + "items": {"$ref": "#/definitions/topic"}, }, - "title": { - "type": "string", - "description": "The title of the channel" + "resources": { + "type": "array", + "description": "A list of content resources to embed", + "items": {"$ref": "#/definitions/resource"}, }, - "language": { - "$ref": "#/definitions/language" - } - }, - "required": ["id", "title", "language"] - } - }, - "required": ["target", "metadata"] + "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"], }; From c050428fba8be6db71bf5a47a1a550e5b1899208 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 15:54:12 +0300 Subject: [PATCH 09/15] Renames files for clarity --- js/{RecommendationsRequest.js => EmbedRequest.js} | 0 .../constants/{recommendations_request.py => embed_request.py} | 0 .../validators/{recommendations_request.py => embed_request.py} | 2 +- tests/test_schemas.py | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) rename js/{RecommendationsRequest.js => EmbedRequest.js} (100%) rename le_utils/constants/{recommendations_request.py => embed_request.py} (100%) rename le_utils/validators/{recommendations_request.py => embed_request.py} (77%) diff --git a/js/RecommendationsRequest.js b/js/EmbedRequest.js similarity index 100% rename from js/RecommendationsRequest.js rename to js/EmbedRequest.js diff --git a/le_utils/constants/recommendations_request.py b/le_utils/constants/embed_request.py similarity index 100% rename from le_utils/constants/recommendations_request.py rename to le_utils/constants/embed_request.py diff --git a/le_utils/validators/recommendations_request.py b/le_utils/validators/embed_request.py similarity index 77% rename from le_utils/validators/recommendations_request.py rename to le_utils/validators/embed_request.py index 2c69744..d7584d2 100644 --- a/le_utils/validators/recommendations_request.py +++ b/le_utils/validators/embed_request.py @@ -1,6 +1,6 @@ import jsonschema -from le_utils.constants.recommendations_request import SCHEMA +from le_utils.constants.embed_request import SCHEMA def validate(data): diff --git a/tests/test_schemas.py b/tests/test_schemas.py index 65f3853..f82fe30 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -7,7 +7,7 @@ from le_utils.constants import completion_criteria from le_utils.constants import mastery_criteria -from le_utils.validators.recommendations_request import ( +from le_utils.validators.embed_request import ( validate as validate_recommendations_request, ) From d08adbe0e289850d530994e9095cc3e97b2bdd61 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 18:19:02 +0300 Subject: [PATCH 10/15] add __init__.py to validators/ --- le_utils/validators/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 le_utils/validators/__init__.py diff --git a/le_utils/validators/__init__.py b/le_utils/validators/__init__.py new file mode 100644 index 0000000..e69de29 From 9ae773261b1b03187c6cf6fca1e579961621c008 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 18:31:48 +0300 Subject: [PATCH 11/15] run regenerate schema file --- js/EmbedRequest.js | 190 +++++++++++++---------- le_utils/constants/embed_request.py | 11 +- spec/schema-embed_request.json | 121 +++++++++++++++ spec/schema-recommendations_request.json | 77 --------- 4 files changed, 235 insertions(+), 164 deletions(-) create mode 100644 spec/schema-embed_request.json delete mode 100644 spec/schema-recommendations_request.json diff --git a/js/EmbedRequest.js b/js/EmbedRequest.js index 2e37169..9337f7f 100644 --- a/js/EmbedRequest.js +++ b/js/EmbedRequest.js @@ -1,96 +1,126 @@ // -*- coding: utf-8 -*- // Generated by scripts/generate_from_specs.py -// RecommendationsRequest +// EmbedRequest 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"}, + "$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" }, - "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]+)?$", + "title": { + "type": "string", + "description": "The title of the topic" }, - "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"], + "description": { + "type": "string", + "description": "The description of the topic" }, - "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"], + "language": { + "$ref": "#/definitions/language" }, + "ancestors": { + "$ref": "#/definitions/ancestors" + } + }, + "required": [ + "id", + "title", + "description" + ] }, - "properties": { - "topics": { - "type": "array", - "description": "A list of topics to embed", - "items": {"$ref": "#/definitions/topic"}, + "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" }, - "resources": { - "type": "array", - "description": "A list of content resources to embed", - "items": {"$ref": "#/definitions/resource"}, + "description": { + "type": "string", + "description": "The description of the content 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"], + "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" + } }, - "required": ["topics", "resources"], + "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" + ] }; diff --git a/le_utils/constants/embed_request.py b/le_utils/constants/embed_request.py index 4422897..6575e45 100644 --- a/le_utils/constants/embed_request.py +++ b/le_utils/constants/embed_request.py @@ -2,12 +2,12 @@ # Generated by scripts/generate_from_specs.py from __future__ import unicode_literals -# RecommendationsRequest +# EmbedRequest choices = () -RECOMMENDATIONSREQUESTLIST = [] +EMBEDREQUESTLIST = [] SCHEMA = { "$id": "/schemas/embed_request", @@ -23,9 +23,7 @@ }, "language": { "type": "string", - "description": "Language code from " - "https://github.com/learningequality/le-utils/blob/main/le_utils/resources/languagelookup" - ".json", + "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": { @@ -66,8 +64,7 @@ }, "text": { "type": "string", - "description": "The cleaned up text extracted from the content resource (in markdown or plaintext " - "format)", + "description": "The cleaned up text extracted from the content resource (in markdown or plaintext format)", }, "language": {"$ref": "#/definitions/language"}, }, diff --git a/spec/schema-embed_request.json b/spec/schema-embed_request.json new file mode 100644 index 0000000..f73710a --- /dev/null +++ b/spec/schema-embed_request.json @@ -0,0 +1,121 @@ +{ + "$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" + ] +} \ No newline at end of file diff --git a/spec/schema-recommendations_request.json b/spec/schema-recommendations_request.json deleted file mode 100644 index f1d545c..0000000 --- a/spec/schema-recommendations_request.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "$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"] -} \ No newline at end of file From 0317474ed23f1d8e6131d49193366b24ac3e4924 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Fri, 12 Jan 2024 18:36:31 +0300 Subject: [PATCH 12/15] rename test --- tests/test_schemas.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_schemas.py b/tests/test_schemas.py index f82fe30..c8fb573 100644 --- a/tests/test_schemas.py +++ b/tests/test_schemas.py @@ -8,7 +8,7 @@ from le_utils.constants import completion_criteria from le_utils.constants import mastery_criteria from le_utils.validators.embed_request import ( - validate as validate_recommendations_request, + validate as validate_embed_request, ) @@ -273,7 +273,7 @@ def test_completion_criteria__reference__invalid(): @pytest.mark.skipif(jsonschema is None, reason="jsonschema package is unavailable") def test_recommendations__topic__valid(): with _assert_not_raises(jsonschema.ValidationError): - validate_recommendations_request( + validate_embed_request( { "topics": [ { From 073776490d825dec5cdffb5bd4864707744080c1 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Mon, 15 Jan 2024 23:48:21 +0300 Subject: [PATCH 13/15] Remove required fields from metadata --- js/EmbedRequest.js | 16 +--------------- le_utils/constants/embed_request.py | 11 ----------- spec/schema-embed_request.json | 16 +--------------- 3 files changed, 2 insertions(+), 41 deletions(-) diff --git a/js/EmbedRequest.js b/js/EmbedRequest.js index 9337f7f..7d26785 100644 --- a/js/EmbedRequest.js +++ b/js/EmbedRequest.js @@ -102,21 +102,7 @@ export const SCHEMA = { }, "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" - ] + "description": "The metadata of the channel for logging purposes" } }, "required": [ diff --git a/le_utils/constants/embed_request.py b/le_utils/constants/embed_request.py index 6575e45..851e4d6 100644 --- a/le_utils/constants/embed_request.py +++ b/le_utils/constants/embed_request.py @@ -85,17 +85,6 @@ "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"], diff --git a/spec/schema-embed_request.json b/spec/schema-embed_request.json index f73710a..983f8d7 100644 --- a/spec/schema-embed_request.json +++ b/spec/schema-embed_request.json @@ -97,21 +97,7 @@ }, "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" - ] + "description": "The metadata of the channel for logging purposes" } }, "required": [ From 303dafd7a1639a22f26323f82936873ca20b1da2 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Mon, 15 Jan 2024 23:49:36 +0300 Subject: [PATCH 14/15] Remove required fields from metadata --- le_utils/constants/embed_request.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/le_utils/constants/embed_request.py b/le_utils/constants/embed_request.py index 851e4d6..216b32a 100644 --- a/le_utils/constants/embed_request.py +++ b/le_utils/constants/embed_request.py @@ -23,7 +23,8 @@ }, "language": { "type": "string", - "description": "Language code from https://github.com/learningequality/le-utils/blob/main/le_utils/resources/languagelookup.json", + "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": { @@ -64,7 +65,8 @@ }, "text": { "type": "string", - "description": "The cleaned up text extracted from the content resource (in markdown or plaintext format)", + "description": "The cleaned up text extracted from the content resource (in markdown or plaintext " + "format)", }, "language": {"$ref": "#/definitions/language"}, }, From 54a2e341c8ddb4d6c71979b8d6a881b59c333ac7 Mon Sep 17 00:00:00 2001 From: Samson Akol Date: Mon, 15 Jan 2024 23:54:44 +0300 Subject: [PATCH 15/15] Fixes linting errors --- le_utils/constants/embed_request.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/le_utils/constants/embed_request.py b/le_utils/constants/embed_request.py index 216b32a..851e4d6 100644 --- a/le_utils/constants/embed_request.py +++ b/le_utils/constants/embed_request.py @@ -23,8 +23,7 @@ }, "language": { "type": "string", - "description": "Language code from https://github.com/learningequality/le-utils/blob/main/le_utils" - "/resources/languagelookup.json", + "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": { @@ -65,8 +64,7 @@ }, "text": { "type": "string", - "description": "The cleaned up text extracted from the content resource (in markdown or plaintext " - "format)", + "description": "The cleaned up text extracted from the content resource (in markdown or plaintext format)", }, "language": {"$ref": "#/definitions/language"}, },