Skip to content

Commit 773efda

Browse files
committed
Merge tag '2027.0.0a6' into led-buffer
2 parents 22c498b + e1a1a2d commit 773efda

857 files changed

Lines changed: 23573 additions & 11087 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/dist.yml

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,9 @@ jobs:
112112
max-parallel: ${{ fromJSON(needs.setup_concurrency.outputs.max-parallel).v }}
113113
fail-fast: true
114114
matrix:
115-
os: ["ubuntu-22.04", "ubuntu-22.04-arm", "macos-14", "windows-2022"]
115+
os: ["ubuntu-24.04", "ubuntu-24.04-arm", "macos-14", "windows-2022"]
116116
include:
117-
- os: ubuntu-22.04-arm
117+
- os: ubuntu-24.04-arm
118118
container: python:3.13-bookworm
119119

120120
container: ${{ matrix.container }}
@@ -125,7 +125,7 @@ jobs:
125125
fetch-depth: 0
126126

127127
- name: Install python
128-
if: matrix.os != 'ubuntu-22.04-arm'
128+
if: matrix.os != 'ubuntu-24.04-arm'
129129
uses: actions/setup-python@v5
130130
with:
131131
python-version: '3.13'
@@ -157,27 +157,26 @@ jobs:
157157
fail-fast: true
158158
matrix:
159159
os:
160-
- "ubuntu-22.04"
160+
- "ubuntu-24.04"
161161
- "macos-15-intel" # x86_64
162162
- "macos-14" # arm64
163163
- "windows-2022"
164164
python_version:
165-
- '3.10'
166165
- '3.11'
167166
- '3.12'
168167
- '3.13'
169168
- '3.14'
170169
include:
171-
- os: ubuntu-22.04-arm
170+
- os: ubuntu-24.04-arm
172171
python_version: '3.11'
173172
container: python:3.11-bookworm
174-
- os: ubuntu-22.04-arm
173+
- os: ubuntu-24.04-arm
175174
python_version: '3.12'
176175
container: python:3.12-bookworm
177-
- os: ubuntu-22.04-arm
176+
- os: ubuntu-24.04-arm
178177
python_version: '3.13'
179178
container: python:3.13-bookworm
180-
- os: ubuntu-22.04-arm
179+
- os: ubuntu-24.04-arm
181180
python_version: '3.14'
182181
container: python:3.14-bookworm
183182

@@ -189,7 +188,7 @@ jobs:
189188
fetch-depth: 0
190189

191190
- name: Install python
192-
if: matrix.os != 'ubuntu-22.04-arm'
191+
if: matrix.os != 'ubuntu-24.04-arm'
193192
uses: actions/setup-python@v5
194193
with:
195194
python-version: ${{ matrix.python_version }}
@@ -212,7 +211,7 @@ jobs:
212211

213212
- name: Install libgl
214213
run: apt-get update && apt-get install -y libgl1
215-
if: matrix.os == 'ubuntu-22.04-arm'
214+
if: matrix.os == 'ubuntu-24.04-arm'
216215

217216
- name: Setup MSVC
218217
uses: bus1/cabuild/action/msdevshell@e22aba57d6e74891d059d66501b6b5aed8123c4d # v1
@@ -262,6 +261,10 @@ jobs:
262261
run: |
263262
python -m devtools ci install-test-pure-wheels
264263
264+
- name: Test examples
265+
run: |
266+
python -m devtools test-examples
267+
265268
- name: Ensure all headers are accounted for
266269
run: |
267270
python -m devtools ci scan-headers
@@ -276,7 +279,7 @@ jobs:
276279
path: dist
277280

278281
#
279-
# Build roboRIO/raspbian wheels
282+
# Build robot/raspbian wheels
280283
#
281284

282285
cross-other:
@@ -286,10 +289,8 @@ jobs:
286289
max-parallel: ${{ fromJSON(needs.setup_concurrency.outputs.max-parallel).v }}
287290
matrix:
288291
os:
289-
- container: wpilib/roborio-cross-ubuntu:2026-22.04-py314
290-
name: roborio
291-
- container: wpilib/raspbian-cross-ubuntu:2026-bookworm-22.04-py314
292-
name: raspbian
292+
- container: wpilib/systemcore-cross-ubuntu:2026-24.04-py314
293+
name: systemcore
293294

294295
container:
295296
image: "${{ matrix.os.container }}"
@@ -300,7 +301,7 @@ jobs:
300301
fetch-depth: 0
301302

302303
- name: Setup cross environment for meson
303-
uses: robotpy/build-actions/setup-cross-meson@semiwrap
304+
uses: robotpy/build-actions/setup-cross-meson@v2027
304305

