Skip to content

Commit 5c9b064

Browse files
authored
Run tests in Python 3.14 in full matrix (#2531)
* tests: use importlib instead of pkgutil.get_loader pkgutil.get_loader has been removed in 3.14 * tests: use plain open instead of codecs.open Since it has been deprecated * elasticapm/contrib/django: swallow exceptions explicitly In 3.14 after https://peps.python.org/pep-0765/ the pattern of using return in a finally block is considered harmful. I guess the intent here is to just swallow any exception raised in the try block and always return the response. * tests: drop unused import * Run tests against 3.14 in full matrix
1 parent 9ad228c commit 5c9b064

9 files changed

Lines changed: 93 additions & 18 deletions

File tree

.ci/.matrix_exclude.yml

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ exclude:
5757
FRAMEWORK: flask-2.3
5858
- VERSION: python-3.7
5959
FRAMEWORK: flask-3.0
60+
- VERSION: python-3.14
61+
FRAMEWORK: flask-1.0
6062
# Python 3.10 removed a bunch of classes from collections, now in collections.abc
6163
- VERSION: python-3.10
6264
FRAMEWORK: django-1.11
@@ -80,6 +82,12 @@ exclude:
8082
FRAMEWORK: celery-5-django-3
8183
- VERSION: python-3.13 # https://github.com/celery/billiard/issues/377
8284
FRAMEWORK: celery-5-django-4
85+
- VERSION: python-3.14 # https://github.com/celery/billiard/issues/377
86+
FRAMEWORK: celery-5-flask-2
87+
- VERSION: python-3.14 # https://github.com/celery/billiard/issues/377
88+
FRAMEWORK: celery-5-django-3
89+
- VERSION: python-3.14 # https://github.com/celery/billiard/issues/377
90+
FRAMEWORK: celery-5-django-4
8391
- VERSION: python-3.10
8492
FRAMEWORK: graphene-2
8593
- VERSION: python-3.10
@@ -146,7 +154,35 @@ exclude:
146154
FRAMEWORK: aiohttp-4.0
147155
- VERSION: python-3.13
148156
FRAMEWORK: cassandra-3.4
149-
- VERSION: python-3.13
157+
- VERSION: python-3.14
158+
FRAMEWORK: django-1.11
159+
- VERSION: python-3.14
160+
FRAMEWORK: django-2.0
161+
- VERSION: python-3.14
162+
FRAMEWORK: django-2.1
163+
- VERSION: python-3.14
164+
FRAMEWORK: django-2.2
165+
- VERSION: python-3.14
166+
FRAMEWORK: django-3.0
167+
- VERSION: python-3.14
168+
FRAMEWORK: django-3.1
169+
- VERSION: python-3.14
170+
FRAMEWORK: django-3.2
171+
- VERSION: python-3.14
172+
FRAMEWORK: django-4.0
173+
- VERSION: python-3.14
174+
FRAMEWORK: django-4.2
175+
- VERSION: python-3.14
176+
FRAMEWORK: django-5.0
177+
- VERSION: python-3.14
178+
FRAMEWORK: graphene-2
179+
- VERSION: python-3.14
180+
FRAMEWORK: aiohttp-3.0
181+
- VERSION: python-3.14
182+
FRAMEWORK: aiohttp-4.0
183+
- VERSION: python-3.14
184+
FRAMEWORK: cassandra-3.4
185+
- VERSION: python-3.14
150186
FRAMEWORK: pymongo-3.5
151187
# pymongo
152188
- VERSION: python-3.10
@@ -157,6 +193,8 @@ exclude:
157193
FRAMEWORK: pymongo-3.1
158194
- VERSION: python-3.13
159195
FRAMEWORK: pymongo-3.1
196+
- VERSION: python-3.14
197+
FRAMEWORK: pymongo-3.1
160198
- VERSION: python-3.10
161199
FRAMEWORK: pymongo-3.2
162200
- VERSION: python-3.11
@@ -165,6 +203,8 @@ exclude:
165203
FRAMEWORK: pymongo-3.2
166204
- VERSION: python-3.13
167205
FRAMEWORK: pymongo-3.2
206+
- VERSION: python-3.14
207+
FRAMEWORK: pymongo-3.2
168208
- VERSION: python-3.10
169209
FRAMEWORK: pymongo-3.3
170210
- VERSION: python-3.11
@@ -173,6 +213,8 @@ exclude:
173213
FRAMEWORK: pymongo-3.3
174214
- VERSION: python-3.13
175215
FRAMEWORK: pymongo-3.3
216+
- VERSION: python-3.14
217+
FRAMEWORK: pymongo-3.3
176218
- VERSION: python-3.8
177219
FRAMEWORK: pymongo-3.4
178220
- VERSION: python-3.9
@@ -185,6 +227,12 @@ exclude:
185227
FRAMEWORK: pymongo-3.4
186228
- VERSION: python-3.13
187229
FRAMEWORK: pymongo-3.4
230+
- VERSION: python-3.13
231+
FRAMEWORK: pymongo-3.5
232+
- VERSION: python-3.14
233+
FRAMEWORK: pymongo-3.4
234+
- VERSION: python-3.14
235+
FRAMEWORK: pymongo-3.5
188236
- VERSION: pypy-3
189237
FRAMEWORK: pymongo-3.0
190238
# pymssql
@@ -212,6 +260,10 @@ exclude:
212260
FRAMEWORK: boto3-1.5
213261
- VERSION: python-3.13
214262
FRAMEWORK: boto3-1.6
263+
- VERSION: python-3.14
264+
FRAMEWORK: boto3-1.5
265+
- VERSION: python-3.14
266+
FRAMEWORK: boto3-1.6
215267
# aiohttp client, only supported in Python 3.7+
216268
- VERSION: pypy-3
217269
FRAMEWORK: aiohttp-3.0
@@ -259,6 +311,8 @@ exclude:
259311
FRAMEWORK: asyncpg-0.28
260312
- VERSION: python-3.13
261313
FRAMEWORK: asyncpg-0.28
314+
- VERSION: python-3.14
315+
FRAMEWORK: asyncpg-0.28
262316
# sanic
263317
- VERSION: pypy-3
264318
FRAMEWORK: sanic-newest
@@ -272,6 +326,8 @@ exclude:
272326
FRAMEWORK: sanic-newest
273327
- VERSION: python-3.13
274328
FRAMEWORK: sanic-20.12
329+
- VERSION: python-3.14
330+
FRAMEWORK: sanic-20.12
275331
# aioredis
276332
- VERSION: pypy-3
277333
FRAMEWORK: aioredis-newest
@@ -315,13 +371,23 @@ exclude:
315371
FRAMEWORK: twisted-16
316372
- VERSION: python-3.13
317373
FRAMEWORK: twisted-15
374+
- VERSION: python-3.14
375+
FRAMEWORK: twisted-18
376+
- VERSION: python-3.14
377+
FRAMEWORK: twisted-17
378+
- VERSION: python-3.14
379+
FRAMEWORK: twisted-16
380+
- VERSION: python-3.14
381+
FRAMEWORK: twisted-15
318382
# pylibmc
319383
- VERSION: python-3.11
320384
FRAMEWORK: pylibmc-1.4
321385
- VERSION: python-3.12
322386
FRAMEWORK: pylibmc-1.4
323387
- VERSION: python-3.13
324388
FRAMEWORK: pylibmc-1.4
389+
- VERSION: python-3.14
390+
FRAMEWORK: pylibmc-1.4
325391
# grpc
326392
- VERSION: python-3.6
327393
FRAMEWORK: grpc-newest
@@ -339,6 +405,8 @@ exclude:
339405
FRAMEWORK: grpc-1.24
340406
- VERSION: python-3.13
341407
FRAMEWORK: grpc-1.24
408+
- VERSION: python-3.14
409+
FRAMEWORK: grpc-1.24
342410
- VERSION: python-3.7
343411
FRAMEWORK: flask-1.0
344412
- VERSION: python-3.7
@@ -350,10 +418,18 @@ exclude:
350418
FRAMEWORK: sanic-20.12 # no wheels available yet
351419
- VERSION: python-3.13
352420
FRAMEWORK: cassandra-newest # c extension issue
421+
- VERSION: python-3.14
422+
FRAMEWORK: cassandra-newest # c extension issue
353423
# httpx
354424
- VERSION: python-3.13
355425
FRAMEWORK: httpx-0.13
356426
- VERSION: python-3.13
357427
FRAMEWORK: httpx-0.14
358428
- VERSION: python-3.13
359429
FRAMEWORK: httpx-0.21
430+
- VERSION: python-3.14
431+
FRAMEWORK: httpx-0.13
432+
- VERSION: python-3.14
433+
FRAMEWORK: httpx-0.14
434+
- VERSION: python-3.14
435+
FRAMEWORK: httpx-0.21

.ci/.matrix_python_full.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ VERSION:
77
- python-3.11
88
- python-3.12
99
- python-3.13
10+
- python-3.14
1011
# - pypy-3 # excluded due to build issues with SQLite/Django

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ test:
1111
# delete any __pycache__ folders to avoid hard-to-debug caching issues
1212
find . -type f -name '*.py[co]' -delete -o -type d -name __pycache__ -delete
1313
# pypy3 should be added to the first `if` once it supports py3.7
14-
if [[ "$$PYTHON_VERSION" =~ ^(3.7|3.8|3.9|3.10|3.11|3.12|3.13|nightly)$$ ]] ; then \
14+
if [[ "$$PYTHON_VERSION" =~ ^(3.7|3.8|3.9|3.10|3.11|3.12|3.13|3.14|nightly)$$ ]] ; then \
1515
echo "Python 3.7+, with asyncio"; \
1616
pytest -v $(PYTEST_ARGS) --showlocals $(PYTEST_MARKER) $(PYTEST_JUNIT); \
1717
else \

elasticapm/contrib/django/middleware/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ def process_request_wrapper(wrapped, instance, args, kwargs):
110110
elasticapm.set_transaction_name(
111111
build_name_with_http_method_prefix(get_name_from_middleware(wrapped, instance), request)
112112
)
113-
finally:
114-
return response
113+
except Exception:
114+
pass
115+
return response
115116

116117

117118
def process_response_wrapper(wrapped, instance, args, kwargs):
@@ -125,8 +126,9 @@ def process_response_wrapper(wrapped, instance, args, kwargs):
125126
elasticapm.set_transaction_name(
126127
build_name_with_http_method_prefix(get_name_from_middleware(wrapped, instance), request)
127128
)
128-
finally:
129-
return response
129+
except Exception:
130+
pass
131+
return response
130132

131133

132134
class TracingMiddleware(MiddlewareMixin, ElasticAPMClientMiddlewareMixin):

setup.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4242

4343
import ast
44-
import codecs
4544
import os
4645

4746
from setuptools import setup
@@ -68,7 +67,7 @@ def get_version():
6867
6968
:return: a string, indicating the version
7069
"""
71-
version_file = codecs.open(os.path.join("elasticapm", "version.py"), encoding="utf-8")
70+
version_file = open(os.path.join("elasticapm", "version.py"), encoding="utf-8")
7271
for line in version_file:
7372
if line.startswith("__version__"):
7473
version_tuple = ast.literal_eval(line.split(" = ")[1])

tests/contrib/asyncio/starlette_tests.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

31-
from shutil import ExecError
32-
3331
from tests.fixtures import TempStoreClient
3432

3533
import pytest # isort:skip

tests/fixtures.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

31-
import codecs
3231
import gzip
3332
import io
3433
import itertools
@@ -75,11 +74,11 @@
7574
SPAN_TYPES = json.load(f)
7675

7776

78-
with codecs.open(ERRORS_SCHEMA, encoding="utf8") as errors_json, codecs.open(
77+
with open(ERRORS_SCHEMA, encoding="utf8") as errors_json, open(
7978
TRANSACTIONS_SCHEMA, encoding="utf8"
80-
) as transactions_json, codecs.open(SPAN_SCHEMA, encoding="utf8") as span_json, codecs.open(
79+
) as transactions_json, open(SPAN_SCHEMA, encoding="utf8") as span_json, open(
8180
METRICSET_SCHEMA, encoding="utf8"
82-
) as metricset_json, codecs.open(
81+
) as metricset_json, open(
8382
METADATA_SCHEMA, encoding="utf8"
8483
) as metadata_json:
8584
VALIDATORS = {

tests/utils/stacks/tests.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232

3333
from __future__ import absolute_import
3434

35+
import importlib
3536
import os
36-
import pkgutil
3737

3838
import pytest
3939
from mock import Mock
@@ -240,7 +240,8 @@ def test_get_lines_from_file(lineno, context, expected):
240240
def test_get_lines_from_loader(lineno, context, expected):
241241
stacks.get_lines_from_file.cache_clear()
242242
module = "tests.utils.stacks.linenos"
243-
loader = pkgutil.get_loader(module)
243+
spec = importlib.util.find_spec(module)
244+
loader = spec.loader if spec is not None else None
244245
fname = os.path.join(os.path.dirname(__file__), "linenos.py")
245246
result = stacks.get_lines_from_file(fname, lineno, context, loader=loader, module_name=module)
246247
assert result == expected

tests/utils/test_wildcard_matcher_cases/conftest.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30-
import codecs
3130
import json
3231
import os
3332

@@ -40,7 +39,7 @@ def pytest_generate_tests(metafunc):
4039
json_cases = os.path.join(
4140
os.path.dirname(__file__), "..", "..", "upstream", "json-specs", "wildcard_matcher_tests.json"
4241
)
43-
with codecs.open(json_cases, encoding="utf8") as test_cases_file:
42+
with open(json_cases, encoding="utf8") as test_cases_file:
4443
test_cases = json.load(test_cases_file)
4544
for test_case, pattern_sets in test_cases.items():
4645
for pattern, texts in pattern_sets.items():

0 commit comments

Comments
 (0)