Skip to content

Commit d6bc1d6

Browse files
committed
Fix mypy protobuf in team com
1 parent 3bed187 commit d6bc1d6

File tree

8 files changed

+88
-60
lines changed

8 files changed

+88
-60
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ doku/*
222222
/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/RobocupProtocol
223223
# Protobuf generated file
224224
/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/robocup_extension_pb2.py
225+
/bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/robocup_extension_pb2.pyi
225226

226227
# Workspace git status file from the deploy tool
227228
**/workspace_status.json

bitbots_team_communication/bitbots_team_communication/CMakeLists.txt

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,16 @@ find_package(ament_cmake_python REQUIRED)
66
find_package(bitbots_docs REQUIRED)
77
find_package(Protobuf REQUIRED)
88

9-
protobuf_generate_python(
10-
PROTO_PY bitbots_team_communication/RobocupProtocol/robocup_extension.proto)
9+
add_custom_target(${PROJECT_NAME}_generate_proto ALL)
1110

12-
add_custom_target(
13-
bitbots_team_communication ALL
14-
DEPENDS ${PROTO_PY}
15-
COMMENT "Generating protobuf")
1611
add_custom_command(
17-
TARGET bitbots_team_communication
18-
POST_BUILD
19-
COMMAND ${CMAKE_COMMAND} -E copy ${PROTO_PY}
20-
${CMAKE_SOURCE_DIR}/bitbots_team_communication
21-
COMMENT "Copying protobuf to source dir")
12+
TARGET ${PROJECT_NAME}_generate_proto
13+
COMMAND protoc
14+
--pyi_out ${CMAKE_SOURCE_DIR}/bitbots_team_communication/
15+
--python_out ${CMAKE_SOURCE_DIR}/bitbots_team_communication/
16+
--proto_path ${CMAKE_SOURCE_DIR}/bitbots_team_communication/RobocupProtocol
17+
${CMAKE_SOURCE_DIR}/bitbots_team_communication/RobocupProtocol/robocup_extension.proto
18+
COMMENT "Generating protobuf python interface including stubs")
2219

2320
enable_bitbots_docs()
2421
ament_python_install_package(${PROJECT_NAME})
@@ -50,7 +47,34 @@ if(BUILD_TESTING)
5047
endforeach()
5148

