Fix support for older versions of zope-interface (#19274)

Fixes #19269 

Versions of zope-interface from RHEL, Ubuntu LTS 22 & 24 and OpenSuse
don't support the new python union `X | Y` syntax for interfaces. This
PR partially reverts the change over to fully use the new syntax, adds a
minimum supported version of zope-interface to Synapse's dependency
list, and removes the linter auto-upgrades which prefer the newer
syntax.

### Pull Request Checklist

<!-- Please read
https://element-hq.github.io/synapse/latest/development/contributing_guide.html
before submitting your pull request -->

* [X] Pull request is based on the develop branch
* [X] Pull request includes a [changelog
file](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#changelog).
The entry should:
- Be a short description of your change which makes sense to users.
"Fixed a bug that prevented receiving messages from other servers."
instead of "Moved X method from `EventStore` to `EventWorkerStore`.".
  - Use markdown where necessary, mostly for `code blocks`.
  - End with either a period (.) or an exclamation mark (!).
  - Start with a capital letter.
- Feel free to credit yourself, by adding a sentence "Contributed by
@github_username." or "Contributed by [Your Name]." to the end of the
entry.
* [X] [Code
style](https://element-hq.github.io/synapse/latest/code_style.html) is
correct (run the
[linters](https://element-hq.github.io/synapse/latest/development/contributing_guide.html#run-the-linters))

---------

Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
This commit is contained in:
Devon Hudson
2025-12-12 15:34:13 +00:00
committed by GitHub
parent 048629dd13
commit df24e0f302
25 changed files with 65 additions and 56 deletions

1
changelog.d/19274.bugfix Normal file
View File

@@ -0,0 +1 @@
Fix bug introduced in 1.143.0 that broke support for versions of `zope-interface` older than 6.2.

2
poetry.lock generated
View File

@@ -3542,4 +3542,4 @@ url-preview = ["lxml"]
[metadata] [metadata]
lock-version = "2.1" lock-version = "2.1"
python-versions = ">=3.10.0,<4.0.0" python-versions = ">=3.10.0,<4.0.0"
content-hash = "abbbdff591a306b56cc8890dbb2f477ac5f1a2d328baa6409e01084abc655bbf" content-hash = "1caa5072f6304122c89377420f993a54f54587f3618ccc8094ec31642264592c"

View File

@@ -109,7 +109,12 @@ dependencies = [
"pyrsistent>=0.18.0", # via jsonschema "pyrsistent>=0.18.0", # via jsonschema
"requests>=2.16.0", # 2.16.0+ no longer vendors urllib3, avoiding Python 3.10+ incompatibility "requests>=2.16.0", # 2.16.0+ no longer vendors urllib3, avoiding Python 3.10+ incompatibility
"urllib3>=1.26.5", # via treq; 1.26.5 fixes Python 3.10+ collections.abc compatibility "urllib3>=1.26.5", # via treq; 1.26.5 fixes Python 3.10+ collections.abc compatibility
"zope-interface>=6.2", # via twisted # 5.2 is the current version in Debian oldstable. If we don't care to support that, then 5.4 is
# the minimum version from Ubuntu 22.04 and RHEL 9. (as of 2025-12)
# When bumping this version to 6.2 or above, refer to https://github.com/element-hq/synapse/pull/19274
# for details of Synapse improvements that may be unlocked. Particularly around the use of `|`
# syntax with zope interface types.
"zope-interface>=5.2", # via twisted
] ]
[project.optional-dependencies] [project.optional-dependencies]
@@ -383,15 +388,10 @@ select = [
"G", "G",
# pyupgrade # pyupgrade
"UP006", "UP006",
"UP007",
"UP045",
] ]
extend-safe-fixes = [ extend-safe-fixes = [
# pyupgrade rules compatible with Python >= 3.9 # pyupgrade rules compatible with Python >= 3.9
"UP006", "UP006",
"UP007",
# pyupgrade rules compatible with Python >= 3.10
"UP045",
# Allow ruff to automatically fix trailing spaces within a multi-line string/comment. # Allow ruff to automatically fix trailing spaces within a multi-line string/comment.
"W293" "W293"
] ]

View File

@@ -36,6 +36,7 @@ from typing import (
Awaitable, Awaitable,
Callable, Callable,
NoReturn, NoReturn,
Optional,
cast, cast,
) )
from wsgiref.simple_server import WSGIServer from wsgiref.simple_server import WSGIServer
@@ -455,7 +456,7 @@ def listen_http(
root_resource: Resource, root_resource: Resource,
version_string: str, version_string: str,
max_request_body_size: int, max_request_body_size: int,
context_factory: IOpenSSLContextFactory | None, context_factory: Optional[IOpenSSLContextFactory],
reactor: ISynapseReactor = reactor, reactor: ISynapseReactor = reactor,
) -> list[Port]: ) -> list[Port]:
""" """

View File

@@ -24,7 +24,7 @@ import logging
import os import os
import sys import sys
import tempfile import tempfile
from typing import Mapping, Sequence from typing import Mapping, Optional, Sequence
from twisted.internet import defer, task from twisted.internet import defer, task
@@ -291,7 +291,7 @@ def load_config(argv_options: list[str]) -> tuple[HomeServerConfig, argparse.Nam
def create_homeserver( def create_homeserver(
config: HomeServerConfig, config: HomeServerConfig,
reactor: ISynapseReactor | None = None, reactor: Optional[ISynapseReactor] = None,
) -> AdminCmdServer: ) -> AdminCmdServer:
""" """
Create a homeserver instance for the Synapse admin command process. Create a homeserver instance for the Synapse admin command process.

View File

@@ -21,6 +21,7 @@
# #
import logging import logging
import sys import sys
from typing import Optional
from twisted.web.resource import Resource from twisted.web.resource import Resource
@@ -335,7 +336,7 @@ def load_config(argv_options: list[str]) -> HomeServerConfig:
def create_homeserver( def create_homeserver(
config: HomeServerConfig, config: HomeServerConfig,
reactor: ISynapseReactor | None = None, reactor: Optional[ISynapseReactor] = None,
) -> GenericWorkerServer: ) -> GenericWorkerServer:
""" """
Create a homeserver instance for the Synapse worker process. Create a homeserver instance for the Synapse worker process.

View File

@@ -22,7 +22,7 @@
import logging import logging
import os import os
import sys import sys
from typing import Iterable from typing import Iterable, Optional
from twisted.internet.tcp import Port from twisted.internet.tcp import Port
from twisted.web.resource import EncodingResourceWrapper, Resource from twisted.web.resource import EncodingResourceWrapper, Resource
@@ -350,7 +350,7 @@ def load_or_generate_config(argv_options: list[str]) -> HomeServerConfig:
def create_homeserver( def create_homeserver(
config: HomeServerConfig, config: HomeServerConfig,
reactor: ISynapseReactor | None = None, reactor: Optional[ISynapseReactor] = None,
) -> SynapseHomeServer: ) -> SynapseHomeServer:
""" """
Create a homeserver instance for the Synapse main process. Create a homeserver instance for the Synapse main process.

View File

@@ -13,7 +13,7 @@
# #
import logging import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Optional
from twisted.internet.interfaces import IDelayedCall from twisted.internet.interfaces import IDelayedCall
@@ -74,7 +74,7 @@ class DelayedEventsHandler:
cfg=self._config.ratelimiting.rc_delayed_event_mgmt, cfg=self._config.ratelimiting.rc_delayed_event_mgmt,
) )
self._next_delayed_event_call: IDelayedCall | None = None self._next_delayed_event_call: Optional[IDelayedCall] = None
# The current position in the current_state_delta stream # The current position in the current_state_delta stream
self._event_pos: int | None = None self._event_pos: int | None = None

