Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions master/custom/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
MAIN_BRANCH_VERSION = "3.15"
# The Git branch is called "main", but we give it a different name in buildbot.
# See git_branches in master/master.cfg.
MAIN_BRANCH_NAME = "3.x"
JUNIT_FILENAME = "test-results.xml"
134 changes: 134 additions & 0 deletions master/custom/branches.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
"""All the info about Buildbot branches

We treat the main branch specially, and we use a pseudo-branch for the
Pull Request buildbots.
In older branches some config needs to be nudged -- for example,
free-threading builds only make sense in 3.13+.

Complex enough to wrap up in a dataclass: BranchInfo.


Run this as a CLI command to print the info out:

python master/custom/branches.py

"""

import dataclasses
from functools import total_ordering
from typing import Any

# Buildbot configuration first; see below for the BranchInfo class.

def generate_branches():
yield BranchInfo(
'main',
version_tuple=(3, 15),
git_ref='main',
is_main=True,
builddir_name='main',
builder_tag='main',
sort_key=-9999,
)
yield _maintenance_branch(3, 14)
yield _maintenance_branch(3, 13)
yield _maintenance_branch(3, 12)
yield _maintenance_branch(3, 11)
yield _maintenance_branch(3, 10)
yield BranchInfo(
'PR',
version_tuple=None,
git_ref=None,
is_pr=True,
builddir_name='pull_request',
builder_tag='PullRequest',
sort_key=0,
)


def _maintenance_branch(major, minor, **kwargs):
version_tuple = (major, minor)
version_str = f'{major}.{minor}'
result = BranchInfo(
name=version_str,
builder_tag=version_str,
version_tuple=version_tuple,
git_ref=version_str,
builddir_name=version_str,
sort_key=-minor,
)

if version_tuple < (3, 11):
# Before 3.11, test_asyncio wasn't split out, and refleaks tests
# need more time.
result.monolithic_test_asyncio = True

if version_tuple < (3, 11):
# WASM wasn't a supported platform until 3.11.
result.wasm_tier = None
elif version_tuple < (3, 13):
# Tier 3 support is 3.11 & 3.12.
result.wasm_tier = 3

if version_tuple < (3, 13):
# Free-threaded builds are available since 3.13
result.gil_only = True

return result


@total_ordering
@dataclasses.dataclass
class BranchInfo:
name: str
version_tuple: tuple[int, int] | None
git_ref: str | None
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little bit confused by "git_ref" name. You may rename it to "git_branch".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I guess Git terminology isn't commonly known.
Reusing “branch” for something else is confusing too, though.

builddir_name: str
builder_tag: str

sort_key: Any

is_main: bool = False
is_pr: bool = False

# Branch features.
# Defaults are for main (and PR), overrides are in _maintenance_branch.
gil_only: bool = False
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nowadays, Free Threading term is more common. You may replace gil_only with its opposite value: "free_threading = True".

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But, the opposite would be both_free_threading_and_gil = True :)
Let's use free_threading_only = True when the GIL builds are dropped.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of if 'nogil' in tags and branch.gil_only: continue, I would expect something like if 'nogil' in tags and not branch.support_free_threading: continue. But it's not a big deal, I'm fine with gil_only if you prefer to keep it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with gil_only here for now, especially since we're still using the nogil tag for FT. We should probably migrate both towards 'free-threading' verbiage at some point, but I'm not in a rush for it.

monolithic_test_asyncio: bool = False
wasm_tier: int | None = 2

def __str__(self):
return self.name

def __eq__(self, other):
try:
other_key = other.sort_key
except AttributeError:
return NotImplemented
return self.sort_key == other.sort_key

def __lt__(self, other):
try:
other_key = other.sort_key
except AttributeError:
return NotImplemented
return self.sort_key < other.sort_key


BRANCHES = list(generate_branches())
PR_BRANCH = BRANCHES[-1]

# Verify that we've defined these in sort order
assert BRANCHES == sorted(BRANCHES)

