Skip to content

Drop support for Python 3.10 - #20359

Merged
MadLittleMods merged 31 commits into
developfrom
madlittlemods/20041-drop-python-3.10
Oct 26, 2026
Merged

MadLittleMods merged 31 commits into
developfrom
madlittlemods/20041-drop-python-3.10

Conversation

@MadLittleMods

@MadLittleMods MadLittleMods commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Drop support for Python 3.10

Fix #20041

Thinking out loud, it would be nice to merge this before the RC next Tuesday as this is probably the last release before the next LTS. And it would be nice for any potential future security fixes not to have to contend with old Python differences. (didn't make it)

Dev notes

Keywords:

  • 3.10
  • py310
  • cp310

Previous times we had to drop Python versions:

Python 3.9

Python 3.8:

Python 3.7:

Todo

Pull Request Checklist

  • Pull request is based on the develop branch
  • Pull request includes a changelog file. 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.
  • Code style is correct (run the linters)

Comment thread tox.ini
@@ -1,5 +1,5 @@
[tox]
envlist = py310, py311, py312, py313
envlist = py311, py312, py313, py314

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added py314 as we do support Python 3.14 (supported added in #19055)

Comment thread pyproject.toml
Comment on lines -311 to -312
# Used for checking the Poetry lockfile
"tomli>=1.2.3",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need tomli as Python 3.11 now has tomllib built-in

logger = self._create_explicitly_configured_logger()

with self.assertLogs(logger=logger, level=logging.NOTSET) as cm:
with self.assertNoLogs(logger=logger, level=logging.NOTSET):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change matches the FIXME

Comment thread synapse/types/__init__.py
Comment on lines -211 to -229
def __copy__(self) -> "AbsentType":
"""
Copy implementation used by `copy.copy()`.
Always use the same instance.

Without this and the deep version `__deepcopy__`,
`copy.copy(Absent)` on Python 3.10 (olddeps)
had a problem where it tried to construct a new Absent
as part of a deepcopy operation and resulted in:
ValueError: <object object at 0x7f64b3b6d930> is not a valid AbsentType
"""
return self

def __deepcopy__(self, memo: object) -> "AbsentType":
"""
Copy implementation used by `copy.deepcopy()`.
Always use the same instance.
"""
return self

@MadLittleMods MadLittleMods Oct 14, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No longer necessary with Python 3.11

And there is test coverage that would yell if it was necessary: SYNAPSE_TEST_LOG_LEVEL=INFO poetry run trial tests.test_types.AbsentTestCase.test_copy

synapse/tests/test_types.py

Lines 285 to 297 in 0635bf6

def test_copy(self) -> None:
"""
Tests that the `copy` module always uses the same instance of Absent.
"""
class MyModel(BaseModel):
absent: AbsentType = Absent
a = MyModel.model_validate({})
b = copy.deepcopy(a)
self.assertIs(copy.copy(Absent), Absent)
self.assertIs(a.absent, b.absent)

DISTS = (
"debian:bookworm", # (EOL 2028-06-30) (our EOL forced by Python 3.11 is 2027-10-31)
"debian:sid", # (rolling distro, no EOL)
"ubuntu:jammy", # 22.04 LTS (EOL 2027-04-01) (our EOL forced by Python 3.10 is 2026-10-31)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're able to drop this as ubuntu:jammy uses Python 3.10 which we no longer support (per the comment)

Comment thread docs/upgrade.md
Comment on lines +120 to +129
# Upgrading to v1.164.0

## Python 3.11+ is now required

The minimum supported Python version has been increased from v3.10 to v3.11.
You will need Python 3.11+ to run Synapse v1.164.0.

If you use current versions of the
[matrixorg/synapse](setup/installation.html#docker-images-and-ansible-playbooks)
Docker images, no action is required.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matches the previous language we used for this kind of thing:

synapse/docs/upgrade.md

Lines 301 to 308 in 0635bf6

## Python 3.10+ is now required
The minimum supported Python version has been increased from v3.9 to v3.10.
You will need Python 3.10+ to run Synapse v1.142.0.
If you use current versions of the
[matrixorg/synapse](setup/installation.html#docker-images-and-ansible-playbooks)
Docker images, no action is required.

Comment thread pyproject.toml
Comment on lines +125 to +126
# Support for Python 3.11 introduced in `psycopg2@2.9.5
"psycopg2>=2.9.5;platform_python_implementation != 'PyPy'",

@MadLittleMods MadLittleMods Oct 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MadLittleMods
MadLittleMods force-pushed the madlittlemods/20041-drop-python-3.10 branch from 1c8ae16 to 23aae81 Compare October 15, 2026 00:21
> Python 3.11 is now officially supported
>
> *-- https://github.com/python-attrs/attrs/blob/ee66e7274852438cc23d4240a1a9cd632fda8b52/CHANGELOG.md#2210---2022-07-28*

And we run into real errors without bumping when using Python 3.11:

```
/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/attr/_make.py:640: RuntimeWarning: Running interpreter doesn't sufficiently support code object introspection.  Some features like bare super() or accessing __class__ will not work with slotted classes.
  set_closure_cell(cell, cls)
Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 112, in _get_module_details
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/__init__.py", line 31, in <module>
    from synapse.util.rust import check_rust_lib_up_to_date
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/util/__init__.py", line 41, in <module>
    from synapse.types import JsonDict
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/types/__init__.py", line 1571, in <module>
    room_key=RoomStreamToken(stream=0),
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<attrs generated init synapse.types.RoomStreamToken>", line 13, in __init__
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/types/__init__.py", line 891, in __attrs_post_init__
    super().__attrs_post_init__()
    ^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type
```
Comment thread pyproject.toml
"attrs>=19.2.0,!=21.1.0",
# We use attrs 22.1.0 as it introduced official support for Python 3.11 and we see
# actual breakages without it.
"attrs>=22.1.0",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bumping because:

Python 3.11 is now officially supported

-- attrs changelog for 22.1.0 - 2022-07-28

And we run into real errors without bumping when using Python 3.11:

❌ https://github.com/element-hq/synapse/actions/runs/38659529140/job/116177840872?pr=20359

/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/attr/_make.py:640: RuntimeWarning: Running interpreter doesn't sufficiently support code object introspection.  Some features like bare super() or accessing __class__ will not work with slotted classes.
  set_closure_cell(cell, cls)
Traceback (most recent call last):
  File "<frozen runpy>", line 189, in _run_module_as_main
  File "<frozen runpy>", line 112, in _get_module_details
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/__init__.py", line 31, in <module>
    from synapse.util.rust import check_rust_lib_up_to_date
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/util/__init__.py", line 41, in <module>
    from synapse.types import JsonDict
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/types/__init__.py", line 1571, in <module>
    room_key=RoomStreamToken(stream=0),
             ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<attrs generated init synapse.types.RoomStreamToken>", line 13, in __init__
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/types/__init__.py", line 891, in __attrs_post_init__
    super().__attrs_post_init__()
    ^^^^^^^
TypeError: super(type, obj): obj must be an instance or subtype of type

See diff from to `v8.7.1` -> `v8.8.0` for the change
daviddrysdale/python-phonenumbers@v8.7.1...v8.8.0#diff-a163e9caf9ba1eb648d821e36dfabebf016bfde72e3e88e000302e7194f6635fR102

Error we previously ran into:
```
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/app/homeserver.py", line 42, in <module>
    from synapse.app import _base
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/app/_base.py", line 75, in <module>
    from synapse.events.auto_accept_invites import InviteAutoAccepter
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/events/auto_accept_invites.py", line 28, in <module>
    from synapse.module_api import EventBase, ModuleApi, run_as_background_process
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/module_api/__init__.py", line 58, in <module>
    from synapse.handlers.auth import (
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/handlers/auth.py", line 78, in <module>
    from synapse.util.msisdn import phone_number_to_msisdn
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/util/msisdn.py", line 22, in <module>
    import phonenumbers
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/phonenumbers/__init__.py", line 137, in <module>
    from .phonenumbermatcher import PhoneNumberMatch, PhoneNumberMatcher, Leniency
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/phonenumbers/phonenumbermatcher.py", line 119, in <module>
    _PATTERN = re.compile(u("(?:") + _LEAD_CLASS + _PUNCTUATION + u(")") + _LEAD_LIMIT +
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/__init__.py", line 227, in compile
    return _compile(pattern, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/__init__.py", line 294, in _compile
    p = _compiler.compile(pattern, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_compiler.py", line 745, in compile
    p = _parser.parse(p, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_parser.py", line 989, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_parser.py", line 464, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_parser.py", line 850, in _parse
    raise source.error('global flags not at the start '
re.error: global flags not at the start of the expression at position 57
```
See changelog, https://github.com/ICRAR/ijson/blob/82982f469fbff8def2c76a122ab7d23b7f313894/CHANGELOG.md#320

Previous error we would see with Python 3.11 running with the minimum dependency versions specified:
```
KeyError: 'char unsigned'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/app/homeserver.py", line 71, in <module>
    from synapse.server import HomeServer
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/server.py", line 72, in <module>
    from synapse.federation.federation_client import FederationClient
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/federation/federation_client.py", line 70, in <module>
    from synapse.federation.transport.client import SendJoinResponse
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/federation/transport/client.py", line 37, in <module>
    import ijson
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/__init__.py", line 36, in <module>
    backend = _default_backend()
              ^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/__init__.py", line 32, in _default_backend
    return get_backend(backend)
           ^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/__init__.py", line 24, in get_backend
    return importlib.import_module('ijson.backends.' + backend)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/backends/yajl2_cffi.py", line 13, in <module>
    ffi.cdef("""
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/api.py", line 112, in cdef
    self._cdef(csource, override=override, packed=packed, pack=pack)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/api.py", line 126, in _cdef
    self._parser.parse(csource, override=override, **options)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 389, in parse
    self._internal_parse(csource)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 428, in _internal_parse
    realtype, quals = self._get_type_and_quals(
                      ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 674, in _get_type_and_quals
    tp = self._get_struct_union_enum_type('struct', type, name)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 839, in _get_struct_union_enum_type
    type, fqual = self._get_type_and_quals(decl.type,
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 631, in _get_type_and_quals
    itemtype, itemquals = self._get_type_and_quals(typenode.type)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 689, in _get_type_and_quals
    return self._parse_function_type(typenode, name), 0
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 723, in _parse_function_type
    args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 723, in <listcomp>
    args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 631, in _get_type_and_quals
    itemtype, itemquals = self._get_type_and_quals(typenode.type)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 669, in _get_type_and_quals
    tp0, quals0 = resolve_common_type(self, ident)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/commontypes.py", line 39, in resolve_common_type
    raise FFIError(
cffi.FFIError: Unsupported type: 'char unsigned'.  Please look at http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations and file an issue if you think this type should really be supported.
```
Comment thread pyproject.toml
Comment on lines +62 to +64
# 8.8.0 is the first release that is compatible with Python 3.11.
# Previous versions run into `re.error: global flags not at the start of the expression`
"phonenumbers>=8.8.0",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to minimum version compatible with Python 3.11

See diff from to v8.7.1 -> v8.8.0 for the change that made us compatible
daviddrysdale/python-phonenumbers@v8.7.1...v8.8.0#diff-a163e9caf9ba1eb648d821e36dfabebf016bfde72e3e88e000302e7194f6635fR102

Error we previously ran into:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/app/homeserver.py", line 42, in <module>
    from synapse.app import _base
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/app/_base.py", line 75, in <module>
    from synapse.events.auto_accept_invites import InviteAutoAccepter
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/events/auto_accept_invites.py", line 28, in <module>
    from synapse.module_api import EventBase, ModuleApi, run_as_background_process
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/module_api/__init__.py", line 58, in <module>
    from synapse.handlers.auth import (
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/handlers/auth.py", line 78, in <module>
    from synapse.util.msisdn import phone_number_to_msisdn
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/util/msisdn.py", line 22, in <module>
    import phonenumbers
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/phonenumbers/__init__.py", line 137, in <module>
    from .phonenumbermatcher import PhoneNumberMatch, PhoneNumberMatcher, Leniency
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/phonenumbers/phonenumbermatcher.py", line 119, in <module>
    _PATTERN = re.compile(u("(?:") + _LEAD_CLASS + _PUNCTUATION + u(")") + _LEAD_LIMIT +
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/__init__.py", line 227, in compile
    return _compile(pattern, flags)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/__init__.py", line 294, in _compile
    p = _compiler.compile(pattern, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_compiler.py", line 745, in compile
    p = _parser.parse(p, flags)
        ^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_parser.py", line 989, in parse
    p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_parser.py", line 464, in _parse_sub
    itemsappend(_parse(source, state, verbose, nested + 1,
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/re/_parser.py", line 850, in _parse
    raise source.error('global flags not at the start '
re.error: global flags not at the start of the expression at position 57

Comment thread pyproject.toml
Comment on lines +83 to +84
# ijson 3.2.0 marks Python 3.11 as officially supported
"ijson>=3.2.0",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to version with official Python 3.11 support

Mark Python 3.10 and 3.11 as explicitly supported.

-- ijson@3.2.0 changelog

Previous error we would see with Python 3.11 running with the minimum dependency versions specified:

KeyError: 'char unsigned'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/app/homeserver.py", line 71, in <module>
    from synapse.server import HomeServer
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/server.py", line 72, in <module>
    from synapse.federation.federation_client import FederationClient
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/federation/federation_client.py", line 70, in <module>
    from synapse.federation.transport.client import SendJoinResponse
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/federation/transport/client.py", line 37, in <module>
    import ijson
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/__init__.py", line 36, in <module>
    backend = _default_backend()
              ^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/__init__.py", line 32, in _default_backend
    return get_backend(backend)
           ^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/__init__.py", line 24, in get_backend
    return importlib.import_module('ijson.backends.' + backend)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/ijson/backends/yajl2_cffi.py", line 13, in <module>
    ffi.cdef("""
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/api.py", line 112, in cdef
    self._cdef(csource, override=override, packed=packed, pack=pack)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/api.py", line 126, in _cdef
    self._parser.parse(csource, override=override, **options)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 389, in parse
    self._internal_parse(csource)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 428, in _internal_parse
    realtype, quals = self._get_type_and_quals(
                      ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 674, in _get_type_and_quals
    tp = self._get_struct_union_enum_type('struct', type, name)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 839, in _get_struct_union_enum_type
    type, fqual = self._get_type_and_quals(decl.type,
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 631, in _get_type_and_quals
    itemtype, itemquals = self._get_type_and_quals(typenode.type)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 689, in _get_type_and_quals
    return self._parse_function_type(typenode, name), 0
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 723, in _parse_function_type
    args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 723, in <listcomp>
    args = [self._as_func_arg(*self._get_type_and_quals(argdeclnode.type))
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 631, in _get_type_and_quals
    itemtype, itemquals = self._get_type_and_quals(typenode.type)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/cparser.py", line 669, in _get_type_and_quals
    tp0, quals0 = resolve_common_type(self, ident)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/cffi/commontypes.py", line 39, in resolve_common_type
    raise FFIError(
cffi.FFIError: Unsupported type: 'char unsigned'.  Please look at http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations and file an issue if you think this type should really be supported.

Previous error:

```
tests.logging.test_remote_handler.RemoteHandlerTestCase.test_log_backpressure_cut_middle
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/home/runner/work/synapse/synapse/tests/logging/test_remote_handler.py", line 58, in test_log_output
    handler = RemoteHandler("127.0.0.1", 9000, _reactor=self.reactor)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/logging/_remote.py", line 148, in __init__
    self._service.startService()
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/twisted/application/internet.py", line 1179, in startService
    self._machine.start()
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_methodical.py", line 232, in __get__
    @preserveName(self.method)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_introspection.py", line 43, in decorator
    return copyfunction(decorated,
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_introspection.py", line 35, in copyfunction
    return function(copycode(template.__code__, codechanges), *values)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_introspection.py", line 23, in copycode
    return code(*values)
builtins.TypeError: code() argument 13 must be str, not int
```

`automat` doesn't have a changelog but tracked Python 3.11 compatibility with
glyph/automat#135. From the backlinks there, you
can also see how we ran into this before when we first introduced Python 3.11
support to Synapse.
Comment thread pyproject.toml
Comment on lines +18 to +21
# `automat` < 22.10.0 builds code objects positionally, which breaks on Python 3.11.
# `automat` doesn't have a changelog but Python 3.11 support was tracked by
# https://github.com/glyph/automat/issues/135
"automat>=22.10.0", # via twisted

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

automat doesn't have a changelog but tracked Python 3.11 compatibility with glyph/automat#135. From the backlinks there, you can also see how we ran into this before when we first introduced Python 3.11 support to Synapse.

Previous error:

tests.logging.test_remote_handler.RemoteHandlerTestCase.test_log_backpressure_cut_middle
===============================================================================
[ERROR]
Traceback (most recent call last):
  File "/home/runner/work/synapse/synapse/tests/logging/test_remote_handler.py", line 58, in test_log_output
    handler = RemoteHandler("127.0.0.1", 9000, _reactor=self.reactor)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/synapse/logging/_remote.py", line 148, in __init__
    self._service.startService()
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/twisted/application/internet.py", line 1179, in startService
    self._machine.start()
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_methodical.py", line 232, in __get__
    @preserveName(self.method)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_introspection.py", line 43, in decorator
    return copyfunction(decorated,
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_introspection.py", line 35, in copyfunction
    return function(copycode(template.__code__, codechanges), *values)
  File "/opt/hostedtoolcache/Python/3.11.17/x64/lib/python3.11/site-packages/automat/_introspection.py", line 23, in copycode
    return code(*values)
builtins.TypeError: code() argument 13 must be str, not int

Comment thread pyproject.toml
Comment on lines +44 to +45
# Twisted 23.8.0 adds official support for Python 3.11
"Twisted[tls]>=23.8.0",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bump minimum twisted version for official Python 3.11 support

Twisted now officially supports Python 3.11.

-- Twisted 23.8.0. (2023-08-28) changelog

Comment thread changelog.d/20359.removal
@@ -0,0 +1 @@
Remove support for Python 3.10.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sytest CI failures expected to fail until matrix-org/sytest#1431 merges

@MadLittleMods
MadLittleMods marked this pull request as ready for review October 24, 2026 00:07
@MadLittleMods
MadLittleMods requested a review from a team as a code owner October 24, 2026 00:07
@MadLittleMods
MadLittleMods requested review from devonh and removed request for a team October 24, 2026 00:07
Comment thread pyproject.toml
@@ -1 +1 @@
[project]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the changes here look fine to me.
Any idea what's up with the CI failures?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complement is just normal flakes

Sytest was because the Docker image builds didn't finish yet after merging matrix-org/sytest#1431

@MadLittleMods
MadLittleMods merged commit 4cece59 into develop Oct 26, 2026
81 of 84 checks passed
@MadLittleMods
MadLittleMods deleted the madlittlemods/20041-drop-python-3.10 branch October 26, 2026 21:26
@MadLittleMods

Copy link
Copy Markdown
Contributor Author

Thanks for the review @devonh 🦕

@MadLittleMods MadLittleMods mentioned this pull request Oct 26, 2026
3 tasks done
MadLittleMods added a commit that referenced this pull request Oct 27, 2026
As far as I can tell, no one uses it. @reivilibre also asked this in
[`#synapse-dev:matrix.org`](https://matrix.to/#/!i5D5LLct_DYG-4hQprLzrxdbZ580U9UB6AEgFnk6rZQ/$NrW3QmLEGgcjNqW-SaPZrS-EVwq1-9fO_Ds_1QIZX0E?via=element.io&via=matrix.org&via=starstruck.systems)
and
[`#element-backend-internal:matrix.org`](https://matrix.to/#/!SGNQGPGUwtcPBUotTL:matrix.org/$_rh3S79z4q1Q93SJ3ncQ_ZUzudks4Egan5dwutH2AKg?via=jki.re&via=element.io&via=matrix.org)
on 2026-02-20 with a couple of 🔥 emoji reactions in the public
channel.

As long as I've worked on Synapse, as far as I know, I've never used
this for local dev.

We no longer use this in CI.

Noticed the file again while working on
#20359
sakaru pushed a commit to sakaru/synapse that referenced this pull request Oct 28, 2026
Fix element-hq#20041

Keywords:

 - `3.10`
 - `py310`
 - `cp310`
sakaru pushed a commit to sakaru/synapse that referenced this pull request Oct 28, 2026
As far as I can tell, no one uses it. @reivilibre also asked this in
[`#synapse-dev:matrix.org`](https://matrix.to/#/!i5D5LLct_DYG-4hQprLzrxdbZ580U9UB6AEgFnk6rZQ/$NrW3QmLEGgcjNqW-SaPZrS-EVwq1-9fO_Ds_1QIZX0E?via=element.io&via=matrix.org&via=starstruck.systems)
and
[`#element-backend-internal:matrix.org`](https://matrix.to/#/!SGNQGPGUwtcPBUotTL:matrix.org/$_rh3S79z4q1Q93SJ3ncQ_ZUzudks4Egan5dwutH2AKg?via=jki.re&via=element.io&via=matrix.org)
on 2026-02-20 with a couple of 🔥 emoji reactions in the public
channel.

As long as I've worked on Synapse, as far as I know, I've never used
this for local dev.

We no longer use this in CI.

Noticed the file again while working on
element-hq#20359
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Drop support for Python 3.10 (action on 2026-10-01)

2 participants