From ea49975a733585d85e0ea953777b202015653268 Mon Sep 17 00:00:00 2001 From: Feanil Patel Date: Wed, 18 Sep 2019 11:08:25 -0400 Subject: [PATCH] BOM-617 Fix test_static_replace test failures. Update the tests around static_file code to use byte streams instead of string streams for generating static content. This is a fix to get these tests passing on python 3. --- .../djangoapps/static_replace/test/test_static_replace.py | 6 +++--- common/lib/xmodule/xmodule/contentstore/content.py | 6 +++--- common/lib/xmodule/xmodule/contentstore/mongo.py | 4 +++- common/lib/xmodule/xmodule/modulestore/__init__.py | 3 ++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/common/djangoapps/static_replace/test/test_static_replace.py b/common/djangoapps/static_replace/test/test_static_replace.py index ace36a09fe..04da1ad689 100644 --- a/common/djangoapps/static_replace/test/test_static_replace.py +++ b/common/djangoapps/static_replace/test/test_static_replace.py @@ -3,7 +3,7 @@ from __future__ import absolute_import, print_function import re -from six import StringIO +from six import BytesIO from six.moves.urllib.parse import parse_qsl, urlparse, urlunparse import ddt @@ -331,7 +331,7 @@ class CanonicalContentTest(SharedModuleStoreTestCase): StaticContent: the StaticContent object for the created image """ new_image = Image.new('RGB', dimensions, color) - new_buf = StringIO() + new_buf = BytesIO() new_image.save(new_buf, format='png') new_buf.seek(0) new_name = name.format(prefix) @@ -355,7 +355,7 @@ class CanonicalContentTest(SharedModuleStoreTestCase): StaticContent: the StaticContent object for the created content """ - new_buf = StringIO('testingggggggggggg') + new_buf = BytesIO(b'testingggggggggggg') new_name = name.format(prefix) new_key = StaticContent.compute_location(cls.courses[prefix].id, new_name) new_content = StaticContent(new_key, new_name, 'application/octet-stream', new_buf.getvalue(), locked=locked) diff --git a/common/lib/xmodule/xmodule/contentstore/content.py b/common/lib/xmodule/xmodule/contentstore/content.py index bbfb8fe80e..0842219b90 100644 --- a/common/lib/xmodule/xmodule/contentstore/content.py +++ b/common/lib/xmodule/xmodule/contentstore/content.py @@ -270,7 +270,7 @@ class StaticContent(object): if query_val.startswith("/static/"): new_val = StaticContent.get_canonicalized_asset_path( course_key, query_val, base_url, excluded_exts, encode=False) - updated_query_params.append((query_name, new_val)) + updated_query_params.append((query_name, new_val.encode('utf-8'))) else: # Make sure we're encoding Unicode strings down to their byte string # representation so that `urlencode` can handle it. @@ -286,11 +286,11 @@ class StaticContent(object): # Only encode this if told to. Important so that we don't double encode # when working with paths that are in query parameters. - asset_path = asset_path.encode('utf-8') if encode: + asset_path = asset_path.encode('utf-8') asset_path = quote_plus(asset_path, '/:+@') - return urlunparse(('', base_url.encode('utf-8'), asset_path, params, urlencode(updated_query_params), '')) + return urlunparse(('', base_url, asset_path, params, urlencode(updated_query_params), '')) def stream_data(self): yield self._data diff --git a/common/lib/xmodule/xmodule/contentstore/mongo.py b/common/lib/xmodule/xmodule/contentstore/mongo.py index f3faa47146..7ab6c42d2d 100644 --- a/common/lib/xmodule/xmodule/contentstore/mongo.py +++ b/common/lib/xmodule/xmodule/contentstore/mongo.py @@ -99,7 +99,9 @@ class MongoContentStore(ContentStore): import_path=content.import_path, # getattr b/c caching may mean some pickled instances don't have attr locked=getattr(content, 'locked', False)) as fp: - if hasattr(content.data, '__iter__'): + # It seems that this code thought that only some specific object would have the `__iter__` attribute + # but the bytes object in python 3 has one and should not use the chunking logic. + if hasattr(content.data, '__iter__') and not isinstance(content.data, six.binary_type): for chunk in content.data: fp.write(chunk) else: diff --git a/common/lib/xmodule/xmodule/modulestore/__init__.py b/common/lib/xmodule/xmodule/modulestore/__init__.py index 7993996fe7..1d72ef9169 100644 --- a/common/lib/xmodule/xmodule/modulestore/__init__.py +++ b/common/lib/xmodule/xmodule/modulestore/__init__.py @@ -1298,7 +1298,8 @@ class ModuleStoreWriteBase(ModuleStoreReadBase, ModuleStoreWrite): result = defaultdict(dict) if fields is None: return result - cls = self.mixologist.mix(XBlock.load_class(category, select=prefer_xmodules)) + classes = XBlock.load_class(category, select=prefer_xmodules) + cls = self.mixologist.mix(classes) for field_name, value in six.iteritems(fields): field = getattr(cls, field_name) result[field.scope][field_name] = value