Skip to content

Commit 049d802

Browse files
authored
[DEV-12949] Python 3.13 Compatibility (#349)
* Fix unconditional import missed by reduce base install size PR * Replace `cgi.parse_header()` with `email.message.EmailMessage` This makes `indico-client` compatible with Python 3.13, which removed the deprecated `cgi` module. https://docs.python.org/3/whatsnew/3.13.html#pep-594-remove-dead-batteries-from-the-standard-library * Update readme and tox with supported Python versions
1 parent 54fccb6 commit 049d802

File tree

4 files changed

+11
-8
lines changed

4 files changed

+11
-8
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
---
1010

11-
Required: Python 3.6, 3.7, or 3.8
11+
Required: Python 3.9+
1212

1313
From PyPI:
1414

indico/http/serialization.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
"""
22
Handles deserialization / decoding of responses
33
"""
4-
import cgi
54
import gzip
65
import io
76
import json
87
import logging
98
import traceback
109
from collections import defaultdict
11-
12-
import msgpack
10+
from email.message import EmailMessage
1311

1412
from indico.errors import IndicoDecodingError
1513

@@ -23,7 +21,7 @@ def decompress(response):
2321

2422

2523
def deserialize(response, force_json=False, force_decompress=False):
26-
content_type, params = cgi.parse_header(response.headers.get("Content-Type"))
24+
content_type, params = parse_header(response.headers.get("Content-Type"))
2725

2826
if force_decompress or content_type in ["application/x-gzip", "application/gzip"]:
2927
content = decompress(response)
@@ -45,7 +43,7 @@ def deserialize(response, force_json=False, force_decompress=False):
4543
)
4644

4745
async def aio_deserialize(response, force_json=False, force_decompress=False):
48-
content_type, params = cgi.parse_header(response.headers.get("Content-Type"))
46+
content_type, params = parse_header(response.headers.get("Content-Type"))
4947
content = await response.read()
5048

5149
if force_decompress or content_type in ["application/x-gzip", "application/gzip"]:
@@ -65,6 +63,11 @@ async def aio_deserialize(response, force_json=False, force_decompress=False):
6563
content_type, charset, content.decode("ascii", "ignore")
6664
)
6765

66+
def parse_header(header: str) -> tuple[str, dict[str, str]]:
67+
email = EmailMessage()
68+
email["Content-Type"] = header
69+
return email.get_content_type(), email["Content-Type"].params
70+
6871
def raw_bytes(content, *args, **kwargs):
6972
return content
7073

tox.Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -yqq apt-tr
66
#deadsnakes holds old versions of python for ubuntu
77
RUN DEBIAN_FRONTEND=noninteractive apt-get install -yqq software-properties-common && add-apt-repository ppa:deadsnakes/ppa
88

9-
RUN DEBIAN_FRONTEND=noninteractive apt-get -yqq install python3.7 python3.8 python3.9 python3.10 python3.11 python3.12 python3-pip
9+
RUN DEBIAN_FRONTEND=noninteractive apt-get -yqq install python3.9 python3.10 python3.11 python3.12 python3.13 python3-pip
1010

1111
RUN pip3 install tox==4.11.3
1212

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# content of: tox.ini , put in same dir as setup.py
22
[tox]
3-
envlist = py38,py39,py310,py311,py312
3+
envlist = py39,py310,py311,py312,py313
44

55
[testenv]
66
extras = all

0 commit comments

Comments
 (0)