diff --git a/.gitignore b/.gitignore --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ .cache .pytest_cache .tox/ +.mypy_cache/ debian/ package-lock.json yarn-error.log diff --git a/MANIFEST.in b/MANIFEST.in --- a/MANIFEST.in +++ b/MANIFEST.in @@ -6,6 +6,7 @@ include requirements-test.txt include tox.ini include version.txt +recursive-include swh py.typed recursive-include swh/web/assets * recursive-include swh/web/static * recursive-include swh/web/templates * diff --git a/Makefile.local b/Makefile.local --- a/Makefile.local +++ b/Makefile.local @@ -87,3 +87,11 @@ test-frontend-full-ui: export CYPRESS_SKIP_SLOW_TESTS=0 test-frontend-full-ui: test-frontend-ui-cmd + + +# Override default rule to make sure DJANGO env var is properly set. It +# *should* work without any override thanks to the mypy django-stubs plugin, +# but it currently doesn't; see +# https://github.com/typeddjango/django-stubs/issues/166 +typecheck: + DJANGO_SETTINGS_MODULE=swh.web.settings.development $(MYPY) $(MYPYFLAGS) swh diff --git a/mypy.ini b/mypy.ini new file mode 100644 --- /dev/null +++ b/mypy.ini @@ -0,0 +1,49 @@ +[mypy] +namespace_packages = True +warn_unused_ignores = True +# support for django magic: https://github.com/typeddjango/django-stubs +plugins = mypy_django_plugin.main + +[mypy.plugins.django-stubs] +django_settings_module = swh.web.settings.development + +# 3rd party libraries without stubs (yet) + +[mypy-bs4.*] +ignore_missing_imports = True + +[mypy-django_js_reverse.*] +ignore_missing_imports = True + +[mypy-htmlmin.*] +ignore_missing_imports = True + +[mypy-magic.*] +ignore_missing_imports = True + +[mypy-pkg_resources.*] +ignore_missing_imports = True + +[mypy-pygments.*] +ignore_missing_imports = True + +[mypy-pypandoc.*] +ignore_missing_imports = True + +[mypy-pytest.*] +ignore_missing_imports = True + +[mypy-rest_framework.*] +ignore_missing_imports = True + +[mypy-requests_mock.*] +ignore_missing_imports = True + +[mypy-sphinx.*] +ignore_missing_imports = True + +[mypy-sphinxcontrib.*] +ignore_missing_imports = True + +[mypy-swh.docs.*] +ignore_missing_imports = True diff --git a/package.json b/package.json --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "swh-web", - "version": "0.0.217", + "version": "0.0.218", "description": "Static assets management for swh-web", "scripts": { "build-dev": "NODE_ENV=development webpack --config ./swh/web/assets/config/webpack.config.development.js --colors", @@ -9,8 +9,7 @@ "build": "NODE_ENV=production webpack --config ./swh/web/assets/config/webpack.config.production.js --colors", "mochawesome": "mochawesome-merge --reportDir cypress/mochawesome/results > cypress/mochawesome/mochawesome.json && marge -o cypress/mochawesome/report cypress/mochawesome/mochawesome.json", "eslint": "eslint -c swh/web/assets/config/.eslintrc --fix swh/web/assets/**", - "preinstall": "npm -v || SWH_WEB=$PWD && cd /tmp && yarn add npm && cd node_modules/npm && yarn link && cd $SWH_WEB && yarn link npm", - "postinstall": "patch-package" + "preinstall": "npm -v || (SWH_WEB=$PWD && cd /tmp && yarn add npm && cd node_modules/npm && yarn link && cd $SWH_WEB && yarn link npm)" }, "repository": { "type": "git", @@ -20,19 +19,19 @@ "license": "AGPL-3.0-or-later", "dependencies": { "@babel/runtime-corejs3": "^7.6.3", - "admin-lte": "^3.0.0-rc.6", + "admin-lte": "^3.0.0", "ansi_up": "^4.0.4", "bootstrap": "^4.3.1", "chosen-js": "^1.8.7", "clipboard": "^2.0.4", - "core-js": "^3.3.5", + "core-js": "^3.3.6", "d3": "^5.12.0", "datatables.net-responsive-bs4": "^2.2.3", "dompurify": "^2.0.7", "elementsfrompoint-polyfill": "^1.0.0", "eslint-plugin-cypress": "^2.7.0", "font-awesome": "^4.7.0", - "highlight.js": "^9.15.10", + "highlight.js": "^9.16.2", "highlightjs-line-numbers.js": "^2.7.0", "html-encoder-decoder": "^1.3.8", "iframe-resizer": "^4.2.3", @@ -46,7 +45,7 @@ "org": "^0.2.0", "pdfjs-dist": "^2.2.228", "popper.js": "^1.16.0", - "showdown": "^1.9.0", + "showdown": "^1.9.1", "typeface-alegreya": "0.0.69", "typeface-alegreya-sans": "^0.0.72", "validate.js": "^0.13.1", @@ -59,7 +58,7 @@ "@babel/plugin-transform-runtime": "^7.6.2", "@babel/preset-env": "^7.6.3", "@cypress/code-coverage": "^1.10.1", - "autoprefixer": "^9.7.0", + "autoprefixer": "^9.7.1", "axios": "^0.19.0", "babel-eslint": "^10.0.3", "babel-loader": "^8.0.6", @@ -69,7 +68,7 @@ "clean-webpack-plugin": "^3.0.0", "copy-webpack-plugin": "^5.0.4", "css-loader": "^3.2.0", - "cypress": "^3.5.0", + "cypress": "^3.6.0", "cypress-multi-reporters": "^1.2.3", "ejs": "^2.7.1", "eslint": "^6.6.0", @@ -95,7 +94,6 @@ "nodemon": "^1.19.4", "nyc": "^14.1.1", "optimize-css-assets-webpack-plugin": "^5.0.3", - "patch-package": "^6.2.0", "postcss-loader": "^3.0.0", "postcss-normalize": "^8.0.1", "postcss-reporter": "^6.0.1", diff --git a/patches/cypress+3.5.0.patch b/patches/cypress+3.5.0.patch deleted file mode 100644 --- a/patches/cypress+3.5.0.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/node_modules/cypress/lib/tasks/verify.js b/node_modules/cypress/lib/tasks/verify.js -index 7dfbe4c..887c704 100644 ---- a/node_modules/cypress/lib/tasks/verify.js -+++ b/node_modules/cypress/lib/tasks/verify.js -@@ -323,7 +323,7 @@ var isRootUser = function isRootUser() { - * @see https://crbug.com/638180 - */ - var needsSandbox = function needsSandbox() { -- return isLinuxLike() && isRootUser(); -+ return true; - }; - - module.exports = { diff --git a/requirements-test.txt b/requirements-test.txt --- a/requirements-test.txt +++ b/requirements-test.txt @@ -2,6 +2,7 @@ pytest pytest-django pytest-mock +django-stubs requests-mock swh.core[http] >= 0.0.61 swh.loader.git >= 0.0.47 diff --git a/swh/__init__.py b/swh/__init__.py --- a/swh/__init__.py +++ b/swh/__init__.py @@ -1 +1,4 @@ -__path__ = __import__('pkgutil').extend_path(__path__, __name__) +from pkgutil import extend_path +from typing import Iterable + +__path__ = extend_path(__path__, __name__) # type: Iterable[str] diff --git a/swh/web/admin/deposit.py b/swh/web/admin/deposit.py --- a/swh/web/admin/deposit.py +++ b/swh/web/admin/deposit.py @@ -22,14 +22,14 @@ @admin_route(r'deposit/', view_name='admin-deposit') -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save(request): return render(request, 'admin/deposit.html') @admin_route(r'deposit/list/', view_name='admin-deposit-list') -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_deposit_list(request): table_data = {} table_data['draw'] = int(request.GET['draw']) diff --git a/swh/web/admin/origin_save.py b/swh/web/admin/origin_save.py --- a/swh/web/admin/origin_save.py +++ b/swh/web/admin/origin_save.py @@ -26,7 +26,7 @@ @admin_route(r'origin/save/', view_name='admin-origin-save') -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save(request): return render(request, 'admin/origin-save.html') @@ -68,7 +68,7 @@ @admin_route(r'origin/save/authorized_urls/add/(?P.+)/', view_name='admin-origin-save-add-authorized-url') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_add_authorized_url(request, origin_url): try: SaveAuthorizedOrigin.objects.get(url=origin_url) @@ -91,7 +91,7 @@ @admin_route(r'origin/save/authorized_urls/remove/(?P.+)/', view_name='admin-origin-save-remove-authorized-url') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_remove_authorized_url(request, origin_url): try: entry = SaveAuthorizedOrigin.objects.get(url=origin_url) @@ -105,7 +105,7 @@ @admin_route(r'origin/save/unauthorized_urls/list/', view_name='admin-origin-save-unauthorized-urls-list') -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_unauthorized_urls_list(request): unauthorized_urls = SaveUnauthorizedOrigin.objects.all() return _datatables_origin_urls_response(request, unauthorized_urls) @@ -114,7 +114,7 @@ @admin_route(r'origin/save/unauthorized_urls/add/(?P.+)/', view_name='admin-origin-save-add-unauthorized-url') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_add_unauthorized_url(request, origin_url): try: SaveUnauthorizedOrigin.objects.get(url=origin_url) @@ -137,7 +137,7 @@ @admin_route(r'origin/save/unauthorized_urls/remove/(?P.+)/', view_name='admin-origin-save-remove-unauthorized-url') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_remove_unauthorized_url(request, origin_url): try: entry = SaveUnauthorizedOrigin.objects.get(url=origin_url) @@ -152,7 +152,7 @@ @admin_route(r'origin/save/request/accept/(?P.+)/url/(?P.+)/', # noqa view_name='admin-origin-save-request-accept') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_request_accept(request, visit_type, origin_url): try: SaveAuthorizedOrigin.objects.get(url=origin_url) @@ -165,7 +165,7 @@ @admin_route(r'origin/save/request/reject/(?P.+)/url/(?P.+)/', # noqa view_name='admin-origin-save-request-reject') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_request_reject(request, visit_type, origin_url): try: SaveUnauthorizedOrigin.objects.get(url=origin_url) @@ -182,7 +182,7 @@ @admin_route(r'origin/save/request/remove/(?P.+)/', view_name='admin-origin-save-request-remove') @require_POST -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _admin_origin_save_request_remove(request, sor_id): try: entry = SaveOriginRequest.objects.get(id=sor_id) @@ -196,7 +196,7 @@ @admin_route(r'origin/save/task/info/(?P.+)/', view_name='admin-origin-save-task-info') -@staff_member_required(login_url=settings.LOGIN_URL) +@staff_member_required(view_func=None, login_url=settings.LOGIN_URL) def _save_origin_task_info(request, save_request_id): request_info = get_save_origin_task_info(save_request_id) for date_field in ('scheduled', 'started', 'ended'): diff --git a/swh/web/api/apiresponse.py b/swh/web/api/apiresponse.py --- a/swh/web/api/apiresponse.py +++ b/swh/web/api/apiresponse.py @@ -13,7 +13,7 @@ from swh.storage.exc import StorageDBError, StorageAPIError from swh.web.api import utils -from swh.web.common.exc import NotFoundExc, ForbiddenExc +from swh.web.common.exc import NotFoundExc, ForbiddenExc, BadInputExc from swh.web.common.utils import shorten_path, gen_path_info from swh.web.config import get_config @@ -164,8 +164,10 @@ doc_data: documentation data for HTML response """ - error_code = 400 - if isinstance(error, NotFoundExc): + error_code = 500 + if isinstance(error, BadInputExc): + error_code = 400 + elif isinstance(error, NotFoundExc): error_code = 404 elif isinstance(error, ForbiddenExc): error_code = 403 diff --git a/swh/web/api/apiurls.py b/swh/web/api/apiurls.py --- a/swh/web/api/apiurls.py +++ b/swh/web/api/apiurls.py @@ -5,6 +5,8 @@ import functools +from typing import Dict + from rest_framework.decorators import api_view from swh.web.common.urlsindex import UrlsIndex @@ -20,8 +22,7 @@ generating related urls in API documentation """ - _apidoc_routes = {} - _method_endpoints = {} + _apidoc_routes = {} # type: Dict[str, Dict[str, str]] scope = 'api' @classmethod diff --git a/swh/web/api/views/origin.py b/swh/web/api/views/origin.py --- a/swh/web/api/views/origin.py +++ b/swh/web/api/views/origin.py @@ -195,6 +195,7 @@ :param string url_pattern: a string pattern or a regular expression :query int limit: the maximum number of found origins to return + (bounded to 1000) :query boolean regexp: if true, consider provided pattern as a regular expression and search origins whose urls match it :query boolean with_visit: if true, only return origins with at least @@ -218,7 +219,7 @@ """ result = {} offset = int(request.query_params.get('offset', '0')) - limit = int(request.query_params.get('limit', '70')) + limit = min(int(request.query_params.get('limit', '70')), 1000) regexp = request.query_params.get('regexp', 'false') with_visit = request.query_params.get('with_visit', 'false') diff --git a/swh/web/browse/views/origin.py b/swh/web/browse/views/origin.py --- a/swh/web/browse/views/origin.py +++ b/swh/web/browse/views/origin.py @@ -178,7 +178,7 @@ The search is performed in a case insensitive way. """ offset = int(request.GET.get('offset', '0')) - limit = int(request.GET.get('limit', '50')) + limit = min(int(request.GET.get('limit', '50')), 1000) regexp = request.GET.get('regexp', 'false') with_visit = request.GET.get('with_visit', 'false') diff --git a/swh/web/common/highlightjs.py b/swh/web/common/highlightjs.py --- a/swh/web/common/highlightjs.py +++ b/swh/web/common/highlightjs.py @@ -1,10 +1,12 @@ -# Copyright (C) 2017-2018 The Software Heritage developers +# Copyright (C) 2017-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 functools +from typing import Dict + from pygments.lexers import ( get_all_lexers, get_lexer_for_filename @@ -239,7 +241,7 @@ } # dictionary mapping pygment lexers to hljs languages -_pygments_lexer_to_hljs_language = {} +_pygments_lexer_to_hljs_language = {} # type: Dict[str, str] # dictionary mapping mime types to hljs languages diff --git a/swh/web/common/migrations/0001_initial.py b/swh/web/common/migrations/0001_initial.py --- a/swh/web/common/migrations/0001_initial.py +++ b/swh/web/common/migrations/0001_initial.py @@ -32,9 +32,6 @@ initial = True - dependencies = [ - ] - operations = [ migrations.CreateModel( name='SaveAuthorizedOrigin', diff --git a/swh/web/common/urlsindex.py b/swh/web/common/urlsindex.py --- a/swh/web/common/urlsindex.py +++ b/swh/web/common/urlsindex.py @@ -3,6 +3,10 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information +from typing import Dict, List + +import django.urls + from django.conf.urls import url from django.shortcuts import redirect @@ -16,7 +20,7 @@ all declared patterns will be grouped under the default one. """ - _urlpatterns = {} + _urlpatterns = {} # type: Dict[str, List[django.urls.URLPattern]] scope = 'default' @classmethod diff --git a/swh/web/config.py b/swh/web/config.py --- a/swh/web/config.py +++ b/swh/web/config.py @@ -5,6 +5,8 @@ import os +from typing import Any, Dict + from swh.core import config from swh.indexer.storage import get_indexer_storage from swh.scheduler import get_scheduler @@ -97,7 +99,7 @@ 'history_counters_url': ('string', 'https://stats.export.softwareheritage.org/history_counters.json'), # noqa } -swhweb_config = {} +swhweb_config = {} # type: Dict[str, Any] def get_config(config_file='web/web'): diff --git a/swh/web/py.typed b/swh/web/py.typed new file mode 100644 --- /dev/null +++ b/swh/web/py.typed @@ -0,0 +1 @@ +# Marker file for PEP 561. diff --git a/swh/web/settings/tests.py b/swh/web/settings/tests.py --- a/swh/web/settings/tests.py +++ b/swh/web/settings/tests.py @@ -100,4 +100,4 @@ ALLOWED_HOSTS += ['testserver'] # Silent DEBUG output when running unit tests - LOGGING['handlers']['console']['level'] = 'INFO' + LOGGING['handlers']['console']['level'] = 'INFO' # type: ignore diff --git a/swh/web/templates/misc/coverage.html b/swh/web/templates/misc/coverage.html --- a/swh/web/templates/misc/coverage.html +++ b/swh/web/templates/misc/coverage.html @@ -46,7 +46,7 @@ -
+
diff --git a/swh/web/tests/api/test_apidoc.py b/swh/web/tests/api/test_apidoc.py --- a/swh/web/tests/api/test_apidoc.py +++ b/swh/web/tests/api/test_apidoc.py @@ -6,8 +6,11 @@ from rest_framework.test import APITestCase from rest_framework.response import Response +from swh.storage.exc import StorageDBError, StorageAPIError + from swh.web.api.apidoc import api_doc, _parse_httpdomain_doc from swh.web.api.apiurls import api_route +from swh.web.common.exc import BadInputExc, ForbiddenExc, NotFoundExc from swh.web.tests.testcase import WebTestCase # flake8: noqa @@ -58,6 +61,15 @@ class APIDocTestCase(WebTestCase, APITestCase): + exception_http_code = { + BadInputExc: 400, + ForbiddenExc: 403, + NotFoundExc: 404, + Exception: 500, + StorageAPIError: 503, + StorageDBError: 503, + } + def test_apidoc_nodoc_failure(self): with self.assertRaises(Exception): @api_doc('/my/nodoc/url/') @@ -90,6 +102,26 @@ # then self.assertEqual(rv.status_code, 200, rv.data) + @staticmethod + @api_route(r'/test/error/(?P.+)/', + 'test-error') + @api_doc('/test/error/') + def apidoc_test_error_route(request, exc_name): + """ + Sample doc + """ + for e in APIDocTestCase.exception_http_code.keys(): + if e.__name__ == exc_name: + raise e('Error') + + def test_apidoc_error(self): + for exc, code in self.exception_http_code.items(): + # when + rv = self.client.get('/api/1/test/error/%s/' % exc.__name__) + + # then + self.assertEqual(rv.status_code, code) + @staticmethod @api_route(r'/some/full/(?P[0-9]+)/(?P[0-9]+)/', 'some-complete-doc-route') diff --git a/swh/web/tests/api/views/test_origin.py b/swh/web/tests/api/views/test_origin.py --- a/swh/web/tests/api/views/test_origin.py +++ b/swh/web/tests/api/views/test_origin.py @@ -12,6 +12,7 @@ from swh.storage.exc import StorageDBError, StorageAPIError +from swh.web.common.exc import BadInputExc from swh.web.common.utils import reverse from swh.web.common.origin_visits import get_origin_visits from swh.web.tests.strategies import ( @@ -55,7 +56,7 @@ err_msg = 'voluntary error to check the bad request middleware.' - mock_get_origin_visits.side_effect = ValueError(err_msg) + mock_get_origin_visits.side_effect = BadInputExc(err_msg) url = reverse( 'api-1-origin-visits', url_args={'origin_url': 'http://foo'}) @@ -64,7 +65,7 @@ self.assertEqual(rv.status_code, 400, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { - 'exception': 'ValueError', + 'exception': 'BadInputExc', 'reason': err_msg}) @patch('swh.web.api.views.origin.get_origin_visits') @@ -474,6 +475,20 @@ self.assertEqual({origin['url'] for origin in results}, expected_origins) + def test_api_origin_search_limit(self): + self.storage.origin_add([ + {'url': 'http://foobar/{}'.format(i)} + for i in range(2000) + ]) + + url = reverse('api-1-origin-search', + url_args={'url_pattern': 'foobar'}, + query_params={'limit': 1050}) + rv = self.client.get(url) + self.assertEqual(rv.status_code, 200, rv.data) + self.assertEqual(rv['Content-Type'], 'application/json') + self.assertEqual(len(rv.data), 1000) + @given(origin()) def test_api_origin_metadata_search(self, origin): with patch('swh.web.common.service.idx_storage') as mock_idx_storage: diff --git a/swh/web/tests/api/views/test_stat.py b/swh/web/tests/api/views/test_stat.py --- a/swh/web/tests/api/views/test_stat.py +++ b/swh/web/tests/api/views/test_stat.py @@ -8,6 +8,7 @@ from swh.storage.exc import StorageDBError, StorageAPIError +from swh.web.common.exc import BadInputExc from swh.web.common.utils import reverse from swh.web.tests.testcase import WebTestCase @@ -16,7 +17,7 @@ @patch('swh.web.api.views.stat.service') def test_api_1_stat_counters_raise_error(self, mock_service): - mock_service.stat_counters.side_effect = ValueError( + mock_service.stat_counters.side_effect = BadInputExc( 'voluntary error to check the bad request middleware.') url = reverse('api-1-stat-counters') @@ -25,7 +26,7 @@ self.assertEqual(rv.status_code, 400, rv.data) self.assertEqual(rv['Content-Type'], 'application/json') self.assertEqual(rv.data, { - 'exception': 'ValueError', + 'exception': 'BadInputExc', 'reason': 'voluntary error to check the bad request middleware.'}) @patch('swh.web.api.views.stat.service') diff --git a/swh/web/tests/data.py b/swh/web/tests/data.py --- a/swh/web/tests/data.py +++ b/swh/web/tests/data.py @@ -3,10 +3,11 @@ # License: GNU Affero General Public License version 3, or any later version # See top-level LICENSE file for more information -from copy import deepcopy import os import random +from copy import deepcopy +from typing import Dict from rest_framework.decorators import api_view from rest_framework.response import Response @@ -326,9 +327,9 @@ # Implement some special endpoints used to provide input tests data # when executing end to end tests with cypress -_content_code_data_exts = {} -_content_code_data_filenames = {} -_content_other_data_exts = {} +_content_code_data_exts = {} # type: Dict[str, Dict[str, str]] +_content_code_data_filenames = {} # type: Dict[str, Dict[str, str]] +_content_other_data_exts = {} # type: Dict[str, Dict[str, str]] def _init_content_tests_data(data_path, data_dict, ext_key): diff --git a/tox.ini b/tox.ini --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist=flake8,py3 +envlist=flake8,mypy,py3 [testenv:py3] deps = @@ -24,3 +24,11 @@ commands = {envpython} -m flake8 \ --exclude=.tox,.git,__pycache__,.eggs,*.egg,node_modules + +[testenv:mypy] +skip_install = true +deps = + .[testing] + mypy +commands = + DJANGO_SETTINGS_MODULE=swh.web.settings.development mypy swh diff --git a/yarn.lock b/yarn.lock --- a/yarn.lock +++ b/yarn.lock @@ -1409,11 +1409,6 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -"@yarnpkg/lockfile@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" - integrity sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ== - JSONStream@^1.0.3, JSONStream@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -1499,10 +1494,10 @@ object-path "0.11.4" regex-parser "2.2.10" -admin-lte@^3.0.0-rc.6: - version "3.0.0-rc.6" - resolved "https://registry.yarnpkg.com/admin-lte/-/admin-lte-3.0.0-rc.6.tgz#ab37bba52882c27dc148e7b62fcb1f4a16c27627" - integrity sha512-55Cw5/i6wZD9ILFB3ci9Y2slaWeHOLADOBp2CTGshXxOY71c694FTIjDQ2OIPlGVKnKLu+ZpXngnA+9kCpjq6g== +admin-lte@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/admin-lte/-/admin-lte-3.0.0.tgz#ba8ae56fbdeec22b75e0b0d6cdcfd15d05723e28" + integrity sha512-VawEaSMAnT7ZXJzr6oud7eOTj5ub0928BernSRGbKPATTnlVFD+X9OrEarIXahiVgjQIlUOxDotbxbRs+jRE9Q== dependencies: "@fortawesome/fontawesome-free" "^5.11.2" "@fullcalendar/bootstrap" "^4.3.0" @@ -1953,17 +1948,17 @@ postcss "^7.0.17" postcss-value-parser "^4.0.0" -autoprefixer@^9.7.0: - version "9.7.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.0.tgz#905ec19e50f04545fe9ff131182cc9ab25246901" - integrity sha512-j2IRvaCfrUxIiZun9ba4mhJ2omhw4OY88/yVzLO+lHhGBumAAK72PgM6gkbSN8iregPOn1ZlxGkmZh2CQ7X4AQ== +autoprefixer@^9.7.1: + version "9.7.1" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.1.tgz#9ffc44c55f5ca89253d9bb7186cefb01ef57747f" + integrity sha512-w3b5y1PXWlhYulevrTJ0lizkQ5CyqfeU6BIRDbuhsMupstHQOeb1Ur80tcB1zxSu7AwyY/qCQ7Vvqklh31ZBFw== dependencies: browserslist "^4.7.2" - caniuse-lite "^1.0.30001004" + caniuse-lite "^1.0.30001006" chalk "^2.4.2" normalize-range "^0.1.2" num2fraction "^1.2.2" - postcss "^7.0.19" + postcss "^7.0.21" postcss-value-parser "^4.0.2" aws-sign2@~0.7.0: @@ -2834,6 +2829,11 @@ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001006.tgz#5b6e8288792cfa275f007b2819a00ccad7112655" integrity sha512-MXnUVX27aGs/QINz+QG1sWSLDr3P1A3Hq5EUWoIt0T7K24DuvMxZEnh3Y5aHlJW6Bz2aApJdSewdYLd8zQnUuw== +caniuse-lite@^1.0.30001006: + version "1.0.30001008" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001008.tgz#b8841b1df78a9f5ed9702537ef592f1f8772c0d9" + integrity sha512-b8DJyb+VVXZGRgJUa30cbk8gKHZ3LOZTBLaUEEVr2P4xpmFigOCc62CO4uzquW641Ouq1Rm9N+rWLWdSYDaDIw== + capture-stack-trace@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" @@ -3462,10 +3462,10 @@ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== -core-js@^3.3.5: - version "3.3.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.3.5.tgz#58d20f48a95a07304b62ff752742b82b56431ed8" - integrity sha512-0J3K+Par/ZydhKg8pEiTcK/9d65/nqJOzY62uMkjeBmt05fDOt/khUVjDdh8TpeIuGQDy1yLDDCjiWN/8pFIuw== +core-js@^3.3.6: + version "3.3.6" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.3.6.tgz#6ad1650323c441f45379e176ed175c0d021eac92" + integrity sha512-u4oM8SHwmDuh5mWZdDg9UwNVq5s1uqq6ZDLLIs07VY+VJU91i3h4f3K/pgFvtUQPGdeStrZ+odKyfyt4EnKHfA== core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" @@ -3793,10 +3793,10 @@ debug "^4.1.1" lodash "^4.17.11" -cypress@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.5.0.tgz#e188bc8f48782953f6865d8830a4dc342334b81c" - integrity sha512-I1iSReD2C8CTP6s4BvQky4gEqHBnKLmhBIqFyCUZdj6BQ6ZDxGnmIbQPM5g79E2iP60KTIbTK99ZPSDVtsNUUg== +cypress@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/cypress/-/cypress-3.6.0.tgz#b7c88c169970aeb74a00182a1e8dc43a355d9eea" + integrity sha512-ODhbOrH1XZx0DUoYmJSvOSbEQjycNOpFYe7jOnHkT1+sdsn2+uqwAjZ1x982q3H4R/5iZjpSd50gd/iw2bofzg== dependencies: "@cypress/listr-verbose-renderer" "0.4.1" "@cypress/xvfb" "1.2.4" @@ -5669,14 +5669,6 @@ dependencies: locate-path "^2.0.0" -find-yarn-workspace-root@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" - integrity sha512-dVtfb0WuQG+8Ag2uWkbG79hOUzEsRrhBzgfn86g2sJPkzmcpGdghbNTfUKGTxymFrY/tLIodDzLoW9nOJ4FY8Q== - dependencies: - fs-extra "^4.0.3" - micromatch "^3.1.4" - findup-sync@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" @@ -5839,15 +5831,6 @@ jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -6353,10 +6336,10 @@ resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== -highlight.js@^9.15.10: - version "9.15.10" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" - integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== +highlight.js@^9.16.2: + version "9.16.2" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.16.2.tgz#68368d039ffe1c6211bcc07e483daf95de3e403e" + integrity sha512-feMUrVLZvjy0oC7FVJQcSQRqbBq9kwqnYE4+Kj9ZjbHh3g+BisiPgF49NyQbVLNdrL/qqZr3Ca9yOKwgn2i/tw== highlightjs-line-numbers.js@^2.7.0: version "2.7.0" @@ -7623,13 +7606,6 @@ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== -klaw-sync@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/klaw-sync/-/klaw-sync-6.0.0.tgz#1fd2cfd56ebb6250181114f0a581167099c2b28c" - integrity sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ== - dependencies: - graceful-fs "^4.1.11" - kleur@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" @@ -8158,13 +8134,6 @@ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - mem@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" @@ -8304,11 +8273,6 @@ resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -9280,15 +9244,6 @@ dependencies: lcid "^1.0.0" -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-locale@^3.0.0, os-locale@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -9569,25 +9524,6 @@ resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.0.tgz#677de858e352b6ca4e6cb48a6efde2cec9fde566" - integrity sha512-HWlQflaBBMjLBfOWomfolF8aqsFDeNbSNro1JDUgYqnVvPM5OILJ9DQdwIRiKmGaOsmHvhkl1FYkvv1I9r2ZJw== - dependencies: - "@yarnpkg/lockfile" "^1.1.0" - chalk "^2.4.2" - cross-spawn "^6.0.5" - find-yarn-workspace-root "^1.2.1" - fs-extra "^7.0.1" - is-ci "^2.0.0" - klaw-sync "^6.0.0" - minimist "^1.2.0" - rimraf "^2.6.3" - semver "^5.6.0" - slash "^2.0.0" - tmp "^0.0.33" - update-notifier "^2.5.0" - path-browserify@0.0.1, path-browserify@~0.0.0: version "0.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" @@ -9698,9 +9634,9 @@ png-js ">=0.1.0" pdfmake@^0.1.60: - version "0.1.61" - resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.1.61.tgz#2c8bc9ca886b454598e09893f9e9d13cb48da145" - integrity sha512-ISt9HkCpmV8IUK/vTxf0gqSn838KVRLiPHHP2AIlSwG5Rlc1Ud51tJ1xyizLJIMiELc5L9kELjdPQgC3eO9H+Q== + version "0.1.62" + resolved "https://registry.yarnpkg.com/pdfmake/-/pdfmake-0.1.62.tgz#62f2400eba066cc271736b95c7d0cdf9c8e06983" + integrity sha512-2QIzijdkwFBChTFu5nVmMe+fLBQTAYTPTxi4jGbUTyGxZBq7YR1I17FBk1Cs+3nrYufNKNukT6OR1RNxbovsTA== dependencies: iconv-lite "^0.5.0" linebreak "^1.0.2" @@ -10264,7 +10200,7 @@ source-map "^0.6.1" supports-color "^6.1.0" -postcss@^7.0.19: +postcss@^7.0.21: version "7.0.21" resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.21.tgz#06bb07824c19c2021c5d056d5b10c35b989f7e17" integrity sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ== @@ -11576,12 +11512,12 @@ array-reduce "~0.0.0" jsonify "~0.0.0" -showdown@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/showdown/-/showdown-1.9.0.tgz#d49d2a0b6db21b7c2e96ef855f7b3b2a28ef46f4" - integrity sha512-x7xDCRIaOlicbC57nMhGfKamu+ghwsdVkHMttyn+DelwzuHOx4OHCVL/UW/2QOLH7BxfCcCCVVUix3boKXJKXQ== +showdown@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/showdown/-/showdown-1.9.1.tgz#134e148e75cd4623e09c21b0511977d79b5ad0ef" + integrity sha512-9cGuS382HcvExtf5AHk7Cb4pAeQQ+h0eTr33V1mu+crYWV4KvWAw6el92bDrqGEk5d46Ai/fhbEUwqJ/mTCNEA== dependencies: - yargs "^10.0.3" + yargs "^14.2" signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" @@ -12312,9 +12248,9 @@ util.promisify "~1.0.0" sweetalert2@^8.18.5: - version "8.18.6" - resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-8.18.6.tgz#9df053369cb2b4ae0b955280505bf0cad0f8c4fe" - integrity sha512-6Jio6FH3p5hm+VHYN8mUyGhGozVo+r+eJtkUC/+bvSpXss84hcMRXNqKQs+J1+LWPy2DT7ozdyVXaVY6sMnm+w== + version "8.19.0" + resolved "https://registry.yarnpkg.com/sweetalert2/-/sweetalert2-8.19.0.tgz#692269bc8ddc5760e2b5070da2cf5e9e278bac0b" + integrity sha512-nFL++N3bitkEkd487Tv4i5ZxusmnoAAXHjtk7lp603Opxb8wlvVnz3hqa7qiIw6QFL04JC810E6qVQNf8s0vYQ== symbol-observable@1.0.1: version "1.0.1" @@ -13595,6 +13531,14 @@ camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" + integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" @@ -13602,13 +13546,6 @@ dependencies: camelcase "^3.0.0" -yargs-parser@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== - dependencies: - camelcase "^4.1.0" - yargs-unparser@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" @@ -13669,23 +13606,22 @@ y18n "^4.0.0" yargs-parser "^13.1.1" -yargs@^10.0.3: - version "10.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== +yargs@^14.2: + version "14.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.0.tgz#f116a9242c4ed8668790b40759b4906c276e76c3" + integrity sha512-/is78VKbKs70bVZH7w4YaZea6xcJWOAwkhbR0CFuZBmYtfTYF0xjGJF43AYd8g2Uii1yJwmS5GR2vBmrc32sbg== dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" require-directory "^2.1.1" - require-main-filename "^1.0.1" + require-main-filename "^2.0.0" set-blocking "^2.0.0" - string-width "^2.0.0" + string-width "^3.0.0" which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^8.1.0" + y18n "^4.0.0" + yargs-parser "^15.0.0" yargs@^7.0.0: version "7.1.0"