Skip to content

Commit 0b6520a

Browse files
authored
Merge pull request #9 from robotpy/ensure-case
Ensure that robot.py is lowercase
2 parents 7653506 + 8bf7ae9 commit 0b6520a

File tree

5 files changed

+122
-1
lines changed

5 files changed

+122
-1
lines changed

.github/workflows/dist.yml

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ jobs:
2727
run: |
2828
pip --disable-pip-version-check install mypy
2929
pip --disable-pip-version-check install -e .
30+
pip --disable-pip-version-check install -r tests/requirements.txt
3031
- name: Run mypy
3132
uses: liskin/gh-problem-matcher-wrap@v2
3233
with:
@@ -57,9 +58,42 @@ jobs:
5758
name: dist
5859
path: dist
5960

61+
test:
62+
needs: [build]
63+
runs-on: ${{ matrix.os }}
64+
strategy:
65+
matrix:
66+
os: ["ubuntu-22.04", "macos-14", "windows-2022"]
67+
68+
steps:
69+
- uses: actions/checkout@v5
70+
71+
- uses: actions/setup-python@v5
72+
with:
73+
python-version: "3.13"
74+
75+
- name: Download build artifacts
76+
uses: actions/download-artifact@v4
77+
with:
78+
name: dist
79+
path: dist
80+
81+
- name: Install
82+
shell: bash
83+
working-directory: dist
84+
run: python -m pip --disable-pip-version-check install *.whl
85+
86+
- name: Install test dependencies
87+
working-directory: tests
88+
run: python -m pip --disable-pip-version-check install -r requirements.txt
89+
90+
- name: Test wheel
91+
working-directory: tests
92+
run: python run_tests.py
93+
6094
publish:
6195
runs-on: ubuntu-latest
62-
needs: [check, check-mypy, build]
96+
needs: [check, check-mypy, build, test]
6397
permissions:
6498
id-token: write
6599
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')

robotpy/main.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ def _load_robot_class():
4949
print(f"ERROR: {robot_py_path} is a directory", file=sys.stderr)
5050
sys.exit(1)
5151

52+
# Ensure that it's robot.py and not Robot.py or similar by checking the
53+
# directory entries of its parent
54+
lower_name = robot_py_path.name.lower()
55+
for entry in robot_py_path.parent.iterdir():
56+
if entry.name.lower() == lower_name and entry.name != robot_py_path.name:
57+
print(
58+
f"ERROR: {robot_py_path} must be {robot_py_path.name} (found '{entry.name}')",
59+
file=sys.stderr,
60+
)
61+
sys.exit(1)
62+
5263
# Add that directory to sys.path to ensure that imports work as expected
5364
sys.path.insert(0, str(robot_py_path.parent.absolute()))
5465

tests/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest

tests/run_tests.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env python3
2+
3+
import os
4+
from os.path import abspath, dirname, join
5+
import sys
6+
import subprocess
7+
8+
if __name__ == "__main__":
9+
root = abspath(dirname(__file__))
10+
os.chdir(root)
11+
12+
# Run pytest
13+
subprocess.check_call([sys.executable, "-m", "pytest"])

tests/test_robot_case.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import sys
2+
import textwrap
3+
4+
import pytest
5+
6+
from robotpy import main
7+
8+
9+
class DummyWpilib:
10+
class RobotBase:
11+
pass
12+
13+
14+
@pytest.fixture(autouse=True)
15+
def mock_wpilib(monkeypatch):
16+
monkeypatch.setitem(sys.modules, "wpilib", DummyWpilib)
17+
18+
19+
def test_load_robot_class_exact_case(tmp_path, monkeypatch, capsys):
20+
# create correct-case file
21+
robot_py = tmp_path / "robot.py"
22+
robot_py.write_text(
23+
textwrap.dedent(
24+
"""
25+
import wpilib
26+
class MyRobot(wpilib.RobotBase):
27+
pass
28+
"""
29+
)
30+
)
31+
32+
monkeypatch.setattr(main, "robot_py_path", robot_py)
33+
34+
# Should pass (exact case)
35+
main._load_robot_class()
36+
37+
38+
def test_load_robot_class_wrong_case(tmp_path, monkeypatch, capsys):
39+
robot_py = tmp_path / "robot.py"
40+
Robot_py = tmp_path / "Robot.py"
41+
Robot_py.write_text(
42+
textwrap.dedent(
43+
"""
44+
import wpilib
45+
class MyRobot(wpilib.RobotBase):
46+
pass
47+
"""
48+
)
49+
)
50+
51+
case_insensitive_fs = robot_py.exists()
52+
53+
monkeypatch.setattr(main, "robot_py_path", robot_py)
54+
55+
with pytest.raises(SystemExit):
56+
main._load_robot_class()
57+
err = capsys.readouterr().err
58+
59+
if case_insensitive_fs:
60+
assert "must be robot.py" in err
61+
else:
62+
assert "does not exist" in err

0 commit comments

Comments
 (0)