Skip to content

Commit 341d8e0

Browse files
authored
Merge pull request #517 from ianmcorvidae/pylint-wrangling
Pylint wrangling
2 parents 0528a6f + 9b59431 commit 341d8e0

12 files changed

Lines changed: 73 additions & 54 deletions

File tree

meshtastic/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1260,7 +1260,7 @@ def initParser():
12601260
help="Request telemetry from a node. "
12611261
"You need pass the destination ID as argument with '--dest'. "
12621262
"For repeaters, the nodeNum is required.",
1263-
action="store_true",
1263+
action="store_true",
12641264
)
12651265

12661266
parser.add_argument(

meshtastic/ble_interface.py

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import logging
44
import time
55
import struct
6+
import asyncio
67
from threading import Thread, Event
7-
from meshtastic.mesh_interface import MeshInterface
8-
from meshtastic.util import our_exit
98
from bleak import BleakScanner, BleakClient
10-
import asyncio
119

10+
from meshtastic.mesh_interface import MeshInterface
11+
from meshtastic.util import our_exit
1212

1313
SERVICE_UUID = "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
1414
TORADIO_UUID = "f75c76d2-129e-4dad-a1dd-7866124401e7"
@@ -17,13 +17,14 @@
1717

1818

1919
class BLEInterface(MeshInterface):
20+
"""MeshInterface using BLE to connect to devices"""
2021
class BLEError(Exception):
22+
"""An exception class for BLE errors"""
2123
def __init__(self, message):
2224
self.message = message
2325
super().__init__(self.message)
2426

25-
26-
class BLEState():
27+
class BLEState(): # pylint: disable=C0115
2728
THREADS = False
2829
BLE = False
2930
MESH = False
@@ -69,13 +70,14 @@ def __init__(self, address, noProto = False, debugOut = None):
6970
self.client.start_notify(FROMNUM_UUID, self.from_num_handler)
7071

7172

72-
async def from_num_handler(self, _, b):
73+
async def from_num_handler(self, _, b): # pylint: disable=C0116
7374
from_num = struct.unpack('<I', bytes(b))[0]
7475
logging.debug(f"FROMNUM notify: {from_num}")
7576
self.should_read = True
7677

7778

7879
def scan(self):
80+
"Scan for available BLE devices"
7981
with BLEClient() as client:
8082
return [
8183
(x[0], x[1]) for x in (client.discover(
@@ -86,27 +88,32 @@ def scan(self):
8688

8789

8890
def find_device(self, address):
91+
"Find a device by address"
8992
meshtastic_devices = self.scan()
9093

91-
addressed_devices = list(filter(lambda x: address == x[1].local_name or address == x[0].name, meshtastic_devices))
94+
addressed_devices = list(filter(lambda x: address in (x[1].local_name, x[0].name), meshtastic_devices))
9295
# If nothing is found try on the address
9396
if len(addressed_devices) == 0:
94-
addressed_devices = list(filter(lambda x: BLEInterface._sanitize_address(address) == BLEInterface._sanitize_address(x[0].address), meshtastic_devices))
97+
addressed_devices = list(filter(
98+
lambda x: BLEInterface._sanitize_address(address) == BLEInterface._sanitize_address(x[0].address),
99+
meshtastic_devices))
95100

96101
if len(addressed_devices) == 0:
97102
raise BLEInterface.BLEError(f"No Meshtastic BLE peripheral with identifier or address '{address}' found. Try --ble-scan to find it.")
98103
if len(addressed_devices) > 1:
99104
raise BLEInterface.BLEError(f"More than one Meshtastic BLE peripheral with identifier or address '{address}' found.")
100105
return addressed_devices[0][0]
101106

102-
def _sanitize_address(address):
107+
def _sanitize_address(address): # pylint: disable=E0213
108+
"Standardize BLE address by removing extraneous characters and lowercasing"
103109
return address \
104110
.replace("-", "") \
105111
.replace("_", "") \
106112
.replace(":", "") \
107113
.lower()
108114

109115
def connect(self, address):
116+
"Connect to a device by address"
110117
device = self.find_device(address)
111118
client = BLEClient(device.address)
112119
client.connect()
@@ -156,13 +163,14 @@ def close(self):
156163
if self.state.THREADS:
157164
self._receiveThread_started.clear()
158165
self._receiveThread_stopped.wait(5)
159-
166+
160167
if self.state.BLE:
161168
self.client.disconnect()
162169
self.client.close()
163170

164171

165172
class BLEClient():
173+
"""Client for managing connection to a BLE device"""
166174
def __init__(self, address = None, **kwargs):
167175
self._eventThread = Thread(target = self._run_event_loop)
168176
self._eventThread_started = Event()
@@ -177,47 +185,46 @@ def __init__(self, address = None, **kwargs):
177185
self.bleak_client = BleakClient(address, **kwargs)
178186

179187

180-
def discover(self, **kwargs):
188+
def discover(self, **kwargs): # pylint: disable=C0116
181189
return self.async_await(BleakScanner.discover(**kwargs))
182190

183-
def pair(self, **kwargs):
191+
def pair(self, **kwargs): # pylint: disable=C0116
184192
return self.async_await(self.bleak_client.pair(**kwargs))
185193

186-
def connect(self, **kwargs):
194+
def connect(self, **kwargs): # pylint: disable=C0116
187195
return self.async_await(self.bleak_client.connect(**kwargs))
188196

189-
def disconnect(self, **kwargs):
197+
def disconnect(self, **kwargs): # pylint: disable=C0116
190198
self.async_await(self.bleak_client.disconnect(**kwargs))
191199

192-
def read_gatt_char(self, *args, **kwargs):
200+
def read_gatt_char(self, *args, **kwargs): # pylint: disable=C0116
193201
return self.async_await(self.bleak_client.read_gatt_char(*args, **kwargs))
194202

195-
def write_gatt_char(self, *args, **kwargs):
203+
def write_gatt_char(self, *args, **kwargs): # pylint: disable=C0116
196204
self.async_await(self.bleak_client.write_gatt_char(*args, **kwargs))
197205

198-
def start_notify(self, *args, **kwargs):
206+
def start_notify(self, *args, **kwargs): # pylint: disable=C0116
199207
self.async_await(self.bleak_client.start_notify(*args, **kwargs))
200208

201-
202-
def close(self):
209+
def close(self): # pylint: disable=C0116
203210
self.async_run(self._stop_event_loop())
204211
self._eventThread_stopped.wait(5)
205212

206213
def __enter__(self):
207214
return self
208215

209-
def __exit__(self, type, value, traceback):
216+
def __exit__(self, _type, _value, _traceback):
210217
self.close()
211218

212-
213-
def async_await(self, coro, timeout = None):
219+
def async_await(self, coro, timeout = None): # pylint: disable=C0116
214220
return self.async_run(coro).result(timeout)
215221

216-
def async_run(self, coro):
222+
def async_run(self, coro): # pylint: disable=C0116
217223
return asyncio.run_coroutine_threadsafe(coro, self._eventLoop)
218224

219225
def _run_event_loop(self):
220-
self._eventLoop = asyncio.new_event_loop()
226+
# I don't know if the event loop can be initialized in __init__ so silencing pylint
227+
self._eventLoop = asyncio.new_event_loop() # pylint: disable=W0201
221228
self._eventThread_started.set()
222229
try:
223230
self._eventLoop.run_forever()

meshtastic/globals.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def getInstance():
2424
def __init__(self):
2525
"""Constructor for the Globals CLass"""
2626
if Globals.__instance is not None:
27-
raise Exception("This class is a singleton")
27+
raise Exception("This class is a singleton") # pylint: disable=W0719
2828
else:
2929
Globals.__instance = self
3030
self.args = None

meshtastic/mesh_interface.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
BROADCAST_ADDR,
2424
BROADCAST_NUM,
2525
LOCAL_ADDR,
26-
OUR_APP_VERSION,
2726
ResponseHandler,
2827
protocols,
2928
publishingThread,
@@ -48,6 +47,12 @@ class MeshInterface:
4847
debugOut
4948
"""
5049

50+
class MeshInterfaceError(Exception):
51+
"""An exception class for general mesh interface errors"""
52+
def __init__(self, message):
53+
self.message = message
54+
super().__init__(self.message)
55+
5156
def __init__(self, debugOut=None, noProto=False):
5257
"""Constructor
5358
@@ -314,7 +319,7 @@ def sendData(
314319
f"mesh_pb2.Constants.DATA_PAYLOAD_LEN: {mesh_pb2.Constants.DATA_PAYLOAD_LEN}"
315320
)
316321
if len(data) > mesh_pb2.Constants.DATA_PAYLOAD_LEN:
317-
raise Exception("Data payload too big")
322+
raise MeshInterface.MeshInterfaceError("Data payload too big")
318323

319324
if (
320325
portNum == portnums_pb2.PortNum.UNKNOWN_APP
@@ -440,7 +445,7 @@ def sendTelemetry(self, destinationId=BROADCAST_ADDR, wantResponse=False):
440445
destinationId = int(destinationId[1:], 16)
441446
else:
442447
destinationId = int(destinationId)
443-
448+
444449
self.sendData(
445450
r,
446451
destinationId=destinationId,
@@ -469,7 +474,7 @@ def onResponseTelemetry(self, p):
469474
)
470475
if telemetry.device_metrics.air_util_tx is not None:
471476
print(f"Transmit air utilization: {telemetry.device_metrics.air_util_tx:.2f}%")
472-
477+
473478
elif p["decoded"]["portnum"] == 'ROUTING_APP':
474479
if p["decoded"]["routing"]["errorReason"] == 'NO_RESPONSE':
475480
our_exit("No response from node. At least firmware 2.1.22 is required on the destination node.")
@@ -543,25 +548,25 @@ def waitForConfig(self):
543548
and self.localNode.waitForConfig()
544549
)
545550
if not success:
546-
raise Exception("Timed out waiting for interface config")
551+
raise MeshInterface.MeshInterfaceError("Timed out waiting for interface config")
547552

548553
def waitForAckNak(self):
549554
"""Wait for the ack/nak"""
550555
success = self._timeout.waitForAckNak(self._acknowledgment)
551556
if not success:
552-
raise Exception("Timed out waiting for an acknowledgment")
557+
raise MeshInterface.MeshInterfaceError("Timed out waiting for an acknowledgment")
553558

554559
def waitForTraceRoute(self, waitFactor):
555560
"""Wait for trace route"""
556561
success = self._timeout.waitForTraceRoute(waitFactor, self._acknowledgment)
557562
if not success:
558-
raise Exception("Timed out waiting for traceroute")
559-
563+
raise MeshInterface.MeshInterfaceError("Timed out waiting for traceroute")
564+
560565
def waitForTelemetry(self):
561566
"""Wait for telemetry"""
562567
success = self._timeout.waitForTelemetry(self._acknowledgment)
563568
if not success:
564-
raise Exception("Timed out waiting for telemetry")
569+
raise MeshInterface.MeshInterfaceError("Timed out waiting for telemetry")
565570

566571
def getMyNodeInfo(self):
567572
"""Get info about my node."""
@@ -596,7 +601,7 @@ def _waitConnected(self, timeout=30.0):
596601
and raise an exception"""
597602
if not self.noProto:
598603
if not self.isConnected.wait(timeout): # timeout after x seconds
599-
raise Exception("Timed out waiting for connection completion")
604+
raise MeshInterface.MeshInterfaceError("Timed out waiting for connection completion")
600605

601606
# If we failed while connecting, raise the connection to the client
602607
if self.failure:
@@ -605,7 +610,7 @@ def _waitConnected(self, timeout=30.0):
605610
def _generatePacketId(self):
606611
"""Get a new unique packet ID"""
607612
if self.currentPacketId is None:
608-
raise Exception("Not connected yet, can not generate packet")
613+
raise MeshInterface.MeshInterfaceError("Not connected yet, can not generate packet")
609614
else:
610615
self.currentPacketId = (self.currentPacketId + 1) & 0xFFFFFFFF
611616
return self.currentPacketId
@@ -774,7 +779,7 @@ def _handleFromRadio(self, fromRadioBytes):
774779
failmsg = None
775780

776781
if failmsg:
777-
self.failure = Exception(failmsg)
782+
self.failure = MeshInterface.MeshInterfaceError(failmsg)
778783
self.isConnected.set() # let waitConnected return this exception
779784
self.close()
780785

@@ -920,7 +925,7 @@ def _nodeNumToId(self, num):
920925
def _getOrCreateByNum(self, nodeNum):
921926
"""Given a nodenum find the NodeInfo in the DB (or create if necessary)"""
922927
if nodeNum == BROADCAST_NUM:
923-
raise Exception("Can not create/find nodenum by the broadcast num")
928+
raise MeshInterface.MeshInterfaceError("Can not create/find nodenum by the broadcast num")
924929

925930
if nodeNum in self.nodesByNum:
926931
return self.nodesByNum[nodeNum]

meshtastic/node.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def onResponseRequestSettings(self, p):
115115
print(f"{str(camel_to_snake(field))}:\n{str(config_values)}")
116116

117117
def requestConfig(self, configType):
118+
"""Request the config from the node via admin message"""
118119
if self == self.iface.localNode:
119120
onResponse = None
120121
else:
@@ -688,9 +689,6 @@ def onResponseRequestChannel(self, p):
688689
logging.debug(f"Received channel {stripnl(c)}")
689690
index = c.index
690691

691-
# for stress testing, we can always download all channels
692-
fastChannelDownload = True
693-
694692
if index >= 8 - 1:
695693
logging.debug("Finished downloading channels")
696694

@@ -703,6 +701,7 @@ def onResponseRequestChannel(self, p):
703701
self._requestChannel(index + 1)
704702

705703
def onAckNak(self, p):
704+
"""Informative handler for ACK/NAK responses"""
706705
if p["decoded"]["routing"]["errorReason"] != "NONE":
707706
print(
708707
f'Received a NAK, error reason: {p["decoded"]["routing"]["errorReason"]}'

meshtastic/stream_interface.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(self, debugOut=None, noProto=False, connectNow=True):
3232
"""
3333

3434
if not hasattr(self, "stream") and not noProto:
35-
raise Exception(
35+
raise Exception( # pylint: disable=W0719
3636
"StreamInterface is now abstract (to update existing code create SerialInterface instead)"
3737
)
3838
self._rxBuf = bytes() # empty

meshtastic/tests/test_main.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
tunnelMain,
2424
)
2525

26-
from ..channel_pb2 import Channel
26+
from ..channel_pb2 import Channel # pylint: disable=E0611
2727

2828
# from ..ble_interface import BLEInterface
2929
from ..node import Node
@@ -388,7 +388,7 @@ def test_main_onConnected_exception(capsys):
388388
Globals.getInstance().set_args(sys.argv)
389389

390390
def throw_an_exception(junk):
391-
raise Exception("Fake exception.")
391+
raise Exception("Fake exception.") # pylint: disable=W0719
392392

393393
iface = MagicMock(autospec=SerialInterface)
394394
with patch("meshtastic.serial_interface.SerialInterface", return_value=iface):

meshtastic/tests/test_node.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import pytest
88

99
# from ..admin_pb2 import AdminMessage
10-
from ..channel_pb2 import Channel
10+
from ..channel_pb2 import Channel # pylint: disable=E0611
1111
from ..node import Node
1212
from ..serial_interface import SerialInterface
1313

meshtastic/tests/test_util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def test_catchAndIgnore(caplog):
177177
"""Test catchAndIgnore() does not actually throw an exception, but just logs"""
178178

179179
def some_closure():
180-
raise Exception("foo")
180+
raise Exception("foo") # pylint: disable=W0719
181181

182182
with caplog.at_level(logging.DEBUG):
183183
catchAndIgnore("something", some_closure)

0 commit comments

Comments
 (0)