305306
- name: Install deps
306307
shell: bash
@@ -324,22 +325,9 @@ jobs:
324325
max-parallel: ${{ fromJSON(needs.setup_concurrency.outputs.max-parallel).v }}
325326
matrix:
326327
os:
327-
- container: wpilib/roborio-cross-ubuntu:2026-22.04-py314
328-
name: roborio
329-
base: roborio
330-
331-
- container: wpilib/raspbian-cross-ubuntu:2026-bookworm-22.04-py311
332-
name: raspbian-py311
333-
base: raspbian
334-
- container: wpilib/raspbian-cross-ubuntu:2026-bookworm-22.04-py312
335-
name: raspbian-py312
336-
base: raspbian
337-
- container: wpilib/raspbian-cross-ubuntu:2026-bookworm-22.04-py313
338-
name: raspbian-py313
339-
base: raspbian
340-
- container: wpilib/raspbian-cross-ubuntu:2026-bookworm-22.04-py314
341-
name: raspbian-py314
342-
base: raspbian
328+
- container: wpilib/systemcore-cross-ubuntu:2026-24.04-py314
329+
name: systemcore
330+
base: systemcore
343331

344332
container:
345333
image: "${{ matrix.os.container }}"
@@ -355,7 +343,7 @@ jobs:
355343
path: dist-other
356344

357345
- name: Setup cross environment for meson
358-
uses: robotpy/build-actions/setup-cross-meson@semiwrap
346+
uses: robotpy/build-actions/setup-cross-meson@v2027
359347

360348
- run: apt-get update
361349
- name: Setup ccache
@@ -401,7 +389,7 @@ jobs:
401389
verify-metadata: false
402390
user: ${{ secrets.WPI_ARTIFACTORY_USERNAME }}
403391
password: ${{ secrets.WPI_ARTIFACTORY_TOKEN }}
404-
repository-url: https://wpilib.jfrog.io/artifactory/api/pypi/wpilib-python-release-2026-local
392+
repository-url: https://wpilib.jfrog.io/artifactory/api/pypi/wpilib-python-release-2027-local
405393

406394
publish-rpyrepo-other:
407395
runs-on: ubuntu-latest
@@ -421,7 +409,7 @@ jobs:
421409
skip-existing: true # native packages can be uploaded multiple times
422410
user: ${{ secrets.WPI_ARTIFACTORY_USERNAME }}
423411
password: ${{ secrets.WPI_ARTIFACTORY_TOKEN }}
424-
repository-url: https://wpilib.jfrog.io/artifactory/api/pypi/wpilib-python-release-2026-local
412+
repository-url: https://wpilib.jfrog.io/artifactory/api/pypi/wpilib-python-release-2027-local
425413

426414
publish-pypi:
427415
runs-on: ubuntu-latest

.readthedocs.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ sphinx:
44
configuration: docs/conf.py
55

66
build:
7-
os: ubuntu-22.04
7+
os: ubuntu-24.04
88
tools:
9-
python: "3.11"
9+
python: "3.14"
1010
jobs:
1111
post_install:
1212
- python -m robotpy_sphinx.download_and_install robotpy mostrobotpy main dist pypi-other-Linux-X64
13-
- python -m robotpy_sphinx.download_and_install robotpy mostrobotpy main dist pypi-meson-Linux-X64-3.11
13+
- python -m robotpy_sphinx.download_and_install robotpy mostrobotpy main dist pypi-meson-Linux-X64-3.14
1414
- python -m robotpy_sphinx.download_and_install robotpy mostrobotpy main dist pypi-pure
1515
post_build:
1616
- mkdir --parents _readthedocs/htmlzip

devtools/__main__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from .ctx import Context
88
from . import ci
9+
from . import examples
910
from . import update_pyproject
1011

1112
#
@@ -33,6 +34,7 @@ def main(ctx: click.Context, verbose: bool):
3334

3435

3536
main.add_command(ci.ci)
37+
main.add_command(examples.test_examples)
3638
main.add_command(update_pyproject.update_pyproject)
3739

3840

devtools/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ class Parameters:
2424
wpilib_bin_version: str
2525
wpilib_bin_url: str
2626

27+
mrclib_bin_version: str
28+
mrclib_bin_url: str
29+
mrclib_artifacts: T.Set[str]
30+
2731
#: renames [project.entry-points.KEY*] to [project.entry-points.VALUE]
2832
entrypoints: T.Dict[str, str]
2933

