Skip to content

Commit be42fae

Browse files
feat(numericalInput): endpoint to validate numerical input refactored
1 parent 4755294 commit be42fae

File tree

7 files changed

+80
-39
lines changed

7 files changed

+80
-39
lines changed

cms/djangoapps/contentstore/api/urls.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.conf import settings
55
from django.urls import re_path
66

7-
from cms.djangoapps.contentstore.api.views import course_import, course_quality, course_validation, utils
7+
from cms.djangoapps.contentstore.api.views import course_import, course_quality, course_validation
88

99

1010
app_name = 'contentstore'
@@ -16,7 +16,5 @@
1616
course_validation.CourseValidationView.as_view(), name='course_validation'),
1717
re_path(fr'^v1/quality/{settings.COURSE_ID_PATTERN}/$',
1818
course_quality.CourseQualityView.as_view(), name='course_quality'),
19-
re_path(r'^v1/validate/numerical-input/$',
20-
utils.NumericalInputValidationView.as_view(), name='numerical_input_validation'),
2119

2220
]

cms/djangoapps/contentstore/api/views/utils.py

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,12 @@
77

88
from opaque_keys.edx.keys import CourseKey
99
from rest_framework import status
10-
from rest_framework.response import Response
1110
from rest_framework.generics import GenericAPIView
12-
1311
from common.djangoapps.student.auth import has_course_author_access
1412
from openedx.core.djangoapps.util.forms import to_bool
1513
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, view_auth_classes
1614
from openedx.core.lib.cache_utils import request_cached
1715
from xmodule.modulestore.django import modulestore # lint-amnesty, pylint: disable=wrong-import-order
18-
from calc.preview import latex_preview
19-
import pyparsing
2016

2117

2218
@view_auth_classes()
@@ -138,19 +134,3 @@ def _wrapper_view(self, request, course_id, *args, **kwargs):
138134
)
139135
return view(self, request, course_key, *args, **kwargs)
140136
return _wrapper_view
141-
142-
143-
class NumericalInputValidationView(GenericAPIView):
144-
"""Class in charge of NumericalInputValidations"""
145-
def post(self, request):
146-
"""function to validate a math expression (formula) and return of the numeric input is valid or not"""
147-
result = {'preview': '',
148-
'is_valid': True,
149-
'error': ''}
150-
try:
151-
result['preview'] = latex_preview(request.data.get('formula'))
152-
except pyparsing.ParseException:
153-
result["error"] = "Sorry, couldn't parse formula"
154-
result['is_valid'] = False
155-
return Response(result, status=400)
156-
return Response(result)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
"""
2+
Serializers for the contentstore v2 utils views module.
3+
4+
This module contains DRF serializers for different utils like validations.
5+
"""
6+
7+
from rest_framework import serializers
8+
9+
10+
class NumericalInputValidationRequestSerializer(serializers.Serializer):
11+
formula = serializers.CharField()
12+
13+
14+
class NumericalInputValidationReponseSerializer(serializers.Serializer):
15+
preview = serializers.CharField()
16+
is_valid = serializers.BooleanField()
17+
error = serializers.CharField(allow_null=True)

cms/djangoapps/contentstore/rest_api/v2/urls.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from django.conf import settings
44
from django.urls import path, re_path
55

6-
from cms.djangoapps.contentstore.rest_api.v2.views import downstreams, home
6+
from cms.djangoapps.contentstore.rest_api.v2.views import downstreams, home, utils
77

88
app_name = "v2"
99

