diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index df9a70ceb..0880cbf95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -190,8 +190,11 @@ jobs: - name: flake8 tox: flake8 # continue_on_error: true + - name: isort + tox: isort_CI + # continue_on_error: true - name: black - tox: black + tox: black_CI # continue_on_error: true - name: Docs tox: docs diff --git a/examples/client_async.py b/examples/client_async.py index bb0d3164b..c9c368fb7 100755 --- a/examples/client_async.py +++ b/examples/client_async.py @@ -20,9 +20,9 @@ The corresponding server must be started before e.g. as: python3 server_sync.py """ -import os import asyncio import logging +import os # --------------------------------------------------------------------------- # # import the various client implementations diff --git a/examples/client_async_basic_calls.py b/examples/client_async_basic_calls.py index 6aa9d2fc6..846ecd404 100755 --- a/examples/client_async_basic_calls.py +++ b/examples/client_async_basic_calls.py @@ -9,8 +9,8 @@ import asyncio import logging -from examples.helper import get_commandline from examples.client_async import run_async_client, setup_async_client +from examples.helper import get_commandline _logger = logging.getLogger() diff --git a/examples/client_async_extended_calls.py b/examples/client_async_extended_calls.py index cd263c06d..4a7ac69d0 100755 --- a/examples/client_async_extended_calls.py +++ b/examples/client_async_extended_calls.py @@ -25,9 +25,8 @@ import asyncio import logging -from examples.helper import get_commandline from examples.client_async import run_async_client, setup_async_client - +from examples.helper import get_commandline from pymodbus.diag_message import ( ChangeAsciiInputDelimiterRequest, ClearCountersRequest, @@ -54,6 +53,7 @@ ReportSlaveIdRequest, ) + _logger = logging.getLogger() UNIT = 0x01 @@ -168,6 +168,7 @@ async def run_async_ext_calls(client): await _execute_information_requests(client) await _execute_diagnostic_requests(client) + # --------------------------------------------------------------------------- # # Extra code, to allow commandline parameters instead of changing the code # --------------------------------------------------------------------------- # diff --git a/examples/client_payload.py b/examples/client_payload.py index 473efd422..c790ee770 100755 --- a/examples/client_payload.py +++ b/examples/client_payload.py @@ -7,8 +7,8 @@ Works out of the box together with payload_server.py """ -from collections import OrderedDict import logging +from collections import OrderedDict from pymodbus.client import ModbusTcpClient as ModbusClient from pymodbus.constants import Endian diff --git a/examples/client_sync.py b/examples/client_sync.py index 321c7e9b8..cd9f8999f 100755 --- a/examples/client_sync.py +++ b/examples/client_sync.py @@ -20,8 +20,8 @@ The corresponding server must be started before e.g. as: python3 server_sync.py """ -import os import logging +import os # --------------------------------------------------------------------------- # # import the various client implementations diff --git a/examples/client_sync_basic_calls.py b/examples/client_sync_basic_calls.py index 509aedc66..d5ae1bef0 100755 --- a/examples/client_sync_basic_calls.py +++ b/examples/client_sync_basic_calls.py @@ -8,8 +8,8 @@ """ import logging -from examples.helper import get_commandline from examples.client_sync import run_sync_client, setup_sync_client +from examples.helper import get_commandline _logger = logging.getLogger() diff --git a/examples/client_sync_extended_calls.py b/examples/client_sync_extended_calls.py index 7a6d92d84..fb80a1905 100755 --- a/examples/client_sync_extended_calls.py +++ b/examples/client_sync_extended_calls.py @@ -24,9 +24,8 @@ """ import logging -from examples.helper import get_commandline from examples.client_sync import run_sync_client, setup_sync_client - +from examples.helper import get_commandline from pymodbus.diag_message import ( ChangeAsciiInputDelimiterRequest, ClearCountersRequest, diff --git a/examples/common/custom_synchronous_server.py b/examples/common/custom_synchronous_server.py index 8e72e63ed..b2d1366de 100755 --- a/examples/common/custom_synchronous_server.py +++ b/examples/common/custom_synchronous_server.py @@ -57,10 +57,6 @@ def decode(self, data): """ import logging -from .custom_message import ( # pylint: disable=relative-beyond-top-level - CustomModbusRequest, -) - from pymodbus.datastore import ( ModbusSequentialDataBlock, ModbusServerContext, @@ -70,6 +66,10 @@ def decode(self, data): from pymodbus.server import StartTcpServer from pymodbus.version import version +from .custom_message import ( # pylint: disable=relative-beyond-top-level + CustomModbusRequest, +) + # --------------------------------------------------------------------------- # # configure the service logging diff --git a/examples/common/performance.py b/examples/common/performance.py index 3349aaab2..d4a36e2a2 100755 --- a/examples/common/performance.py +++ b/examples/common/performance.py @@ -5,21 +5,23 @@ The following is an quick performance check of the synchronous modbus client. """ -from concurrent.futures import ThreadPoolExecutor as eWorker, as_completed - # --------------------------------------------------------------------------- # # import the necessary modules # --------------------------------------------------------------------------- # import logging import os -from threading import Lock, Thread as tWorker +from concurrent.futures import ThreadPoolExecutor as eWorker +from concurrent.futures import as_completed +from threading import Lock +from threading import Thread as tWorker from time import time from pymodbus.client import ModbusTcpClient try: - from multiprocessing import Process as mWorker, log_to_stderr + from multiprocessing import Process as mWorker + from multiprocessing import log_to_stderr except ImportError: log_to_stderr = logging.getLogger diff --git a/examples/contrib/concurrent_client.py b/examples/contrib/concurrent_client.py index 26bbb197c..3cacf3c36 100755 --- a/examples/contrib/concurrent_client.py +++ b/examples/contrib/concurrent_client.py @@ -6,8 +6,6 @@ a high level of concurrency by using worker threads/processes to handle writing/reading from one or more client handles at once. """ -from collections import namedtuple -from concurrent.futures import Future import itertools # -------------------------------------------------------------------------- # @@ -15,13 +13,13 @@ # -------------------------------------------------------------------------- # import logging import multiprocessing -from multiprocessing import ( - Event as mEvent, - Process as mProcess, - Queue as mQueue, -) -from queue import Queue as qQueue import threading +from collections import namedtuple +from concurrent.futures import Future +from multiprocessing import Event as mEvent +from multiprocessing import Process as mProcess +from multiprocessing import Queue as mQueue +from queue import Queue as qQueue from threading import Event, Thread # -------------------------------------------------------------------------- # diff --git a/examples/contrib/message_generator.py b/examples/contrib/message_generator.py index eea3d8a22..c27c425a0 100755 --- a/examples/contrib/message_generator.py +++ b/examples/contrib/message_generator.py @@ -14,6 +14,7 @@ import logging from optparse import OptionParser # pylint: disable=deprecated-module +import pymodbus.diag_message as modbus_diag from pymodbus.bit_read_message import ( ReadCoilsRequest, ReadCoilsResponse, @@ -26,7 +27,6 @@ WriteSingleCoilRequest, WriteSingleCoilResponse, ) -import pymodbus.diag_message as modbus_diag from pymodbus.file_message import ( ReadFifoQueueRequest, ReadFifoQueueResponse, diff --git a/examples/contrib/message_parser.py b/examples/contrib/message_parser.py index 761bf71df..a076ec3d5 100755 --- a/examples/contrib/message_parser.py +++ b/examples/contrib/message_parser.py @@ -17,8 +17,8 @@ import codecs as c import collections import logging -from optparse import OptionParser # pylint: disable=deprecated-module import textwrap +from optparse import OptionParser # pylint: disable=deprecated-module from pymodbus.factory import ClientDecoder, ServerDecoder from pymodbus.transaction import ( diff --git a/examples/contrib/modbus_mapper.py b/examples/contrib/modbus_mapper.py index c69da8d9f..30aa60f92 100644 --- a/examples/contrib/modbus_mapper.py +++ b/examples/contrib/modbus_mapper.py @@ -124,16 +124,14 @@ StartTcpServer(context=context, identity=identity, address=("localhost", 5020)) """ -from collections import defaultdict import csv -from io import StringIO import json +from collections import defaultdict +from io import StringIO from tokenize import generate_tokens -from pymodbus.datastore import ( - ModbusSlaveContext, - ModbusSparseDataBlock, -) +from pymodbus.datastore import ModbusSlaveContext, ModbusSparseDataBlock + # --------------------------------------------------------------------------- # # raw mapping input parsers diff --git a/examples/contrib/modbus_simulator.py b/examples/contrib/modbus_simulator.py index 96a3b6efa..f7310badb 100644 --- a/examples/contrib/modbus_simulator.py +++ b/examples/contrib/modbus_simulator.py @@ -5,8 +5,8 @@ with read/write data as well as user configurable base data """ import logging -from optparse import OptionParser # pylint: disable=deprecated-module import pickle # nosec +from optparse import OptionParser # pylint: disable=deprecated-module from pymodbus.datastore import ModbusServerContext, ModbusSlaveContext from pymodbus.server import StartTcpServer diff --git a/examples/contrib/thread_safe_datastore.py b/examples/contrib/thread_safe_datastore.py index 8d9d4c8dc..cb085fb7e 100644 --- a/examples/contrib/thread_safe_datastore.py +++ b/examples/contrib/thread_safe_datastore.py @@ -1,7 +1,7 @@ # pylint: disable=missing-type-doc """Thread safe datastore.""" -from contextlib import contextmanager import threading +from contextlib import contextmanager from pymodbus.datastore.store import BaseModbusDataBlock diff --git a/examples/contrib/tornado_twisted/modbus_scraper.py b/examples/contrib/tornado_twisted/modbus_scraper.py index 0ddbe6a78..a226a4dc1 100755 --- a/examples/contrib/tornado_twisted/modbus_scraper.py +++ b/examples/contrib/tornado_twisted/modbus_scraper.py @@ -5,10 +5,13 @@ them as a collection of sequential data blocks. """ import logging -from optparse import OptionParser import pickle # nosec +from optparse import OptionParser -from twisted.internet import reactor, serialport # pylint: disable=import-error +from twisted.internet import ( # pylint: disable=import-error + reactor, + serialport, +) from twisted.internet.protocol import ( ClientFactory, # pylint: disable=import-error ) diff --git a/examples/serial_forwarder.py b/examples/serial_forwarder.py index 99782b3ab..7df3c8f8c 100644 --- a/examples/serial_forwarder.py +++ b/examples/serial_forwarder.py @@ -4,14 +4,15 @@ python3 serial_forwarder.py --log DEBUG --port "/dev/ttyUSB0" --baudrate 9600 --server_ip "192.168.1.27" --server_port 5020 --slaves 1 2 3 """ import argparse +import asyncio import logging import signal -import asyncio -from pymodbus.server.async_io import ModbusTcpServer from pymodbus.client import ModbusSerialClient from pymodbus.datastore import ModbusServerContext from pymodbus.datastore.remote import RemoteSlaveContext +from pymodbus.server.async_io import ModbusTcpServer + FORMAT = "%(asctime)-15s %(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s" logging.basicConfig(format=FORMAT) @@ -24,7 +25,7 @@ def raise_graceful_exit(*args): # pylint: disable=unused-argument raise SystemExit -class SerialForwarderTCPServer(): +class SerialForwarderTCPServer: """SerialRTU2TCP Forwarder Server""" def __init__(self): @@ -34,17 +35,19 @@ def __init__(self): async def run(self): """Run the server""" port, baudrate, server_port, server_ip, slaves = get_commandline() - client = ModbusSerialClient(method='rtu', port=port, baudrate=baudrate) - message = f'RTU bus on {port} - baudrate {baudrate}' + client = ModbusSerialClient(method="rtu", port=port, baudrate=baudrate) + message = f"RTU bus on {port} - baudrate {baudrate}" _logger.info(message) store = {} for i in slaves: store[i] = RemoteSlaveContext(client, unit=i) context = ModbusServerContext(slaves=store, single=False) - self.server = ModbusTcpServer(context, address=(server_ip, server_port), allow_reuse_address=True) - message = f'serving on {server_ip} port {server_port}' + self.server = ModbusTcpServer( + context, address=(server_ip, server_port), allow_reuse_address=True + ) + message = f"serving on {server_ip} port {server_port}" _logger.info(message) - message = f'listening to slaves {context.slaves()}' + message = f"listening to slaves {context.slaves()}" _logger.info(message) await self.server.serve_forever() @@ -61,16 +64,22 @@ def get_commandline(): parser = argparse.ArgumentParser(description="Command line options") parser.add_argument("--log", help=",".join(logchoices), default="info", type=str) - parser.add_argument("--port", help="RTU serial port", default='/dev/ttyUSB0', type=str) + parser.add_argument( + "--port", help="RTU serial port", default="/dev/ttyUSB0", type=str + ) parser.add_argument("--baudrate", help="RTU baudrate", default=9600, type=int) parser.add_argument("--server_port", help="server port", default=5020, type=int) parser.add_argument("--server_ip", help="server IP", default="127.0.0.1", type=str) - parser.add_argument("--slaves", help="list of slaves to forward", type=int, nargs="+") + parser.add_argument( + "--slaves", help="list of slaves to forward", type=int, nargs="+" + ) args = parser.parse_args() # set defaults - _logger.setLevel(args.log.upper() if args.log.lower() in logchoices else logging.INFO) + _logger.setLevel( + args.log.upper() if args.log.lower() in logchoices else logging.INFO + ) if not args.slaves: args.slaves = {1, 2, 3} return args.port, args.baudrate, args.server_port, args.server_ip, args.slaves diff --git a/examples/server_async.py b/examples/server_async.py index cd7d97511..59e2f8657 100755 --- a/examples/server_async.py +++ b/examples/server_async.py @@ -27,9 +27,9 @@ The corresponding client can be started as: python3 client_sync.py """ -import os import asyncio import logging +import os from examples.helper import get_commandline from pymodbus.datastore import ( diff --git a/examples/server_sync.py b/examples/server_sync.py index ec7fc1b98..560cfab33 100755 --- a/examples/server_sync.py +++ b/examples/server_sync.py @@ -31,8 +31,8 @@ is just a thin cover on top of the async server and is in some aspects a lot slower. """ -import os import logging +import os from examples.helper import get_commandline from examples.server_async import setup_server diff --git a/pymodbus/bit_read_message.py b/pymodbus/bit_read_message.py index be9d89e9b..6fcdb436e 100644 --- a/pymodbus/bit_read_message.py +++ b/pymodbus/bit_read_message.py @@ -3,11 +3,8 @@ import struct from pymodbus.constants import Defaults -from pymodbus.pdu import ( - ModbusExceptions as merror, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ModbusExceptions as merror +from pymodbus.pdu import ModbusRequest, ModbusResponse from pymodbus.utilities import pack_bitstring, unpack_bitstring diff --git a/pymodbus/bit_write_message.py b/pymodbus/bit_write_message.py index 3d6cb10c7..2292a34fa 100644 --- a/pymodbus/bit_write_message.py +++ b/pymodbus/bit_write_message.py @@ -6,11 +6,8 @@ import struct from pymodbus.constants import ModbusStatus -from pymodbus.pdu import ( - ModbusExceptions as merror, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ModbusExceptions as merror +from pymodbus.pdu import ModbusRequest, ModbusResponse from pymodbus.utilities import pack_bitstring, unpack_bitstring diff --git a/pymodbus/client/__init__.py b/pymodbus/client/__init__.py index 904de56d7..236dcd43b 100644 --- a/pymodbus/client/__init__.py +++ b/pymodbus/client/__init__.py @@ -2,11 +2,11 @@ import external classes, to make them easier to use: """ +from pymodbus.client.base import ModbusBaseClient from pymodbus.client.serial import AsyncModbusSerialClient, ModbusSerialClient from pymodbus.client.tcp import AsyncModbusTcpClient, ModbusTcpClient from pymodbus.client.tls import AsyncModbusTlsClient, ModbusTlsClient from pymodbus.client.udp import AsyncModbusUdpClient, ModbusUdpClient -from pymodbus.client.base import ModbusBaseClient # ---------------------------------------------------------------------------# diff --git a/pymodbus/client/base.py b/pymodbus/client/base.py index 500e6ad28..45a58f679 100644 --- a/pymodbus/client/base.py +++ b/pymodbus/client/base.py @@ -2,9 +2,9 @@ from __future__ import annotations import asyncio -from dataclasses import dataclass import logging import socket +from dataclasses import dataclass from pymodbus.client.mixin import ModbusClientMixin from pymodbus.constants import Defaults @@ -155,7 +155,7 @@ def is_socket_open(self) -> bool: raise NotImplementedException def idle_time(self) -> int: - """Time before initiatiating next transaction (call **sync**). + """Time before initiating next transaction (call **sync**). Applications can call message functions without checking idle_time(), this is done automatically. diff --git a/pymodbus/client/mixin.py b/pymodbus/client/mixin.py index b50a619d8..72a89456b 100644 --- a/pymodbus/client/mixin.py +++ b/pymodbus/client/mixin.py @@ -4,12 +4,12 @@ import pymodbus.bit_read_message as pdu_bit_read import pymodbus.bit_write_message as pdu_bit_write -from pymodbus.constants import Defaults import pymodbus.diag_message as pdu_diag import pymodbus.other_message as pdu_other_msg -from pymodbus.pdu import ModbusRequest, ModbusResponse import pymodbus.register_read_message as pdu_reg_read import pymodbus.register_write_message as pdu_req_write +from pymodbus.constants import Defaults +from pymodbus.pdu import ModbusRequest, ModbusResponse from pymodbus.utilities import ModbusTransactionState diff --git a/pymodbus/client/serial.py b/pymodbus/client/serial.py index 4b64483b3..5dc68224f 100644 --- a/pymodbus/client/serial.py +++ b/pymodbus/client/serial.py @@ -1,16 +1,17 @@ """Modbus client async serial communication.""" -from functools import partial import asyncio -import time import logging +import time +from functools import partial from pymodbus.client.base import ModbusBaseClient, ModbusClientProtocol from pymodbus.constants import Defaults +from pymodbus.exceptions import ConnectionException from pymodbus.framer import ModbusFramer from pymodbus.framer.rtu_framer import ModbusRtuFramer -from pymodbus.exceptions import ConnectionException from pymodbus.utilities import ModbusTransactionState, hexlify_packets + try: import serial from serial_asyncio import create_serial_connection diff --git a/pymodbus/client/tcp.py b/pymodbus/client/tcp.py index 1c5517a5f..aaf08fb6b 100644 --- a/pymodbus/client/tcp.py +++ b/pymodbus/client/tcp.py @@ -8,11 +8,12 @@ from pymodbus.client.base import ModbusBaseClient, ModbusClientProtocol from pymodbus.constants import Defaults +from pymodbus.exceptions import ConnectionException from pymodbus.framer import ModbusFramer from pymodbus.framer.socket_framer import ModbusSocketFramer -from pymodbus.exceptions import ConnectionException from pymodbus.utilities import ModbusTransactionState + _logger = logging.getLogger(__name__) diff --git a/pymodbus/client/tls.py b/pymodbus/client/tls.py index 637f05015..b88ed9bd2 100644 --- a/pymodbus/client/tls.py +++ b/pymodbus/client/tls.py @@ -9,6 +9,7 @@ from pymodbus.framer import ModbusFramer from pymodbus.framer.tls_framer import ModbusTlsFramer + _logger = logging.getLogger(__name__) @@ -37,9 +38,7 @@ def sslctx_provider( sslctx.options |= ssl.OP_NO_SSLv3 sslctx.options |= ssl.OP_NO_SSLv2 if certfile and keyfile: - sslctx.load_cert_chain( - certfile=certfile, keyfile=keyfile, password=password - ) + sslctx.load_cert_chain(certfile=certfile, keyfile=keyfile, password=password) return sslctx diff --git a/pymodbus/client/udp.py b/pymodbus/client/udp.py index dd4efe272..8ac652622 100644 --- a/pymodbus/client/udp.py +++ b/pymodbus/client/udp.py @@ -7,9 +7,10 @@ from pymodbus.client.base import ModbusBaseClient, ModbusClientProtocol from pymodbus.constants import Defaults +from pymodbus.exceptions import ConnectionException from pymodbus.framer import ModbusFramer from pymodbus.framer.socket_framer import ModbusSocketFramer -from pymodbus.exceptions import ConnectionException + _logger = logging.getLogger(__name__) diff --git a/pymodbus/datastore/database/sql_datastore.py b/pymodbus/datastore/database/sql_datastore.py index 6227e999f..a9f43b185 100644 --- a/pymodbus/datastore/database/sql_datastore.py +++ b/pymodbus/datastore/database/sql_datastore.py @@ -3,10 +3,10 @@ import logging import sqlalchemy +import sqlalchemy.types as sqltypes from sqlalchemy.schema import UniqueConstraint from sqlalchemy.sql import and_ from sqlalchemy.sql.expression import bindparam -import sqlalchemy.types as sqltypes from pymodbus.interfaces import IModbusSlaveContext @@ -28,6 +28,10 @@ def __init__(self, *args, **kwargs): # pylint: disable=unused-argument :param kwargs: Each element is a ModbusDataBlock """ + self._engine = None + self._metadata = None + self._table = None + self._connection = None self.table = kwargs.get("table", "pymodbus") self.database = kwargs.get("database", "sqlite:///pymodbus.db") self._db_create(self.table, self.database) diff --git a/pymodbus/device.py b/pymodbus/device.py index f29906696..6ccd5ce1a 100644 --- a/pymodbus/device.py +++ b/pymodbus/device.py @@ -4,9 +4,10 @@ maintained in the server context and the various methods should be inserted in the correct locations. """ +import struct + # pylint: disable=missing-type-doc from collections import OrderedDict -import struct from pymodbus.constants import DeviceInformation from pymodbus.interfaces import Singleton diff --git a/pymodbus/factory.py b/pymodbus/factory.py index ae2ecbb07..9ea58c24b 100644 --- a/pymodbus/factory.py +++ b/pymodbus/factory.py @@ -85,13 +85,9 @@ ReportSlaveIdRequest, ReportSlaveIdResponse, ) -from pymodbus.pdu import ( - ExceptionResponse, - IllegalFunctionRequest, - ModbusExceptions as ecode, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ExceptionResponse, IllegalFunctionRequest +from pymodbus.pdu import ModbusExceptions as ecode +from pymodbus.pdu import ModbusRequest, ModbusResponse from pymodbus.register_read_message import ( ReadHoldingRegistersRequest, ReadHoldingRegistersResponse, diff --git a/pymodbus/file_message.py b/pymodbus/file_message.py index 6dcdf7a78..20c765917 100644 --- a/pymodbus/file_message.py +++ b/pymodbus/file_message.py @@ -5,11 +5,8 @@ # pylint: disable=missing-type-doc import struct -from pymodbus.pdu import ( - ModbusExceptions as merror, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ModbusExceptions as merror +from pymodbus.pdu import ModbusRequest, ModbusResponse # ---------------------------------------------------------------------------# diff --git a/pymodbus/framer/ascii_framer.py b/pymodbus/framer/ascii_framer.py index 62816638d..c01576195 100644 --- a/pymodbus/framer/ascii_framer.py +++ b/pymodbus/framer/ascii_framer.py @@ -1,8 +1,8 @@ """Ascii_framer.""" # pylint: disable=missing-type-doc -from binascii import a2b_hex, b2a_hex import logging import struct +from binascii import a2b_hex, b2a_hex from pymodbus.exceptions import ModbusIOException from pymodbus.framer import BYTE_ORDER, FRAME_HEADER, ModbusFramer diff --git a/pymodbus/mei_message.py b/pymodbus/mei_message.py index 686abb4d1..0fc386b27 100644 --- a/pymodbus/mei_message.py +++ b/pymodbus/mei_message.py @@ -4,11 +4,8 @@ from pymodbus.constants import DeviceInformation, MoreData from pymodbus.device import DeviceInformationFactory, ModbusControlBlock -from pymodbus.pdu import ( - ModbusExceptions as merror, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ModbusExceptions as merror +from pymodbus.pdu import ModbusRequest, ModbusResponse _MCB = ModbusControlBlock() diff --git a/pymodbus/pdu.py b/pymodbus/pdu.py index c7b3ebe83..b761f58a5 100644 --- a/pymodbus/pdu.py +++ b/pymodbus/pdu.py @@ -99,6 +99,8 @@ def calculateRtuFrameSize(cls, buffer): # pylint: disable=invalid-name class ModbusRequest(ModbusPDU): """Base class for a modbus request PDU.""" + function_code = -1 + def __init__(self, unit=Defaults.Slave, **kwargs): """Proxy to the lower level initializer. @@ -112,9 +114,7 @@ def doException(self, exception): # pylint: disable=invalid-name :param exception: The exception to return :raises: An exception response """ - exc = ExceptionResponse( - self.function_code, exception # pylint: disable=no-member - ) + exc = ExceptionResponse(self.function_code, exception) _logger.error(exc) return exc diff --git a/pymodbus/register_read_message.py b/pymodbus/register_read_message.py index b4a249374..cafcd439d 100644 --- a/pymodbus/register_read_message.py +++ b/pymodbus/register_read_message.py @@ -3,11 +3,8 @@ import struct from pymodbus.constants import Defaults -from pymodbus.pdu import ( - ModbusExceptions as merror, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ModbusExceptions as merror +from pymodbus.pdu import ModbusRequest, ModbusResponse class ReadRegistersRequestBase(ModbusRequest): diff --git a/pymodbus/register_write_message.py b/pymodbus/register_write_message.py index c1b4fda78..1b64f3f2c 100644 --- a/pymodbus/register_write_message.py +++ b/pymodbus/register_write_message.py @@ -2,11 +2,8 @@ # pylint: disable=missing-type-doc import struct -from pymodbus.pdu import ( - ModbusExceptions as merror, - ModbusRequest, - ModbusResponse, -) +from pymodbus.pdu import ModbusExceptions as merror +from pymodbus.pdu import ModbusRequest, ModbusResponse class WriteSingleRegisterRequest(ModbusRequest): diff --git a/pymodbus/repl/client/helper.py b/pymodbus/repl/client/helper.py index cc7354785..ec13d8385 100644 --- a/pymodbus/repl/client/helper.py +++ b/pymodbus/repl/client/helper.py @@ -1,13 +1,13 @@ """Helper Module for REPL actions.""" -from collections import OrderedDict import inspect # pylint: disable=missing-type-doc import json +from collections import OrderedDict +import pygments from prompt_toolkit import print_formatted_text from prompt_toolkit.formatted_text import HTML, PygmentsTokens -import pygments from pygments.lexers.data import JsonLexer from pymodbus.payload import BinaryPayloadDecoder, Endian diff --git a/pymodbus/repl/client/main.py b/pymodbus/repl/client/main.py index a22afb220..f40ce155f 100644 --- a/pymodbus/repl/client/main.py +++ b/pymodbus/repl/client/main.py @@ -29,7 +29,10 @@ from pygments.lexers.python import PythonLexer from pymodbus.exceptions import ParameterException -from pymodbus.repl.client.completer import CmdCompleter, has_selected_completion +from pymodbus.repl.client.completer import ( + CmdCompleter, + has_selected_completion, +) from pymodbus.repl.client.helper import CLIENT_ATTRIBUTES, Result from pymodbus.repl.client.mclient import ModbusSerialClient, ModbusTcpClient from pymodbus.transaction import ( @@ -121,7 +124,7 @@ def convert(self, value, param, ctx): return None -def _process_args(args: list, string: bool=True): +def _process_args(args: list, string: bool = True): """Internal function to parse arguments provided on command line. :param args: Array of argument values diff --git a/pymodbus/repl/client/mclient.py b/pymodbus/repl/client/mclient.py index 53e31b145..c76ce98b9 100644 --- a/pymodbus/repl/client/mclient.py +++ b/pymodbus/repl/client/mclient.py @@ -2,10 +2,8 @@ # pylint: disable=missing-type-doc import functools -from pymodbus.client import ( - ModbusSerialClient as _ModbusSerialClient, - ModbusTcpClient as _ModbusTcpClient, -) +from pymodbus.client import ModbusSerialClient as _ModbusSerialClient +from pymodbus.client import ModbusTcpClient as _ModbusTcpClient from pymodbus.constants import Defaults from pymodbus.diag_message import ( ChangeAsciiInputDelimiterRequest, @@ -74,7 +72,10 @@ class ExtendedRequestSupport: # pylint: disable=(too-many-public-methods def _process_exception(resp, **kwargs): """Set internal process exception.""" unit = kwargs.get("unit") - if unit == 0: # pylint: disable=compare-to-zero,disable=consider-using-assignment-expr + if ( + unit # pylint: disable=compare-to-zero,disable=consider-using-assignment-expr + == 0 + ): err = {"message": "Broadcast message, ignoring errors!!!"} else: if isinstance(resp, ExceptionResponse): # pylint: disable=else-if-used diff --git a/pymodbus/repl/server/main.py b/pymodbus/repl/server/main.py index ae9079058..d438334be 100644 --- a/pymodbus/repl/server/main.py +++ b/pymodbus/repl/server/main.py @@ -2,9 +2,9 @@ from __future__ import annotations import asyncio -from enum import Enum import json import logging +from enum import Enum from pathlib import Path from typing import List diff --git a/pymodbus/server/__init__.py b/pymodbus/server/__init__.py index cee5fbdcb..1a6150af7 100644 --- a/pymodbus/server/__init__.py +++ b/pymodbus/server/__init__.py @@ -5,10 +5,10 @@ from pymodbus.server.async_io import ( ServerAsyncStop, ServerStop, + StartAsyncSerialServer, StartAsyncTcpServer, StartAsyncTlsServer, StartAsyncUdpServer, - StartAsyncSerialServer, StartSerialServer, StartTcpServer, StartTlsServer, diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py index b7cd09589..6191cbe5b 100755 --- a/pymodbus/server/async_io.py +++ b/pymodbus/server/async_io.py @@ -1,10 +1,10 @@ """Implementation of a Threaded Modbus Server.""" # pylint: disable=missing-type-doc import asyncio -from binascii import b2a_hex import logging -import traceback import ssl +import traceback +from binascii import b2a_hex from time import sleep from pymodbus.constants import Defaults @@ -21,6 +21,7 @@ ) from pymodbus.utilities import hexlify_packets + try: import serial from serial_asyncio import create_serial_connection @@ -37,7 +38,7 @@ # Allow access to server object, to e.g. make a shutdown # --------------------------------------------------------------------------- # _server_stopped = None # pylint: disable=invalid-name -_server_stop = None # pylint: disable=invalid-name +_server_stop = None # pylint: disable=invalid-name def sslctx_provider( @@ -72,6 +73,7 @@ def sslctx_provider( return sslctx + # --------------------------------------------------------------------------- # # Protocol Handlers # --------------------------------------------------------------------------- # @@ -891,8 +893,8 @@ async def serve_forever(self): """Start endless loop.""" if self.device.startswith("socket:"): # Socket server means listen so start a socket server - parts = self.device[7:].split(':') - host_port = ('', int(parts[1])) + parts = self.device[7:].split(":") + host_port = ("", int(parts[1])) self.server = await asyncio.get_event_loop().create_server( lambda: self.handler(self), *host_port, @@ -912,6 +914,7 @@ async def serve_forever(self): # Creation Factories # --------------------------------------------------------------------------- # + async def _helper_run_server(server, custom_functions): """Help starting/stopping server.""" global _server_stopped, _server_stop # pylint: disable=global-statement,invalid-name @@ -961,13 +964,7 @@ async def StartAsyncTcpServer( # pylint: disable=invalid-name,dangerous-default :return: an initialized but inactive server object coroutine """ framer = kwargs.pop("framer", ModbusSocketFramer) - server = ModbusTcpServer( - context, - framer, - identity, - address, - **kwargs - ) + server = ModbusTcpServer(context, framer, identity, address, **kwargs) if defer_start: return server @@ -1051,13 +1048,7 @@ async def StartAsyncUdpServer( # pylint: disable=invalid-name,dangerous-default :param kwargs: """ framer = kwargs.pop("framer", ModbusSocketFramer) - server = ModbusUdpServer( - context, - framer, - identity, - address, - **kwargs - ) + server = ModbusUdpServer(context, framer, identity, address, **kwargs) if defer_start: return server await _helper_run_server(server, custom_functions) @@ -1082,12 +1073,7 @@ async def StartAsyncSerialServer( # pylint: disable=invalid-name,dangerous-defa :param kwargs: The rest """ framer = kwargs.pop("framer", ModbusAsciiFramer) - server = ModbusSerialServer( - context, - framer, - identity=identity, - **kwargs - ) + server = ModbusSerialServer(context, framer, identity=identity, **kwargs) if defer_start: return server await server.start() diff --git a/pymodbus/transaction.py b/pymodbus/transaction.py index d173d36e5..57b2c085e 100644 --- a/pymodbus/transaction.py +++ b/pymodbus/transaction.py @@ -1,11 +1,11 @@ """Collection of transaction based abstractions.""" # pylint: disable=missing-type-doc -from functools import partial import logging import socket import struct -from threading import RLock import time +from functools import partial +from threading import RLock from pymodbus.constants import Defaults from pymodbus.exceptions import ( @@ -505,7 +505,7 @@ def __iter__(self): def addTransaction(self, request, tid=None): """Add a transaction to the handler. - This holds the requets in case it needs to be resent. + This holds the requests in case it needs to be resent. After being sent, the request is removed. :param request: The request to hold on to @@ -567,7 +567,7 @@ def __iter__(self): def addTransaction(self, request, tid=None): """Add a transaction to the handler. - This holds the requets in case it needs to be resent. + This holds the requests in case it needs to be resent. After being sent, the request is removed. :param request: The request to hold on to diff --git a/pymodbus/utilities.py b/pymodbus/utilities.py index 14076e427..6ede25d22 100644 --- a/pymodbus/utilities.py +++ b/pymodbus/utilities.py @@ -213,7 +213,7 @@ def computeLRC(data): # pylint: disable=invalid-name This is only used on the serial ASCII modbus protocol. A full description of this implementation - can be found in appendex B of the serial line modbus description. + can be found in appendix B of the serial line modbus description. :param data: The data to apply a lrc to :returns: The calculated LRC diff --git a/pymodbus/version.py b/pymodbus/version.py index fd472575d..a21e83e51 100644 --- a/pymodbus/version.py +++ b/pymodbus/version.py @@ -47,6 +47,4 @@ def __str__(self): # Exported symbols # --------------------------------------------------------------------------- # -__all__ = [ - "version" -] +__all__ = ["version"] diff --git a/requirements.txt b/requirements.txt index 8ef5be05c..70251d182 100644 --- a/requirements.txt +++ b/requirements.txt @@ -53,21 +53,21 @@ sphinx-rtd-theme # ------------------------------------------------------------------- # install:development] bandit==1.7.4 -black==22.3.0 -codespell==2.1.0 -coverage==6.4 -flake8==4.0.1 +black==22.10.0 +codespell==2.2.2 +coverage==6.5 +flake8==5.0.4 flake8-docstrings==1.6.0 -flake8-noqa==1.2.2 +flake8-noqa==1.2.9 flake8-comprehensions==3.10.0 isort==5.10.1 pep8==1.7.1 -pyflakes==2.4.0 +pyflakes==2.5.0 pydocstyle==6.1.1 -pycodestyle==2.8.0 -pylint==2.14.5 -pytest==7.1.2 -pytest-asyncio==0.18.3 -pytest-cov==3.0.0 +pycodestyle==2.9.1 +pylint==2.15.4 +pytest==7.1.3 +pytest-asyncio==0.19.0 +pytest-cov==4.0.0 pytest-timeout==2.1.0 -tox==3.25.0 +tox==3.26.0 diff --git a/setup.cfg b/setup.cfg index 9c07b4484..eb0695efe 100644 --- a/setup.cfg +++ b/setup.cfg @@ -274,7 +274,7 @@ const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ # Naming style matching correct attribute names. attr-naming-style=snake_case -attr-rgx=[a-z_][a-z0-9_]{2,}$ +attr-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ # Naming style matching correct argument names. argument-naming-style=snake_case @@ -386,7 +386,7 @@ max-parents=7 ignored-parents= # Maximum number of attributes for a class (see R0902). -max-attributes=11 +max-attributes=20 # Minimum number of public methods for a class (see R0903). min-public-methods=2 @@ -543,20 +543,8 @@ omit = [isort] py_version=38 profile=black -line_length = 80 +line_length = 79 lines_after_imports = 2 known_local_folder = common contrib -sections = - FUTURE - STDLIB - THIRDPARTY - FIRSTPARTY - LOCALFOLDER -include_trailing_comma = true -use_parentheses = true -combine_as_imports = true -force_sort_within_sections = true -forced_separate = doc,examples,pymodbus,test -known_first_party = doc,examples,pymodbus,test diff --git a/test/test_bit_read_messages.py b/test/test_bit_read_messages.py index 6b9beea3d..5af92a65c 100644 --- a/test/test_bit_read_messages.py +++ b/test/test_bit_read_messages.py @@ -7,9 +7,8 @@ * Read Coils """ import struct - -from test.conftest import MockContext import unittest +from test.conftest import MockContext from pymodbus.bit_read_message import ( ReadBitsRequestBase, diff --git a/test/test_bit_write_messages.py b/test/test_bit_write_messages.py index f4e40259c..fd40a53c1 100644 --- a/test/test_bit_write_messages.py +++ b/test/test_bit_write_messages.py @@ -6,8 +6,8 @@ * Read/Write Discretes * Read Coils """ -from test.conftest import FakeList, MockContext import unittest +from test.conftest import FakeList, MockContext from pymodbus.bit_write_message import ( WriteMultipleCoilsRequest, diff --git a/test/test_client.py b/test/test_client.py index 46cc537f5..d55f8a7ca 100755 --- a/test/test_client.py +++ b/test/test_client.py @@ -2,26 +2,26 @@ import asyncio import socket import ssl - from test.conftest import return_as_coroutine, run_coroutine from unittest import mock + import pytest import pymodbus.bit_read_message as pdu_bit_read import pymodbus.bit_write_message as pdu_bit_write import pymodbus.client as lib_client +import pymodbus.diag_message as pdu_diag +import pymodbus.other_message as pdu_other_msg +import pymodbus.register_read_message as pdu_reg_read +import pymodbus.register_write_message as pdu_req_write from pymodbus.client.base import ModbusBaseClient, ModbusClientProtocol from pymodbus.client.mixin import ModbusClientMixin from pymodbus.constants import Defaults -import pymodbus.diag_message as pdu_diag from pymodbus.exceptions import ConnectionException, NotImplementedException from pymodbus.framer.ascii_framer import ModbusAsciiFramer from pymodbus.framer.rtu_framer import ModbusRtuFramer from pymodbus.framer.socket_framer import ModbusSocketFramer from pymodbus.framer.tls_framer import ModbusTlsFramer -import pymodbus.other_message as pdu_other_msg -import pymodbus.register_read_message as pdu_reg_read -import pymodbus.register_write_message as pdu_req_write @pytest.mark.parametrize( @@ -247,12 +247,10 @@ def test_client_instanciate( client.reset_delay() assert client.delay_ms == initial_delay - assert socket.AF_INET == client._get_address_family( # pylint: disable=protected-access - "127.0.0.1" - ) - assert socket.AF_INET6 == client._get_address_family( # pylint: disable=protected-access - "::1" - ) + rc1 = client._get_address_family("127.0.0.1") # pylint: disable=protected-access + assert socket.AF_INET == rc1 + rc2 = client._get_address_family("::1") # pylint: disable=protected-access + assert socket.AF_INET6 == rc2 # a successful execute client.connect = lambda: True diff --git a/test/test_client_sync.py b/test/test_client_sync.py index 37adc5ba3..e53ff1d65 100755 --- a/test/test_client_sync.py +++ b/test/test_client_sync.py @@ -1,9 +1,8 @@ """Test client sync.""" -from itertools import count import ssl - -from test.conftest import mockSocket import unittest +from itertools import count +from test.conftest import mockSocket from unittest.mock import MagicMock, Mock, patch import serial diff --git a/test/test_client_sync_diag.py b/test/test_client_sync_diag.py index 220a1486d..69d8508f3 100755 --- a/test/test_client_sync_diag.py +++ b/test/test_client_sync_diag.py @@ -1,10 +1,9 @@ """Test client sync diag.""" -from itertools import count import socket - import unittest -from unittest.mock import MagicMock, patch +from itertools import count from test.test_client_sync import mockSocket +from unittest.mock import MagicMock, patch from pymodbus.client.sync_diag import ModbusTcpDiagClient, get_client from pymodbus.exceptions import ConnectionException diff --git a/test/test_examples.py b/test/test_examples.py index af2bbe645..93c416b33 100755 --- a/test/test_examples.py +++ b/test/test_examples.py @@ -1,9 +1,9 @@ """Test client async.""" import asyncio +import logging from dataclasses import dataclass from threading import Thread from time import sleep -import logging import pytest import pytest_asyncio @@ -11,10 +11,9 @@ from examples.client_async import run_async_client, setup_async_client from examples.client_async_basic_calls import run_async_basic_calls from examples.client_async_extended_calls import run_async_ext_calls -from examples.server_async import setup_server, run_async_server +from examples.server_async import run_async_server, setup_server from examples.server_sync import run_sync_server - -from pymodbus.server import ServerStop, ServerAsyncStop +from pymodbus.server import ServerAsyncStop, ServerStop from pymodbus.transaction import ( ModbusAsciiFramer, ModbusBinaryFramer, @@ -70,11 +69,7 @@ async def _helper_server( await ServerAsyncStop() -async def run_client( - test_comm, - test_type, - args=Commandline -): +async def run_client(test_comm, test_type, args=Commandline): """Help run async client.""" args.comm = test_comm @@ -133,15 +128,12 @@ def test_exp_sync_simple( ], ) async def test_exp_async_framer( # pylint: disable=unused-argument - test_comm, - test_framer, - test_port_offset, - test_port, - mock_run_server, - test_type + test_comm, test_framer, test_port_offset, test_port, mock_run_server, test_type ): """Test client-server async with different framers and calls.""" - if test_type == run_async_ext_calls and test_framer == ModbusRtuFramer: # pylint: disable=comparison-with-callable + rc1 = test_type == run_async_ext_calls # pylint: disable=comparison-with-callable + rc2 = test_framer == ModbusRtuFramer + if rc1 and rc2: return if test_comm == "serial": return diff --git a/test/test_factory.py b/test/test_factory.py index 30ba35d81..ddd9d2ee6 100644 --- a/test/test_factory.py +++ b/test/test_factory.py @@ -1,7 +1,7 @@ """Test factory.""" import unittest -from pymodbus.exceptions import ModbusException, MessageRegisterException +from pymodbus.exceptions import MessageRegisterException, ModbusException from pymodbus.factory import ClientDecoder, ServerDecoder from pymodbus.pdu import ModbusRequest, ModbusResponse @@ -168,7 +168,7 @@ class CustomRequest(ModbusRequest): function_code = 0xFF - class NoCustomRequest(): # pylint: disable=too-few-public-methods + class NoCustomRequest: # pylint: disable=too-few-public-methods """Custom request.""" function_code = 0xFF @@ -193,7 +193,7 @@ class CustomResponse(ModbusResponse): function_code = 0xFF - class NoCustomResponse(): # pylint: disable=too-few-public-methods + class NoCustomResponse: # pylint: disable=too-few-public-methods """Custom request.""" function_code = 0xFF diff --git a/test/test_file_message.py b/test/test_file_message.py index e649f08c4..49558bacf 100644 --- a/test/test_file_message.py +++ b/test/test_file_message.py @@ -6,8 +6,8 @@ * Read/Write Discretes * Read Coils """ -from test.conftest import MockContext import unittest +from test.conftest import MockContext from pymodbus.file_message import ( FileRecord, diff --git a/test/test_framers.py b/test/test_framers.py index 68a3ade05..3206b3748 100644 --- a/test/test_framers.py +++ b/test/test_framers.py @@ -266,7 +266,11 @@ def test_rtu_incoming_packet(rtu_framer, data): # pylint: disable=redefined-out """Test rtu process incoming packet.""" buffer, units, reset_called, process_called = data - with patch.object(rtu_framer, "_process", wraps=rtu_framer._process) as mock_process, patch.object( # pylint: disable=protected-access + with patch.object( + rtu_framer, + "_process", + wraps=rtu_framer._process, # pylint: disable=protected-access + ) as mock_process, patch.object( rtu_framer, "resetFrame", wraps=rtu_framer.resetFrame ) as mock_reset: rtu_framer.processIncomingPacket(buffer, Mock(), units) diff --git a/test/test_register_read_messages.py b/test/test_register_read_messages.py index 100f62236..a873378fb 100644 --- a/test/test_register_read_messages.py +++ b/test/test_register_read_messages.py @@ -1,6 +1,6 @@ """Test register read messages.""" -from test.conftest import FakeList, MockContext import unittest +from test.conftest import FakeList, MockContext from pymodbus.pdu import ModbusExceptions from pymodbus.register_read_message import ( diff --git a/test/test_register_write_messages.py b/test/test_register_write_messages.py index b0a54e6dd..a73398863 100644 --- a/test/test_register_write_messages.py +++ b/test/test_register_write_messages.py @@ -1,6 +1,6 @@ """Test register write messages.""" -from test.conftest import MockContext, MockLastValuesContext import unittest +from test.conftest import MockContext, MockLastValuesContext from pymodbus.payload import BinaryPayloadBuilder, Endian from pymodbus.pdu import ModbusExceptions diff --git a/test/test_server_asyncio.py b/test/test_server_asyncio.py index bf8f0e33c..2584b20a1 100755 --- a/test/test_server_asyncio.py +++ b/test/test_server_asyncio.py @@ -1,9 +1,9 @@ """Test server asyncio.""" import asyncio -from asyncio import CancelledError import logging import ssl import unittest +from asyncio import CancelledError from unittest.mock import AsyncMock, Mock, patch import pytest diff --git a/test/test_transaction.py b/test/test_transaction.py index 04f87cc36..4ac0aa34e 100755 --- a/test/test_transaction.py +++ b/test/test_transaction.py @@ -1,7 +1,7 @@ """Test transaction.""" +import unittest from binascii import a2b_hex from itertools import count -import unittest from unittest.mock import MagicMock, patch from pymodbus.exceptions import ( diff --git a/tox.ini b/tox.ini index 720373ccf..61bf3bcdb 100644 --- a/tox.ini +++ b/tox.ini @@ -34,7 +34,13 @@ commands = deps = -r requirements.txt ignore_errors = false commands = - isort examples pymodbus test + isort --recursive examples pymodbus test + +[testenv:isort_CI] +deps = -r requirements.txt +ignore_errors = false +commands = + isort --check --recursive examples pymodbus test [testenv:bandit] deps = -r requirements.txt @@ -44,14 +50,22 @@ commands = [testenv:flake8] deps = -r requirements.txt +ignore_errors = false commands = flake8 doc/ examples/ pymodbus/ test/ [testenv:black] deps = -r requirements.txt +ignore_errors = false commands = black --safe --quiet examples/ pymodbus/ test/ +[testenv:black_CI] +deps = -r requirements.txt +ignore_errors = false +commands = + black --check --safe --quiet examples/ pymodbus/ test/ + [testenv:docs] allowlist_externals = make @@ -68,4 +82,3 @@ commands = ls -la coverage_reports coverage combine coverage_reports coverage report --fail-under=60 --ignore-errors -