Skip to content

Commit

Permalink
fix: Workflow update to integrate the waffle flag course and be able …
Browse files Browse the repository at this point in the history
…to send to edx-submission

test: Adjust styles

feat: course unit - edit iframe modal window (openedx#35777)

Adds logic to support the functionality of editing xblocks via the legacy modal editing window.

docs: fixing make docs command. (openedx#36280)

* docs: fixing make docs command.

fix: import authoring filter from content_authoring instead (openedx#36109)

Correctly name authoring subdomain according to DDD docs: https://openedx.atlassian.net/wiki/spaces/AC/pages/663224968/edX+DDD+Bounded+Contexts

fix: ADR document update for change from Xqueue to edx-submission
  • Loading branch information
gabrielC1409 committed Feb 21, 2025
1 parent aa728c1 commit 5358a8b
Show file tree
Hide file tree
Showing 14 changed files with 441 additions and 196 deletions.
58 changes: 0 additions & 58 deletions docs/decisions/0022-create-waffle-switch.rst

This file was deleted.

2 changes: 2 additions & 0 deletions lms/envs/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3060,6 +3060,8 @@ def _make_locale_paths(settings): # pylint: disable=missing-function-docstring
'openedx.core.djangoapps.staticfiles.apps.EdxPlatformStaticFilesConfig',

'django_celery_results',



# Common Initialization
'openedx.core.djangoapps.common_initialization.apps.CommonInitializationConfig',
Expand Down
8 changes: 8 additions & 0 deletions lms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,14 @@
xqueue_callback,
name='xqueue_callback',
),

re_path(
r'^courses/{}/xqueue/(?P<userid>[^/]*)/(?P<mod_id>.*?)/(?P<dispatch>[^/]*)$'.format(
settings.COURSE_ID_PATTERN,
),
xqueue_callback,
name='callback_submission',
),

# TODO: These views need to be updated before they work
path('calculate', util_views.calculate),
Expand Down
Empty file added pylint.log
Empty file.
8 changes: 7 additions & 1 deletion xmodule/capa/capa_problem.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import xmodule.capa.inputtypes as inputtypes
import xmodule.capa.responsetypes as responsetypes
import xmodule.capa.xqueue_interface as xqueue_interface
import xmodule.capa.xqueue_submission as xqueue_submission
from xmodule.capa.xqueue_interface import get_flag_by_name
from xmodule.capa.correctmap import CorrectMap
from xmodule.capa.safe_exec import safe_exec
from xmodule.capa.util import contextualize_text, convert_files_to_filenames, get_course_id_from_capa_block
Expand Down Expand Up @@ -432,8 +434,12 @@ def get_recentmost_queuetime(self):
for answer_id in self.correct_map
if self.correct_map.is_queued(answer_id)
]
if get_flag_by_name('send_to_submission_course.enable'):
data_format = xqueue_submission.dateformat
else:
data_format = xqueue_interface.dateformat
queuetimes = [
datetime.strptime(qt_str, xqueue_interface.dateformat).replace(tzinfo=UTC)
datetime.strptime(qt_str, data_format).replace(tzinfo=UTC)
for qt_str in queuetime_strs
]

Expand Down
37 changes: 19 additions & 18 deletions xmodule/capa/inputtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,16 @@

from lxml import etree

from xmodule.capa.xqueue_interface import XQUEUE_TIMEOUT
from xmodule.capa.xqueue_interface import XQUEUE_TIMEOUT, get_flag_by_name
from openedx.core.djangolib.markup import HTML, Text
from xmodule.stringify import stringify_children

from . import xqueue_interface
from . import xqueue_interface, xqueue_submission
from .registry import TagRegistry
from .util import sanitize_html

log = logging.getLogger(__name__)

#########################################################################

registry = TagRegistry() # pylint: disable=invalid-name


Expand Down Expand Up @@ -408,7 +406,7 @@ class OptionInput(InputTypeBase):
Example:
<optioninput options="('Up','Down')" correct="Up"/><text>The location of the sky</text>
<optioninput options="('Up', 'Down')" correct="Up"/><text>The location of the sky</text>
# TODO: allow ordering to be randomized
"""
Expand All @@ -423,8 +421,8 @@ def parse_options(options):
id==description for now. TODO: make it possible to specify different id and descriptions.
"""
# convert single quotes inside option values to html encoded string
options = re.sub(r"([a-zA-Z])('|\\')([a-zA-Z])", r"\1&#39;\3", options)
options = re.sub(r"\\'", r"&#39;", options) # replace already escaped single quotes
options = re.sub(r"([a-zA-Z])('|\\')([a-zA-Z])", r"\1& #39;\3", options)
options = re.sub(r"\\'", r"& #39;", options) # replace already escaped single quotes
# parse the set of possible options
lexer = shlex.shlex(options[1:-1])

Expand All @@ -434,7 +432,7 @@ def parse_options(options):

# remove quotes
# convert escaped single quotes (html encoded string) back to single quotes
tokens = [x[1:-1].replace("&#39;", "'") for x in lexer]
tokens = [x[1:-1].replace("& #39;", "'") for x in lexer]

# make list of (option_id, option_description), with description=id
return [(t, t) for t in tokens]
Expand Down Expand Up @@ -505,7 +503,7 @@ def setup(self):
raise Exception(msg)

self.choices = self.extract_choices(self.xml, i18n)
self._choices_map = dict(self.choices,)
self._choices_map = dict(self.choices, )

@classmethod
def get_attributes(cls):
Expand Down Expand Up @@ -602,16 +600,16 @@ def get_attributes(cls):
Register the attributes.
"""
return [
Attribute('params', None), # extra iframe params
Attribute('params', None), # extra iframe params
Attribute('html_file', None),
Attribute('gradefn', "gradefn"),
Attribute('get_statefn', None), # Function to call in iframe
# to get current state.
# to get current state.
Attribute('initial_state', None), # JSON string to be used as initial state
Attribute('set_statefn', None), # Function to call iframe to
# set state
Attribute('width', "400"), # iframe width
Attribute('height', "300"), # iframe height
# set state
Attribute('width', "400"), # iframe width
Attribute('height', "300"), # iframe height
# Title for the iframe, which should be supplied by the author of the problem. Not translated
# because we are in a class method and therefore do not have access to capa_system.i18n.
# Note that the default "display name" for the problem is also not translated.
Expand Down Expand Up @@ -987,7 +985,10 @@ def _plot_data(self, data):

# construct xqueue headers
qinterface = self.capa_system.xqueue.interface
qtime = datetime.utcnow().strftime(xqueue_interface.dateformat)
if get_flag_by_name('send_to_submission_course.enable'):
qtime = datetime.utcnow().strftime(xqueue_submission.dateformat)
else:
qtime = datetime.utcnow().strftime(xqueue_interface.dateformat)
callback_url = self.capa_system.xqueue.construct_callback('ungraded_response')
anonymous_student_id = self.capa_system.anonymous_student_id
# TODO: Why is this using self.capa_system.seed when we have self.seed???
Expand Down Expand Up @@ -1086,9 +1087,9 @@ def get_attributes(cls):

def setup(self):
"""
if value is of the form [x,y] then parse it and send along coordinates of previous answer
if value is of the form [x, y] then parse it and send along coordinates of previous answer
"""
m = re.match(r'\[([0-9]+),([0-9]+)]',
m = re.match(r'\[([0-9]+), ([0-9]+)]',
self.value.strip().replace(' ', ''))
if m:
# Note: we subtract 15 to compensate for the size of the dot on the screen.
Expand Down Expand Up @@ -1626,7 +1627,7 @@ class ChoiceTextGroup(InputTypeBase):
CheckboxProblem:
<problem>
<startouttext/>
A person randomly selects 100 times, with replacement, from the list of numbers \(\sqrt{2}\) , 2, 3, 4 ,5 ,6
A person randomly selects 100 times, with replacement, from the list of numbers \(\sqrt{2}\) , 2, 3, 4 , 5 , 6
and records the results. The first number they pick is \(\sqrt{2}\) Given this information
select the correct choices and fill in numbers to make them accurate.
<endouttext/>
Expand Down
8 changes: 6 additions & 2 deletions xmodule/capa/responsetypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@

import xmodule.capa.safe_exec as safe_exec
import xmodule.capa.xqueue_interface as xqueue_interface
import xmodule.capa.xqueue_submission as xqueue_submission
from xmodule.capa.xqueue_interface import get_flag_by_name
from openedx.core.djangolib.markup import HTML, Text
from openedx.core.lib.grade_utils import round_away_from_zero

Expand Down Expand Up @@ -2675,8 +2677,10 @@ def get_score(self, student_answers):
#------------------------------------------------------------

qinterface = self.capa_system.xqueue.interface
qtime = datetime.strftime(datetime.now(UTC), xqueue_interface.dateformat)

if get_flag_by_name('send_to_submission_course.enable'):
qtime = datetime.strftime(datetime.now(UTC), xqueue_submission.dateformat)
else:
qtime = datetime.strftime(datetime.now(UTC), xqueue_submission.dateformat)
anonymous_student_id = self.capa_system.anonymous_student_id

# Generate header
Expand Down
47 changes: 46 additions & 1 deletion xmodule/capa/tests/test_inputtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,10 +476,12 @@ def test_rendering(self):
assert context == expected


@pytest.mark.django_db
class MatlabTest(unittest.TestCase):
"""
Test Matlab input types
"""

def setUp(self):
super(MatlabTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.rows = '10'
Expand Down Expand Up @@ -928,6 +930,40 @@ def test_matlab_sanitize_msg(self):
expected = ""
assert self.the_input._get_render_context()['msg'] == expected # pylint: disable=protected-access

@patch('xmodule.capa.inputtypes.get_flag_by_name', return_value=True)
@patch('xmodule.capa.inputtypes.datetime')
def test_plot_data_with_flag_active(self, mock_datetime, mock_get_flag_by_name):
"""
Test that the correct date format is used when the flag is active.
"""
mock_datetime.utcnow.return_value.strftime.return_value = 'formatted_date_with_flag'
data = {'submission': 'x = 1234;'}
response = self.the_input.handle_ajax("plot", data)
self.the_input.capa_system.xqueue.interface.send_to_queue.assert_called_with(header=ANY, body=ANY)
assert response['success']
assert self.the_input.input_state['queuekey'] is not None
assert self.the_input.input_state['queuestate'] == 'queued'
assert 'formatted_date_with_flag' in self.the_input.capa_system.xqueue.interface.send_to_queue.call_args[1][
'body'
]

@patch('xmodule.capa.inputtypes.get_flag_by_name', return_value=False)
@patch('xmodule.capa.inputtypes.datetime')
def test_plot_data_with_flag_inactive(self, mock_datetime, mock_get_flag_by_name):
"""
Test that the correct date format is used when the flag is inactive.
"""
mock_datetime.utcnow.return_value.strftime.return_value = 'formatted_date_without_flag'
data = {'submission': 'x = 1234;'}
response = self.the_input.handle_ajax("plot", data)
self.the_input.capa_system.xqueue.interface.send_to_queue.assert_called_with(header=ANY, body=ANY)
assert response['success']
assert self.the_input.input_state['queuekey'] is not None
assert self.the_input.input_state['queuestate'] == 'queued'
assert 'formatted_date_without_flag' in self.the_input.capa_system.xqueue.interface.send_to_queue.call_args[1][
'body'
]


def html_tree_equal(received, expected):
"""
Expand All @@ -947,6 +983,7 @@ class SchematicTest(unittest.TestCase):
"""
Check that schematic inputs work
"""

def test_rendering(self):
height = '12'
width = '33'
Expand Down Expand Up @@ -1002,6 +1039,7 @@ class ImageInputTest(unittest.TestCase):
"""
Check that image inputs work
"""

def check(self, value, egx, egy): # lint-amnesty, pylint: disable=missing-function-docstring
height = '78'
width = '427'
Expand Down Expand Up @@ -1044,7 +1082,7 @@ def check(self, value, egx, egy): # lint-amnesty, pylint: disable=missing-funct

def test_with_value(self):
# Check that compensating for the dot size works properly.
self.check('[50,40]', 35, 25)
print("Context:", self.check('[50,40]', 35, 25))

def test_without_value(self):
self.check('', 0, 0)
Expand All @@ -1061,6 +1099,7 @@ class CrystallographyTest(unittest.TestCase):
"""
Check that crystallography inputs work
"""

def test_rendering(self):
height = '12'
width = '33'
Expand Down Expand Up @@ -1102,6 +1141,7 @@ class VseprTest(unittest.TestCase):
"""
Check that vsepr inputs work
"""

def test_rendering(self):
height = '12'
width = '33'
Expand Down Expand Up @@ -1149,6 +1189,7 @@ class ChemicalEquationTest(unittest.TestCase):
"""
Check that chemical equation inputs work.
"""

def setUp(self):
super(ChemicalEquationTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.size = "42"
Expand Down Expand Up @@ -1244,6 +1285,7 @@ class FormulaEquationTest(unittest.TestCase):
"""
Check that formula equation inputs work.
"""

def setUp(self):
super(FormulaEquationTest, self).setUp() # lint-amnesty, pylint: disable=super-with-arguments
self.size = "42"
Expand Down Expand Up @@ -1392,6 +1434,7 @@ class DragAndDropTest(unittest.TestCase):
"""
Check that drag and drop inputs work
"""

def test_rendering(self):
path_to_images = '/dummy-static/images/'

Expand Down Expand Up @@ -1466,6 +1509,7 @@ class AnnotationInputTest(unittest.TestCase):
"""
Make sure option inputs work
"""

def test_rendering(self):
xml_str = '''
<annotationinput>
Expand Down Expand Up @@ -1626,6 +1670,7 @@ class TestStatus(unittest.TestCase):
"""
Tests for Status class
"""

def test_str(self):
"""
Test stringifing Status objects
Expand Down
Loading

0 comments on commit 5358a8b

Please sign in to comment.