5249
find_package(ament_cmake_mypy REQUIRED)
53-
ament_mypy(CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/mypy.ini")
50+
51+
52+
# The following logic for manually filtering out the files can be removed if
53+
# https://github.com/ament/ament_lint/pull/516 is merged and released in our ROS distro
54+
55+
# Collect all .py and .pyi files
56+
file(GLOB_RECURSE PY_FILES "${CMAKE_CURRENT_LIST_DIR}/**/*.py")
57+
file(GLOB_RECURSE PYI_FILES "${CMAKE_CURRENT_LIST_DIR}/**/*.pyi")
58+
59+
# Filter out .py files if a corresponding .pyi file exists
60+
foreach(py_file IN LISTS PY_FILES)
61+
# Get the directory and basename (without extension)
62+
get_filename_component(py_dir "${py_file}" DIRECTORY)
63+
get_filename_component(py_basename "${py_file}" NAME_WE)
64+
65+
# Construct the corresponding .pyi file path
66+
set(pyi_file "${py_dir}/${py_basename}.pyi")
67+
68+
# If a corresponding .pyi file exists, remove the .py file from the list
69+
if(EXISTS "${pyi_file}")
70+
list(REMOVE_ITEM PY_FILES "${py_file}")
71+
endif()
72+
endforeach()
73+
74+
ament_mypy(
75+
CONFIG_FILE "${CMAKE_CURRENT_LIST_DIR}/mypy.ini"
76+
${PY_FILES} ${PYI_FILES}
77+
)
5478
endif()
5579

5680
ament_package()

bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/converter/robocup_protocol_converter.py

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,40 @@ class TeamColor(IntEnum):
1616
class RobocupProtocolConverter:
1717
def __init__(self, own_team_color: TeamColor):
1818
self.role_mapping = (
19-
(Proto.Role.ROLE_UNDEFINED, Strategy.ROLE_UNDEFINED),
20-
(Proto.Role.ROLE_IDLING, Strategy.ROLE_IDLING),
21-
(Proto.Role.ROLE_OTHER, Strategy.ROLE_OTHER),
22-
(Proto.Role.ROLE_STRIKER, Strategy.ROLE_STRIKER),
23-
(Proto.Role.ROLE_SUPPORTER, Strategy.ROLE_SUPPORTER),
24-
(Proto.Role.ROLE_DEFENDER, Strategy.ROLE_DEFENDER),
25-
(Proto.Role.ROLE_GOALIE, Strategy.ROLE_GOALIE),
19+
(Proto.ROLE_UNDEFINED, Strategy.ROLE_UNDEFINED),
20+
(Proto.ROLE_IDLING, Strategy.ROLE_IDLING),
21+
(Proto.ROLE_OTHER, Strategy.ROLE_OTHER),
22+
(Proto.ROLE_STRIKER, Strategy.ROLE_STRIKER),
23+
(Proto.ROLE_SUPPORTER, Strategy.ROLE_SUPPORTER),
24+
(Proto.ROLE_DEFENDER, Strategy.ROLE_DEFENDER),
25+
(Proto.ROLE_GOALIE, Strategy.ROLE_GOALIE),
2626
)
2727
self.action_mapping = (
28-
(Proto.Action.ACTION_UNDEFINED, Strategy.ACTION_UNDEFINED),
29-
(Proto.Action.ACTION_POSITIONING, Strategy.ACTION_POSITIONING),
30-
(Proto.Action.ACTION_GOING_TO_BALL, Strategy.ACTION_GOING_TO_BALL),
31-
(Proto.Action.ACTION_TRYING_TO_SCORE, Strategy.ACTION_TRYING_TO_SCORE),
32-
(Proto.Action.ACTION_WAITING, Strategy.ACTION_WAITING),
33-
(Proto.Action.ACTION_KICKING, Strategy.ACTION_KICKING),
34-
(Proto.Action.ACTION_SEARCHING, Strategy.ACTION_SEARCHING),
35-
(Proto.Action.ACTION_LOCALIZING, Strategy.ACTION_LOCALIZING),
28+
(Proto.ACTION_UNDEFINED, Strategy.ACTION_UNDEFINED),
29+
(Proto.ACTION_POSITIONING, Strategy.ACTION_POSITIONING),
30+
(Proto.ACTION_GOING_TO_BALL, Strategy.ACTION_GOING_TO_BALL),
31+
(Proto.ACTION_TRYING_TO_SCORE, Strategy.ACTION_TRYING_TO_SCORE),
32+
(Proto.ACTION_WAITING, Strategy.ACTION_WAITING),
33+
(Proto.ACTION_KICKING, Strategy.ACTION_KICKING),
34+
(Proto.ACTION_SEARCHING, Strategy.ACTION_SEARCHING),
35+
(Proto.ACTION_LOCALIZING, Strategy.ACTION_LOCALIZING),
3636
)
3737
self.side_mapping = (
38-
(Proto.OffensiveSide.SIDE_UNDEFINED, Strategy.SIDE_UNDEFINED),
39-
(Proto.OffensiveSide.SIDE_LEFT, Strategy.SIDE_LEFT),
40-
(Proto.OffensiveSide.SIDE_MIDDLE, Strategy.SIDE_MIDDLE),
41-
(Proto.OffensiveSide.SIDE_RIGHT, Strategy.SIDE_RIGHT),
38+
(Proto.SIDE_UNDEFINED, Strategy.SIDE_UNDEFINED),
39+
(Proto.SIDE_LEFT, Strategy.SIDE_LEFT),
40+
(Proto.SIDE_MIDDLE, Strategy.SIDE_MIDDLE),
41+
(Proto.SIDE_RIGHT, Strategy.SIDE_RIGHT),
4242
)
4343

4444
self.proto_to_team_data_team_mapping = {
45-
Proto.Team.UNKNOWN_TEAM: RobotRelative.ROBOT_UNDEFINED,
46-
Proto.Team.BLUE: RobotRelative.ROBOT_BLUE,
47-
Proto.Team.RED: RobotRelative.ROBOT_RED,
45+
Proto.UNKNOWN_TEAM: RobotRelative.ROBOT_UNDEFINED,
46+
Proto.BLUE: RobotRelative.ROBOT_BLUE,
47+
Proto.RED: RobotRelative.ROBOT_RED,
4848
}
4949
self.state_to_proto_team_mapping = {
50-
RobotAttributes.TEAM_OWN: Proto.Team.RED if own_team_color == TeamColor.RED else Proto.Team.BLUE,
51-
RobotAttributes.TEAM_OPPONENT: Proto.Team.BLUE if own_team_color == TeamColor.RED else Proto.Team.RED,
52-
RobotAttributes.TEAM_UNKNOWN: Proto.Team.UNKNOWN_TEAM,
50+
RobotAttributes.TEAM_OWN: Proto.RED if own_team_color == TeamColor.RED else Proto.BLUE,
51+
RobotAttributes.TEAM_OPPONENT: Proto.BLUE if own_team_color == TeamColor.RED else Proto.RED,
52+
RobotAttributes.TEAM_UNKNOWN: Proto.UNKNOWN_TEAM,
5353
}
5454

5555
proto_to_team_data_mappings = {

bitbots_team_communication/bitbots_team_communication/bitbots_team_communication/converter/state_to_message_converter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ def convert(
2525
) -> Proto.Message:
2626
def convert_gamestate(gamestate: Optional[GameState], message: Proto.Message):
2727
if gamestate is not None and is_still_valid_checker(gamestate.header.stamp):
28-
message.state = Proto.State.PENALISED if gamestate.penalized else Proto.State.UNPENALISED
28+
message.state = Proto.PENALISED if gamestate.penalized else Proto.UNPENALISED
2929
else:
30-
message.state = Proto.State.UNKNOWN_STATE
30+
message.state = Proto.UNKNOWN_STATE
3131

3232
return message
3333

bitbots_team_communication/bitbots_team_communication/mypy.ini

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
[mypy]
44
check_untyped_defs = True
55
ignore_missing_imports = True
6-
exclude = .*_pb2\.py
6+
7+
# Ignore var-annotations because it is in autogenerated code from protobuf
8+
disable_error_code = var-annotated

bitbots_team_communication/bitbots_team_communication/test/converter/test_message_to_team_data_converter.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ def convert_from_message(message: Proto.Message, team_data: TeamData | None = No
6060

6161
@pytest.fixture
6262
def message_with_strategy(message) -> Proto.Message:
63-
message.role = Proto.Role.ROLE_STRIKER
64-
message.action = Proto.Action.ACTION_KICKING
65-
message.offensive_side = Proto.OffensiveSide.SIDE_RIGHT
63+
message.role = Proto.ROLE_STRIKER
64+
message.action = Proto.ACTION_KICKING
65+
message.offensive_side = Proto.SIDE_RIGHT
6666

6767
return message
6868

@@ -111,9 +111,9 @@ def message() -> Proto.Message:
111111
def robot_message(player_id, is_own_team):
112112
robot = Proto.Robot()
113113
robot.player_id = player_id
114-
robot.team = own_team_id
114+
robot.team = own_team_id # type: ignore[assignment]
115115
if not is_own_team:
116-
robot.team = own_team_id + 1
116+
robot.team = own_team_id + 1 # type: ignore[assignment]
117117

118118
set_position(robot.position)
119119
set_covariance_matrix(robot.covariance)

bitbots_team_communication/bitbots_team_communication/test/converter/test_robocup_protocol_converter.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@ def test_setup_of_mappings(snapshot):
2020

2121
def test_setup_of_team_color_mapping(snapshot):
2222
converter = protocol_converter()
23-
assert converter.state_to_proto_team_mapping[RobotAttributes.TEAM_OWN] == Proto.Team.BLUE
24-
assert converter.state_to_proto_team_mapping[RobotAttributes.TEAM_OPPONENT] == Proto.Team.RED
25-
assert converter.state_to_proto_team_mapping[RobotAttributes.TEAM_UNKNOWN] == Proto.Team.UNKNOWN_TEAM
23+
assert converter.state_to_proto_team_mapping[RobotAttributes.TEAM_OWN] == Proto.BLUE
24+
assert converter.state_to_proto_team_mapping[RobotAttributes.TEAM_OPPONENT] == Proto.RED
25+
assert converter.state_to_proto_team_mapping[RobotAttributes.TEAM_UNKNOWN] == Proto.UNKNOWN_TEAM
2626
assert converter.proto_to_team_data_team_mapping == snapshot
2727

2828

bitbots_team_communication/bitbots_team_communication/test/converter/test_state_to_message_converter.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from typing import Optional
12
from unittest.mock import Mock
23

34
import numpy
@@ -44,23 +45,23 @@ def test_convert_gamestate(state_with_gamestate):
4445

4546
gamestate.penalized = False
4647
result = convert_to_message(state_with_gamestate)
47-
assert result.state == Proto.State.UNPENALISED
48+
assert result.state == Proto.UNPENALISED
4849

4950
gamestate.penalized = True
5051
result = convert_to_message(state_with_gamestate)
51-
assert result.state == Proto.State.PENALISED
52+
assert result.state == Proto.PENALISED
5253

5354
assert validity_checker_valid.call_count == 2
5455
validity_checker_valid.assert_called_with(gamestate.header.stamp)
5556

5657

5758
def test_convert_gamestate_expired_headers(state_with_gamestate):
5859
message = Proto.Message()
59-
message.state = Proto.State.UNPENALISED
60+
message.state = Proto.UNPENALISED
6061

6162
result = convert_to_message(state_with_gamestate, message, is_state_expired=True)
6263

63-
assert result.state == Proto.State.UNKNOWN_STATE
64+
assert result.state == Proto.UNKNOWN_STATE
6465

6566

6667
def test_convert_current_pose(snapshot, state_with_current_pose):
@@ -164,22 +165,22 @@ def test_convert_obstacles_to_robots_expired_headers(state_with_seen_robots):
164165
def test_convert_strategy(state_with_strategy):
165166
result = convert_to_message(state_with_strategy)
166167

167-
assert result.role == Proto.Role.ROLE_STRIKER
168-
assert result.action == Proto.Action.ACTION_KICKING
169-
assert result.offensive_side == Proto.OffensiveSide.SIDE_RIGHT
168+
assert result.role == Proto.ROLE_STRIKER
169+
assert result.action == Proto.ACTION_KICKING
170+
assert result.offensive_side == Proto.SIDE_RIGHT
170171

171172
validity_checker_valid.assert_called_with(state_with_strategy.strategy_time)
172173

173174

174175
def test_convert_strategy_expired_headers(state_with_strategy):
175176
message = Proto.Message()
176-
message.role = Proto.Role.ROLE_DEFENDER
177+
message.role = Proto.ROLE_DEFENDER
177178

178179
result = convert_to_message(state_with_strategy, message, is_state_expired=True)
179180

180-
assert result.role == Proto.Role.ROLE_DEFENDER
181-
assert result.action == Proto.Action.ACTION_UNDEFINED
182-
assert result.offensive_side == Proto.OffensiveSide.SIDE_UNDEFINED
181+
assert result.role == Proto.ROLE_DEFENDER
182+
assert result.action == Proto.ACTION_UNDEFINED
183+
assert result.offensive_side == Proto.SIDE_UNDEFINED
183184

184185

185186
def test_convert_time_to_ball(state_with_time_to_ball):
@@ -208,7 +209,7 @@ def test_convert_time_to_ball_expired_headers(state_with_time_to_ball):
208209
assert pytest.approx(result.time_to_ball) == 9999.0
209210

210211

211-
def convert_to_message(team_data_state, message: Proto.Message = None, is_state_expired=False):
212+
def convert_to_message(team_data_state, message: Optional[Proto.Message] = None, is_state_expired=False):
212213
message = message if message else Proto.Message()
213214
validity_checker = validity_checker_expired if is_state_expired else validity_checker_valid
214215
return RobocupProtocolConverter(own_team_color).convert_to_message(team_data_state, message, validity_checker)

0 commit comments

Comments
 (0)