Skip to content

Commit c4477f1

Browse files
committed
Use a dataclass for "branches"
1 parent befe468 commit c4477f1

File tree

5 files changed

+180
-59
lines changed

5 files changed

+180
-59
lines changed

master/custom/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
MAIN_BRANCH_VERSION = "3.15"
2-
# The Git branch is called "main", but we give it a different name in buildbot.
3-
# See git_branches in master/master.cfg.
4-
MAIN_BRANCH_NAME = "3.x"
51
JUNIT_FILENAME = "test-results.xml"

master/custom/branches.py

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
"""All the info about Buildbot branches
2+
3+
We treat the main branch specially, and we use a pseudo-branch for the
4+
Pull Request buildbots.
5+
In older branches some config needs to be nudged -- for example,
6+
free-threading builds only make sense in 3.13+.
7+
8+
Complex enough to wrap up in a dataclass: BranchInfo.
9+
10+
11+
Run this as a CLI command to print the info out:
12+
13+
python master/custom/branches.py
14+
15+
"""
16+
17+
import dataclasses
18+
from functools import total_ordering
19+
from typing import Any
20+
21+
# Buildbot configuration first; see below for the BranchInfo class.
22+
23+
def generate_branches():
24+
yield BranchInfo(
25+
'main',
26+
version_tuple=(3, 15),
27+
git_ref='main',
28+
is_main=True,
29+
builddir_name='main',
30+
builder_tag='main',
31+
sort_key=-9999,
32+
)
33+
yield _maintenance_branch(3, 14)
34+
yield _maintenance_branch(3, 13)
35+
yield _maintenance_branch(3, 12)
36+
yield _maintenance_branch(3, 11)
37+
yield _maintenance_branch(3, 10)
38+
yield BranchInfo(
39+
'PR',
40+
version_tuple=None,
41+
git_ref=None,
42+
is_pr=True,
43+
builddir_name='pull_request',
44+
builder_tag='PullRequest',
45+
sort_key=0,
46+
)
47+
48+
49+
def _maintenance_branch(major, minor, **kwargs):
50+
version_tuple = (major, minor)
51+
version_str = f'{major}.{minor}'
52+
result = BranchInfo(
53+
name=version_str,
54+
builder_tag=version_str,
55+
version_tuple=version_tuple,
56+
git_ref=version_str,
57+
builddir_name=version_str,
58+
sort_key=-minor,
59+
)
60+
61+
if version_tuple < (3, 11):
62+
# Before 3.11, test_asyncio wasn't split out, and refleaks tests
63+
# need more time.
64+
result.monolithic_test_asyncio = True
65+
66+
if version_tuple < (3, 11):
67+
# WASM wasn't a supported platform until 3.11.
68+
result.wasm_tier = None
69+
elif version_tuple < (3, 13):
70+
# Tier 3 support is 3.11 & 3.12.
71+
result.wasm_tier = 3
72+
73+
if version_tuple < (3, 13):
74+
# Free-threaded builds are available since 3.13
75+
result.gil_only = True
76+
77+
return result
78+
79+
80+
@total_ordering
81+
@dataclasses.dataclass
82+
class BranchInfo:
83+
name: str
84+
version_tuple: tuple[int, int] | None
85+
git_ref: str | None
86+
builddir_name: str
87+
builder_tag: str
88+
89+
sort_key: Any
90+
91+
is_main: bool = False
92+
is_pr: bool = False
93+
94+
# Branch features.
95+
# Defaults are for main (and PR), overrides are in _maintenance_branch.
96+
gil_only: bool = False
97+
monolithic_test_asyncio: bool = False
98+
wasm_tier: int | None = 2
99+
100+
def __str__(self):
101+
return self.name
102+
103+
def __eq__(self, other):
104+
try:
105+
other_key = other.sort_key
106+
except AttributeError:
107+
return NotImplemented
108+
return self.sort_key == other.sort_key
109+
110+
def __lt__(self, other):
111+
try:
112+
other_key = other.sort_key
113+
except AttributeError:
114+
return NotImplemented
115+
return self.sort_key < other.sort_key
116+
117+
118+
BRANCHES = list(generate_branches())
119+
PR_BRANCH = BRANCHES[-1]
120+
121+
# Verify that we've defined these in sort order
122+
assert BRANCHES == sorted(BRANCHES)
123+
124+
if __name__ == "__main__":
125+
# Print a table to the terminal
126+
cols = [[f.name + ':' for f in dataclasses.fields(BranchInfo)]]
127+
for branch in BRANCHES:
128+
cols.append([repr(val) for val in dataclasses.astuple(branch)])
129+
column_sizes = [max(len(val) for val in col) for col in cols]
130+
column_sizes[-2] += 2 # PR is special, offset it a bit
131+
for row in zip(*cols):
132+
for size, val in zip(column_sizes, row):
133+
print(val.ljust(size), end=' ')
134+
print()