devtools/examples.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import dataclasses
2+
import os
3+
import pathlib
4+
import subprocess
5+
import sys
6+
import typing as T
7+
8+
import click
9+
import tomlkit
10+
11+
from .util import parse_input, run_cmd
12+
13+
14+
def _validate_example_list(root: pathlib.Path, expected_dirs: T.Sequence[str]) -> None:
15+
expected = sorted(f"{name}/robot.py" for name in expected_dirs)
16+
actual = sorted(p.relative_to(root).as_posix() for p in root.rglob("robot.py"))
17+
18+
if expected == actual:
19+
return
20+
21+
missing = sorted(set(expected) - set(actual))
22+
extra = sorted(set(actual) - set(expected))
23+
for path in missing:
24+
print(f"Missing: {path}")
25+
for path in extra:
26+
print(f"Extra: {path}")
27+
28+
if not os.environ.get("FORCE_ANYWAYS"):
29+
print("ERROR: Not every robot.py file is in the list of tests!")
30+
sys.exit(1)
31+
32+
33+
@dataclasses.dataclass
34+
class ExamplesTests:
35+
base: T.List[str]
36+
ignored: T.List[str]
37+
38+
39+
@dataclasses.dataclass
40+
class ExamplesConfig:
41+
tests: ExamplesTests
42+
43+
44+
def _load_tests_config(config_path: pathlib.Path) -> ExamplesConfig:
45+
try:
46+
data = tomlkit.parse(config_path.read_text(encoding="utf-8"))
47+
except FileNotFoundError:
48+
raise click.ClickException(f"Missing tests config: {config_path}")
49+
except Exception as exc:
50+
raise click.ClickException(f"Invalid tests config: {config_path}: {exc}")
51+
52+
try:
53+
return parse_input(data, ExamplesConfig, config_path)
54+
except Exception as exc:
55+
raise click.ClickException(str(exc))
56+
57+
58+
@click.command(name="test-examples")
59+
@click.argument("test_name", required=False)
60+
@click.option("-x", "--exitfirst", is_flag=True, help="Exit on first failed test.")
61+
def test_examples(test_name: str | None, exitfirst: bool) -> None:
62+
"""Run tests on robot examples."""
63+
root = pathlib.Path(__file__).parent.parent / "examples" / "robot"
64+
config_path = root / "examples.toml"
65+
66+
cfg = _load_tests_config(config_path)
67+
base_tests = cfg.tests.base
68+
ignored_tests = cfg.tests.ignored
69+
70+
every_tests = [*base_tests, *ignored_tests]
71+
_validate_example_list(root, every_tests)
72+
73+
tests_to_run = base_tests
74+
if test_name:
75+
if test_name not in every_tests:
76+
raise click.BadParameter(f"unknown example {test_name}")
77+
tests_to_run = [test_name]
78+
79+
failed_tests = []
80+
81+
for example_name in tests_to_run:
82+
test_dir = root / example_name
83+
print(test_dir.resolve())
84+
try:
85+
run_cmd(
86+
sys.executable,
87+
"-m",
88+
"robotpy",
89+
"test",
90+
"--builtin",
91+
cwd=test_dir,
92+
)
93+
except subprocess.CalledProcessError:
94+
print(f"Test in {test_dir.resolve()} failed")
95+
failed_tests.append(example_name)
96+
if exitfirst:
97+
break
98+
99+
if failed_tests:
100+
print("Failed tests:")
101+
for name in failed_tests:
102+
print(f"- {name}")
103+
sys.exit(1)
104+
105+
print("All tests successful!")

devtools/subproject.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
import shutil
33
import sys
44
import tempfile
5+
import tomllib
56
import typing as T
67

78
from packaging.requirements import Requirement
8-
import tomli
99

1010
from .config import SubprojectConfig
1111
from .util import run_cmd
@@ -24,9 +24,9 @@ def __init__(
2424
self.pyproject_path = self.path / "pyproject.toml"
2525
self.name = path.name
2626

27-
# Use tomli here because it's faster and we just need the data
27+
# Use tomllib here because it's faster and we just need the data
2828
with open(self.pyproject_path, "rb") as fp:
29-
self.pyproject_data = tomli.load(fp)
29+
self.pyproject_data = tomllib.load(fp)
3030

3131
self.build_requires = [
3232
Requirement(req) for req in self.pyproject_data["build-system"]["requires"]
@@ -175,7 +175,9 @@ def build_wheel(
175175
}
176176

177177
def _fix_wheel_name(self, wheel_path: pathlib.Path) -> str:
178-
if sys.platform == "linux":
178+
if self.ctx.is_robot:
179+
name = wheel_path.name
180+
elif sys.platform == "linux":
179181
name = self._fix_linux_wheel_name(wheel_path)
180182
else:
181183
name = wheel_path.name

0 commit comments

Comments
 (0)