tutor icon indicating copy to clipboard operation
tutor copied to clipboard

Emojis in course description cause failures after Olive -> Palm upgrade

Open regisb opened this issue 2 years ago • 0 comments

Bug description

After upgrading from Olive to Palm, if a single course contains emojis in its short description (such as "📌" or "📣") then the LMS dashboard will fail to load.

How to reproduce

Launch an olive platform:

export TUTOR_ROOT=$(pwd)
pip install 'tutor[full]<16.0.0'
tutor local lauch
tutor local do createuser --superuser --staff --password=1234 admin [email protected]
  • Go to http://studio.local.overhang.io, login and create a new course.
  • Go to "Schedule & details"
  • In "Course Short Description" write "📌". Hit save.

Then, upgrade to Palm:

pip install --upgrade 'tutor[full]'
tutor local launch

Load the LMS dashboard: http://local.overhang.io. It will produce a 500 error with the following logs:

tutor_local-lms-1            | Traceback (most recent call last):                                                                                                                                           
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner                                                                      
tutor_local-lms-1            |     response = get_response(request)                                                                                                                                         
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response                                                                  
tutor_local-lms-1            |     response = wrapped_callback(request, *callback_args, **callback_kwargs)                                                                                                  
tutor_local-lms-1            |   File "/opt/pyenv/versions/3.8.15/lib/python3.8/contextlib.py", line 75, in inner                                                                                           
tutor_local-lms-1            |     return func(*args, **kwds)                                                                                                                                               
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view                                                              
tutor_local-lms-1            |     return view_func(request, *args, **kwargs)                                                                                                                               
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 130, in _wrapped_view                                                                    
tutor_local-lms-1            |     response = view_func(request, *args, **kwargs)                                                                                                                           
tutor_local-lms-1            |   File "/openedx/edx-platform/./openedx/core/djangoapps/util/maintenance_banner.py", line 42, in _decorated                                                                  
tutor_local-lms-1            |     return func(request, *args, **kwargs)                                                                                                                                    
tutor_local-lms-1            |   File "/openedx/edx-platform/common/djangoapps/student/views/dashboard.py", line 904, in student_dashboard                                                                  
tutor_local-lms-1            |     response = render_to_response(dashboard_template, context)                                                                                                               
tutor_local-lms-1            |   File "/openedx/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 188, in render_to_response                                                                       
tutor_local-lms-1            |     return HttpResponse(render_to_string(template_name, dictionary, namespace, request), **kwargs)                                                                           
tutor_local-lms-1            |   File "/openedx/edx-platform/common/djangoapps/edxmako/shortcuts.py", line 178, in render_to_string                                                                         
tutor_local-lms-1            |     return template.render(dictionary, request)                                                                                                                              
tutor_local-lms-1            |   File "/openedx/edx-platform/common/djangoapps/edxmako/template.py", line 82, in render                                                                                     
tutor_local-lms-1            |     return self.mako_template.render_unicode(**context_dictionary)                                                                                                           
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/mako/template.py", line 444, in render_unicode                                                                             
tutor_local-lms-1            |     return runtime._render(                                                                                                                                                  
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 874, in _render                                                                                     
tutor_local-lms-1            |     _render_context(                                                                                                                                                         
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 916, in _render_context                                                                             
tutor_local-lms-1            |     _exec_template(inherit, lclcontext, args=args, kwargs=kwargs)                                                                                                            
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/mako/runtime.py", line 943, in _exec_template                                                                              
tutor_local-lms-1            |     callable_(context, *args, **kwargs)                                                                                                                                      
tutor_local-lms-1            |   File "/tmp/mako_lms/e2555543ddce7402e2f4f062ddd48a94/main.html.py", line 378, in render_body                                                                               
tutor_local-lms-1            |     __M_writer(filters.html_escape(filters.decode.utf8(next.body())))                                                                                                        
tutor_local-lms-1            |   File "/tmp/mako_lms/e2555543ddce7402e2f4f062ddd48a94/dashboard.html.py", line 225, in render_body                                                                          
tutor_local-lms-1            |     course_overview = CourseOverview.get_from_id(enrollment.course_id)                                                                                                       
tutor_local-lms-1            |   File "/openedx/edx-platform/./openedx/core/lib/cache_utils.py", line 74, in decorator                                                                                      
tutor_local-lms-1            |     result = wrapped(*args, **kwargs)                                                                                                                                        
tutor_local-lms-1            |   File "/openedx/edx-platform/./openedx/core/djangoapps/content/course_overviews/models.py", line 407, in get_from_id                                                        
tutor_local-lms-1            |     course_overview = cls.load_from_module_store(course_id)                                                                                                                  
tutor_local-lms-1            |   File "/openedx/edx-platform/./openedx/core/djangoapps/content/course_overviews/models.py", line 305, in load_from_module_store                                             
tutor_local-lms-1            |     course_overview.save()                                                                                                                                                   
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/model_utils/models.py", line 38, in save                                                                                   
tutor_local-lms-1            |     super().save(*args, **kwargs)                                                                                                                                            
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 739, in save                                                                               
tutor_local-lms-1            |     self.save_base(using=using, force_insert=force_insert,                                                                                                                   
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 776, in save_base                                                                          
tutor_local-lms-1            |     updated = self._save_table(                                                                                                                                              
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 858, in _save_table                                                                        
tutor_local-lms-1            |     updated = self._do_update(base_qs, using, pk_val, values, update_fields,                                                                                                 
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/base.py", line 912, in _do_update                                                                         
tutor_local-lms-1            |     return filtered._update(values) > 0                                                                                                                                      
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/query.py", line 802, in _update                                                                           
tutor_local-lms-1            |     return query.get_compiler(self.db).execute_sql(CURSOR)                                                                                                                   
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1559, in execute_sql                                                               
tutor_local-lms-1            |     cursor = super().execute_sql(result_type)                                                                                                                                
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql                                          
tutor_local-lms-1            |     cursor.execute(sql, params)                                                                                                                                              
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute                                                                          
tutor_local-lms-1            |     return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)                                                                                      
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers                                                           
tutor_local-lms-1            |     return executor(sql, params, many, context)                                                                                                                              
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute                                                                         
tutor_local-lms-1            |     return self.cursor.execute(sql, params)                                                                                                                                  
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__                                                                                  
tutor_local-lms-1            |     raise dj_exc_value.with_traceback(traceback) from exc_value                                                                                                              
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute                                                                         
tutor_local-lms-1            |     return self.cursor.execute(sql, params)                                                                                                                                  
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/django/db/backends/mysql/base.py", line 73, in execute                                                                     
tutor_local-lms-1            |     return self.cursor.execute(query, args)                                                                                                                                  
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 206, in execute                                                                                  
tutor_local-lms-1            |     res = self._query(query)                                                                                                                                                 
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/cursors.py", line 319, in _query                                                                                   
tutor_local-lms-1            |     db.query(q)                                                                                                                                                              
tutor_local-lms-1            |   File "/openedx/venv/lib/python3.8/site-packages/MySQLdb/connections.py", line 254, in query                                                                                
tutor_local-lms-1            |     _mysql.connection.query(self, query)                                                                                                                                     
tutor_local-lms-1            | django.db.utils.OperationalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x93\\x8C' for column 'short_description' at row 1")                                           
tutor_local-caddy-1          | {"level":"error","ts":1696252737.2936494,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"172.24.0.1","remote_port":"47008","proto":"HTTP/1.1"
,"method":"GET","host":"local.overhang.io","uri":"/dashboard"},"user_id":"","duration":0.312947733,"size":3140,"status":500}                                                                                
tutor_local-lms-1            | [pid: 7|app: 0|req: 2/18] 172.24.0.3 () {46 vars in 3090 bytes} [Mon Oct  2 13:18:56 2023] GET /dashboard => generated 9591 bytes in 311 msecs (HTTP/1.1 500) 7 headers in 50
7 bytes (1 switches on core 0)                                                                                                                               

Additional context

This issue was initially raised here: https://discuss.openedx.org/t/mysql-error-after-upgrade-from-olive-to-palm/11304/

It is very likely that this issue is related to #887.

regisb avatar Oct 02 '23 13:10 regisb