diff --git a/app.py b/app.py index 09ce6025dff..7d1dcfc62e6 100644 --- a/app.py +++ b/app.py @@ -25,7 +25,7 @@ redirect, request, send_file, url_for, send_from_directory, session) from flask_babel import Babel -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext from website.flask_commonmark import Commonmark from flask_compress import Compress from urllib.parse import quote_plus diff --git a/gettext_with_fallback.py b/gettext_with_fallback.py deleted file mode 100644 index f52740d0d83..00000000000 --- a/gettext_with_fallback.py +++ /dev/null @@ -1,8 +0,0 @@ -from flask_babel import gettext -from website.flask_helpers import gettext_with_fallback - - -# Explicitly substitute the flask_babel function gettext with our own implementation that -# adds a fallback language. Note that we need to monkey-patch instead of use the gettext_with_fallback -# directly because the Babel extract function works if we use gettext with literal strings. -gettext = gettext_with_fallback # noqa diff --git a/hedy.py b/hedy.py index 5afafa91ea4..0411a492138 100644 --- a/hedy.py +++ b/hedy.py @@ -2,7 +2,7 @@ from functools import lru_cache import lark -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext from lark import Lark from lark.exceptions import UnexpectedEOF, UnexpectedCharacters, VisitError from lark import Tree, Transformer, visitors, v_args diff --git a/hedy_error.py b/hedy_error.py index 8b2f2554945..b1edc32b0e4 100644 --- a/hedy_error.py +++ b/hedy_error.py @@ -1,7 +1,7 @@ import hedy import hedy_translation import re -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext # TODO: we should not maintain a list like this. Translation of exception arguments should happen when the exception diff --git a/tests/tests_z_yamlfile.py b/tests/tests_z_yamlfile.py index f280bff2403..8aa96d4f93f 100644 --- a/tests/tests_z_yamlfile.py +++ b/tests/tests_z_yamlfile.py @@ -41,3 +41,76 @@ def test_load_yaml_equivalent(self): print( f'YAML loading takes {original_seconds / n} seconds, unpickling takes {cached_seconds / n}' f'({original_seconds / cached_seconds:.1f}x faster)') + + # Merging of YAML content + # Key of type dict + def test_merge_dicts_prefers_source(self): + result = YamlFile.merge_yaml({"key1": "source"}, {"key1": "fallback"}) + self.assertEqual({"key1": "source"}, result) + + def test_merge_dicts_uses_fallback_if_source_key_not_present(self): + result = YamlFile.merge_yaml({}, {"key1": "fallback"}) + self.assertEqual({"key1": "fallback"}, result) + + def test_merge_dicts_skips_key_if_not_present_in_fallback_empty(self): + result = YamlFile.merge_yaml({"key1": "source"}, {}) + self.assertEqual({}, result) + + def test_merge_dicts_skips_key_if_not_present_in_fallback(self): + result = YamlFile.merge_yaml({"key2": "source"}, {"key1": "fallback"}) + self.assertEqual({"key1": "fallback"}, result) + + # Key of type list + def test_merge_lists_prefers_source(self): + result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["a", "b"]}, result) + + def test_merge_lists_skips_key_if_not_present_in_fallback(self): + result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {}) + self.assertEqual({}, result) + + def test_merge_lists_uses_fallback_if_source_key_not_present_empty(self): + result = YamlFile.merge_yaml({}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["c", "d"]}, result) + + def test_merge_lists_uses_fallback_if_source_key_not_present(self): + result = YamlFile.merge_yaml({"key2": ["a", "b"]}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["c", "d"]}, result) + + # Elements in list + def test_merge_lists_values_prefers_source(self): + result = YamlFile.merge_yaml({"key1": [None, "b"]}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["c", "b"]}, result) + + def test_merge_lists_values_uses_fallback_if_value_is_empty(self): + result = YamlFile.merge_yaml({"key1": ["", "b"]}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["c", "b"]}, result) + + def test_merge_lists_values_prefers_len_of_fallback(self): + result = YamlFile.merge_yaml({"key1": ["a", "b", "e"]}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["a", "b"]}, result) + + def test_merge_lists_values_prefers_source_values(self): + result = YamlFile.merge_yaml({"key1": ["a"]}, {"key1": ["c", "d"]}) + self.assertEqual({"key1": ["a", "d"]}, result) + + # Keys with mismatched types + def test_merge_dicts_prefers_fallback_type_dict(self): + result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {"key1": {"a": "c", "b": "d"}}) + self.assertEqual({"key1": {"a": "c", "b": "d"}}, result) + + def test_merge_dicts_prefers_fallback_type_str(self): + result = YamlFile.merge_yaml({"key1": ["a", "b"]}, {"key1": "string value"}) + self.assertEqual({"key1": "string value"}, result) + + def test_merge_dicts_prefers_fallback_type_list(self): + result = YamlFile.merge_yaml({"key1": {"a": "c", "b": "d"}}, {"key1": ["a", "b"]}) + self.assertEqual({"key1": ["a", "b"]}, result) + + def test_merge_dicts_prefers_fallback_type_string(self): + result = YamlFile.merge_yaml({"key1": {"a": "c", "b": "d"}}, {"key1": "string value"}) + self.assertEqual({"key1": "string value"}, result) + + def test_merge_dicts_prefers_fallback_type_bool(self): + result = YamlFile.merge_yaml({"key1": True}, {"key1": "string value"}) + self.assertEqual({"key1": True}, result) diff --git a/translations/en/LC_MESSAGES/messages.po b/translations/en/LC_MESSAGES/messages.po index ef2aee4b699..80537726995 100644 --- a/translations/en/LC_MESSAGES/messages.po +++ b/translations/en/LC_MESSAGES/messages.po @@ -1577,7 +1577,7 @@ msgid "star" msgstr "a star" msgid "start_learning" -msgstr "Start learning EN" +msgstr "Start learning" msgid "start_quiz" msgstr "Start quiz" diff --git a/utils.py b/utils.py index 07a13b9b322..661b7ed6505 100644 --- a/utils.py +++ b/utils.py @@ -19,7 +19,7 @@ from email_validator import EmailNotValidError, validate_email from flask_babel import format_date, format_datetime, format_timedelta -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext from ruamel import yaml import commonmark diff --git a/website/admin.py b/website/admin.py index 55dbf0fa763..22a7822e4cd 100644 --- a/website/admin.py +++ b/website/admin.py @@ -1,5 +1,5 @@ from flask import make_response, request -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import utils from website.flask_helpers import render_template diff --git a/website/auth.py b/website/auth.py index 0f3ffa35d88..ca5f5ec9cb7 100644 --- a/website/auth.py +++ b/website/auth.py @@ -12,7 +12,7 @@ from botocore.exceptions import NoCredentialsError from flask import g, request, session, redirect from flask_babel import force_locale -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import utils from config import config diff --git a/website/auth_pages.py b/website/auth_pages.py index ed726596960..d708fdad6d7 100644 --- a/website/auth_pages.py +++ b/website/auth_pages.py @@ -1,7 +1,7 @@ import datetime from flask import make_response, redirect, request, session -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext from config import config from safe_format import safe_format diff --git a/website/classes.py b/website/classes.py index 0b90ffb83b8..59487aa3a27 100644 --- a/website/classes.py +++ b/website/classes.py @@ -2,7 +2,7 @@ from flask import make_response, redirect, request, session from jinja_partials import render_partial -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import utils from config import config diff --git a/website/feedback.py b/website/feedback.py index 0caff5ff7ff..42474d3a3a5 100644 --- a/website/feedback.py +++ b/website/feedback.py @@ -1,6 +1,6 @@ from flask import request, make_response, render_template -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import json import uuid from collections import defaultdict diff --git a/website/for_teachers.py b/website/for_teachers.py index 04b2ac3d3e4..af808f3e70f 100644 --- a/website/for_teachers.py +++ b/website/for_teachers.py @@ -7,7 +7,7 @@ from bs4 import BeautifulSoup from flask import g, make_response, request, session, url_for, redirect from jinja_partials import render_partial -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import jinja_partials import hedy diff --git a/website/parsons.py b/website/parsons.py index 4766ea1ba7c..898cf26e9de 100644 --- a/website/parsons.py +++ b/website/parsons.py @@ -1,5 +1,5 @@ from flask import g, make_response -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext from .website_module import WebsiteModule, route diff --git a/website/profile.py b/website/profile.py index b24f824337a..a68dbd1eadd 100644 --- a/website/profile.py +++ b/website/profile.py @@ -3,7 +3,7 @@ import requests from flask import make_response, request, session -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext from safe_format import safe_format from hedy_content import ALL_KEYWORD_LANGUAGES, ALL_LANGUAGES, COUNTRIES diff --git a/website/programs.py b/website/programs.py index fe2232d4243..7e93d84ffaf 100644 --- a/website/programs.py +++ b/website/programs.py @@ -3,7 +3,7 @@ from typing import Optional from flask import g, make_response, request -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import jinja_partials import hedy_content diff --git a/website/public_adventures.py b/website/public_adventures.py index 0f9bf3f0e80..9e19c3d9191 100644 --- a/website/public_adventures.py +++ b/website/public_adventures.py @@ -1,6 +1,6 @@ import uuid from flask import g, request, make_response -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import json import hedy diff --git a/website/tags.py b/website/tags.py index e8c7a3c55b2..5c9c9590878 100644 --- a/website/tags.py +++ b/website/tags.py @@ -1,5 +1,5 @@ from flask import make_response, request, g -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import jinja_partials import uuid diff --git a/website/user_activity.py b/website/user_activity.py index 6641117f996..5b5cbd68a03 100644 --- a/website/user_activity.py +++ b/website/user_activity.py @@ -1,5 +1,5 @@ -from gettext_with_fallback import gettext +from website.flask_helpers import gettext_with_fallback as gettext import os from flask import make_response, request, session