Skip to content

Commit 031c457

Browse files
Lint and type hints for REPL (#1364)
* avoid re-using `file` variable * Click version >=8 dropped this warning for Python2 * Make `click` an explicit requirement * annotations is already part of Python3.8 * fix flake8 warnings * avoid redefining extra_args * Fix mangled docstring * Use slave argument * Give default values, and fix values/write_registers mismatch * `list` is native type, `List[...]` is a type hint --------- Co-authored-by: jan iversen <[email protected]>
1 parent 64a4f7b commit 031c457

File tree

8 files changed

+38
-58
lines changed

8 files changed

+38
-58
lines changed

pymodbus/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ class Defaults(Singleton): # pylint: disable=too-few-public-methods
142142
TransactionId = 0
143143
Strict = True
144144
ProtocolId = 0
145-
Slave = 0x00
145+
Slave: int = 0x00
146146
Baudrate = 19200
147147
Parity = "N"
148148
Bytesize = 8

pymodbus/repl/client/main.py

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,9 @@
11
"""Pymodbus REPL Entry point."""
2-
# pylint: disable=anomalous-backslash-in-string
3-
# flake8: noqa
42
import logging
53
import pathlib
6-
import sys
7-
8-
9-
try:
10-
import click
11-
except ImportError:
12-
print('click not installed!! Install with "pip install click"')
13-
sys.exit(1)
14-
try:
15-
from prompt_toolkit import PromptSession, print_formatted_text
16-
except ImportError:
17-
print(
18-
"prompt toolkit is not installed!! "
19-
'Install with "pip install prompt_toolkit --upgrade"'
20-
)
21-
sys.exit(1)
224

5+
import click
6+
from prompt_toolkit import PromptSession, print_formatted_text
237
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
248
from prompt_toolkit.formatted_text import HTML
259
from prompt_toolkit.history import FileHistory
@@ -46,9 +30,7 @@
4630

4731
_logger = logging.getLogger()
4832

49-
click.disable_unicode_literals_warning = True
50-
51-
TITLE = f"""
33+
TITLE = rf"""
5234
----------------------------------------------------------------------------
5335
__________ _____ .___ __________ .__
5436
\______ \___.__. / \ ____ __| _/ \______ \ ____ ______ | |
@@ -124,8 +106,8 @@ def convert(self, value, param, ctx):
124106
return None
125107

126108

127-
def process_args(args: list, string: bool = True):
128-
"""Internal function to parse arguments provided on command line.
109+
def _process_args(args: list, string: bool = True):
110+
"""Parse arguments provided on command line.
129111
130112
:param args: Array of argument values
131113
:param string: True if arguments values are strings, false if argument values are integers
@@ -226,7 +208,7 @@ def _(event):
226208
text = text.strip().split()
227209
cmd = text[0].split(".")[1]
228210
args = text[1:]
229-
kwargs, execute = process_args(args, string=False)
211+
kwargs, execute = _process_args(args, string=False)
230212
if execute:
231213
if text[0] in CLIENT_ATTRIBUTES:
232214
result = Result(getattr(client, cmd))
@@ -242,7 +224,7 @@ def _(event):
242224
result.raw()
243225
if words[0] == "result.decode":
244226
args = words[1:]
245-
kwargs, execute = process_args(args)
227+
kwargs, execute = _process_args(args)
246228
if execute:
247229
result.decode(**kwargs)
248230
except KeyboardInterrupt:

pymodbus/repl/client/mclient.py

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,10 @@ def read_input_registers(self, address, count=1, slave=Defaults.Slave, **kwargs)
220220

221221
def readwrite_registers(
222222
self,
223-
read_address,
224-
read_count,
225-
write_address,
226-
write_registers,
223+
read_address=0,
224+
read_count=0,
225+
write_address=0,
226+
values=0,
227227
slave=Defaults.Slave,
228228
**kwargs,
229229
):
@@ -235,7 +235,7 @@ def readwrite_registers(
235235
:param read_address: register offset to read from
236236
:param read_count: Number of registers to read
237237
:param write_address: register offset to write to
238-
:param write_registers: List of register values to write (comma separated)
238+
:param values: List of register values to write (comma separated)
239239
:param slave: Modbus slave unit ID
240240
:param kwargs:
241241
:return:
@@ -244,7 +244,7 @@ def readwrite_registers(
244244
read_address=read_address,
245245
read_count=read_count,
246246
write_address=write_address,
247-
write_registers=write_registers,
247+
values=values,
248248
slave=slave,
249249
**kwargs,
250250
)
@@ -321,15 +321,14 @@ def report_slave_id(self, slave=Defaults.Slave, **kwargs):
321321
}
322322
return ExtendedRequestSupport._process_exception(resp)
323323

324-
def read_exception_status(self, **kwargs):
325-
"""Read tcontents of eight Exception Status output.
326-
327-
In a remote device.
324+
def read_exception_status(self, slave=Defaults.Slave, **kwargs):
325+
"""Read contents of eight Exception Status output in a remote device.
328326
327+
:param slave: Modbus slave unit ID
329328
:param kwargs:
330329
:return:
331330
"""
332-
request = ReadExceptionStatusRequest(**kwargs)
331+
request = ReadExceptionStatusRequest(slave, **kwargs)
333332
resp = self.execute(request) # pylint: disable=no-member
334333
if not resp.isError():
335334
return {"function_code": resp.function_code, "status": resp.status}

pymodbus/repl/server/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Pymodbus REPL Server
22

3-
Pymodbus REPL server helps to quicky spin an [asynchronous server](../../../examples/common/asyncio_server.py) from command line.
3+
Pymodbus REPL server helps to quickly start an [asynchronous server](../../../examples/common/asyncio_server.py) from the command line.
44

55
Support both `Modbus TCP` and `Modbus RTU` server.
66

@@ -9,7 +9,7 @@ Some features offered are
99

1010
---
1111
1. Runs a [reactive server](../../server/reactive/main.py) in `REPL` and `NON REPL` mode.
12-
2. Exposes REST API's to manipulate the behaviour of the server in non repl mode.
12+
2. Exposes REST API's to manipulate the behaviour of the server in non REPL mode.
1313
3. Ability to manipulate the out-going response dynamically (either via REPL console or via REST API request).
1414
4. Ability to delay the out-going response dynamically (either via REPL console or via REST API request).
1515
5. Auto revert to normal response after pre-defined number of manipulated responses.

pymodbus/repl/server/main.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
"""Repl server main."""
2-
from __future__ import annotations
3-
42
import asyncio
53
import json
64
import sys
@@ -71,11 +69,11 @@ def servers(incomplete: str) -> List[str]:
7169
return _completer(incomplete, _servers)
7270

7371

74-
def process_extra_args(extra_args: list[str], modbus_config: dict) -> dict:
72+
def process_extra_args(extra_args: List[str], modbus_config: dict) -> dict:
7573
"""Process extra args passed to server."""
7674
options_stripped = [x.strip().replace("--", "") for x in extra_args[::2]]
77-
extra_args = dict(list(zip(options_stripped, extra_args[1::2])))
78-
for option, value in extra_args.items():
75+
extra_args_dict = dict(list(zip(options_stripped, extra_args[1::2])))
76+
for option, value in extra_args_dict.items():
7977
if option in modbus_config:
8078
try:
8179
modbus_config[option] = type(modbus_config[option])(value)

pymodbus/server/simulator/http_server.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,8 @@ def __init__(
173173
"server_json": [None, self.build_json_server],
174174
}
175175
for entry in self.generator_html: # pylint: disable=consider-using-dict-items
176-
file = os.path.join(self.web_path, "generator", entry)
177-
with open(file, encoding="utf-8") as handle:
176+
html_file = os.path.join(self.web_path, "generator", entry)
177+
with open(html_file, encoding="utf-8") as handle:
178178
self.generator_html[entry][0] = handle.read()
179179
self.refresh_rate = 0
180180
self.register_filter: List[int] = []

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ aiohttp==3.8.3
2828
typer[all]==0.7.0
2929
prompt-toolkit==3.0.36
3030
pygments==2.14.0
31+
click>=8.0.0
3132

3233
# install:serial
3334
pyserial>=3.5

test/test_repl_client.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""Test client sync."""
2-
from pymodbus.repl.client.main import process_args
2+
from pymodbus.repl.client.main import _process_args
33
from pymodbus.server.reactive.default_config import DEFAULT_CONFIG
44

55

@@ -10,39 +10,39 @@ def test_repl_default_config():
1010

1111

1212
def test_repl_client_process_args():
13-
"""Test argument processing in repl.client.main ( process_args function)."""
14-
resp = process_args(["address=11"], False)
13+
"""Test argument processing in repl.client.main ( _process_args function)."""
14+
resp = _process_args(["address=11"], False)
1515
assert resp == ({"address": 11}, True)
1616

17-
resp = process_args(["address=0x11"], False)
17+
resp = _process_args(["address=0x11"], False)
1818
assert resp == ({"address": 17}, True)
1919

20-
resp = process_args(["address=0b11"], False)
20+
resp = _process_args(["address=0b11"], False)
2121
assert resp == ({"address": 3}, True)
2222

23-
resp = process_args(["address=0o11"], False)
23+
resp = _process_args(["address=0o11"], False)
2424
assert resp == ({"address": 9}, True)
2525

26-
resp = process_args(["address=11", "value=0x10"], False)
26+
resp = _process_args(["address=11", "value=0x10"], False)
2727
assert resp == ({"address": 11, "value": 16}, True)
2828

29-
resp = process_args(["value=11", "address=0x10"], False)
29+
resp = _process_args(["value=11", "address=0x10"], False)
3030
assert resp == ({"address": 16, "value": 11}, True)
3131

32-
resp = process_args(["address=0b11", "value=0x10"], False)
32+
resp = _process_args(["address=0b11", "value=0x10"], False)
3333
assert resp == ({"address": 3, "value": 16}, True)
3434

3535
try:
36-
resp = process_args(["address=0xhj", "value=0x10"], False)
36+
resp = _process_args(["address=0xhj", "value=0x10"], False)
3737
except ValueError:
3838
pass
3939

4040
try:
41-
resp = process_args(["address=11ah", "value=0x10"], False)
41+
resp = _process_args(["address=11ah", "value=0x10"], False)
4242
except ValueError:
4343
pass
4444

4545
try:
46-
resp = process_args(["address=0b12", "value=0x10"], False)
46+
resp = _process_args(["address=0b12", "value=0x10"], False)
4747
except ValueError:
4848
pass

0 commit comments

Comments
 (0)