View File

@@ -22,7 +22,7 @@
import logging import logging
import random import random
from http import HTTPStatus from http import HTTPStatus
from typing import TYPE_CHECKING, Any, Mapping, Sequence from typing import TYPE_CHECKING, Any, Mapping, Optional, Sequence
from canonicaljson import encode_canonical_json from canonicaljson import encode_canonical_json
@@ -111,7 +111,7 @@ class MessageHandler:
# The scheduled call to self._expire_event. None if no call is currently # The scheduled call to self._expire_event. None if no call is currently
# scheduled. # scheduled.
self._scheduled_expiry: IDelayedCall | None = None self._scheduled_expiry: Optional[IDelayedCall] = None
if not hs.config.worker.worker_app: if not hs.config.worker.worker_app:
self.hs.run_as_background_process( self.hs.run_as_background_process(

View File

@@ -21,7 +21,7 @@
import logging import logging
from http import HTTPStatus from http import HTTPStatus
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Optional
from twisted.internet.interfaces import IDelayedCall from twisted.internet.interfaces import IDelayedCall
@@ -125,7 +125,7 @@ class UserDirectoryHandler(StateDeltasHandler):
# Guard to ensure we only have one process for refreshing remote profiles # Guard to ensure we only have one process for refreshing remote profiles
self._is_refreshing_remote_profiles = False self._is_refreshing_remote_profiles = False
# Handle to cancel the `call_later` of `kick_off_remote_profile_refresh_process` # Handle to cancel the `call_later` of `kick_off_remote_profile_refresh_process`
self._refresh_remote_profiles_call_later: IDelayedCall | None = None self._refresh_remote_profiles_call_later: Optional[IDelayedCall] = None
# Guard to ensure we only have one process for refreshing remote profiles # Guard to ensure we only have one process for refreshing remote profiles
# for the given servers. # for the given servers.

View File

@@ -28,6 +28,7 @@ from typing import (
BinaryIO, BinaryIO,
Callable, Callable,
Mapping, Mapping,
Optional,
Protocol, Protocol,
) )
@@ -313,7 +314,7 @@ class BlocklistingAgentWrapper(Agent):
method: bytes, method: bytes,
uri: bytes, uri: bytes,
headers: Headers | None = None, headers: Headers | None = None,
bodyProducer: IBodyProducer | None = None, bodyProducer: Optional[IBodyProducer] = None,
) -> defer.Deferred: ) -> defer.Deferred:
h = urllib.parse.urlparse(uri.decode("ascii")) h = urllib.parse.urlparse(uri.decode("ascii"))
@@ -1033,7 +1034,7 @@ class BodyExceededMaxSize(Exception):
class _DiscardBodyWithMaxSizeProtocol(protocol.Protocol): class _DiscardBodyWithMaxSizeProtocol(protocol.Protocol):
"""A protocol which immediately errors upon receiving data.""" """A protocol which immediately errors upon receiving data."""
transport: ITCPTransport | None = None transport: Optional[ITCPTransport] = None
def __init__(self, deferred: defer.Deferred): def __init__(self, deferred: defer.Deferred):
self.deferred = deferred self.deferred = deferred
@@ -1075,7 +1076,7 @@ class _MultipartParserProtocol(protocol.Protocol):
Protocol to read and parse a MSC3916 multipart/mixed response Protocol to read and parse a MSC3916 multipart/mixed response
""" """
transport: ITCPTransport | None = None transport: Optional[ITCPTransport] = None
def __init__( def __init__(
self, self,
@@ -1188,7 +1189,7 @@ class _MultipartParserProtocol(protocol.Protocol):
class _ReadBodyWithMaxSizeProtocol(protocol.Protocol): class _ReadBodyWithMaxSizeProtocol(protocol.Protocol):
"""A protocol which reads body to a stream, erroring if the body exceeds a maximum size.""" """A protocol which reads body to a stream, erroring if the body exceeds a maximum size."""
transport: ITCPTransport | None = None transport: Optional[ITCPTransport] = None
def __init__( def __init__(
self, stream: ByteWriteable, deferred: defer.Deferred, max_size: int | None self, stream: ByteWriteable, deferred: defer.Deferred, max_size: int | None

View File

@@ -19,7 +19,7 @@
# #
import logging import logging
import urllib.parse import urllib.parse
from typing import Any, Generator from typing import Any, Generator, Optional
from urllib.request import ( # type: ignore[attr-defined] from urllib.request import ( # type: ignore[attr-defined]
proxy_bypass_environment, proxy_bypass_environment,
) )
@@ -173,7 +173,7 @@ class MatrixFederationAgent:
method: bytes, method: bytes,
uri: bytes, uri: bytes,
headers: Headers | None = None, headers: Headers | None = None,
bodyProducer: IBodyProducer | None = None, bodyProducer: Optional[IBodyProducer] = None,
) -> Generator[defer.Deferred, Any, IResponse]: ) -> Generator[defer.Deferred, Any, IResponse]:
""" """
Args: Args:

View File

@@ -33,6 +33,7 @@ from typing import (
Callable, Callable,
Generic, Generic,
Literal, Literal,
Optional,
TextIO, TextIO,
TypeVar, TypeVar,
cast, cast,
@@ -691,7 +692,7 @@ class MatrixFederationHttpClient:
destination_bytes, method_bytes, url_to_sign_bytes, json destination_bytes, method_bytes, url_to_sign_bytes, json
) )
data = encode_canonical_json(json) data = encode_canonical_json(json)
producer: IBodyProducer | None = QuieterFileBodyProducer( producer: Optional[IBodyProducer] = QuieterFileBodyProducer(
BytesIO(data), cooperator=self._cooperator BytesIO(data), cooperator=self._cooperator
) )
else: else:

