Skip to content

Commit 2b8ae93

Browse files
Python 3.14 Support (#1540)
* Change PyPy3.10 to 3.11 * Add tests for Python 3.14 * Add 3.14 classifier * Fix BaseDefaultEventLoopPolicy name * Fix graphql apps * Fix sqlite tests * Increase timeout on test_collector_hostname * Change get-envs output * Clean up cornice reference in tox * Add comment to tox * Cleanup references to old version files * Change syntax of tox run * Tox summary in CI * Ignore false positive from actionlint * Fix fixture warning message * Disable aiobotocore Python 3.14 tests * Disable confluent-kafka tests for 3.14 * Disable autogen 3.14 and pypy3.11 tests * Disable sanic 3.14 tests * Disable gunicorn 3.14 tests * Disable langchain tests --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent befd738 commit 2b8ae93

File tree

20 files changed

+726
-195
lines changed

20 files changed

+726
-195
lines changed

.github/actionlint.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,4 @@ paths:
1717
ignore:
1818
# This runner exists, but is in beta and not known to actionlint.
1919
- 'label "windows-11-arm" is unknown\. .+'
20+
- 'property "check_run_id" is not defined.+'

.github/scripts/get-envs.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,23 +15,22 @@
1515

1616
import fileinput
1717
import os
18+
from pathlib import Path
1819
from textwrap import dedent
1920

2021
GROUP_NUMBER = int(os.environ["GROUP_NUMBER"]) - 1
2122
TOTAL_GROUPS = int(os.environ["TOTAL_GROUPS"])
2223
GITHUB_JOB = os.environ["GITHUB_JOB"]
24+
GITHUB_OUTPUT = os.environ.get("GITHUB_OUTPUT", None)
2325

2426

2527
def main(stdin):
2628
environments = [env.rstrip() for env in stdin]
2729
filtered_envs = [env for env in environments if env.startswith(GITHUB_JOB + "-")]
2830
grouped_envs = filtered_envs[GROUP_NUMBER::TOTAL_GROUPS]
29-
joined_envs = ",".join(grouped_envs)
3031

3132
# If not environments are found, raise an error with helpful information.
32-
if joined_envs:
33-
print(joined_envs)
34-
else:
33+
if not grouped_envs:
3534
error_msg = dedent(f"""
3635
No matching environments found.
3736
GITHUB_JOB = {GITHUB_JOB}
@@ -41,10 +40,17 @@ def main(stdin):
4140
environments = {environments}
4241
filtered_envs = {filtered_envs}
4342
grouped_envs = {grouped_envs}
44-
joined_envs = {joined_envs}
4543
""")
4644
raise RuntimeError(error_msg(environments))
4745

46+
# Output results to GITHUB_OUTPUT for use in later steps.
47+
if GITHUB_OUTPUT:
48+
with Path(GITHUB_OUTPUT).open("a") as output_fh:
49+
print(f"envs={','.join(grouped_envs)}", file=output_fh)
50+
51+
# Output human readable results to stdout for visibility in logs.
52+
print("\n".join(grouped_envs))
53+
4854

4955
if __name__ == "__main__":
5056
with fileinput.input() as stdin:

.github/scripts/tox-summary.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env python
2+
# Copyright 2010 New Relic, Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
import json
17+
import os
18+
import re
19+
from pathlib import Path
20+
from textwrap import dedent
21+
22+
REPO_DIR = Path(__file__).parent.parent.parent
23+
TOX_DIR = REPO_DIR / ".tox"
24+
GITHUB_SUMMARY = Path(os.environ.get("GITHUB_STEP_SUMMARY", TOX_DIR / "summary.md"))
25+
RESULTS_FILE_RE = re.compile(
26+
r"(?P<job_name>[a-zA-Z0-9_-]+)-(?P<job_num>\d+)-(?P<run_id>[a-zA-Z0-9]+)-(?P<job_id>[a-zA-Z0-9_-]+)-results.json"
27+
)
28+
29+
GITHUB_SERVER_URL = os.environ.get("GITHUB_SERVER_URL", "https://github.com")
30+
GITHUB_REPOSITORY = os.environ.get("GITHUB_REPOSITORY", "newrelic/newrelic-python-agent")
31+
32+
TABLE_HEADER = """
33+
# Tox Results Summary
34+
35+
| Environment | Status | Duration (s) | Setup Duration (s) | Test Duration (s) | Runner |
36+
|-------------|--------|--------------|--------------------|-------------------|--------|
37+
"""
38+
TABLE_HEADER = dedent(TABLE_HEADER).strip()
39+
40+
41+
def main():
42+
results = {}
43+
# Search both repo and .tox dirs
44+
filepaths = list(REPO_DIR.glob("*-results.json")) + list(TOX_DIR.glob("*-results.json"))
45+
for filepath in filepaths:
46+
with filepath.open() as f:
47+
# Load the JSON data
48+
data = json.load(f)
49+
envs = data.get("testenvs", ())
50+
51+
# Extract GitHub info from filename
52+
match = RESULTS_FILE_RE.match(filepath.name)
53+
if match:
54+
runner_link = f"{GITHUB_SERVER_URL}/{GITHUB_REPOSITORY}/actions/runs/{match.group('run_id')}/job/{match.group('job_id')}"
55+
runner = f"[{match.group('job_name')} ({match.group('job_num')})]({runner_link})"
56+
else:
57+
runner = "N/A"
58+
59+
# Aggregate any non-empty results
60+
sub_results = {k: v for k, v in envs.items() if v and k != ".pkg"}
61+
for result in sub_results.values():
62+
result["runner"] = runner
63+
results.update(sub_results)
64+
65+
if not results:
66+
raise RuntimeError("No tox results found.")
67+
68+
with GITHUB_SUMMARY.open("w") as output_fp:
69+
summary = summarize_results(results)
70+
# Print table header
71+
print(TABLE_HEADER, file=output_fp)
72+
73+
for result in summary:
74+
line = "| {env_name} | {status} | {duration} | {setup_duration} | {test_duration} | {runner} |".format(
75+
**result
76+
)
77+
print(line, file=output_fp)
78+
79+
80+
def summarize_results(results):
81+
summary = []
82+
for env, result in results.items():
83+
duration = result["result"].get("duration", 0)
84+
duration = f"{duration:.2f}" if duration >= 0 else "N/A"
85+
status = "OK ✅" if result["result"]["success"] else "FAIL ❌"
86+
runner = result.get("runner", "N/A")
87+
88+
# Sum up setup and test durations from individual commands
89+
setup_duration = 0
90+
for cmd in result.get("setup", ()):
91+
setup_duration += cmd.get("elapsed", 0)
92+
setup_duration = f"{setup_duration:.2f}" if setup_duration >= 0 else "N/A"
93+
94+
test_duration = 0
95+
for cmd in result.get("test", ()):
96+
test_duration += cmd.get("elapsed", 0)
97+
test_duration = f"{test_duration:.2f}" if test_duration >= 0 else "N/A"
98+
99+
summary.append(
100+
{
101+
"env_name": env,
102+
"status": status,
103+
"duration": duration,
104+
"setup_duration": setup_duration,
105+
"test_duration": test_duration,
106+
"runner": runner,
107+
}
108+
)
109+
110+
return sorted(summary, key=lambda result: (1 if "OK" in result["status"] else 0, result["env_name"]))
111+
112+
113+
if __name__ == "__main__":
114+
main()

.github/workflows/benchmarks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
timeout-minutes: 30
3232
strategy:
3333
matrix:
34-
python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"]
34+
python: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
3535

3636
env:
3737
ASV_FACTOR: "1.1"

.github/workflows/deploy.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ jobs:
4141
os: ubuntu-24.04
4242
- wheel: cp313-manylinux
4343
os: ubuntu-24.04
44+
- wheel: cp314-manylinux
45+
os: ubuntu-24.04
4446
# Linux musllibc
4547
- wheel: cp38-musllinux
4648
os: ubuntu-24.04
@@ -54,10 +56,14 @@ jobs:
5456
os: ubuntu-24.04
5557
- wheel: cp313-musllinux
5658
os: ubuntu-24.04
59+
- wheel: cp314-musllinux
60+
os: ubuntu-24.04
5761
# Windows
5862
# Windows wheels won't but published until the full release announcement.
5963
# - wheel: cp313-win
6064
# os: windows-2025
65+
# - wheel: cp314-win
66+
# os: windows-2025
6167

6268
name: Build wheels for ${{ matrix.wheel }}
6369
runs-on: ${{ matrix.os }}

0 commit comments

Comments
 (0)