diff --git a/requirements.txt b/requirements.txt index 2abe5093..b5169317 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,31 +1,31 @@ # Add here external Python modules dependencies, one per line. Module names # should match https://pypi.python.org/pypi names. For the full spec or # dependency lines, see https://pip.readthedocs.org/en/1.1/requirements.html # Runtime dependencies beautifulsoup4 -Django >= 1.11.0, < 2.0 +django < 3 django-cors-headers -djangorestframework >= 3.4.0 +djangorestframework django_webpack_loader django_js_reverse docutils python-magic >= 0.4.0 htmlmin lxml prometheus_client pygments pypandoc python-dateutil pyyaml requests python-memcached pybadges sentry-sdk typing-extensions # Doc dependencies sphinx sphinxcontrib-httpdomain diff --git a/swh/web/common/exc.py b/swh/web/common/exc.py index 63f2725c..fea79b8d 100644 --- a/swh/web/common/exc.py +++ b/swh/web/common/exc.py @@ -1,125 +1,125 @@ # Copyright (C) 2015-2019 The Software Heritage developers # See the AUTHORS file at the top-level directory of this distribution # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information import traceback from django.http import HttpResponse from django.shortcuts import render from django.utils.safestring import mark_safe from django.utils.html import escape import sentry_sdk from swh.web.config import get_config class BadInputExc(ValueError): """Wrong request to the api. Example: Asking a content with the wrong identifier format. """ pass class NotFoundExc(Exception): """Good request to the api but no result were found. Example: Asking a content with the right identifier format but that content does not exist. """ pass class ForbiddenExc(Exception): """Good request to the api, forbidden result to return due to enforce policy. Example: Asking for a raw content which exists but whose mimetype is not text. """ pass http_status_code_message = { 400: 'Bad Request', 401: 'Unauthorized', 403: 'Access Denied', 404: 'Resource not found', 500: 'Internal Server Error', 501: 'Not Implemented', 502: 'Bad Gateway', 503: 'Service unavailable' } def _generate_error_page(request, error_code, error_description): return render(request, 'error.html', {'error_code': error_code, 'error_message': http_status_code_message[error_code], 'error_description': mark_safe(error_description)}, status=error_code) -def swh_handle400(request): +def swh_handle400(request, exception=None): """ Custom Django HTTP error 400 handler for swh-web. """ - error_description = 'The server cannot process the request to %s due to '\ - 'something that is perceived to be a client error.' %\ - escape(request.META['PATH_INFO']) + error_description = ('The server cannot process the request to %s due to ' + 'something that is perceived to be a client error.' % + escape(request.META['PATH_INFO'])) return _generate_error_page(request, 400, error_description) -def swh_handle403(request): +def swh_handle403(request, exception=None): """ Custom Django HTTP error 403 handler for swh-web. """ - error_description = 'The resource %s requires an authentication.' %\ - escape(request.META['PATH_INFO']) + error_description = ('The resource %s requires an authentication.' % + escape(request.META['PATH_INFO'])) return _generate_error_page(request, 403, error_description) -def swh_handle404(request): +def swh_handle404(request, exception=None): """ Custom Django HTTP error 404 handler for swh-web. """ - error_description = 'The resource %s could not be found on the server.' %\ - escape(request.META['PATH_INFO']) + error_description = ('The resource %s could not be found on the server.' % + escape(request.META['PATH_INFO'])) return _generate_error_page(request, 404, error_description) def swh_handle500(request): """ Custom Django HTTP error 500 handler for swh-web. """ - error_description = 'An unexpected condition was encountered when '\ - 'requesting resource %s.' %\ - escape(request.META['PATH_INFO']) + error_description = ('An unexpected condition was encountered when ' + 'requesting resource %s.' % + escape(request.META['PATH_INFO'])) return _generate_error_page(request, 500, error_description) def handle_view_exception(request, exc, html_response=True): """ Function used to generate an error page when an exception was raised inside a swh-web browse view. """ sentry_sdk.capture_exception(exc) error_code = 500 error_description = '%s: %s' % (type(exc).__name__, str(exc)) if get_config()['debug']: error_description = traceback.format_exc() if isinstance(exc, BadInputExc): error_code = 400 if isinstance(exc, ForbiddenExc): error_code = 403 if isinstance(exc, NotFoundExc): error_code = 404 if html_response: return _generate_error_page(request, error_code, error_description) else: return HttpResponse(error_description, content_type='text/plain', status=error_code) diff --git a/tox.ini b/tox.ini index 7bb4f12d..5a777df9 100644 --- a/tox.ini +++ b/tox.ini @@ -1,30 +1,32 @@ [tox] -envlist=flake8,mypy,py3 +envlist=flake8,mypy,py3-django{1,2} [testenv] extras = testing deps = pytest-cov + django1: django>=1.11,<2 + django2: django>=2,<3 commands = pytest \ slow: --hypothesis-profile=swh-web \ !slow: --hypothesis-profile=swh-web-fast \ --cov {envsitepackagesdir}/swh/web --cov-branch {posargs} {envsitepackagesdir}/swh/web [testenv:flake8] skip_install = true deps = flake8 commands = {envpython} -m flake8 \ --exclude=.tox,.git,__pycache__,.eggs,*.egg,node_modules [testenv:mypy] setenv = DJANGO_SETTINGS_MODULE = swh.web.settings.development extras = testing deps = mypy commands = mypy swh