From 8291aa8fd7b4890832165c4053a92ef5c8589c50 Mon Sep 17 00:00:00 2001 From: Renaud Allard Date: Wed, 20 Nov 2024 12:48:04 +0100 Subject: [PATCH] Support both import names of PyPI package `python-multipart`. (#17932) --- changelog.d/17932.misc | 1 + synapse/http/client.py | 21 +++++++++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 changelog.d/17932.misc diff --git a/changelog.d/17932.misc b/changelog.d/17932.misc new file mode 100644 index 0000000000..2401c4cf21 --- /dev/null +++ b/changelog.d/17932.misc @@ -0,0 +1 @@ +Support new package name of PyPI package `python-multipart` 0.0.13 so that distro packagers do not need to work around name conflict with PyPI package `multipart`. diff --git a/synapse/http/client.py b/synapse/http/client.py index c3b2299c95..85923d956b 100644 --- a/synapse/http/client.py +++ b/synapse/http/client.py @@ -36,7 +36,6 @@ from typing import ( ) import attr -import multipart import treq from canonicaljson import encode_canonical_json from netaddr import AddrFormatError, IPAddress, IPSet @@ -93,6 +92,20 @@ from synapse.util.async_helpers import timeout_deferred if TYPE_CHECKING: from synapse.server import HomeServer +# Support both import names for the `python-multipart` (PyPI) library, +# which renamed its package name from `multipart` to `python_multipart` +# in 0.0.13 (though supports the old import name for compatibility). +# Note that the `multipart` package name conflicts with `multipart` (PyPI) +# so we should prefer importing from `python_multipart` when possible. +try: + from python_multipart import MultipartParser + + if TYPE_CHECKING: + from python_multipart import multipart +except ImportError: + from multipart import MultipartParser # type: ignore[no-redef] + + logger = logging.getLogger(__name__) outgoing_requests_counter = Counter("synapse_http_client_requests", "", ["method"]) @@ -1039,7 +1052,7 @@ class _MultipartParserProtocol(protocol.Protocol): self.deferred = deferred self.boundary = boundary self.max_length = max_length - self.parser: Optional[multipart.MultipartParser] = None + self.parser: Optional[MultipartParser] = None self.multipart_response = MultipartResponse() self.has_redirect = False self.in_json = False @@ -1097,12 +1110,12 @@ class _MultipartParserProtocol(protocol.Protocol): self.deferred.errback() self.file_length += end - start - callbacks: "multipart.multipart.MultipartCallbacks" = { + callbacks: "multipart.MultipartCallbacks" = { "on_header_field": on_header_field, "on_header_value": on_header_value, "on_part_data": on_part_data, } - self.parser = multipart.MultipartParser(self.boundary, callbacks) + self.parser = MultipartParser(self.boundary, callbacks) self.total_length += len(incoming_data) if self.max_length is not None and self.total_length >= self.max_length: