sr-robot3 2025.0.1__py3-none-any.whl → 2026.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sr/robot3/_version.py CHANGED
@@ -1,16 +1,34 @@
1
- # file generated by setuptools_scm
1
+ # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
3
13
  TYPE_CHECKING = False
4
14
  if TYPE_CHECKING:
5
- from typing import Tuple, Union
15
+ from typing import Tuple
16
+ from typing import Union
17
+
6
18
  VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
7
20
  else:
8
21
  VERSION_TUPLE = object
22
+ COMMIT_ID = object
9
23
 
10
24
  version: str
11
25
  __version__: str
12
26
  __version_tuple__: VERSION_TUPLE
13
27
  version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '2026.0.2'
32
+ __version_tuple__ = version_tuple = (2026, 0, 2)
14
33
 
15
- __version__ = version = '2025.0.1'
16
- __version_tuple__ = version_tuple = (2025, 0, 1)
34
+ __commit_id__ = commit_id = None
sr/robot3/robot.py CHANGED
@@ -8,7 +8,7 @@ import time
8
8
  from pathlib import Path
9
9
  from socket import socket
10
10
  from types import MappingProxyType
11
- from typing import Mapping, Optional
11
+ from typing import Mapping, Optional, final
12
12
 
13
13
  from . import game_specific, timeout
14
14
  from ._version import __version__
@@ -23,12 +23,15 @@ from .power_board import Note, PowerBoard
23
23
  from .raw_serial import RawSerial
24
24
  from .servo_board import ServoBoard
25
25
  from .simulator.time_server import TimeServer
26
- from .utils import IN_SIMULATOR, ensure_atexit_on_term, obtain_lock, singular
26
+ from .utils import (
27
+ IN_SIMULATOR, FinalMeta, ensure_atexit_on_term, obtain_lock, singular,
28
+ )
27
29
 
28
30
  logger = logging.getLogger(__name__)
29
31
 
30
32
 
31
- class Robot:
33
+ @final
34
+ class Robot(metaclass=FinalMeta):
32
35
  """
33
36
  The main robot class that provides access to all the boards.
34
37
 
@@ -444,7 +447,7 @@ class Robot:
444
447
  self.power_board._run_led.flash()
445
448
  self.kch._flash_start()
446
449
 
447
- while not start_button_pressed() or remote_start_pressed():
450
+ while not (start_button_pressed() or remote_start_pressed()):
448
451
  self.sleep(0.1)
449
452
  logger.info("Start signal received; continuing.")
450
453
  if not self._no_powerboard:
@@ -6,6 +6,7 @@ and for handling port timeouts and disconnections.
6
6
  """
7
7
  from __future__ import annotations
8
8
 
9
+ import atexit
9
10
  import logging
10
11
  import sys
11
12
  import threading
@@ -106,6 +107,8 @@ class SerialWrapper:
106
107
  do_not_open=True,
107
108
  )
108
109
 
110
+ atexit.register(self._disconnect, quiet=True)
111
+
109
112
  def start(self) -> None:
110
113
  """
111
114
  Helper method to open the serial port.
@@ -230,7 +233,7 @@ class SerialWrapper:
230
233
  )
231
234
  return True
232
235
 
233
- def _disconnect(self) -> None:
236
+ def _disconnect(self, quiet: bool = False) -> None:
234
237
  """
235
238
  Close the class's serial port.
236
239
 
@@ -238,9 +241,10 @@ class SerialWrapper:
238
241
  The serial port will be reopened on the next message.
239
242
  """
240
243
  self.serial.close()
241
- logger.warning(
242
- f'Board {self.identity.board_type}:{self.identity.asset_tag} disconnected'
243
- )
244
+ if not quiet:
245
+ logger.warning(
246
+ f'Board {self.identity.board_type}:{self.identity.asset_tag} disconnected'
247
+ )
244
248
 
245
249
  def set_identity(self, identity: BoardIdentity) -> None:
246
250
  """
@@ -1,3 +1,4 @@
1
+ import atexit
1
2
  import struct
2
3
 
3
4
  import cv2
@@ -39,6 +40,8 @@ class WebotsRemoteCameraSource(FrameSource):
39
40
  self.image_size = tuple(map(int, response.split(b":")))
40
41
  assert len(self.image_size) == 2, f"Invalid image dimensions: {self.image_size}"
41
42
 
43
+ atexit.register(self.close)
44
+
42
45
  def read(self, fresh: bool = True) -> NDArray:
