Skip to content

Commit 2f309e4

Browse files
authored
Python formatting tools (#26)
* Formatting fixes * Configuration formatting * PR fixes * Formatting * Make module names clearer
1 parent a886a38 commit 2f309e4

18 files changed

+321
-143
lines changed

.github/workflows/run-tests.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ jobs:
3939
- name: Install zbar library
4040
run: sudo apt-get install libzbar0
4141

42+
# Run linters and formatters
43+
- name: Linters and formatters
44+
run: |
45+
black --check .
46+
flake8 .
47+
pylint .
48+
4249
# Install dependencies and run tests with PyTest
4350
- name: Run PyTest
4451
run: pytest -vv

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
# Python
66
__pycache__/
7-
.pytest_cache/
87
venv/
98

109
# Logging
11-
*log*
10+
logs/

README.md

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,3 @@
33
Common code across WARG repositories.
44

55
Follow the [instructions](https://uwarg-docs.atlassian.net/l/cp/2a6u0duY).
6-
7-
## comms
8-
9-
Python serialization and deserialization for Autonomy.
10-
11-
## camera
12-
13-
Python video ingest from camera device.
14-
15-
## mavlink
16-
17-
Connection to drone using the MAVLink protocol.
18-
19-
## qr
20-
21-
QR scanning and text output.

camera/modules/camera_device.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
2-
Camera device using OpenCV
2+
Camera device using OpenCV.
33
"""
4+
45
import sys
56
import time
67

@@ -10,15 +11,15 @@
1011

1112
class CameraDevice:
1213
"""
13-
Wrapper for camera
14+
Wrapper for camera.
1415
"""
1516

16-
def __init__(self, name: "int | str", save_nth_image: int = 0, save_name: str = ""):
17+
def __init__(self, name: "int | str", save_nth_image: int = 0, save_name: str = "") -> None:
1718
"""
18-
name: Device name or index (e.g. /dev/video0 )
19+
name: Device name or index (e.g. /dev/video0 ).
1920
(optional) save_nth_image: For debugging, saves every nth image.
2021
A value of 0 indicates no images should be saved
21-
(optional) save_name: For debugging, file name for saved images
22+
(optional) save_name: For debugging, file name for saved images.
2223
"""
2324
self.__camera = cv2.VideoCapture(name)
2425
assert self.__camera.isOpened()
@@ -32,7 +33,10 @@ def __init__(self, name: "int | str", save_nth_image: int = 0, save_name: str =
3233
if save_name != "":
3334
self.__filename_prefix = save_name + "_" + str(int(time.time())) + "_"
3435

35-
def __del__(self):
36+
def __del__(self) -> None:
37+
"""
38+
Destructor.
39+
"""
3640
self.__camera.release()
3741

3842
def get_image(self) -> "tuple[bool, np.ndarray]":
@@ -41,9 +45,9 @@ def get_image(self) -> "tuple[bool, np.ndarray]":
4145
"""
4246
result, image = self.__camera.read()
4347
if not result:
44-
return result, image
48+
return False, None
4549

46-
if self.__divisor != 0:
50+
if self.__filename_prefix != "" and self.__divisor != 0:
4751
if self.__counter % self.__divisor == 0:
4852
filename = self.__filename_prefix + str(self.__counter) + ".png"
4953
cv2.imwrite(filename, image)

camera/test_camera.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,20 @@
22
Test camera physically.
33
"""
44

5+
import pathlib
6+
57
import cv2
68

79
from camera.modules.camera_device import CameraDevice
810

911

10-
IMAGE_LOG_PREFIX = "log_image"
12+
IMAGE_LOG_PREFIX = pathlib.Path("logs", "log_image")
1113

1214

13-
if __name__ == "__main__":
15+
def main() -> int:
16+
"""
17+
Main function.
18+
"""
1419
device = CameraDevice(0, 100, IMAGE_LOG_PREFIX)
1520

1621
while True:
@@ -24,7 +29,15 @@
2429
cv2.imshow("Camera", image)
2530

2631
# Delay for 1 ms
27-
if cv2.waitKey(1) & 0xFF == ord('q'):
32+
if cv2.waitKey(1) & 0xFF == ord("q"):
2833
break
2934

35+
return 0
36+
37+
38+
if __name__ == "__main__":
39+
result_main = main()
40+
if result_main < 0:
41+
print(f"ERROR: Status code: {result_main}")
42+
3043
print("Done!")

camera_qr_example.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
from qr.modules import qr_scanner
99

1010

11-
if __name__ == "__main__":
12-
11+
def main() -> int:
12+
"""
13+
Main function.
14+
"""
1315
camera = camera_device.CameraDevice(0, 0, "")
1416

1517
text = ""
@@ -30,4 +32,12 @@
3032

3133
print(text)
3234

35+
return 0
36+
37+
38+
if __name__ == "__main__":
39+
result_main = main()
40+
if result_main < 0:
41+
print(f"ERROR: Status code: {result_main}")
42+
3343
print("Done!")

kml/modules/ground_locations_to_kml.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Module to convert ground locations list to kml document.
33
"""
4+
45
import pathlib
56
import time
67

@@ -9,9 +10,11 @@
910
from . import location_ground
1011

1112

12-
def ground_locations_to_kml(ground_locations: "list[location_ground.LocationGround]",
13-
document_name_prefix: str,
14-
save_directory: pathlib.Path) -> "tuple[bool, pathlib.Path | None]":
13+
def ground_locations_to_kml(
14+
ground_locations: "list[location_ground.LocationGround]",
15+
document_name_prefix: str,
16+
save_directory: pathlib.Path,
17+
) -> "tuple[bool, pathlib.Path | None]":
1518
"""
1619
Generates KML file from a list of ground locations.
1720

kml/modules/location_ground.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Class to use instead of tuple for coordinates.
33
"""
44

5+
56
class LocationGround:
67
"""
78
LocationGround class represents a geographical ground location with
@@ -15,9 +16,10 @@ class LocationGround:
1516
Methods:
1617
__init__(name, latitude, longitude): Initializes a LocationGround object.
1718
__eq__(other): Checks if two LocationGround objects are equal.
18-
__repr__(): Returns a string representation of the LocationGround object.
19+
__str__(): Returns a string representation of the LocationGround object.
1920
"""
20-
def __init__(self, name: str, latitude: float, longitude: float):
21+
22+
def __init__(self, name: str, latitude: float, longitude: float) -> None:
2123
"""
2224
Constructor for the LocationGround object.
2325
@@ -46,9 +48,10 @@ def __eq__(self, other: "LocationGround") -> bool:
4648
and self.longitude == other.longitude
4749
)
4850

49-
def __repr__(self) -> str:
51+
def __str__(self) -> str:
5052
"""
51-
String representation
53+
To string.
5254
"""
53-
return \
55+
return (
5456
f"LocationGround: {self.name}, latitude: {self.latitude}, longitude: {self.longitude}"
57+
)

kml/test_ground_locations_to_kml.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""
22
Test Process.
33
"""
4+
45
import pathlib
56

67
import pytest
@@ -13,8 +14,13 @@
1314
EXPECTED_KML_DOCUMENT_PATH = pathlib.Path(PARENT_DIRECTORY, "expected_document.kml")
1415

1516

17+
# Test functions use test fixture signature names and access class privates
18+
# No enable
19+
# pylint: disable=protected-access,redefined-outer-name
20+
21+
1622
@pytest.fixture
17-
def locations():
23+
def locations() -> "list[location_ground.LocationGround]": # type: ignore
1824
"""
1925
List of LocationGround.
2026
"""
@@ -25,8 +31,9 @@ def locations():
2531
]
2632

2733

28-
def test_locations_to_kml_with_save_path(locations: "list[location_ground.LocationGround]",
29-
tmp_path: pathlib.Path):
34+
def test_locations_to_kml_with_save_path(
35+
locations: "list[location_ground.LocationGround]", tmp_path: pathlib.Path
36+
) -> None:
3037
"""
3138
Basic test case to save KML to the correct path when provided.
3239
"""
@@ -51,5 +58,6 @@ def test_locations_to_kml_with_save_path(locations: "list[location_ground.Locati
5158
assert actual_kml_file_path.suffix == ".kml"
5259

5360
# Compare the contents of the generated KML file with the static KML file
54-
assert actual_kml_file_path.read_text(encoding="utf-8") \
55-
== EXPECTED_KML_DOCUMENT_PATH.read_text(encoding="utf-8")
61+
assert actual_kml_file_path.read_text(encoding="utf-8") == EXPECTED_KML_DOCUMENT_PATH.read_text(
62+
encoding="utf-8"
63+
)

mavlink/modules/drone_odometry.py

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
"""
22
Position and orientation of drone.
33
"""
4+
45
import math
56

67

7-
# Basically a struct
8-
# pylint: disable=too-few-public-methods
98
class DronePosition:
109
"""
1110
WGS 84 following ISO 6709 (latitude before longitude).
1211
"""
12+
1313
__create_key = object()
1414

1515
@classmethod
16-
def create(cls,
17-
latitude: "float | None",
18-
longitude: "float | None",
19-
altitude: "float | None") -> "tuple[bool, DronePosition | None]":
16+
def create(
17+
cls, latitude: "float | None", longitude: "float | None", altitude: "float | None"
18+
) -> "tuple[bool, DronePosition | None]":
2019
"""
2120
latitude, longitude in decimal degrees.
2221
altitude in metres.
@@ -35,11 +34,9 @@ def create(cls,
3534

3635
return True, DronePosition(cls.__create_key, latitude, longitude, altitude)
3736

38-
def __init__(self,
39-
class_private_create_key,
40-
latitude: float,
41-
longitude: float,
42-
altitude: float):
37+
def __init__(
38+
self, class_private_create_key: object, latitude: float, longitude: float, altitude: float
39+
) -> None:
4340
"""
4441
Private constructor, use create() method.
4542
"""
@@ -49,25 +46,21 @@ def __init__(self,
4946
self.longitude = longitude
5047
self.altitude = altitude
5148

52-
# pylint: enable=too-few-public-methods
53-
5449

55-
# Basically a struct
56-
# pylint: disable=too-few-public-methods
5750
class DroneOrientation:
5851
"""
5952
Yaw, pitch, roll following NED system (x forward, y right, z down).
6053
Specifically, intrinsic (Tait-Bryan) rotations in the zyx/3-2-1 order.
6154
"""
55+
6256
__create_key = object()
6357

6458
@classmethod
6559
# Required for checks
6660
# pylint: disable-next=too-many-return-statements
67-
def create(cls,
68-
yaw: "float | None",
69-
pitch: "float | None",
70-
roll: "float | None") -> "tuple[bool, DroneOrientation | None]":
61+
def create(
62+
cls, yaw: "float | None", pitch: "float | None", roll: "float | None"
63+
) -> "tuple[bool, DroneOrientation | None]":
7164
"""
7265
yaw, pitch, roll in radians.
7366
"""
@@ -91,7 +84,9 @@ def create(cls,
9184

9285
return True, DroneOrientation(cls.__create_key, yaw, pitch, roll)
9386

94-
def __init__(self, class_private_create_key, yaw: float, pitch: float, roll: float):
87+
def __init__(
88+
self, class_private_create_key: object, yaw: float, pitch: float, roll: float
89+
) -> None:
9590
"""
9691
Private constructor, use create() method.
9792
"""
@@ -101,21 +96,18 @@ def __init__(self, class_private_create_key, yaw: float, pitch: float, roll: flo
10196
self.pitch = pitch
10297
self.roll = roll
10398

104-
# pylint: enable=too-few-public-methods
105-
10699

107-
# Basically a struct
108-
# pylint: disable=too-few-public-methods
109100
class DroneOdometry:
110101
"""
111102
Wrapper for DronePosition and DroneOrientation.
112103
"""
104+
113105
__create_key = object()
114106

115107
@classmethod
116-
def create(cls,
117-
position: DronePosition,
118-
orientation: DroneOrientation) -> "tuple[bool, DroneOdometry | None]":
108+
def create(
109+
cls, position: DronePosition, orientation: DroneOrientation
110+
) -> "tuple[bool, DroneOdometry | None]":
119111
"""
120112
Position and orientation in one class.
121113
"""
@@ -127,10 +119,12 @@ def create(cls,
127119

128120
return True, DroneOdometry(cls.__create_key, position, orientation)
129121

130-
def __init__(self,
131-
class_private_create_key,
132-
position: DronePosition,
133-
orientation: DroneOrientation):
122+
def __init__(
123+
self,
124+
class_private_create_key: object,
125+
position: DronePosition,
126+
orientation: DroneOrientation,
127+
) -> None:
134128
"""
135129
Private constructor, use create() method.
136130
"""

0 commit comments

Comments
 (0)