Get rid of lepl deprecation warning by removing rfc6266 dependency (#24059)

The LEPL dependency was triggering a lot of deprecation warnings of the
form:

    venv/lib/python3.5/site-packages/lepl/matchers/support.py:497:
    DeprecationWarning: inspect.getargspec() is deprecated, use
    inspect.signature() instead
    argspec = getargspec(func)

It turns out that LEPL was only used by the rfc6266_parser package, which
itself was only used in one place to generate utf8-compliant
Content-Disposition headers.

This issue was noticed here:
https://github.com/SWW13/python-rfc6266-parser/issues/2
Unfortunately it is quite difficult to extract LEPL from the
rfc6266-parser package.

The rfc6266-parser package (https://pypi.org/project/rfc6266-parser/) is
itself a fork of the now-unmaintained rfc6266 package
(https://pypi.org/project/rfc6266/). Thus, it became high time to get
rid of this package. The FileResponse object can appropriately set the
Content-Disposition header, and thus replace the rfc6266 functionality,
since Django 2.0: https://code.djangoproject.com/ticket/16470

In our testing, the FileResponse object correctly set the
`filename*=utf-8''` value, following the RFC. The only difference is
that it does not provide "filename" fallback value, as expressed in the
RFC: https://tools.ietf.org/html/rfc6266#appendix-D

With rfc6266_parser:

    >> import rfc6266_parser
    >> rfc6266_parser.build_header("my_file_é.csv", filename_compat="video_urls.csv")
    b"attachment; filename=video_urls.csv; filename*=utf-8''my_file_%C3%A9.csv"

With FileResponse we have:

    >> from django.http import FileResponse
    >> import io
    >> response = FileResponse(io.StringIO(), as_attachment=True, filename="my_file_é.csv", content_type="text/csv")
    >> response.get("Content-Disposition")
    "attachment; filename*=utf-8''my_file_%C3%A9.csv"

We consider that this is a sufficiently minor difference, that will
impact very few browsers.
This commit is contained in:
Régis Behmo
2020-08-31 15:30:27 +02:00
committed by GitHub
parent 4e6bff8868
commit ba18d48ac3
6 changed files with 18 additions and 23 deletions

View File

@@ -1541,9 +1541,10 @@ class VideoUrlsCsvTestCase(VideoUploadTestMixin, CourseTestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(
response["Content-Disposition"],
u"attachment; filename={course}_video_urls.csv".format(course=self.course.id.course)
u"attachment; filename=\"{course}_video_urls.csv\"".format(course=self.course.id.course)
)
response_reader = StringIO(response.content.decode('utf-8') if six.PY3 else response.content)
response_content = b"".join(response.streaming_content)
response_reader = StringIO(response_content.decode('utf-8') if six.PY3 else response_content)
reader = csv.DictReader(response_reader, dialect=csv.excel)
self.assertEqual(
reader.fieldnames,
@@ -1605,5 +1606,5 @@ class VideoUrlsCsvTestCase(VideoUploadTestMixin, CourseTestCase):
self.assertEqual(response.status_code, 200)
self.assertEqual(
response["Content-Disposition"],
u"attachment; filename=video_urls.csv; filename*=utf-8''n%C3%B3n-%C3%A4scii_video_urls.csv"
u"attachment; filename*=utf-8''n%C3%B3n-%C3%A4scii_video_urls.csv"
)

View File

@@ -3,21 +3,22 @@ Views related to the video upload feature
"""
import codecs
import csv
import json
import logging
from contextlib import closing
from datetime import datetime, timedelta
import io
from uuid import uuid4
import rfc6266_parser
import six
from boto import s3
from boto.sts import STSConnection
from django.conf import settings
from django.contrib.auth.decorators import login_required
from django.contrib.staticfiles.storage import staticfiles_storage
from django.http import HttpResponse, HttpResponseNotFound
from django.http import FileResponse, HttpResponseNotFound
from django.urls import reverse
from django.utils.translation import ugettext as _
from django.utils.translation import ugettext_noop
@@ -461,17 +462,12 @@ def video_encodings_download(request, course_key_string):
for key, value in ret.items()
}
response = HttpResponse(content_type="text/csv")
# Translators: This is the suggested filename when downloading the URL
# listing for videos uploaded through Studio
filename = _("{course}_video_urls").format(course=course.id.course)
# See https://tools.ietf.org/html/rfc6266#appendix-D
response["Content-Disposition"] = rfc6266_parser.build_header(
filename + ".csv",
filename_compat="video_urls.csv"
)
# Write csv to bytes-like object. We need a separate writer and buffer as the csv
# writer writes str and the FileResponse expects a bytes files.
buffer = io.BytesIO()
buffer_writer = codecs.getwriter("utf-8")(buffer)
writer = csv.DictWriter(
response,
buffer_writer,
[
col_name.encode("utf-8") if six.PY2 else col_name
for col_name
@@ -482,7 +478,12 @@ def video_encodings_download(request, course_key_string):
writer.writeheader()
for video in videos:
writer.writerow(make_csv_dict(video))
return response
buffer.seek(0)
# Translators: This is the suggested filename when downloading the URL
# listing for videos uploaded through Studio
filename = _("{course}_video_urls").format(course=course.id.course) + ".csv"
return FileResponse(buffer, as_attachment=True, filename=filename, content_type="text/csv")
def _get_and_validate_course(course_key_string, user):

View File

@@ -136,7 +136,6 @@ python3-saml
pyuca # For more accurate sorting of translated country names in django-countries
recommender-xblock # https://github.com/edx/RecommenderXBlock
rest-condition # DRF's recommendation for supporting complex permissions
rfc6266-parser # Used to generate Content-Disposition headers.
social-auth-core
pysrt # Support for SubRip subtitle files, used in the video XModule
pytz # Time zone information database

View File

@@ -142,7 +142,6 @@ jsonfield2==3.0.3 # via -c requirements/edx/../constraints.txt, -r requi
kombu==3.0.37 # via celery
laboratory==1.0.2 # via -r requirements/edx/base.in
lazy==1.4 # via -r requirements/edx/paver.txt, acid-xblock, lti-consumer-xblock, ora2
lepl==5.1.3 # via rfc6266-parser
libsass==0.10.0 # via -r requirements/edx/paver.txt, ora2
loremipsum==1.0.5 # via ora2
lti-consumer-xblock==2.3 # via -r requirements/edx/base.in
@@ -206,7 +205,6 @@ regex==2020.7.14 # via -r requirements/edx/../edx-sandbox/shared.txt, n
requests-oauthlib==1.3.0 # via -r requirements/edx/base.in, social-auth-core
requests==2.24.0 # via -r requirements/edx/paver.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core
rest-condition==1.0.3 # via -r requirements/edx/base.in, edx-drf-extensions
rfc6266-parser==0.0.6 # via -r requirements/edx/base.in
ruamel.yaml.clib==0.2.0 # via ruamel.yaml
ruamel.yaml==0.16.10 # via drf-yasg
rules==2.2 # via -r requirements/edx/base.in, edx-enterprise, edx-proctoring

View File

@@ -171,7 +171,6 @@ kombu==3.0.37 # via -r requirements/edx/testing.txt, celery
laboratory==1.0.2 # via -r requirements/edx/testing.txt
lazy-object-proxy==1.4.3 # via -r requirements/edx/testing.txt, astroid
lazy==1.4 # via -r requirements/edx/testing.txt, acid-xblock, bok-choy, lti-consumer-xblock, ora2
lepl==5.1.3 # via -r requirements/edx/testing.txt, rfc6266-parser
libsass==0.10.0 # via -r requirements/edx/testing.txt, ora2
loremipsum==1.0.5 # via -r requirements/edx/testing.txt, ora2
lti-consumer-xblock==2.3 # via -r requirements/edx/testing.txt
@@ -259,7 +258,6 @@ regex==2020.7.14 # via -r requirements/edx/testing.txt, nltk
requests-oauthlib==1.3.0 # via -r requirements/edx/testing.txt, social-auth-core
requests==2.24.0 # via -r requirements/edx/testing.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core, sphinx, transifex-client
rest-condition==1.0.3 # via -r requirements/edx/testing.txt, edx-drf-extensions
rfc6266-parser==0.0.6 # via -r requirements/edx/testing.txt
ruamel.yaml.clib==0.2.0 # via -r requirements/edx/testing.txt, ruamel.yaml
ruamel.yaml==0.16.10 # via -r requirements/edx/testing.txt, drf-yasg
rules==2.2 # via -r requirements/edx/testing.txt, edx-enterprise, edx-proctoring

View File

@@ -165,7 +165,6 @@ kombu==3.0.37 # via -r requirements/edx/base.txt, celery
laboratory==1.0.2 # via -r requirements/edx/base.txt
lazy-object-proxy==1.4.3 # via astroid
lazy==1.4 # via -r requirements/edx/base.txt, acid-xblock, bok-choy, lti-consumer-xblock, ora2
lepl==5.1.3 # via -r requirements/edx/base.txt, rfc6266-parser
libsass==0.10.0 # via -r requirements/edx/base.txt, ora2
loremipsum==1.0.5 # via -r requirements/edx/base.txt, ora2
lti-consumer-xblock==2.3 # via -r requirements/edx/base.txt
@@ -248,7 +247,6 @@ regex==2020.7.14 # via -r requirements/edx/base.txt, nltk
requests-oauthlib==1.3.0 # via -r requirements/edx/base.txt, social-auth-core
requests==2.24.0 # via -r requirements/edx/base.txt, analytics-python, coreapi, django-oauth-toolkit, edx-analytics-data-api-client, edx-bulk-grades, edx-drf-extensions, edx-enterprise, edx-rest-api-client, geoip2, mailsnake, pyjwkest, python-swiftclient, requests-oauthlib, sailthru-client, slumber, social-auth-core, transifex-client
rest-condition==1.0.3 # via -r requirements/edx/base.txt, edx-drf-extensions
rfc6266-parser==0.0.6 # via -r requirements/edx/base.txt
ruamel.yaml.clib==0.2.0 # via -r requirements/edx/base.txt, ruamel.yaml
ruamel.yaml==0.16.10 # via -r requirements/edx/base.txt, drf-yasg
rules==2.2 # via -r requirements/edx/base.txt, edx-enterprise, edx-proctoring