diff --git a/openedx/core/djangoapps/content/search/plain_text_math.py b/openedx/core/djangoapps/content/search/plain_text_math.py index 6600c32050a2..70f6c3fd2cf0 100644 --- a/openedx/core/djangoapps/content/search/plain_text_math.py +++ b/openedx/core/djangoapps/content/search/plain_text_math.py @@ -8,7 +8,11 @@ class InvalidMathEquation(Exception): - """Raised when converting mathjax equations to plain text fails""" + """Raised when mathjax equation is invalid. This is used to skip all transformations.""" + + +class EqnPatternNotFound(Exception): + """Raised when a pattern is not found in equation. This is used to skip a specific transformation.""" class PlainTextMath: @@ -58,7 +62,7 @@ def _nested_bracket_matcher(equation: str, opening_pattern: str) -> str: """ start = equation.find(opening_pattern) if start == -1: - raise InvalidMathEquation() + raise EqnPatternNotFound() open_count = 0 inner_start = start + len(opening_pattern) for i, char in enumerate(equation[inner_start:]): @@ -88,7 +92,7 @@ def _fraction_handler(self, equation: str) -> str: """ try: n_start, n_inner_start, n_inner_end, n_end = self._nested_bracket_matcher(equation, "\\frac{") - except InvalidMathEquation: + except EqnPatternNotFound: return equation numerator = equation[n_inner_start:n_inner_end] @@ -97,7 +101,7 @@ def _fraction_handler(self, equation: str) -> str: try: _, d_inner_start, d_inner_end, d_end = self._nested_bracket_matcher(equation[n_end:], "{") - except InvalidMathEquation: + except EqnPatternNotFound: return equation denominator = equation[n_end + d_inner_start:n_end + d_inner_end] @@ -116,7 +120,7 @@ def _nested_text_extractor(self, equation: str, pattern: str) -> str: inner_text = equation[inner_start:inner_end] inner_text = self._nested_text_extractor(inner_text, pattern) equation = equation[:start] + inner_text + equation[end:] - except InvalidMathEquation: + except EqnPatternNotFound: pass return equation @@ -138,10 +142,15 @@ def run(self, eqn_matches: re.Match) -> str: """ groups = eqn_matches.groups() for group in groups: - if group: + if not group: + continue + original = group + try: group = self._handle_replacements(group) group = self._fraction_handler(group) return unicodeit.replace(group) + except Exception: # pylint: disable=broad-except + return original return None diff --git a/openedx/core/djangoapps/content/search/tests/test_documents.py b/openedx/core/djangoapps/content/search/tests/test_documents.py index 05cfb8b78a07..a97caae168d6 100644 --- a/openedx/core/djangoapps/content/search/tests/test_documents.py +++ b/openedx/core/djangoapps/content/search/tests/test_documents.py @@ -574,6 +574,11 @@ def test_mathjax_plain_text_conversion_for_search(self): ('Fraction error: \\( \\frac{2} \\)', 'Fraction error: \\frac{2}'), ('Fraction error 2: \\( \\frac{\\frac{2}{3}{4} \\)', 'Fraction error 2: \\frac{\\frac{2}{3}{4}'), ('Unclosed: [mathjaxinline]x^2', 'Unclosed: [mathjaxinline]x^2'), + ( + 'Missing closing bracket: \\( \\frac{\\frac{2} {3}{\\frac{4}{3}} \\)', + 'Missing closing bracket: \\frac{\\frac{2} {3}{\\frac{4}{3}}' + ), + ('No equation: normal text', 'No equation: normal text'), ] # pylint: enable=line-too-long block = BlockFactory.create(