View File

@@ -22,7 +22,7 @@
import json import json
import logging import logging
import urllib.parse import urllib.parse
from typing import TYPE_CHECKING, Any, cast from typing import TYPE_CHECKING, Any, Optional, cast
from twisted.internet import protocol from twisted.internet import protocol
from twisted.internet.interfaces import ITCPTransport from twisted.internet.interfaces import ITCPTransport
@@ -237,7 +237,7 @@ class _ProxyResponseBody(protocol.Protocol):
request. request.
""" """
transport: ITCPTransport | None = None transport: Optional[ITCPTransport] = None
def __init__(self, request: "SynapseRequest") -> None: def __init__(self, request: "SynapseRequest") -> None:
self._request = request self._request = request

View File

@@ -21,7 +21,7 @@
import logging import logging
import random import random
import re import re
from typing import Any, Collection, Sequence, cast from typing import Any, Collection, Optional, Sequence, cast
from urllib.parse import urlparse from urllib.parse import urlparse
from urllib.request import ( # type: ignore[attr-defined] from urllib.request import ( # type: ignore[attr-defined]
proxy_bypass_environment, proxy_bypass_environment,
@@ -119,8 +119,8 @@ class ProxyAgent(_AgentBase):
self, self,
*, *,
reactor: IReactorCore, reactor: IReactorCore,
proxy_reactor: IReactorCore | None = None, proxy_reactor: Optional[IReactorCore] = None,
contextFactory: IPolicyForHTTPS | None = None, contextFactory: Optional[IPolicyForHTTPS] = None,
connectTimeout: float | None = None, connectTimeout: float | None = None,
bindAddress: bytes | None = None, bindAddress: bytes | None = None,
pool: HTTPConnectionPool | None = None, pool: HTTPConnectionPool | None = None,
@@ -175,7 +175,7 @@ class ProxyAgent(_AgentBase):
self._policy_for_https = contextFactory self._policy_for_https = contextFactory
self._reactor = cast(IReactorTime, reactor) self._reactor = cast(IReactorTime, reactor)
self._federation_proxy_endpoint: IStreamClientEndpoint | None = None self._federation_proxy_endpoint: Optional[IStreamClientEndpoint] = None
self._federation_proxy_credentials: ProxyCredentials | None = None self._federation_proxy_credentials: ProxyCredentials | None = None
if federation_proxy_locations: if federation_proxy_locations:
assert federation_proxy_credentials is not None, ( assert federation_proxy_credentials is not None, (
@@ -221,7 +221,7 @@ class ProxyAgent(_AgentBase):
method: bytes, method: bytes,
uri: bytes, uri: bytes,
headers: Headers | None = None, headers: Headers | None = None,
bodyProducer: IBodyProducer | None = None, bodyProducer: Optional[IBodyProducer] = None,
) -> "defer.Deferred[IResponse]": ) -> "defer.Deferred[IResponse]":
""" """
Issue a request to the server indicated by the given uri. Issue a request to the server indicated by the given uri.
@@ -365,11 +365,11 @@ class ProxyAgent(_AgentBase):
def http_proxy_endpoint( def http_proxy_endpoint(
proxy: bytes | None, proxy: bytes | None,
reactor: IReactorCore, reactor: IReactorCore,
tls_options_factory: IPolicyForHTTPS | None, tls_options_factory: Optional[IPolicyForHTTPS],
timeout: float = 30, timeout: float = 30,
bindAddress: bytes | str | tuple[bytes | str, int] | None = None, bindAddress: bytes | str | tuple[bytes | str, int] | None = None,
attemptDelay: float | None = None, attemptDelay: float | None = None,
) -> tuple[IStreamClientEndpoint | None, ProxyCredentials | None]: ) -> tuple[Optional[IStreamClientEndpoint], ProxyCredentials | None]:
"""Parses an http proxy setting and returns an endpoint for the proxy """Parses an http proxy setting and returns an endpoint for the proxy
Args: Args:

View File

@@ -20,6 +20,7 @@
# #
import logging import logging
from typing import Optional
from zope.interface import implementer from zope.interface import implementer
@@ -149,7 +150,7 @@ class ReplicationAgent(_AgentBase):
method: bytes, method: bytes,
uri: bytes, uri: bytes,
headers: Headers | None = None, headers: Headers | None = None,
bodyProducer: IBodyProducer | None = None, bodyProducer: Optional[IBodyProducer] = None,
) -> "defer.Deferred[IResponse]": ) -> "defer.Deferred[IResponse]":
""" """
Issue a request to the server indicated by the given uri. Issue a request to the server indicated by the given uri.