if __name__ == "__main__":
# Print a table to the terminal
cols = [[f.name + ':' for f in dataclasses.fields(BranchInfo)]]
for branch in BRANCHES:
cols.append([repr(val) for val in dataclasses.astuple(branch)])
column_sizes = [max(len(val) for val in col) for col in cols]
column_sizes[-2] += 2 # PR is special, offset it a bit
for row in zip(*cols):
for size, val in zip(column_sizes, row):
print(val.ljust(size), end=' ')
print()
28 changes: 15 additions & 13 deletions master/custom/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@

from buildbot.plugins import util

from . import (MAIN_BRANCH_VERSION, MAIN_BRANCH_NAME,
JUNIT_FILENAME)
from . import JUNIT_FILENAME
from .steps import (
Test,
Clean,
Expand Down Expand Up @@ -56,6 +55,8 @@ def get_j_opts(worker, default=None):
class BaseBuild(factory.BuildFactory):
factory_tags = []
test_timeout = TEST_TIMEOUT
buildersuffix = ""
tags = ()

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

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

if self.build_out_of_tree:
Expand Down Expand Up @@ -161,7 +162,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
env=self.test_environ,
**oot_kwargs
))
if branch not in ("3",) and not has_option("-R", self.testFlags):
if not branch.is_pr and not has_option("-R", self.testFlags):
filename = JUNIT_FILENAME
if self.build_out_of_tree:
filename = os.path.join(out_of_tree_dir, filename)
Expand Down Expand Up @@ -214,11 +215,12 @@ class UnixInstalledBuild(BaseBuild):
factory_tags = ["installed"]

def setup(self, branch, worker, test_with_PTY=False, **kwargs):
if branch == MAIN_BRANCH_NAME:
branch = MAIN_BRANCH_VERSION
elif branch == "custom":
branch = "3"
installed_python = f"./target/bin/python{branch}"
if branch.version_tuple:
major, minor = branch.version_tuple
executable_name = f'python{major}.{minor}'
else:
executable_name = f'python3'
installed_python = f"./target/bin/{executable_name}"
self.addStep(
Configure(
command=["./configure", "--prefix", "$(PWD)/target"]
Expand Down Expand Up @@ -633,7 +635,7 @@ def setup(self, branch, worker, **kwargs):
command=test_command,
timeout=step_timeout(self.test_timeout),
))
if branch not in ("3",) and not has_option("-R", self.testFlags):
if not branch.is_pr and not has_option("-R", self.testFlags):
self.addStep(UploadTestResults(branch))
self.addStep(Clean(command=clean_command))

Expand Down Expand Up @@ -856,7 +858,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
env=self.test_environ,
workdir=oot_host_path,
))
if branch not in ("3",) and not has_option("-R", self.testFlags):
if not branch.is_pr and not has_option("-R", self.testFlags):
filename = os.path.join(oot_host_path, JUNIT_FILENAME)
self.addStep(UploadTestResults(branch, filename=filename))
self.addStep(
Expand Down Expand Up @@ -990,7 +992,7 @@ def setup(self, branch, worker, test_with_PTY=False, **kwargs):
workdir=host_path,
)
)
if branch not in ("3",) and not has_option("-R", self.testFlags):
if not branch.is_pr and not has_option("-R", self.testFlags):
filename = os.path.join(host_path, JUNIT_FILENAME)
self.addStep(UploadTestResults(branch, filename=filename))

Expand Down Expand Up @@ -1240,7 +1242,7 @@ def setup(self, branch, *args, **kwargs):
#
# The symlink approach will fail for Python 3.13 *PR* builds, because
# there's no way to identify the base branch for a PR.
if branch == "3.13":
if branch.name == "3.13":
self.py313_setup(branch, *args, **kwargs)
Comment on lines +1245 to 1246
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Branching on name smells, but I kept it here to match the py313_setup name.

else:
self.current_setup(branch, *args, **kwargs)
Expand Down
1 change: 0 additions & 1 deletion master/custom/workers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from buildbot.plugins import worker as _worker

from custom.factories import MAIN_BRANCH_NAME
from custom.worker_downtime import no_builds_between


Expand Down
Loading