diff --git a/citadel/README.md b/citadel/README.md index c9e3a2d..e62aa31 100644 --- a/citadel/README.md +++ b/citadel/README.md @@ -5,6 +5,10 @@ to provide advanced search functionality using an Elasticsearch backend. ## Changelog +### 3.2.1 + +- Stop using deprecated URL utils from werkzeug + ### 3.2 - Update translations diff --git a/citadel/indico_citadel/backend.py b/citadel/indico_citadel/backend.py index 08b56d4..79762cb 100644 --- a/citadel/indico_citadel/backend.py +++ b/citadel/indico_citadel/backend.py @@ -10,6 +10,7 @@ import time from functools import cached_property from operator import attrgetter from pprint import pformat +from urllib.parse import urljoin import requests from jinja2.filters import do_filesizeformat @@ -23,7 +24,6 @@ from sqlalchemy.exc import IntegrityError from sqlalchemy.orm import contains_eager, joinedload from sqlalchemy.orm.attributes import flag_modified from urllib3 import Retry -from werkzeug.urls import url_join from indico.core.db import db from indico.modules.attachments import Attachment @@ -62,7 +62,7 @@ class LiveSyncCitadelUploader(Uploader): self.categories = None self.search_app = self.backend.plugin.settings.get('search_backend_url') - self.endpoint_url = url_join(self.search_app, 'api/records/') + self.endpoint_url = urljoin(self.search_app, 'api/records/') self.headers = { 'Authorization': 'Bearer {}'.format(self.backend.plugin.settings.get('search_backend_token')) } @@ -75,23 +75,23 @@ class LiveSyncCitadelUploader(Uploader): return [ EventRecordSchema(context={ 'categories': self.categories, - 'schema': url_join(self.search_app, 'schemas/indico/events_v1.0.0.json'), + 'schema': urljoin(self.search_app, 'schemas/indico/events_v1.0.0.json'), }), ContributionRecordSchema(context={ 'categories': self.categories, - 'schema': url_join(self.search_app, 'schemas/indico/contributions_v1.0.0.json'), + 'schema': urljoin(self.search_app, 'schemas/indico/contributions_v1.0.0.json'), }), SubContributionRecordSchema(context={ 'categories': self.categories, - 'schema': url_join(self.search_app, 'schemas/indico/subcontributions_v1.0.0.json'), + 'schema': urljoin(self.search_app, 'schemas/indico/subcontributions_v1.0.0.json'), }), AttachmentRecordSchema(context={ 'categories': self.categories, - 'schema': url_join(self.search_app, 'schemas/indico/attachments_v1.0.0.json'), + 'schema': urljoin(self.search_app, 'schemas/indico/attachments_v1.0.0.json'), }), EventNoteRecordSchema(context={ 'categories': self.categories, - 'schema': url_join(self.search_app, 'schemas/indico/notes_v1.0.0.json'), + 'schema': urljoin(self.search_app, 'schemas/indico/notes_v1.0.0.json'), }) ] @@ -134,7 +134,7 @@ class LiveSyncCitadelUploader(Uploader): self.logger.debug('Updating record %d on citadel', citadel_id) assert data is not None try: - resp = session.put(url_join(self.search_app, f'api/record/{citadel_id}'), json=data) + resp = session.put(urljoin(self.search_app, f'api/record/{citadel_id}'), json=data) self.logger.debug('Updated %d on citadel', citadel_id) resp.raise_for_status() resp.close() @@ -147,7 +147,7 @@ class LiveSyncCitadelUploader(Uploader): def _citadel_delete(self, session, citadel_id, *, delete_mapping): self.logger.debug('Deleting record %d from citadel', citadel_id) try: - resp = session.delete(url_join(self.search_app, f'api/record/{citadel_id}')) + resp = session.delete(urljoin(self.search_app, f'api/record/{citadel_id}')) self.logger.debug('Deleted %d from citadel', citadel_id) if resp.status_code == 410: # gone - record was probably already deleted @@ -194,7 +194,7 @@ class LiveSyncCitadelUploader(Uploader): entry.attachment.file.filename, delta) ts = time.time() resp = session.put( - url_join(self.search_app, f'api/record/{entry.citadel_id}/files/attachment'), + urljoin(self.search_app, f'api/record/{entry.citadel_id}/files/attachment'), data=file ) delta = time.time() - ts diff --git a/citadel/indico_citadel/search.py b/citadel/indico_citadel/search.py index e1e91b7..ee1a75d 100644 --- a/citadel/indico_citadel/search.py +++ b/citadel/indico_citadel/search.py @@ -7,11 +7,11 @@ import base64 import zlib +from urllib.parse import urljoin import requests from flask import current_app from requests.exceptions import RequestException -from werkzeug.urls import url_join from indico.modules.search.base import IndicoSearchProvider, SearchOption from indico.util.decorators import classproperty @@ -28,7 +28,7 @@ class CitadelProvider(IndicoSearchProvider): super().__init__(*args, **kwargs) self.token = CitadelPlugin.settings.get('search_backend_token') self.backend_url = CitadelPlugin.settings.get('search_backend_url') - self.records_url = url_join(self.backend_url, 'api/records/') + self.records_url = urljoin(self.backend_url, 'api/records/') @classproperty @classmethod diff --git a/citadel/setup.cfg b/citadel/setup.cfg index 97b2a1d..cc60d14 100644 --- a/citadel/setup.cfg +++ b/citadel/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = indico-plugin-citadel -version = 3.2 +version = 3.2.1 description = Indico search+livesync backend using Citadel+ElasticSearch long_description = file: README.md long_description_content_type = text/markdown; charset=UTF-8; variant=GFM diff --git a/storage_s3/README.md b/storage_s3/README.md index d7ecd22..cb47e69 100644 --- a/storage_s3/README.md +++ b/storage_s3/README.md @@ -15,6 +15,14 @@ to local storage (but it would of course be possible to write a script for this) ## Changelog +### 3.2.1 + +- Stop using deprecated URL utils from werkzeug + +### 3.2 + +- Update translations + ### 3.1.2 - No technical changes, just fixing a mistake in the README change from 3.1.1 diff --git a/storage_s3/indico_storage_s3/storage.py b/storage_s3/indico_storage_s3/storage.py index 44a063b..7f88c8d 100644 --- a/storage_s3/indico_storage_s3/storage.py +++ b/storage_s3/indico_storage_s3/storage.py @@ -14,13 +14,13 @@ from datetime import date from enum import Enum from io import BytesIO from tempfile import NamedTemporaryFile +from urllib.parse import quote import boto3 from boto3.s3.transfer import TransferConfig from botocore.config import Config from botocore.exceptions import ClientError from werkzeug.datastructures import Headers -from werkzeug.urls import url_quote from werkzeug.utils import cached_property, redirect from indico.core.config import config @@ -156,7 +156,7 @@ class S3StorageBase(Storage): if self.proxy_downloads == ProxyDownloadsMode.nginx: # nginx can proxy the request to S3 to avoid exposing the redirect and # bucket URL to the end user (since it is quite ugly and temporary) - response.headers['X-Accel-Redirect'] = '/.xsf/s3/' + url_quote(url.replace('://', '/', 1)) + response.headers['X-Accel-Redirect'] = '/.xsf/s3/' + quote(url.replace('://', '/', 1)) return response except Exception as exc: raise StorageError(f'Could not send file "{file_id}": {exc}') from exc diff --git a/storage_s3/indico_storage_s3/util.py b/storage_s3/indico_storage_s3/util.py index e4f553e..ebc843f 100644 --- a/storage_s3/indico_storage_s3/util.py +++ b/storage_s3/indico_storage_s3/util.py @@ -6,8 +6,7 @@ # see the LICENSE file for more details. import unicodedata - -from werkzeug.urls import url_quote +from urllib.parse import quote def make_content_disposition_args(attachment_filename): @@ -16,7 +15,7 @@ def make_content_disposition_args(attachment_filename): except UnicodeEncodeError: return { 'filename': unicodedata.normalize('NFKD', attachment_filename).encode('ascii', 'ignore'), - 'filename*': "UTF-8''%s" % url_quote(attachment_filename, safe=b''), + 'filename*': "UTF-8''%s" % quote(attachment_filename, safe=b''), } else: return {'filename': attachment_filename} diff --git a/storage_s3/setup.cfg b/storage_s3/setup.cfg index c038732..0957902 100644 --- a/storage_s3/setup.cfg +++ b/storage_s3/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = indico-plugin-storage-s3 -version = 3.2 +version = 3.2.1 description = S3 storage backend for Indico long_description = file: README.md long_description_content_type = text/markdown; charset=UTF-8; variant=GFM diff --git a/ursh/README.md b/ursh/README.md index de21938..b61e9bc 100644 --- a/ursh/README.md +++ b/ursh/README.md @@ -13,6 +13,10 @@ human-friendly shortcuts pointing to an event (such as `https://indico.example.c ## Changelog +### 3.2.1 + +- Stop using deprecated URL utils from werkzeug + ### 3.2 - Update translations diff --git a/ursh/indico_ursh/controllers.py b/ursh/indico_ursh/controllers.py index 55458aa..1e2b6d0 100644 --- a/ursh/indico_ursh/controllers.py +++ b/ursh/indico_ursh/controllers.py @@ -6,11 +6,11 @@ # see the LICENSE file for more details. import posixpath +from urllib.parse import urlsplit from flask import jsonify, request, session from flask_pluginengine import render_plugin_template from werkzeug.exceptions import BadRequest, NotFound -from werkzeug.urls import url_parse from indico.core.config import config from indico.modules.events.management.controllers import RHManageEventBase @@ -30,14 +30,14 @@ class RHGetShortURL(RH): @staticmethod def _resolve_full_url(original_url): - if url_parse(original_url).host: + if urlsplit(original_url).hostname: return original_url original_url = original_url.lstrip('/') return posixpath.join(config.BASE_URL, original_url) @staticmethod def _check_host(full_url): - if url_parse(full_url).host != url_parse(config.BASE_URL).host: + if urlsplit(full_url).hostname != urlsplit(config.BASE_URL).hostname: raise BadRequest('Invalid host for URL shortening service') def _process(self): @@ -73,7 +73,7 @@ class RHCustomShortURLPage(RHManageEventBase): def _process_args(self): from indico_ursh.plugin import UrshPlugin super()._process_args() - api_host = url_parse(UrshPlugin.settings.get('api_host')) + api_host = urlsplit(UrshPlugin.settings.get('api_host')) self.ursh_host = strip_end(api_host.to_url(), api_host.path[1:]).rstrip('/') + '/' def _process_GET(self): diff --git a/ursh/setup.cfg b/ursh/setup.cfg index 64cda56..6e28048 100644 --- a/ursh/setup.cfg +++ b/ursh/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = indico-plugin-ursh -version = 3.2 +version = 3.2.1 description = URL shortening service for Indico long_description = file: README.md long_description_content_type = text/markdown; charset=UTF-8; variant=GFM