View File

@@ -25,7 +25,7 @@ import traceback
from collections import deque from collections import deque
from ipaddress import IPv4Address, IPv6Address, ip_address from ipaddress import IPv4Address, IPv6Address, ip_address
from math import floor from math import floor
from typing import Callable from typing import Callable, Optional
import attr import attr
from zope.interface import implementer from zope.interface import implementer
@@ -113,7 +113,7 @@ class RemoteHandler(logging.Handler):
port: int, port: int,
maximum_buffer: int = 1000, maximum_buffer: int = 1000,
level: int = logging.NOTSET, level: int = logging.NOTSET,
_reactor: IReactorTime | None = None, _reactor: Optional[IReactorTime] = None,
): ):
super().__init__(level=level) super().__init__(level=level)
self.host = host self.host = host

View File

@@ -3,7 +3,7 @@ import time
from logging import Handler, LogRecord from logging import Handler, LogRecord
from logging.handlers import MemoryHandler from logging.handlers import MemoryHandler
from threading import Thread from threading import Thread
from typing import cast from typing import Optional, cast
from twisted.internet.interfaces import IReactorCore from twisted.internet.interfaces import IReactorCore
@@ -26,7 +26,7 @@ class PeriodicallyFlushingMemoryHandler(MemoryHandler):
target: Handler | None = None, target: Handler | None = None,
flushOnClose: bool = True, flushOnClose: bool = True,
period: float = 5.0, period: float = 5.0,
reactor: IReactorCore | None = None, reactor: Optional[IReactorCore] = None,
) -> None: ) -> None:
""" """
period: the period between automatic flushes period: the period between automatic flushes

