From aef36df0111435985675a96756e0dfed07c050df Mon Sep 17 00:00:00 2001 From: Andrew Morgan Date: Thu, 3 Jul 2025 18:29:43 +0100 Subject: [PATCH 1/3] Add AGENTS.md --- AGENTS.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000000..f9aa24368ac --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,19 @@ +# Contributor Guide + +Synapse is a Python application that has Rust modules via pyo3 for performance. + +## Dev Environment Tips +- Source code is primarily in `synapse/`, tests are in `tests/`. +- Run `poetry install --dev` to install development python dependencies. This will also build and install the Synapse rust code. +- Use `./scripts-dev/lint.sh` to lint the codebase (this attempts to fix issues as well). This should be run and produce no errors before every commit. + +## Dev Tips +- If any change creates a breaking change or requires downstream users (sysadmins) to update their environment, call it out in `docs/upgrade.md` as a new entry with the title "# Upgrading to vx.yy.z" with the details of what they should do or be aware of. +- All code comments and documentation should be written in Markdown, NOT RST. + +## Testing Instructions +- Find the CI plan in the .github/workflows folder. +- Use `poetry run trial tests` to run all unit tests, or `poetry run trial tests.metrics.test_phone_home_stats.PhoneHomeStatsTestCase` (for example) to run a single test case. The commit should pass all tests before you merge. +- Some typing warnings are expected currently. Fix any test or type *errors* until the whole suite is green. +- Add or update relevant tests for the code you change, even if nobody asked. + From 3e4dd6f52403d72e70c3af981bdb31cc67667076 Mon Sep 17 00:00:00 2001 From: anoa's Codex Agent Date: Thu, 11 Sep 2025 13:59:14 +0100 Subject: [PATCH 2/3] fix: handle oembed resource loading --- synapse/config/_base.py | 6 +++--- synapse/config/oembed.py | 7 +++++-- synapse/metrics/__init__.py | 2 +- tests/push/test_email.py | 4 ++-- tests/rest/client/test_account.py | 7 +++---- tests/rest/client/test_register.py | 5 ++--- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/synapse/config/_base.py b/synapse/config/_base.py index 0a01fb55826..0f1158e9b1a 100644 --- a/synapse/config/_base.py +++ b/synapse/config/_base.py @@ -22,6 +22,7 @@ import argparse import errno +import importlib.resources as importlib_resources import logging import os import re @@ -46,7 +47,6 @@ import attr import jinja2 -import pkg_resources import yaml from synapse.types import StrSequence @@ -174,8 +174,8 @@ def __init__(self, root_config: "RootConfig"): self.root = root_config # Get the path to the default Synapse template directory - self.default_template_dir = pkg_resources.resource_filename( - "synapse", "res/templates" + self.default_template_dir = str( + importlib_resources.files("synapse").joinpath("res", "templates") ) @staticmethod diff --git a/synapse/config/oembed.py b/synapse/config/oembed.py index b177a75cf68..d8a20c6a7e5 100644 --- a/synapse/config/oembed.py +++ b/synapse/config/oembed.py @@ -18,13 +18,13 @@ # [This file includes modifications made by New Vector Limited] # # +import importlib.resources as importlib_resources import json import re from typing import Any, Dict, Iterable, List, Optional, Pattern from urllib import parse as urlparse import attr -import pkg_resources from synapse.types import JsonDict, StrSequence @@ -64,7 +64,10 @@ def _parse_and_validate_providers( """ # Whether to use the packaged providers.json file. if not oembed_config.get("disable_default_providers") or False: - with pkg_resources.resource_stream("synapse", "res/providers.json") as s: + path = importlib_resources.files("synapse").joinpath( + "res", "providers.json" + ) + with path.open("rt") as s: providers = json.load(s) yield from self._parse_and_validate_provider( diff --git a/synapse/metrics/__init__.py b/synapse/metrics/__init__.py index 5b291aa893b..2ffb14070b7 100644 --- a/synapse/metrics/__init__.py +++ b/synapse/metrics/__init__.py @@ -43,7 +43,7 @@ ) import attr -from pkg_resources import parse_version +from packaging.version import parse as parse_version from prometheus_client import ( CollectorRegistry, Counter, diff --git a/tests/push/test_email.py b/tests/push/test_email.py index 4d885c78ebf..b9e4ba6f2b9 100644 --- a/tests/push/test_email.py +++ b/tests/push/test_email.py @@ -18,12 +18,12 @@ # # import email.message +import importlib.resources as importlib_resources import os from http import HTTPStatus from typing import Any, Dict, List, Sequence, Tuple import attr -import pkg_resources from parameterized import parameterized from twisted.internet.defer import Deferred @@ -62,7 +62,7 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config["email"] = { "enable_notifs": True, "template_dir": os.path.abspath( - pkg_resources.resource_filename("synapse", "res/templates") + importlib_resources.files("synapse").joinpath("res", "templates") ), "expiry_template_html": "notice_expiry.html", "expiry_template_text": "notice_expiry.txt", diff --git a/tests/rest/client/test_account.py b/tests/rest/client/test_account.py index 02d02ae78e0..24aab380113 100644 --- a/tests/rest/client/test_account.py +++ b/tests/rest/client/test_account.py @@ -18,6 +18,7 @@ # [This file includes modifications made by New Vector Limited] # # +import importlib.resources as importlib_resources import os import re from email.parser import Parser @@ -25,8 +26,6 @@ from typing import Any, Dict, List, Optional, Union from unittest.mock import Mock -import pkg_resources - from twisted.internet.interfaces import IReactorTCP from twisted.internet.testing import MemoryReactor @@ -62,7 +61,7 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config["email"] = { "enable_notifs": False, "template_dir": os.path.abspath( - pkg_resources.resource_filename("synapse", "res/templates") + importlib_resources.files("synapse").joinpath("res", "templates") ), "smtp_host": "127.0.0.1", "smtp_port": 20, @@ -801,7 +800,7 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config["email"] = { "enable_notifs": False, "template_dir": os.path.abspath( - pkg_resources.resource_filename("synapse", "res/templates") + importlib_resources.files("synapse").joinpath("res", "templates") ), "smtp_host": "127.0.0.1", "smtp_port": 20, diff --git a/tests/rest/client/test_register.py b/tests/rest/client/test_register.py index f0745cf2982..64cdfcab3b7 100644 --- a/tests/rest/client/test_register.py +++ b/tests/rest/client/test_register.py @@ -20,12 +20,11 @@ # # import datetime +import importlib.resources as importlib_resources import os from typing import Any, Dict, List, Tuple from unittest.mock import AsyncMock -import pkg_resources - from twisted.internet.testing import MemoryReactor import synapse.rest.admin @@ -984,7 +983,7 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config["email"] = { "enable_notifs": True, "template_dir": os.path.abspath( - pkg_resources.resource_filename("synapse", "res/templates") + importlib_resources.files("synapse").joinpath("res", "templates") ), "expiry_template_html": "notice_expiry.html", "expiry_template_text": "notice_expiry.txt", From 141a030869d7c165c3456e3dfe4bec546a805fb3 Mon Sep 17 00:00:00 2001 From: anoa's Codex Agent Date: Thu, 11 Sep 2025 15:05:26 +0100 Subject: [PATCH 3/3] fix: handle Traversable paths --- synapse/config/oembed.py | 8 +++++--- tests/push/test_email.py | 7 ++++--- tests/rest/client/test_account.py | 14 ++++++++------ tests/rest/client/test_register.py | 7 ++++--- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/synapse/config/oembed.py b/synapse/config/oembed.py index d8a20c6a7e5..1b6c5210873 100644 --- a/synapse/config/oembed.py +++ b/synapse/config/oembed.py @@ -64,10 +64,12 @@ def _parse_and_validate_providers( """ # Whether to use the packaged providers.json file. if not oembed_config.get("disable_default_providers") or False: - path = importlib_resources.files("synapse").joinpath( - "res", "providers.json" + path = ( + importlib_resources.files("synapse") + .joinpath("res") + .joinpath("providers.json") ) - with path.open("rt") as s: + with path.open("r", encoding="utf-8") as s: providers = json.load(s) yield from self._parse_and_validate_provider( diff --git a/tests/push/test_email.py b/tests/push/test_email.py index b9e4ba6f2b9..4d9e42ac2cc 100644 --- a/tests/push/test_email.py +++ b/tests/push/test_email.py @@ -59,11 +59,12 @@ class EmailPusherTests(HomeserverTestCase): def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config = self.default_config() + templates = ( + importlib_resources.files("synapse").joinpath("res").joinpath("templates") + ) config["email"] = { "enable_notifs": True, - "template_dir": os.path.abspath( - importlib_resources.files("synapse").joinpath("res", "templates") - ), + "template_dir": os.path.abspath(str(templates)), "expiry_template_html": "notice_expiry.html", "expiry_template_text": "notice_expiry.txt", "notif_template_html": "notif_mail.html", diff --git a/tests/rest/client/test_account.py b/tests/rest/client/test_account.py index 24aab380113..9a3202bd934 100644 --- a/tests/rest/client/test_account.py +++ b/tests/rest/client/test_account.py @@ -58,11 +58,12 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config = self.default_config() # Email config. + templates = ( + importlib_resources.files("synapse").joinpath("res").joinpath("templates") + ) config["email"] = { "enable_notifs": False, - "template_dir": os.path.abspath( - importlib_resources.files("synapse").joinpath("res", "templates") - ), + "template_dir": os.path.abspath(str(templates)), "smtp_host": "127.0.0.1", "smtp_port": 20, "require_transport_security": False, @@ -797,11 +798,12 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: config = self.default_config() # Email config. + templates = ( + importlib_resources.files("synapse").joinpath("res").joinpath("templates") + ) config["email"] = { "enable_notifs": False, - "template_dir": os.path.abspath( - importlib_resources.files("synapse").joinpath("res", "templates") - ), + "template_dir": os.path.abspath(str(templates)), "smtp_host": "127.0.0.1", "smtp_port": 20, "require_transport_security": False, diff --git a/tests/rest/client/test_register.py b/tests/rest/client/test_register.py index 64cdfcab3b7..70e005caf45 100644 --- a/tests/rest/client/test_register.py +++ b/tests/rest/client/test_register.py @@ -980,11 +980,12 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer: # Email config. + templates = ( + importlib_resources.files("synapse").joinpath("res").joinpath("templates") + ) config["email"] = { "enable_notifs": True, - "template_dir": os.path.abspath( - importlib_resources.files("synapse").joinpath("res", "templates") - ), + "template_dir": os.path.abspath(str(templates)), "expiry_template_html": "notice_expiry.html", "expiry_template_text": "notice_expiry.txt", "notif_template_html": "notif_mail.html",