Skip to content

Commit 2ba564c

Browse files
committed
Upgrade dependencies and test matrix for Python 3.13.
Add new migration for updated le-utils. Add cgi forward port compatibility patch.
1 parent 068f25b commit 2ba564c

File tree

8 files changed

+111
-6
lines changed

8 files changed

+111
-6
lines changed

.github/workflows/morango_integration.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
INTEGRATION_TEST: 'true'
3131
strategy:
3232
matrix:
33-
python-version: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11', '3.12']
33+
python-version: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11', '3.12', '3.13']
3434

3535
steps:
3636
- name: Checkout repository

.github/workflows/tox.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
strategy:
3131
max-parallel: 5
3232
matrix:
33-
python-version: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11', '3.12']
33+
python-version: [3.6, 3.7, 3.8, 3.9, '3.10', '3.11', '3.12', '3.13']
3434

3535
steps:
3636
- uses: actions/checkout@v4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Generated by Django 3.2.25 on 2024-10-24 22:56
2+
from django.db import migrations
3+
from django.db import models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("content", "0037_add_bloompub_preset"),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name="localfile",
15+
name="extension",
16+
field=models.CharField(
17+
blank=True,
18+
choices=[
19+
("mp4", "MP4 Video"),
20+
("webm", "WEBM Video"),
21+
("vtt", "VTT Subtitle"),
22+
("mp3", "MP3 Audio"),
23+
("pdf", "PDF Document"),
24+
("jpg", "JPG Image"),
25+
("jpeg", "JPEG Image"),
26+
("png", "PNG Image"),
27+
("gif", "GIF Image"),
28+
("json", "JSON"),
29+
("svg", "SVG Image"),
30+
("perseus", "Perseus Exercise"),
31+
("graphie", "Graphie Exercise"),
32+
("zip", "HTML5 Zip"),
33+
("h5p", "H5P"),
34+
("zim", "ZIM"),
35+
("epub", "ePub Document"),
36+
("bloompub", "Bloom Document"),
37+
("bloomd", "Bloom Document"),
38+
],
39+
max_length=40,
40+
),
41+
),
42+
]

kolibri/utils/compat_cgi.py

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
A minimal port of the removed cgi module for use in Python 3.13.
3+
Only imports the specific parts of the module that are used by Django.
4+
Informed by the PR that removed its use in Django:
5+
https://github.com/django/django/pull/15679
6+
"""
7+
from django.utils.regex_helper import _lazy_re_compile
8+
9+
10+
def _parseparam(s):
11+
while s[:1] == ";":
12+
s = s[1:]
13+
end = s.find(";")
14+
while end > 0 and (s.count('"', 0, end) - s.count('\\"', 0, end)) % 2:
15+
end = s.find(";", end + 1)
16+
if end < 0:
17+
end = len(s)
18+
f = s[:end]
19+
yield f.strip()
20+
s = s[end:]
21+
22+
23+
def parse_header(line):
24+
"""
25+
Parse a Content-type like header.
26+
Return the main content-type and a dictionary of options.
27+
"""
28+
parts = _parseparam(";" + line)
29+
key = parts.__next__()
30+
pdict = {}
31+
for p in parts:
32+
i = p.find("=")
33+
if i >= 0:
34+
name = p[:i].strip().lower()
35+
value = p[i + 1 :].strip()
36+
if len(value) >= 2 and value[0] == value[-1] == '"':
37+
value = value[1:-1]
38+
value = value.replace("\\\\", "\\").replace('\\"', '"')
39+
pdict[name] = value
40+
return key, pdict
41+
42+
43+
boundary_re = _lazy_re_compile(rb"[ -~]{0,200}[!-~]")
44+
45+
46+
def valid_boundary(boundary):
47+
return boundary_re.fullmatch(boundary) is not None

kolibri/utils/env.py

+14
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,19 @@ def monkey_patch_distutils():
109109
sys.modules["distutils.version"] = module
110110

111111

112+
def forward_port_cgi_module():
113+
"""
114+
Forward ports the required parts of the removed cgi module.
115+
This can be removed when we upgrade to a version of Django that is Python 3.13 compatible.
116+
"""
117+
if sys.version_info < (3, 13):
118+
return
119+
from importlib import import_module
120+
121+
module = import_module("kolibri.utils.compat_cgi")
122+
sys.modules["cgi"] = module
123+
124+
112125
def set_env():
113126
"""
114127
Sets the Kolibri environment for the CLI or other application worker
@@ -120,6 +133,7 @@ def set_env():
120133
"""
121134
monkey_patch_markdown()
122135
monkey_patch_distutils()
136+
forward_port_cgi_module()
123137

124138
from kolibri import dist as kolibri_dist # noqa
125139

requirements/base.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ django-mptt==0.14.0
99
requests==2.27.1
1010
cheroot==10.0.1
1111
magicbus==4.1.2
12-
le-utils==0.2.6
12+
le-utils==0.2.8
1313
jsonfield==3.1.0
14-
morango==0.8.1
14+
morango==0.8.2
1515
tzlocal==4.2
1616
pytz==2024.1
1717
python-dateutil==2.9.0.post0

setup.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,9 @@ def run(self):
100100
"Programming Language :: Python :: 3.10",
101101
"Programming Language :: Python :: 3.11",
102102
"Programming Language :: Python :: 3.12",
103+
"Programming Language :: Python :: 3.13",
103104
"Programming Language :: Python :: Implementation :: PyPy",
104105
],
105106
cmdclass={"install_scripts": gen_windows_batch_files},
106-
python_requires=">=3.6, <3.13",
107+
python_requires=">=3.6, <3.14",
107108
)

tox.ini

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[tox]
2-
envlist = py{3.6,3.7,3.8,3.9,3.10,3.11,3.12}, postgres
2+
envlist = py{3.6,3.7,3.8,3.9,3.10,3.11,3.12,3.13}, postgres
33

44
[testenv]
55
usedevelop = True
@@ -21,6 +21,7 @@ basepython =
2121
py3.10: python3.10
2222
py3.11: python3.11
2323
py3.12: python3.12
24+
py3.13: python3.13
2425
deps =
2526
-r{toxinidir}/requirements/test.txt
2627
-r{toxinidir}/requirements/base.txt

0 commit comments

Comments
 (0)