View File

@@ -30,6 +30,7 @@ from typing import (
Awaitable, Awaitable,
BinaryIO, BinaryIO,
Generator, Generator,
Optional,
) )
import attr import attr
@@ -705,7 +706,7 @@ class ThreadedFileSender:
self.file: BinaryIO | None = None self.file: BinaryIO | None = None
self.deferred: "Deferred[None]" = Deferred() self.deferred: "Deferred[None]" = Deferred()
self.consumer: interfaces.IConsumer | None = None self.consumer: Optional[IConsumer] = None
# Signals if the thread should keep reading/sending data. Set means # Signals if the thread should keep reading/sending data. Set means
# continue, clear means pause. # continue, clear means pause.

View File

@@ -20,7 +20,7 @@
# #
import logging import logging
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Optional
from twisted.internet.error import AlreadyCalled, AlreadyCancelled from twisted.internet.error import AlreadyCalled, AlreadyCancelled
from twisted.internet.interfaces import IDelayedCall from twisted.internet.interfaces import IDelayedCall
@@ -71,7 +71,7 @@ class EmailPusher(Pusher):
self.server_name = hs.hostname self.server_name = hs.hostname
self.store = self.hs.get_datastores().main self.store = self.hs.get_datastores().main
self.email = pusher_config.pushkey self.email = pusher_config.pushkey
self.timed_call: IDelayedCall | None = None self.timed_call: Optional[IDelayedCall] = None
self.throttle_params: dict[str, ThrottleParams] = {} self.throttle_params: dict[str, ThrottleParams] = {}
self._inited = False self._inited = False