@@ -33,4 +33,8 @@
3333
downstreams.SyncFromUpstreamView.as_view(),
3434
name="sync_from_upstream"
3535
),
36+
re_path(
37+
'^validate/numerical-input/$',
38+
utils.NumericalInputValidationView.as_view(),
39+
name='numerical_input_validation'),
3640
]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""
2+
Common utilities for V2 APIs.
3+
"""
4+
from rest_framework.response import Response
5+
from rest_framework.generics import GenericAPIView
6+
from rest_framework import permissions
7+
from cms.djangoapps.contentstore.rest_api.v2.serializers.utils import NumericalInputValidationRequestSerializer
8+
from xmodule.capa_block import ProblemBlock
9+
10+
11+
class NumericalInputValidationView(GenericAPIView):
12+
"""Class in charge of NumericalInputValidations"""
13+
permission_classes = (permissions.IsAuthenticated,)
14+
serializer_class = NumericalInputValidationRequestSerializer
15+
16+
def post(self, request):
17+
"""function to validate a math expression (formula) and return of the numeric input is valid or not"""
18+
serializer = self.get_serializer(data=request.data)
19+
serializer.is_valid(raise_exception=True)
20+
formula = serializer.validated_data['formula']
21+
result = ProblemBlock.preview_numeric_input(formula)
22+
return Response(result, status=200)

xmodule/capa/inputtypes.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
import html5lib
5252
import pyparsing
5353
import six
54-
from calc.preview import latex_preview
5554
from chem import chemcalc
5655

5756
from lxml import etree
@@ -1298,20 +1297,18 @@ def preview_formcalc(self, get):
12981297

12991298
result['request_start'] = int(get.get('request_start', 0))
13001299

1301-
try:
1302-
# TODO add references to valid variables and functions
1303-
# At some point, we might want to mark invalid variables as red
1304-
# or something, and this is where we would need to pass those in.
1305-
result['preview'] = latex_preview(formula)
1306-
except pyparsing.ParseException:
1307-
result['error'] = _("Sorry, couldn't parse formula")
1308-
result['formula'] = formula
1309-
except Exception: # lint-amnesty, pylint: disable=broad-except
1310-
# this is unexpected, so log
1311-
log.warning(
1312-
"Error while previewing formula", exc_info=True
1313-
)
1314-
result['error'] = _("Error while rendering preview")
1300+
# TODO add references to valid variables and functions
1301+
# At some point, we might want to mark invalid variables as red
1302+
# or something, and this is where we would need to pass those in.
1303+
from xmodule.capa_block import ProblemBlock
1304+
numeric_result = ProblemBlock.preview_numeric_input(formula)
1305+
# Map results into the correct format
1306+
result["preview"] = numeric_result["preview"]
1307+
if numeric_result["error"]:
1308+
result["error"] = numeric_result["error"]
1309+
# if formula is invalid retrn formula
1310+
if not numeric_result["is_valid"]:
1311+
result["formula"] = formula
13151312

13161313
return result
13171314

xmodule/capa_block.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@
5555
from .capa.xqueue_interface import XQueueService
5656
from .fields import Date, ListScoreField, ScoreField, Timedelta
5757
from .progress import Progress
58+
from calc.preview import latex_preview
59+
import pyparsing
5860

5961
log = logging.getLogger("edx.courseware")
6062

@@ -2392,6 +2394,27 @@ def score_from_lcp(self, lcp):
23922394
lcp_score = lcp.calculate_score()
23932395
return Score(raw_earned=lcp_score['score'], raw_possible=lcp_score['total'])
23942396

2397+
@classmethod
2398+
def preview_numeric_input(cls, formula):
2399+
"""
2400+
A class method for handling numeric validations, in this case
2401+
validates that the formula provided is a valid formula.
2402+
"""
2403+
result = {'preview': '',
2404+
'is_valid': True,
2405+
'error': ''}
2406+
try:
2407+
result['preview'] = latex_preview(formula)
2408+
except pyparsing.ParseException:
2409+
result["error"] = "Sorry, couldn't parse formula"
2410+
result['is_valid'] = False
2411+
return result
2412+
except Exception:
2413+
log.warning("Error while previewing formula", exc_info=True)
2414+
result['error'] = "Error while rendering preview"
2415+
result['is_valid'] = False
2416+
return result
2417+
23952418

23962419
class GradingMethodHandler:
23972420
"""

0 commit comments

Comments
 (0)