4742: Exception when reading UTF-8 encoded metadata of extension

fschlager

What version of Djblets are you using?

1.0.6

Which module(s) have the problem?

djblets/extensions/extension.py

What steps will reproduce the problem?

  1. Install Review Board using pip
  2. Install reviewbot-extension using pip
  3. Try to access Review Board

What is the expected output? What do you see instead?

I expect Djblets to be able to parse the UTF-8 encoded METADATA file of reviewbot-extension

What version of Python and Django?

2.7.12

Please provide any additional information below.

Djblets is reading all lines in reviewbot_extension-1.0.1.dist-info/METADATA and then tries to join them (djblets/extensions/extension.py line 439). This throws the following exception:

Environment:


Request Method: GET
Request URL: https://xxxxx.com/

Django Version: 1.6.11
Python Version: 2.7.12
Installed Applications:
[u'corsheaders',
 u'django.contrib.admin',
 u'django.contrib.auth',
 u'django.contrib.contenttypes',
 u'django.contrib.sites',
 u'django.contrib.sessions',
 u'django.contrib.staticfiles',
 u'djblets',
 u'djblets.avatars',
 u'djblets.configforms',
 u'djblets.datagrid',
 u'djblets.extensions',
 u'djblets.features',
 u'djblets.feedview',
 u'djblets.forms',
 u'djblets.gravatars',
 u'djblets.integrations',
 u'djblets.log',
 u'djblets.pipeline',
 u'djblets.recaptcha',
 u'djblets.siteconfig',
 u'djblets.util',
 u'haystack',
 u'oauth2_provider',
 u'pipeline',
 u'reviewboard',
 u'reviewboard.accounts',
 u'reviewboard.admin',
 u'reviewboard.attachments',
 u'reviewboard.avatars',
 u'reviewboard.changedescs',
 u'reviewboard.diffviewer',
 u'reviewboard.extensions',
 u'reviewboard.hostingsvcs',
 u'reviewboard.integrations',
 u'reviewboard.notifications',
 u'reviewboard.oauth',
 u'reviewboard.reviews',
 u'reviewboard.scmtools',
 u'reviewboard.site',
 u'reviewboard.webapi',
 u'django_evolution']
Installed Middleware:
[u'django.middleware.gzip.GZipMiddleware',
 u'reviewboard.admin.middleware.InitReviewBoardMiddleware',
 u'corsheaders.middleware.CorsMiddleware',
 u'django.middleware.clickjacking.XFrameOptionsMiddleware',
 u'django.middleware.common.CommonMiddleware',
 u'django.middleware.http.ConditionalGetMiddleware',
 u'django.middleware.locale.LocaleMiddleware',
 u'django.contrib.sessions.middleware.SessionMiddleware',
 u'django.contrib.auth.middleware.AuthenticationMiddleware',
 u'django.contrib.messages.middleware.MessageMiddleware',
 u'djblets.siteconfig.middleware.SettingsMiddleware',
 u'reviewboard.admin.middleware.LoadSettingsMiddleware',
 u'djblets.extensions.middleware.ExtensionsMiddleware',
 u'djblets.integrations.middleware.IntegrationsMiddleware',
 u'djblets.log.middleware.LoggingMiddleware',
 u'reviewboard.accounts.middleware.TimezoneMiddleware',
 u'reviewboard.admin.middleware.CheckUpdatesRequiredMiddleware',
 u'reviewboard.admin.middleware.X509AuthMiddleware',
 u'reviewboard.site.middleware.LocalSiteMiddleware',
 u'djblets.extensions.middleware.ExtensionsMiddlewareRunner',
 u'reviewboard.admin.middleware.ExtraExceptionInfoMiddleware']


Traceback:
File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py" in get_response
  88.                 response = middleware_method(request)
File "/usr/local/lib/python2.7/dist-packages/djblets/extensions/middleware.py" in process_request
  45.             self._check_expired()
File "/usr/local/lib/python2.7/dist-packages/djblets/extensions/middleware.py" in _check_expired
  76.                         extension_manager.load(full_reload=True)
File "/usr/local/lib/python2.7/dist-packages/djblets/extensions/manager.py" in load
  655.             self._load_extensions(full_reload)
File "/usr/local/lib/python2.7/dist-packages/djblets/extensions/manager.py" in _load_extensions
  725.                     entrypoint, ext_class)
File "/usr/local/lib/python2.7/dist-packages/djblets/extensions/extension.py" in create_from_entrypoint
  399.         metadata = cls._get_metadata_from_entrypoint(entrypoint, ext_class.id)
File "/usr/local/lib/python2.7/dist-packages/djblets/extensions/extension.py" in _get_metadata_from_entrypoint
  439.         data = '\n'.join(lines)

Exception Type: UnicodeDecodeError at /
Exception Value: 'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)

This can be hotfixed by converting METADATA to ASCII.

chipx86
#1 chipx86

We're preparing a release for this, hopefully out in the next couple days. We hoped to get it out earlier, but had some delays on our end.

You can temporarily work around this if you don't mind modifying extension.py and changing that line to:

data = b'\n'.join(lines)