View File

@@ -21,7 +21,7 @@
import logging import logging
import random import random
import urllib.parse import urllib.parse
from typing import TYPE_CHECKING from typing import TYPE_CHECKING, Optional
from prometheus_client import Counter from prometheus_client import Counter
@@ -120,7 +120,7 @@ class HttpPusher(Pusher):
self.data = pusher_config.data self.data = pusher_config.data
self.backoff_delay = HttpPusher.INITIAL_BACKOFF_SEC self.backoff_delay = HttpPusher.INITIAL_BACKOFF_SEC
self.failing_since = pusher_config.failing_since self.failing_since = pusher_config.failing_since
self.timed_call: IDelayedCall | None = None self.timed_call: Optional[IDelayedCall] = None
self._is_processing = False self._is_processing = False
self._group_unread_count_by_room = ( self._group_unread_count_by_room = (
hs.config.push.push_group_unread_count_by_room hs.config.push.push_group_unread_count_by_room

View File

@@ -34,6 +34,7 @@ from typing import (
Any, Any,
Awaitable, Awaitable,
Callable, Callable,
Optional,
TypeVar, TypeVar,
cast, cast,
) )
@@ -320,7 +321,7 @@ class HomeServer(metaclass=abc.ABCMeta):
self, self,
hostname: str, hostname: str,
config: HomeServerConfig, config: HomeServerConfig,
reactor: ISynapseReactor | None = None, reactor: Optional[ISynapseReactor] = None,
): ):
""" """
Args: Args:
@@ -353,7 +354,7 @@ class HomeServer(metaclass=abc.ABCMeta):
self._module_web_resources_consumed = False self._module_web_resources_consumed = False
# This attribute is set by the free function `refresh_certificate`. # This attribute is set by the free function `refresh_certificate`.
self.tls_server_context_factory: IOpenSSLContextFactory | None = None self.tls_server_context_factory: Optional[IOpenSSLContextFactory] = None
self._is_shutdown = False self._is_shutdown = False
self._async_shutdown_handlers: list[ShutdownInfo] = [] self._async_shutdown_handlers: list[ShutdownInfo] = []

View File

@@ -19,7 +19,7 @@
# #
import queue import queue
from typing import Any, BinaryIO, cast from typing import Any, BinaryIO, Optional, Union, cast
from twisted.internet import threads from twisted.internet import threads
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
@@ -50,7 +50,7 @@ class BackgroundFileConsumer:
self._reactor: ISynapseReactor = reactor self._reactor: ISynapseReactor = reactor
# Producer we're registered with # Producer we're registered with
self._producer: IPushProducer | IPullProducer | None = None self._producer: Optional[Union[IPushProducer, IPullProducer]] = None
# True if PushProducer, false if PullProducer # True if PushProducer, false if PullProducer
self.streaming = False self.streaming = False
@@ -72,7 +72,7 @@ class BackgroundFileConsumer:
self._write_exception: Exception | None = None self._write_exception: Exception | None = None
def registerProducer( def registerProducer(
self, producer: IPushProducer | IPullProducer, streaming: bool self, producer: Union[IPushProducer, IPullProducer], streaming: bool
) -> None: ) -> None:
"""Part of IConsumer interface """Part of IConsumer interface