43
46
  """
44
47
  The method for getting a new frame.
sr/robot3/utils.py CHANGED
@@ -7,7 +7,7 @@ import signal
7
7
  import socket
8
8
  from abc import ABC, abstractmethod
9
9
  from types import FrameType
10
- from typing import Any, Mapping, NamedTuple, Optional, TypeVar
10
+ from typing import Any, Mapping, NamedTuple, Optional, Type, TypeVar
11
11
 
12
12
  from serial.tools.list_ports import comports
13
13
  from serial.tools.list_ports_common import ListPortInfo
@@ -77,6 +77,18 @@ class Board(ABC):
77
77
  pass # pragma: no cover
78
78
 
79
79
 
80
+ class FinalMeta(type):
81
+ """
82
+ A meta class which ensures a given class cannot be subclassed.
83
+
84
+ It's recommended to additionally use typing.final.
85
+ """
86
+ def __new__(cls, name: str, bases: tuple, classdict: dict) -> Type:
87
+ if bases:
88
+ raise TypeError(f"{name} cannot be sub-classed.")
89
+ return super().__new__(cls, name, bases, dict(classdict))
90
+
91
+
80
92
  def map_to_int(
81
93
  x: float,
82
94
  in_min: float,
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: sr-robot3
3
- Version: 2025.0.1
3
+ Version: 2026.0.2
4
4
  Summary: Student Robotics API for Python 3
5
5
  Author-email: Student Robotics <kit-team@studentrobotics.org>
6
6
  License: MIT License
@@ -34,11 +34,11 @@ Classifier: Operating System :: OS Independent
34
34
  Classifier: Development Status :: 5 - Production/Stable
35
35
  Classifier: Typing :: Typed
36
36
  Classifier: Topic :: Education
37
- Requires-Python: >=3.8
37
+ Requires-Python: >=3.9
38
38
  Description-Content-Type: text/markdown
39
39
  License-File: LICENSE
40
40
  Requires-Dist: pyserial<4,>=3
41
- Requires-Dist: april-vision==2.2.0
41
+ Requires-Dist: april_vision==3.0.0
42
42
  Requires-Dist: paho-mqtt<3,>=2
43
43
  Requires-Dist: pydantic<2,>=1.9.1
44
44
  Requires-Dist: typing-extensions; python_version < "3.10"
@@ -46,15 +46,15 @@ Requires-Dist: tomli<3,>=2.0.1; python_version < "3.11"
46
46
  Provides-Extra: dev
47
47
  Requires-Dist: flake8; extra == "dev"
48
48
  Requires-Dist: isort; extra == "dev"
49
+ Requires-Dist: mypy<2,>=1.7; extra == "dev"
49
50
  Requires-Dist: build; extra == "dev"
50
51
  Requires-Dist: types-pyserial; extra == "dev"
51
52
  Requires-Dist: pytest; extra == "dev"
52
53
  Requires-Dist: pytest-cov; extra == "dev"
53
54
  Requires-Dist: paho-mqtt<3,>=2; extra == "dev"
54
- Requires-Dist: mypy==1.10.0; python_version < "3.9" and extra == "dev"
55
- Requires-Dist: mypy<2,>=1.7; python_version >= "3.9" and extra == "dev"
56
55
  Provides-Extra: vision
57
- Requires-Dist: opencv-python-headless<5,>=4; extra == "vision"
56
+ Requires-Dist: opencv-python-headless<5,>=4.10; extra == "vision"
57
+ Dynamic: license-file
58
58
 
59
59
  # sr-robot3
60
60
 
@@ -1,5 +1,5 @@
1
1
  sr/robot3/__init__.py,sha256=lW7j65ruMEkRNJjZzp8929TefPMaMhqXzpsGPJqMkRs,1476
2
- sr/robot3/_version.py,sha256=W_pY-syVlxbrrWCxx4QuswILJ7DO3X_xTciDllu-18A,417
2
+ sr/robot3/_version.py,sha256=AMq-4theMLzodgpl_peU-w6WdJzeuxX6ZkKEnpto0vE,710
3
3
  sr/robot3/arduino.py,sha256=9rGsvGDb1JoHB4c7W61R16Y3eb0-UZ9TE49Qu7BJIZE,16934
4
4
  sr/robot3/astoria.py,sha256=0EIXoxvs1glkGuzLDYG7HptKucc8q7sdWAQiu96NG24,8547
5
5
  sr/robot3/camera.py,sha256=b2r8-ttQgLqbMv9BI6qWb5sHjeg4Zb5VrGo2uWMYGd8,8686
@@ -13,17 +13,17 @@ sr/robot3/mqtt.py,sha256=1xKQ0uwkupURWFXrvsD75TE-GlltfbrpVNqoabgmsrc,6679
13
13
  sr/robot3/power_board.py,sha256=3Skbc7kmG1pr2K6n94POkMOXT4jzbOiYCz2cb60CWv8,17734
14
14
  sr/robot3/py.typed,sha256=dXL7b_5DnfZ_09rOcxu7D-0rT56DRm26uGUohPJOPQc,94
15
15
  sr/robot3/raw_serial.py,sha256=rdh0lyS9tJDyHbAZKyJSO8lKvdJ3-_iZzvmUSOdbo08,7368
16
- sr/robot3/robot.py,sha256=cqUrPFver_yAjdTPBLqPjsoliSuNdiHn7RGrpXLsuMA,15888
17
- sr/robot3/serial_wrapper.py,sha256=CDRVFbIILf4ahiToIHrVf02hz_GXpFeazDHdw3rGgX0,9327
16
+ sr/robot3/robot.py,sha256=Z_HTnw7cg1WSEFSvXKDxnebzkT8eQkS15Efn7m9DaNs,15945
17
+ sr/robot3/serial_wrapper.py,sha256=QLf56KkrqZ737aiYQKv0rU6HlMuE4azJHxanYVKsCUk,9451
18
18
  sr/robot3/servo_board.py,sha256=1GppUoqdx9wUA551bO95dEbtCGdzS10twv8OZ3S6t8U,12505
19
19
  sr/robot3/timeout.py,sha256=qBPCOwnOW9h0fLnL-peraO9RsaKWc92TcTYNgyTzo_g,2678
20
- sr/robot3/utils.py,sha256=dA2WyB73hnw41jLkOpk6ail7mfrW3oxKU0KrpQuHv1Y,9146
20
+ sr/robot3/utils.py,sha256=BT1xhCQDdjeP0VyNWOiqaqhRW1jZu7pYkUdeFVbHwII,9534
21
21
  sr/robot3/calibrations/__init__.py,sha256=TTL-lkU5tj3EszSEInRTftNvX5rsMyRUSHf12RlJ4QY,130
22
22
  sr/robot3/simulator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- sr/robot3/simulator/camera.py,sha256=thenTnlyHzHrosUg9juUSfYCs2U4dfkS7vFoto1b3_k,3138
23
+ sr/robot3/simulator/camera.py,sha256=0t5PxnzZtFhRCumCJcbhjIxMBVvJrg3KJuvWQtG_sH0,3189
24
24
  sr/robot3/simulator/time_server.py,sha256=MwFJM7p3vqf4balmGwIMXcCLBVJQgnq2X4gY_agalwc,2859
25
- sr_robot3-2025.0.1.dist-info/LICENSE,sha256=d9EjkBp2jG1JOJ3zKfKRwBtPe1nhh1VByrw4iH3A9WA,1101
26
- sr_robot3-2025.0.1.dist-info/METADATA,sha256=86E_LEKeDlmczV4MUYwPGMK4FVU-gnfn0LSI32ZhzA4,5322
27
- sr_robot3-2025.0.1.dist-info/WHEEL,sha256=UvcQYKBHoFqaQd6LKyqHw9fxEolWLQnlzP0h_LgJAfI,91
28
- sr_robot3-2025.0.1.dist-info/top_level.txt,sha256=XFzWuC7umCVdV-O6IuC9Rl0qehvEC-U34M9WJ2-2h3E,3
29
- sr_robot3-2025.0.1.dist-info/RECORD,,
25
+ sr_robot3-2026.0.2.dist-info/licenses/LICENSE,sha256=d9EjkBp2jG1JOJ3zKfKRwBtPe1nhh1VByrw4iH3A9WA,1101
26
+ sr_robot3-2026.0.2.dist-info/METADATA,sha256=tiRMOoyCppnqYya5wYh3tzGZAakmHJNFzBNY4zszSNQ,5248
27
+ sr_robot3-2026.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
28
+ sr_robot3-2026.0.2.dist-info/top_level.txt,sha256=XFzWuC7umCVdV-O6IuC9Rl0qehvEC-U34M9WJ2-2h3E,3
29
+ sr_robot3-2026.0.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.0.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5