master/custom/factories.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99

1010
from buildbot.plugins import util
1111

12-
from . import (MAIN_BRANCH_VERSION, MAIN_BRANCH_NAME,
13-
JUNIT_FILENAME)
12+
from . import JUNIT_FILENAME
1413
from .steps import (
1514
Test,
1615
Clean,
@@ -56,6 +55,8 @@ def get_j_opts(worker, default=None):
5655
class BaseBuild(factory.BuildFactory):
5756
factory_tags = []
5857
test_timeout = TEST_TIMEOUT
58+
buildersuffix = ""
59+
tags = ()
5960

6061
def __init__(self, source, *, extra_tags=[], **kwargs):
6162
super().__init__([source])
@@ -97,7 +98,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
9798

9899
# In 3.10, test_asyncio wasn't split out, and refleaks tests
99100
# need more time.
100-
if branch == "3.10" and has_option("-R", self.testFlags):
101+
if branch.monolithic_test_asyncio and has_option("-R", self.testFlags):
101102
self.test_timeout *= 2
102103

103104
if self.build_out_of_tree:
@@ -161,7 +162,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
161162
env=self.test_environ,
162163
**oot_kwargs
163164
))
164-
if branch not in ("3",) and not has_option("-R", self.testFlags):
165+
if not branch.is_pr and not has_option("-R", self.testFlags):
165166
filename = JUNIT_FILENAME
166167
if self.build_out_of_tree:
167168
filename = os.path.join(out_of_tree_dir, filename)
@@ -214,11 +215,12 @@ class UnixInstalledBuild(BaseBuild):
214215
factory_tags = ["installed"]
215216

216217
def setup(self, branch, worker, test_with_PTY=False, **kwargs):
217-
if branch == MAIN_BRANCH_NAME:
218-
branch = MAIN_BRANCH_VERSION
219-
elif branch == "custom":
220-
branch = "3"
221-
installed_python = f"./target/bin/python{branch}"
218+
if branch.version_tuple:
219+
major, minor = branch.version_tuple
220+
executable_name = f'python{major}.{minor}'
221+
else:
222+
executable_name = f'python3'
223+
installed_python = f"./target/bin/{executable_name}"
222224
self.addStep(
223225
Configure(
224226
command=["./configure", "--prefix", "$(PWD)/target"]
@@ -633,7 +635,7 @@ def setup(self, branch, worker, **kwargs):
633635
command=test_command,
634636
timeout=step_timeout(self.test_timeout),
635637
))
636-
if branch not in ("3",) and not has_option("-R", self.testFlags):
638+
if not branch.is_pr and not has_option("-R", self.testFlags):
637639
self.addStep(UploadTestResults(branch))
638640
self.addStep(Clean(command=clean_command))
639641

@@ -856,7 +858,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
856858
env=self.test_environ,
857859
workdir=oot_host_path,
858860
))
859-
if branch not in ("3",) and not has_option("-R", self.testFlags):
861+
if not branch.is_pr and not has_option("-R", self.testFlags):
860862
filename = os.path.join(oot_host_path, JUNIT_FILENAME)
861863
self.addStep(UploadTestResults(branch, filename=filename))
862864
self.addStep(
@@ -990,7 +992,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
990992
workdir=host_path,
991993
)
992994
)
993-
if branch not in ("3",) and not has_option("-R", self.testFlags):
995+
if not branch.is_pr and not has_option("-R", self.testFlags):
994996
filename = os.path.join(host_path, JUNIT_FILENAME)
995997
self.addStep(UploadTestResults(branch, filename=filename))
996998

@@ -1240,7 +1242,7 @@ def setup(self, branch, *args, **kwargs):
12401242
#
12411243
# The symlink approach will fail for Python 3.13 *PR* builds, because
12421244
# there's no way to identify the base branch for a PR.
1243-
if branch == "3.13":
1245+
if branch.name == "3.13":
12441246
self.py313_setup(branch, *args, **kwargs)
12451247
else:
12461248
self.current_setup(branch, *args, **kwargs)

master/custom/workers.py

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

99
from buildbot.plugins import worker as _worker
1010

11-
from custom.factories import MAIN_BRANCH_NAME
1211
from custom.worker_downtime import no_builds_between
1312

1413

0 commit comments

Comments
 (0)