View File

@@ -147,7 +147,7 @@ class FakeChannel:
_reactor: MemoryReactorClock _reactor: MemoryReactorClock
result: dict = attr.Factory(dict) result: dict = attr.Factory(dict)
_ip: str = "127.0.0.1" _ip: str = "127.0.0.1"
_producer: IPullProducer | IPushProducer | None = None _producer: Optional[Union[IPullProducer, IPushProducer]] = None
resource_usage: ContextResourceUsage | None = None resource_usage: ContextResourceUsage | None = None
_request: Request | None = None _request: Request | None = None
@@ -248,7 +248,7 @@ class FakeChannel:
# TODO This should ensure that the IProducer is an IPushProducer or # TODO This should ensure that the IProducer is an IPushProducer or
# IPullProducer, unfortunately twisted.protocols.basic.FileSender does # IPullProducer, unfortunately twisted.protocols.basic.FileSender does
# implement those, but doesn't declare it. # implement those, but doesn't declare it.
self._producer = cast(IPushProducer | IPullProducer, producer) self._producer = cast(Union[IPushProducer, IPullProducer], producer)
self.producerStreaming = streaming self.producerStreaming = streaming
def _produce() -> None: def _produce() -> None:
@@ -852,7 +852,7 @@ class FakeTransport:
"""Test reactor """Test reactor
""" """
_protocol: IProtocol | None = None _protocol: Optional[IProtocol] = None
"""The Protocol which is producing data for this transport. Optional, but if set """The Protocol which is producing data for this transport. Optional, but if set
will get called back for connectionLost() notifications etc. will get called back for connectionLost() notifications etc.
""" """
@@ -871,7 +871,7 @@ class FakeTransport:
disconnected = False disconnected = False
connected = True connected = True
buffer: bytes = b"" buffer: bytes = b""
producer: IPushProducer | None = None producer: Optional[IPushProducer] = None
autoflush: bool = True autoflush: bool = True
def getPeer(self) -> IPv4Address | IPv6Address: def getPeer(self) -> IPv4Address | IPv6Address:
@@ -1073,7 +1073,7 @@ def setup_test_homeserver(
cleanup_func: Callable[[Callable[[], Optional["Deferred[None]"]]], None], cleanup_func: Callable[[Callable[[], Optional["Deferred[None]"]]], None],
server_name: str = "test", server_name: str = "test",
config: HomeServerConfig | None = None, config: HomeServerConfig | None = None,
reactor: ISynapseReactor | None = None, reactor: Optional[ISynapseReactor] = None,
homeserver_to_use: type[HomeServer] = TestHomeServer, homeserver_to_use: type[HomeServer] = TestHomeServer,
db_txn_limit: int | None = None, db_txn_limit: int | None = None,
**extra_homeserver_attributes: Any, **extra_homeserver_attributes: Any,

View File

@@ -37,6 +37,7 @@ from typing import (
Iterable, Iterable,
Mapping, Mapping,
NoReturn, NoReturn,
Optional,
Protocol, Protocol,
TypeVar, TypeVar,
) )
@@ -636,7 +637,7 @@ class HomeserverTestCase(TestCase):
self, self,
server_name: str | None = None, server_name: str | None = None,
config: JsonDict | None = None, config: JsonDict | None = None,
reactor: ISynapseReactor | None = None, reactor: Optional[ISynapseReactor] = None,
clock: Clock | None = None, clock: Clock | None = None,
**extra_homeserver_attributes: Any, **extra_homeserver_attributes: Any,
) -> HomeServer: ) -> HomeServer: