Repository: openedx/edx-ora2

Issue:
"TypeError: u'<url>' is not JSON serializable" on upload to backends other than S3
File upload to "django" and "filesystem" backends is currently broken. Each attempt to generate an upload URL fails with the following error:

```
Traceback (most recent call last):                                                                                                                            
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/exception.py", line 41, in inner                                                          
    response = get_response(request)                                                                                                                          
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 249, in _legacy_get_response                                               
    response = self._get_response(request)                                                                                                                    
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 187, in _get_response                                                      
    response = self.process_exception_by_middleware(e, request)                                                                                               
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 185, in _get_response                                                      
    response = wrapped_callback(request, *callback_args, **callback_kwargs)                                                                                   
  File "/usr/local/lib/python2.7/dist-packages/django/utils/decorators.py", line 185, in inner                                                                
    return func(*args, **kwargs)                                                                                                                              
  File "/openedx/edx-platform/lms/djangoapps/courseware/module_render.py", line 962, in handle_xblock_callback                                                
    return _invoke_xblock_handler(request, course_id, usage_id, handler, suffix, course=course)                                                               
  File "/openedx/edx-platform/lms/djangoapps/courseware/module_render.py", line 1068, in _invoke_xblock_handler                                               
    resp = instance.handle(handler, req, suffix)                                                                                                              
  File "/usr/local/lib/python2.7/dist-packages/xblock/mixins.py", line 90, in handle                                                                          
    return self.runtime.handle(self, handler_name, request, suffix)                                                                                           
  File "/openedx/edx-platform/common/lib/xmodule/xmodule/x_module.py", line 1347, in handle                                                                   
    return super(MetricsMixin, self).handle(block, handler_name, request, suffix=suffix)                                                                      
  File "/usr/local/lib/python2.7/dist-packages/xblock/runtime.py", line 1037, in handle                                                                       
    results = handler(request, suffix)                                                                                                                        
  File "/usr/local/lib/python2.7/dist-packages/xblock/mixins.py", line 74, in wrapper                                                                         
    response = json.dumps(response)                                                                                                                           
  File "/usr/lib/python2.7/json/__init__.py", line 244, in dumps                                                                                              
    return _default_encoder.encode(obj)    
  File "/usr/lib/python2.7/json/encoder.py", line 207, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python2.7/json/encoder.py", line 270, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib/python2.7/json/encoder.py", line 184, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: u'/openassessment/fileupload/django/4dd623a62f4e626d827277cd3fedaf45/course-v1:org+video1+01/block-v1:org+video1+01+type@openassessment+block@25d85
51f741342ac919590db2e72091b/' is not JSON serializable
```

This error is due to the fact that urls returned by 'django' and 'filesystem' backends are computed with `django.core.urlresolvers.reverse_lazy`. Thus, they are not unicode, but `django.utils.functional.__proxy__` objects. The TypeError is raised when calling `json.dumps()` on `{'success': True, 'url': url_object}` in `xblock.mixins.HandlersMixin.json_handler`.

I can easily solve the problem by replacing `reverse_lazy` by `reverse`. However, I wonder what was the original reason to use `reverse_lazy`? The change was introduced in commit 3e13d27df by @efischer19.

Python tests pass successfully if I replace `reverse_lazy` by `reverse`.

I believe both ORA2 backends are broken for the current Open edX Hawthorn release. 
 
(this error was first discovered [here](https://github.com/regisb/openedx-docker/issues/97))


Discussion:

Resolving patch:
diff --git a/openassessment/fileupload/backends/django_storage.py b/openassessment/fileupload/backends/django_storage.py
--- a/openassessment/fileupload/backends/django_storage.py
+++ b/openassessment/fileupload/backends/django_storage.py
@@ -2,7 +2,7 @@
 
 from django.core.files.base import ContentFile
 from django.core.files.storage import default_storage
-from django.core.urlresolvers import reverse_lazy
+from django.core.urlresolvers import reverse
 
 from .base import BaseBackend
 
@@ -15,7 +15,7 @@ def get_upload_url(self, key, content_type):
         """
         Return the URL pointing to the ORA2 django storage upload endpoint.
         """
-        return reverse_lazy("openassessment-django-storage", kwargs={'key': key})
+        return reverse("openassessment-django-storage", kwargs={'key': key})
 
     def get_download_url(self, key):
         """
diff --git a/openassessment/fileupload/backends/filesystem.py b/openassessment/fileupload/backends/filesystem.py
--- a/openassessment/fileupload/backends/filesystem.py
+++ b/openassessment/fileupload/backends/filesystem.py
@@ -1,6 +1,6 @@
 from django.conf import settings
 import django.core.cache
-from django.core.urlresolvers import reverse_lazy
+from django.core.urlresolvers import reverse
 from django.utils.encoding import smart_text
 
 from .. import exceptions
@@ -47,7 +47,7 @@ def remove_file(self, key):
 
     def _get_url(self, key):
         key_name = self._get_key_name(key)
-        url = reverse_lazy("openassessment-filesystem-storage", kwargs={'key': key_name})
+        url = reverse("openassessment-filesystem-storage", kwargs={'key': key_name})
         return url
 
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -34,7 +34,7 @@ def load_requirements(*requirements_paths):
 
 setup(
     name='ora2',
-    version='2.2.1',
+    version='2.2.2',
     author='edX',
     url='http://github.com/edx/edx-ora2',
     description='edx-ora2',


Test patch: