From 75532987ce9a24ba4324953abeb75ac466203fb4 Mon Sep 17 00:00:00 2001 From: Ned Batchelder <ned@nedbatchelder.com> Date: Thu, 21 Nov 2013 20:40:20 -0500 Subject: [PATCH] Properly convert files from Webob to pure files. Webob represents uploaded files as cgi.FieldStorage objects. The XModule code expects pure Python file objects. Each FieldStorage object is wrapped to present the proper file interface, with file names. LMS-1492 --- .../xmodule/xmodule/tests/test_capa_module.py | 1 - .../xmodule/tests/test_xblock_wrappers.py | 2 +- common/lib/xmodule/xmodule/x_module.py | 27 ++++++++++++++++++- requirements/edx/github.txt | 2 +- 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/tests/test_capa_module.py b/common/lib/xmodule/xmodule/tests/test_capa_module.py index 9db5022209a..b7b7d8b6f40 100644 --- a/common/lib/xmodule/xmodule/tests/test_capa_module.py +++ b/common/lib/xmodule/xmodule/tests/test_capa_module.py @@ -590,7 +590,6 @@ class CapaModuleTest(unittest.TestCase): for fpath, fileobj in kwargs['files'].iteritems(): self.assertEqual(fpath, fileobj.name) - @unittest.expectedFailure def test_check_problem_with_files_as_xblock(self): # Check a problem with uploaded files, using the XBlock API. # pylint: disable=W0212 diff --git a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py index 258ee5b0382..c8ac5fcdd35 100644 --- a/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py +++ b/common/lib/xmodule/xmodule/tests/test_xblock_wrappers.py @@ -257,7 +257,7 @@ class TestXModuleHandler(TestXBlockWrapper): def setUp(self): self.module = XModule(descriptor=Mock(), field_data=Mock(), runtime=Mock(), scope_ids=Mock()) self.module.handle_ajax = Mock(return_value='{}') - self.request = Mock() + self.request = webob.Request({}) def test_xmodule_handler_passed_data(self): self.module.xmodule_handler(self.request) diff --git a/common/lib/xmodule/xmodule/x_module.py b/common/lib/xmodule/xmodule/x_module.py index e644185c8c1..cd5a5ef3d90 100644 --- a/common/lib/xmodule/xmodule/x_module.py +++ b/common/lib/xmodule/xmodule/x_module.py @@ -8,6 +8,7 @@ from lxml import etree from collections import namedtuple from pkg_resources import resource_listdir, resource_string, resource_isdir from webob import Response +from webob.multidict import MultiDict from xmodule.modulestore import Location from xmodule.modulestore.exceptions import ItemNotFoundError, InsufficientSpecificationError, InvalidLocationError @@ -406,7 +407,31 @@ class XModule(XModuleMixin, HTMLSnippet, XBlock): # pylint: disable=abstract-me """ XBlock handler that wraps `handle_ajax` """ - response_data = self.handle_ajax(suffix, request.POST) + class FileObjForWebobFiles(object): + """ + Turn Webob cgi.FieldStorage uploaded files into pure file objects. + + Webob represents uploaded files as cgi.FieldStorage objects, which + have a .file attribute. We wrap the FieldStorage object, delegating + attribute access to the .file attribute. But the files have no + name, so we carry the FieldStorage .filename attribute as the .name. + + """ + def __init__(self, webob_file): + self.file = webob_file.file + self.name = webob_file.filename + + def __getattr__(self, name): + return getattr(self.file, name) + + # WebOb requests have multiple entries for uploaded files. handle_ajax + # expects a single entry as a list. + request_post = MultiDict(request.POST) + for key in set(request.POST.iterkeys()): + if hasattr(request.POST[key], "file"): + request_post[key] = map(FileObjForWebobFiles, request.POST.getall(key)) + + response_data = self.handle_ajax(suffix, request_post) return Response(response_data, content_type='application/json') def get_children(self): diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index cf2c5283232..26d12f2af93 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -15,7 +15,7 @@ -e git+https://github.com/eventbrite/zendesk.git@d53fe0e81b623f084e91776bcf6369f8b7b63879#egg=zendesk # Our libraries: --e git+https://github.com/edx/XBlock.git@2daa4e54#egg=XBlock +-e git+https://github.com/edx/XBlock.git@d6d2fc91#egg=XBlock -e git+https://github.com/edx/codejail.git@0a1b468#egg=codejail -e git+https://github.com/edx/diff-cover.git@v0.2.6#egg=diff_cover -e git+https://github.com/edx/js-test-tool.git@v0.1.4#egg=js_test_tool -- GitLab