Skip to content

Commit 6791e6e

Browse files
Unbreak unit tests with Twisted 25.5.0 by add parsePOSTFormSubmission arg to FakeSite (#18577)
Co-authored-by: anoa's Codex Agent <codex@amorgan.xyz>
1 parent 3cabaa8 commit 6791e6e

10 files changed

Lines changed: 110 additions & 78 deletions

File tree

changelog.d/18577.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add support for Twisted `25.5.0`+ releases.

poetry.lock

Lines changed: 45 additions & 46 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

synapse/http/proxyagent.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import logging
2222
import random
2323
import re
24-
from typing import Any, Collection, Dict, List, Optional, Sequence, Tuple, Union
24+
from typing import Any, Collection, Dict, List, Optional, Sequence, Tuple, Union, cast
2525
from urllib.parse import urlparse
2626
from urllib.request import ( # type: ignore[attr-defined]
2727
getproxies_environment,
@@ -40,6 +40,7 @@
4040
IProtocol,
4141
IProtocolFactory,
4242
IReactorCore,
43+
IReactorTime,
4344
IStreamClientEndpoint,
4445
)
4546
from twisted.python.failure import Failure
@@ -129,7 +130,9 @@ def __init__(
129130
):
130131
contextFactory = contextFactory or BrowserLikePolicyForHTTPS()
131132

132-
_AgentBase.__init__(self, reactor, pool)
133+
# `_AgentBase` expects an `IReactorTime` provider. `IReactorCore`
134+
# extends `IReactorTime`, so this cast is safe.
135+
_AgentBase.__init__(self, cast(IReactorTime, reactor), pool)
133136

134137
if proxy_reactor is None:
135138
self.proxy_reactor = reactor
@@ -168,7 +171,7 @@ def __init__(
168171
self.no_proxy = no_proxy
169172

170173
self._policy_for_https = contextFactory
171-
self._reactor = reactor
174+
self._reactor = cast(IReactorTime, reactor)
172175

173176
self._federation_proxy_endpoint: Optional[IStreamClientEndpoint] = None
174177
self._federation_proxy_credentials: Optional[ProxyCredentials] = None
@@ -257,7 +260,11 @@ def request(
257260
raise ValueError(f"Invalid URI {uri!r}")
258261

259262
parsed_uri = URI.fromBytes(uri)
260-
pool_key = f"{parsed_uri.scheme!r}{parsed_uri.host!r}{parsed_uri.port}"
263+
pool_key: tuple[bytes, bytes, int] = (
264+
parsed_uri.scheme,
265+
parsed_uri.host,
266+
parsed_uri.port,
267+
)
261268
request_path = parsed_uri.originForm
262269

263270
should_skip_proxy = False
@@ -283,7 +290,7 @@ def request(
283290
)
284291
# Cache *all* connections under the same key, since we are only
285292
# connecting to a single destination, the proxy:
286-
pool_key = "http-proxy"
293+
pool_key = (b"http-proxy", b"", 0)
287294
endpoint = self.http_proxy_endpoint
288295
request_path = uri
289296
elif (

synapse/http/replicationagent.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,16 @@ def request(
180180
worker_name = parsedURI.netloc.decode("utf-8")
181181
key_scheme = self._endpointFactory.instance_map[worker_name].scheme()
182182
key_netloc = self._endpointFactory.instance_map[worker_name].netloc()
183-
# This sets the Pool key to be:
184-
# (http(s), <host:port>) or (unix, <socket_path>)
185-
key = (key_scheme, key_netloc)
183+
# Build a connection pool key.
184+
#
185+
# `_AgentBase` expects this to be a three-tuple of `(scheme, host,
186+
# port)` of type `bytes`. We don't have a real port when connecting via
187+
# a Unix socket, so use `0`.
188+
key = (
189+
key_scheme.encode("ascii"),
190+
key_netloc.encode("utf-8"),
191+
0,
192+
)
186193

187194
# _requestWithEndpoint comes from _AgentBase class
188195
return self._requestWithEndpoint(

synapse/http/server.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ def _get_handler_for_request(
497497
key word arguments to pass to the callback
498498
"""
499499
# At this point the path must be bytes.
500-
request_path_bytes: bytes = request.path # type: ignore
500+
request_path_bytes: bytes = request.path
501501
request_path = request_path_bytes.decode("ascii")
502502
# Treat HEAD requests as GET requests.
503503
request_method = request.method

tests/logging/test_terse_json.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,14 @@ def test_with_request_context(self) -> None:
160160
logger = self.get_logger(handler)
161161

162162
# A full request isn't needed here.
163-
site = Mock(spec=["site_tag", "server_version_string", "getResourceFor"])
163+
site = Mock(
164+
spec=[
165+
"site_tag",
166+
"server_version_string",
167+
"getResourceFor",
168+
"_parsePOSTFormSubmission",
169+
]
170+
)
164171
site.site_tag = "test-site"
165172
site.server_version_string = "Server v1"
166173
site.reactor = Mock()

tests/replication/_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ def assert_request_is_get_repl_stream_updates(
220220
fetching updates for given stream.
221221
"""
222222

223-
path: bytes = request.path # type: ignore
223+
path: bytes = request.path
224224
self.assertRegex(
225225
path,
226226
rb"^/_synapse/replication/get_repl_stream_updates/%s/[^/]+$"

tests/server.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,8 @@ def __init__(
343343
self,
344344
resource: IResource,
345345
reactor: IReactorTime,
346+
*,
347+
parsePOSTFormSubmission: bool = True,
346348
):
347349
"""
348350
@@ -351,6 +353,7 @@ def __init__(
351353
"""
352354
self._resource = resource
353355
self.reactor = reactor
356+
self._parsePOSTFormSubmission = parsePOSTFormSubmission
354357

355358
def getResourceFor(self, request: Request) -> IResource:
356359
return self._resource
@@ -514,9 +517,13 @@ def getHostByName(
514517

515518
tls._get_default_clock = lambda: self
516519

517-
self.nameResolver = SimpleResolverComplexifier(FakeResolver())
518520
super().__init__()
519521

522+
# Override the default name resolver with our fake resolver. This must
523+
# happen after `super().__init__()` so that the base class doesn't
524+
# overwrite it again.
525+
self.nameResolver = SimpleResolverComplexifier(FakeResolver())
526+
520527
def installNameResolver(self, resolver: IHostnameResolver) -> IHostnameResolver:
521528
raise NotImplementedError()
522529

tests/storage/databases/main/test_events_worker.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -449,24 +449,29 @@ def test_failure(self) -> None:
449449

450450
def test_recovery(self) -> None:
451451
"""Test that event fetchers recover after a database outage."""
452-
with self._outage():
453-
# Kick off a bunch of event fetches but do not pump the reactor
454-
event_deferreds = []
455-
for event_id in self.event_ids:
456-
event_deferreds.append(ensureDeferred(self.store.get_event(event_id)))
457-
458-
# We should have maxed out on event fetcher threads
459-
self.assertEqual(self.store._event_fetch_ongoing, EVENT_QUEUE_THREADS)
460-
461-
# All the event fetchers will fail
462-
self.pump()
463-
self.assertEqual(self.store._event_fetch_ongoing, 0)
464-
465-
for event_deferred in event_deferreds:
466-
failure = self.get_failure(event_deferred, Exception)
467-
self.assertEqual(
468-
str(failure.value), "Could not connect to the database."
469-
)
452+
with self.assertLogs(
453+
"synapse.metrics.background_process_metrics", level="ERROR"
454+
):
455+
with self._outage():
456+
# Kick off a bunch of event fetches but do not pump the reactor
457+
event_deferreds = []
458+
for event_id in self.event_ids:
459+
event_deferreds.append(
460+
ensureDeferred(self.store.get_event(event_id))
461+
)
462+
463+
# We should have maxed out on event fetcher threads
464+
self.assertEqual(self.store._event_fetch_ongoing, EVENT_QUEUE_THREADS)
465+
466+
# All the event fetchers will fail
467+
self.pump()
468+
self.assertEqual(self.store._event_fetch_ongoing, 0)
469+
470+
for event_deferred in event_deferreds:
471+
failure = self.get_failure(event_deferred, Exception)
472+
self.assertEqual(
473+
str(failure.value), "Could not connect to the database."
474+
)
470475

471476
# This next event fetch should succeed
472477
self.get_success(self.store.get_event(self.event_ids[0]))

tests/test_server.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,8 +226,7 @@ class DummyResource(Resource):
226226
isLeaf = True
227227

228228
def render(self, request: SynapseRequest) -> bytes:
229-
# Type-ignore: mypy thinks request.path is Optional[Any], not bytes.
230-
return request.path # type: ignore[return-value]
229+
return request.path
231230

232231
# Setup a resource with some children.
233232
self.resource = OptionsResource()

0 commit comments

Comments
 (0)