From d9b4639c41dcd6d961b2ccc611bd6d114bfd89d6 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Mon, 24 Nov 2025 10:44:49 -0600 Subject: [PATCH 1/9] feat(numericalInput): endpoint added to validate a numerical input --- cms/djangoapps/contentstore/api/urls.py | 4 +++- cms/djangoapps/contentstore/api/views/utils.py | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cms/djangoapps/contentstore/api/urls.py b/cms/djangoapps/contentstore/api/urls.py index e638a59f84f0..67105518f53d 100644 --- a/cms/djangoapps/contentstore/api/urls.py +++ b/cms/djangoapps/contentstore/api/urls.py @@ -4,7 +4,7 @@ from django.conf import settings from django.urls import re_path -from cms.djangoapps.contentstore.api.views import course_import, course_quality, course_validation +from cms.djangoapps.contentstore.api.views import course_import, course_quality, course_validation, utils app_name = 'contentstore' @@ -16,5 +16,7 @@ course_validation.CourseValidationView.as_view(), name='course_validation'), re_path(fr'^v1/quality/{settings.COURSE_ID_PATTERN}/$', course_quality.CourseQualityView.as_view(), name='course_quality'), + re_path(r'^v1/validate/numerical-input/$', + utils.NumericalInputValidationView.as_view(),name='numerical_input_validation'), ] diff --git a/cms/djangoapps/contentstore/api/views/utils.py b/cms/djangoapps/contentstore/api/views/utils.py index da92dc08e1b1..bb169224f06c 100644 --- a/cms/djangoapps/contentstore/api/views/utils.py +++ b/cms/djangoapps/contentstore/api/views/utils.py @@ -7,6 +7,7 @@ from opaque_keys.edx.keys import CourseKey from rest_framework import status +from rest_framework.response import Response from rest_framework.generics import GenericAPIView from common.djangoapps.student.auth import has_course_author_access @@ -14,7 +15,8 @@ from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes from openedx.core.lib.cache_utils import request_cached from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order - +from calc.preview import latex_preview +import pyparsing @view_auth_classes() class BaseCourseView(DeveloperErrorViewMixin, GenericAPIView): @@ -135,3 +137,17 @@ def _wrapper_view(self, request, course_id, *args, **kwargs): ) return view(self, request, course_key, *args, **kwargs) return _wrapper_view + +class NumericalInputValidationView(GenericAPIView): + + def post(self, request): + result = {'preview': '', + 'is_valid': True, + 'error': ''} + try: + result['preview'] = latex_preview(request.data.get('formula')) + except pyparsing.ParseException: + result["error"] = "Sorry, couldn't parse formula" + result['is_valid'] = False + return Response(result, status=400) + return Response(result) From 68b395807d54cb786e11ae78d4b9df19d4abb235 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Mon, 24 Nov 2025 11:40:53 -0600 Subject: [PATCH 2/9] feat(numericalInput): change in utils file to pass pylint checks --- cms/djangoapps/contentstore/api/views/utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/api/views/utils.py b/cms/djangoapps/contentstore/api/views/utils.py index bb169224f06c..2ebc9f0d68fb 100644 --- a/cms/djangoapps/contentstore/api/views/utils.py +++ b/cms/djangoapps/contentstore/api/views/utils.py @@ -18,6 +18,7 @@ from calc.preview import latex_preview import pyparsing + @view_auth_classes() class BaseCourseView(DeveloperErrorViewMixin, GenericAPIView): """ @@ -138,9 +139,11 @@ def _wrapper_view(self, request, course_id, *args, **kwargs): return view(self, request, course_key, *args, **kwargs) return _wrapper_view -class NumericalInputValidationView(GenericAPIView): +class NumericalInputValidationView(GenericAPIView): + """Class in charge of NumericalInputValidations""" def post(self, request): + """function to validate a math expression (formula) and return of the numeric input is valid or not""" result = {'preview': '', 'is_valid': True, 'error': ''} From ac46d44451c84e895bd713a9400a58fdb4f44a72 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Mon, 24 Nov 2025 12:41:08 -0600 Subject: [PATCH 3/9] feat(numericalInput): change in utils file to pass pycodestyle checks --- cms/djangoapps/contentstore/api/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cms/djangoapps/contentstore/api/urls.py b/cms/djangoapps/contentstore/api/urls.py index 67105518f53d..f86876fc493e 100644 --- a/cms/djangoapps/contentstore/api/urls.py +++ b/cms/djangoapps/contentstore/api/urls.py @@ -17,6 +17,6 @@ re_path(fr'^v1/quality/{settings.COURSE_ID_PATTERN}/$', course_quality.CourseQualityView.as_view(), name='course_quality'), re_path(r'^v1/validate/numerical-input/$', - utils.NumericalInputValidationView.as_view(),name='numerical_input_validation'), + utils.NumericalInputValidationView.as_view(), name='numerical_input_validation'), ] From 70a198bef7bfee3d4ff1361a1f35cd996980e8db Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Fri, 28 Nov 2025 14:54:30 -0600 Subject: [PATCH 4/9] feat(numericalInput): endpoint to validate numerical input refactored --- cms/djangoapps/contentstore/api/urls.py | 4 +--- .../contentstore/api/views/utils.py | 20 ---------------- .../rest_api/v2/serializers/utils.py | 17 ++++++++++++++ .../contentstore/rest_api/v2/urls.py | 6 ++++- .../contentstore/rest_api/v2/views/utils.py | 22 ++++++++++++++++++ xmodule/capa/inputtypes.py | 23 +++++++++---------- xmodule/capa_block.py | 23 +++++++++++++++++++ 7 files changed, 79 insertions(+), 36 deletions(-) create mode 100644 cms/djangoapps/contentstore/rest_api/v2/serializers/utils.py create mode 100644 cms/djangoapps/contentstore/rest_api/v2/views/utils.py diff --git a/cms/djangoapps/contentstore/api/urls.py b/cms/djangoapps/contentstore/api/urls.py index f86876fc493e..e638a59f84f0 100644 --- a/cms/djangoapps/contentstore/api/urls.py +++ b/cms/djangoapps/contentstore/api/urls.py @@ -4,7 +4,7 @@ from django.conf import settings from django.urls import re_path -from cms.djangoapps.contentstore.api.views import course_import, course_quality, course_validation, utils +from cms.djangoapps.contentstore.api.views import course_import, course_quality, course_validation app_name = 'contentstore' @@ -16,7 +16,5 @@ course_validation.CourseValidationView.as_view(), name='course_validation'), re_path(fr'^v1/quality/{settings.COURSE_ID_PATTERN}/$', course_quality.CourseQualityView.as_view(), name='course_quality'), - re_path(r'^v1/validate/numerical-input/$', - utils.NumericalInputValidationView.as_view(), name='numerical_input_validation'), ] diff --git a/cms/djangoapps/contentstore/api/views/utils.py b/cms/djangoapps/contentstore/api/views/utils.py index 2ebc9f0d68fb..eb8ea6683e14 100644 --- a/cms/djangoapps/contentstore/api/views/utils.py +++ b/cms/djangoapps/contentstore/api/views/utils.py @@ -7,16 +7,12 @@ from opaque_keys.edx.keys import CourseKey from rest_framework import status -from rest_framework.response import Response from rest_framework.generics import GenericAPIView - from common.djangoapps.student.auth import has_course_author_access from openedx.core.djangoapps.util.forms import to_bool from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes from openedx.core.lib.cache_utils import request_cached from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order -from calc.preview import latex_preview -import pyparsing @view_auth_classes() @@ -138,19 +134,3 @@ def _wrapper_view(self, request, course_id, *args, **kwargs): ) return view(self, request, course_key, *args, **kwargs) return _wrapper_view - - -class NumericalInputValidationView(GenericAPIView): - """Class in charge of NumericalInputValidations""" - def post(self, request): - """function to validate a math expression (formula) and return of the numeric input is valid or not""" - result = {'preview': '', - 'is_valid': True, - 'error': ''} - try: - result['preview'] = latex_preview(request.data.get('formula')) - except pyparsing.ParseException: - result["error"] = "Sorry, couldn't parse formula" - result['is_valid'] = False - return Response(result, status=400) - return Response(result) diff --git a/cms/djangoapps/contentstore/rest_api/v2/serializers/utils.py b/cms/djangoapps/contentstore/rest_api/v2/serializers/utils.py new file mode 100644 index 000000000000..b11329c72e23 --- /dev/null +++ b/cms/djangoapps/contentstore/rest_api/v2/serializers/utils.py @@ -0,0 +1,17 @@ +""" +Serializers for the contentstore v2 utils views module. + +This module contains DRF serializers for different utils like validations. +""" + +from rest_framework import serializers + + +class NumericalInputValidationRequestSerializer(serializers.Serializer): + formula = serializers.CharField() + + +class NumericalInputValidationReponseSerializer(serializers.Serializer): + preview = serializers.CharField() + is_valid = serializers.BooleanField() + error = serializers.CharField(allow_null=True) diff --git a/cms/djangoapps/contentstore/rest_api/v2/urls.py b/cms/djangoapps/contentstore/rest_api/v2/urls.py index 5fa954a4ef82..893069f89aec 100644 --- a/cms/djangoapps/contentstore/rest_api/v2/urls.py +++ b/cms/djangoapps/contentstore/rest_api/v2/urls.py @@ -3,7 +3,7 @@ from django.conf import settings from django.urls import path, re_path -from cms.djangoapps.contentstore.rest_api.v2.views import downstreams, home +from cms.djangoapps.contentstore.rest_api.v2.views import downstreams, home, utils app_name = "v2" @@ -33,4 +33,8 @@ downstreams.SyncFromUpstreamView.as_view(), name="sync_from_upstream" ), + re_path( + '^validate/numerical-input/$', + utils.NumericalInputValidationView.as_view(), + name='numerical_input_validation'), ] diff --git a/cms/djangoapps/contentstore/rest_api/v2/views/utils.py b/cms/djangoapps/contentstore/rest_api/v2/views/utils.py new file mode 100644 index 000000000000..d700bf58941a --- /dev/null +++ b/cms/djangoapps/contentstore/rest_api/v2/views/utils.py @@ -0,0 +1,22 @@ +""" +Common utilities for V2 APIs. +""" +from rest_framework.response import Response +from rest_framework.generics import GenericAPIView +from rest_framework import permissions +from cms.djangoapps.contentstore.rest_api.v2.serializers.utils import NumericalInputValidationRequestSerializer +from xmodule.capa_block import ProblemBlock + + +class NumericalInputValidationView(GenericAPIView): + """Class in charge of NumericalInputValidations""" + permission_classes = (permissions.IsAuthenticated,) + serializer_class = NumericalInputValidationRequestSerializer + + def post(self, request): + """function to validate a math expression (formula) and return of the numeric input is valid or not""" + serializer = self.get_serializer(data=request.data) + serializer.is_valid(raise_exception=True) + formula = serializer.validated_data['formula'] + result = ProblemBlock.preview_numeric_input(formula) + return Response(result, status=200) diff --git a/xmodule/capa/inputtypes.py b/xmodule/capa/inputtypes.py index e85cb1a25b5a..4ce212d2484b 100644 --- a/xmodule/capa/inputtypes.py +++ b/xmodule/capa/inputtypes.py @@ -51,7 +51,6 @@ import nh3 import pyparsing import six -from calc.preview import latex_preview from chem import chemcalc from lxml import etree @@ -1300,18 +1299,18 @@ def preview_formcalc(self, get): result["request_start"] = int(get.get("request_start", 0)) - try: - # TODO add references to valid variables and functions - # At some point, we might want to mark invalid variables as red - # or something, and this is where we would need to pass those in. - result["preview"] = latex_preview(formula) - except pyparsing.ParseException: - result["error"] = _("Sorry, couldn't parse formula") + # TODO add references to valid variables and functions + # At some point, we might want to mark invalid variables as red + # or something, and this is where we would need to pass those in. + from xmodule.capa_block import ProblemBlock + numeric_result = ProblemBlock.preview_numeric_input(formula) + # Map results into the correct format + result["preview"] = numeric_result["preview"] + if numeric_result["error"]: + result["error"] = numeric_result["error"] + # if formula is invalid retrn formula + if not numeric_result["is_valid"]: result["formula"] = formula - except Exception: # lint-amnesty, pylint: disable=broad-except - # this is unexpected, so log - log.warning("Error while previewing formula", exc_info=True) - result["error"] = _("Error while rendering preview") return result diff --git a/xmodule/capa_block.py b/xmodule/capa_block.py index 8ca49eba97a3..0cfd950cd697 100644 --- a/xmodule/capa_block.py +++ b/xmodule/capa_block.py @@ -53,6 +53,8 @@ from .capa.xqueue_interface import XQueueService from .fields import Date, ListScoreField, ScoreField, Timedelta from .progress import Progress +from calc.preview import latex_preview +import pyparsing log = logging.getLogger("edx.courseware") @@ -2390,6 +2392,27 @@ def score_from_lcp(self, lcp): lcp_score = lcp.calculate_score() return Score(raw_earned=lcp_score["score"], raw_possible=lcp_score["total"]) + @classmethod + def preview_numeric_input(cls, formula): + """ + A class method for handling numeric validations, in this case + validates that the formula provided is a valid formula. + """ + result = {'preview': '', + 'is_valid': True, + 'error': ''} + try: + result['preview'] = latex_preview(formula) + except pyparsing.ParseException: + result["error"] = "Sorry, couldn't parse formula" + result['is_valid'] = False + return result + except Exception: + log.warning("Error while previewing formula", exc_info=True) + result['error'] = "Error while rendering preview" + result['is_valid'] = False + return result + class GradingMethodHandler: """ From 83a39a8916bb34866aa773544a26d95e8d43ebe7 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Fri, 28 Nov 2025 15:53:32 -0600 Subject: [PATCH 5/9] feat(numericalInput): fix typos and pylint error --- cms/djangoapps/contentstore/api/views/utils.py | 1 + xmodule/capa/inputtypes.py | 2 +- xmodule/capa_block.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cms/djangoapps/contentstore/api/views/utils.py b/cms/djangoapps/contentstore/api/views/utils.py index eb8ea6683e14..da92dc08e1b1 100644 --- a/cms/djangoapps/contentstore/api/views/utils.py +++ b/cms/djangoapps/contentstore/api/views/utils.py @@ -8,6 +8,7 @@ from opaque_keys.edx.keys import CourseKey from rest_framework import status from rest_framework.generics import GenericAPIView + from common.djangoapps.student.auth import has_course_author_access from openedx.core.djangoapps.util.forms import to_bool from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes diff --git a/xmodule/capa/inputtypes.py b/xmodule/capa/inputtypes.py index 4ce212d2484b..c01db9ff2136 100644 --- a/xmodule/capa/inputtypes.py +++ b/xmodule/capa/inputtypes.py @@ -1308,7 +1308,7 @@ def preview_formcalc(self, get): result["preview"] = numeric_result["preview"] if numeric_result["error"]: result["error"] = numeric_result["error"] - # if formula is invalid retrn formula + # if formula is invalid return formula if not numeric_result["is_valid"]: result["formula"] = formula diff --git a/xmodule/capa_block.py b/xmodule/capa_block.py index 0cfd950cd697..1231f8a44612 100644 --- a/xmodule/capa_block.py +++ b/xmodule/capa_block.py @@ -2407,7 +2407,7 @@ def preview_numeric_input(cls, formula): result["error"] = "Sorry, couldn't parse formula" result['is_valid'] = False return result - except Exception: + except (ValueError, TypeError): log.warning("Error while previewing formula", exc_info=True) result['error'] = "Error while rendering preview" result['is_valid'] = False From 89d5424cd9763076ed7ca8410fa41c96ce615bf0 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Fri, 28 Nov 2025 23:13:31 -0600 Subject: [PATCH 6/9] feat(numericalInput): fix input types tests --- xmodule/capa/inputtypes.py | 23 ++++++++++++++--------- xmodule/capa/tests/test_inputtypes.py | 4 ++-- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/xmodule/capa/inputtypes.py b/xmodule/capa/inputtypes.py index c01db9ff2136..b6ff041c5515 100644 --- a/xmodule/capa/inputtypes.py +++ b/xmodule/capa/inputtypes.py @@ -1302,15 +1302,20 @@ def preview_formcalc(self, get): # TODO add references to valid variables and functions # At some point, we might want to mark invalid variables as red # or something, and this is where we would need to pass those in. - from xmodule.capa_block import ProblemBlock - numeric_result = ProblemBlock.preview_numeric_input(formula) - # Map results into the correct format - result["preview"] = numeric_result["preview"] - if numeric_result["error"]: - result["error"] = numeric_result["error"] - # if formula is invalid return formula - if not numeric_result["is_valid"]: - result["formula"] = formula + try: + from xmodule.capa_block import ProblemBlock + numeric_result = ProblemBlock.preview_numeric_input(formula) + # Map results into the correct format + result["preview"] = numeric_result["preview"] + if numeric_result["error"]: + result["error"] = numeric_result["error"] + # if formula is invalid return formula + if not numeric_result["is_valid"]: + result["formula"] = formula + except Exception: # lint-amnesty, pylint: disable=broad-except + log.warning("Error while previewing formula", exc_info=True) + result["error"] = _("Error while rendering preview") + return result return result diff --git a/xmodule/capa/tests/test_inputtypes.py b/xmodule/capa/tests/test_inputtypes.py index c6b2b705adee..06db1ffe7313 100644 --- a/xmodule/capa/tests/test_inputtypes.py +++ b/xmodule/capa/tests/test_inputtypes.py @@ -1361,7 +1361,7 @@ def test_ajax_parse_err(self): With parse errors, FormulaEquationInput should give an error message """ # Simulate answering a problem that raises the exception - with patch("xmodule.capa.inputtypes.latex_preview") as mock_preview: + with patch('xmodule.capa_block.ProblemBlock.preview_numeric_input') as mock_preview: mock_preview.side_effect = ParseException("Oopsie") response = self.the_input.handle_ajax( "preview_formcalc", @@ -1379,7 +1379,7 @@ def test_ajax_other_err(self, mock_log): """ With other errors, test that FormulaEquationInput also logs it """ - with patch("xmodule.capa.inputtypes.latex_preview") as mock_preview: + with patch('xmodule.capa_block.ProblemBlock.preview_numeric_input') as mock_preview: mock_preview.side_effect = Exception() response = self.the_input.handle_ajax( "preview_formcalc", From 64f05125f1fa879d4343e7f0593012e0262ded65 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Fri, 28 Nov 2025 23:39:13 -0600 Subject: [PATCH 7/9] feat(numericalInput): fix tests in inputtypes --- xmodule/capa/inputtypes.py | 3 +++ xmodule/capa_block.py | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/xmodule/capa/inputtypes.py b/xmodule/capa/inputtypes.py index b6ff041c5515..88ab853c8b4f 100644 --- a/xmodule/capa/inputtypes.py +++ b/xmodule/capa/inputtypes.py @@ -1312,6 +1312,9 @@ def preview_formcalc(self, get): # if formula is invalid return formula if not numeric_result["is_valid"]: result["formula"] = formula + except pyparsing.ParseException: + result['error'] = _("Sorry, couldn't parse formula") + result['formula'] = formula except Exception: # lint-amnesty, pylint: disable=broad-except log.warning("Error while previewing formula", exc_info=True) result["error"] = _("Error while rendering preview") diff --git a/xmodule/capa_block.py b/xmodule/capa_block.py index 1231f8a44612..9da9ec51178c 100644 --- a/xmodule/capa_block.py +++ b/xmodule/capa_block.py @@ -2407,7 +2407,8 @@ def preview_numeric_input(cls, formula): result["error"] = "Sorry, couldn't parse formula" result['is_valid'] = False return result - except (ValueError, TypeError): + + except Exception: # pylint: disable=broad-exception-caught log.warning("Error while previewing formula", exc_info=True) result['error'] = "Error while rendering preview" result['is_valid'] = False From 2498a38b4f8f794671c7feb3c5742958e6a522ec Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Tue, 16 Dec 2025 15:33:01 -0600 Subject: [PATCH 8/9] fix(content): refactor in function that validates to avoid circularity --- .../contentstore/rest_api/v2/views/utils.py | 4 ++-- xmodule/capa/inputtypes.py | 24 ++++++++++++++++--- xmodule/capa_block.py | 24 ------------------- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/cms/djangoapps/contentstore/rest_api/v2/views/utils.py b/cms/djangoapps/contentstore/rest_api/v2/views/utils.py index d700bf58941a..8a6fe461fdb7 100644 --- a/cms/djangoapps/contentstore/rest_api/v2/views/utils.py +++ b/cms/djangoapps/contentstore/rest_api/v2/views/utils.py @@ -5,7 +5,7 @@ from rest_framework.generics import GenericAPIView from rest_framework import permissions from cms.djangoapps.contentstore.rest_api.v2.serializers.utils import NumericalInputValidationRequestSerializer -from xmodule.capa_block import ProblemBlock +from xmodule.capa.inputtypes import preview_numeric_input class NumericalInputValidationView(GenericAPIView): @@ -18,5 +18,5 @@ def post(self, request): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) formula = serializer.validated_data['formula'] - result = ProblemBlock.preview_numeric_input(formula) + result = preview_numeric_input(formula) return Response(result, status=200) diff --git a/xmodule/capa/inputtypes.py b/xmodule/capa/inputtypes.py index 88ab853c8b4f..97f0d5e6f713 100644 --- a/xmodule/capa/inputtypes.py +++ b/xmodule/capa/inputtypes.py @@ -49,8 +49,9 @@ import html5lib import nh3 -import pyparsing import six +from calc.preview import latex_preview +import pyparsing from chem import chemcalc from lxml import etree @@ -1303,8 +1304,7 @@ def preview_formcalc(self, get): # At some point, we might want to mark invalid variables as red # or something, and this is where we would need to pass those in. try: - from xmodule.capa_block import ProblemBlock - numeric_result = ProblemBlock.preview_numeric_input(formula) + numeric_result = preview_numeric_input(formula) # Map results into the correct format result["preview"] = numeric_result["preview"] if numeric_result["error"]: @@ -1323,6 +1323,24 @@ def preview_formcalc(self, get): return result +def preview_numeric_input(formula): + """ + Handles numeric validations, validates that the formula provided is a valid formula. + """ + result = {'preview': '', 'is_valid': True, 'error': ''} + try: + result['preview'] = latex_preview(formula) + except pyparsing.ParseException: + result["error"] = "Sorry, couldn't parse formula" + result['is_valid'] = False + return result + except Exception: # pylint: disable=broad-exception-caught + log.warning("Error while previewing formula", exc_info=True) + result['error'] = "Error while rendering preview" + result['is_valid'] = False + return result + + # ----------------------------------------------------------------------------- diff --git a/xmodule/capa_block.py b/xmodule/capa_block.py index 9da9ec51178c..8ca49eba97a3 100644 --- a/xmodule/capa_block.py +++ b/xmodule/capa_block.py @@ -53,8 +53,6 @@ from .capa.xqueue_interface import XQueueService from .fields import Date, ListScoreField, ScoreField, Timedelta from .progress import Progress -from calc.preview import latex_preview -import pyparsing log = logging.getLogger("edx.courseware") @@ -2392,28 +2390,6 @@ def score_from_lcp(self, lcp): lcp_score = lcp.calculate_score() return Score(raw_earned=lcp_score["score"], raw_possible=lcp_score["total"]) - @classmethod - def preview_numeric_input(cls, formula): - """ - A class method for handling numeric validations, in this case - validates that the formula provided is a valid formula. - """ - result = {'preview': '', - 'is_valid': True, - 'error': ''} - try: - result['preview'] = latex_preview(formula) - except pyparsing.ParseException: - result["error"] = "Sorry, couldn't parse formula" - result['is_valid'] = False - return result - - except Exception: # pylint: disable=broad-exception-caught - log.warning("Error while previewing formula", exc_info=True) - result['error'] = "Error while rendering preview" - result['is_valid'] = False - return result - class GradingMethodHandler: """ From cdd42cae7f9e06c7c16f020ba44eff89f6282260 Mon Sep 17 00:00:00 2001 From: Jesus Balderrama Date: Tue, 16 Dec 2025 15:49:27 -0600 Subject: [PATCH 9/9] fix(content): tests updated to match with the numeric input validation --- xmodule/capa/tests/test_inputtypes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xmodule/capa/tests/test_inputtypes.py b/xmodule/capa/tests/test_inputtypes.py index 06db1ffe7313..80d8427b0c74 100644 --- a/xmodule/capa/tests/test_inputtypes.py +++ b/xmodule/capa/tests/test_inputtypes.py @@ -1361,7 +1361,7 @@ def test_ajax_parse_err(self): With parse errors, FormulaEquationInput should give an error message """ # Simulate answering a problem that raises the exception - with patch('xmodule.capa_block.ProblemBlock.preview_numeric_input') as mock_preview: + with patch('xmodule.capa.inputtypes.preview_numeric_input') as mock_preview: mock_preview.side_effect = ParseException("Oopsie") response = self.the_input.handle_ajax( "preview_formcalc", @@ -1379,7 +1379,7 @@ def test_ajax_other_err(self, mock_log): """ With other errors, test that FormulaEquationInput also logs it """ - with patch('xmodule.capa_block.ProblemBlock.preview_numeric_input') as mock_preview: + with patch('xmodule.capa.inputtypes.preview_numeric_input') as mock_preview: mock_preview.side_effect = Exception() response = self.the_input.handle_ajax( "preview_formcalc",