internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: pymodbus-dev/pymodbus

Issue:
Default framer for async `async_io.ModbusSocketServer` is ambiguous
<!--
Please use the Pymodbus gitter channel at https://gitter.im/pymodbus_dev/Lobby or Stack Overflow(tag [pymodbus](https://stackoverflow.com/questions/tagged/pymodbus) for
support questions.

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://github.com/riptideio/pymodbus/issues
    * prepare a short, runnable example that reproduce the issue with the latest development version of Pymodbus
-->

### Versions

* Python: 3.8.0
* OS: macOS 11.6
* Pymodbus: 2.5.2
* Modbus Hardware (if used): None

### Description

`server.async_io.ModbusSerialServer` uses `ModbusRtuFramer` as default framer, but the factory `server.async_io.StartSerialServer` uses `ModbusAsciiFramer`. Neither default value is mentioned in the documentation, which makes this slightly confusing, especially since all other factories use the same default values as the `__init__` methods. I think the interface should be same. Maybe you should just stop double-booking the default values between `__init__` and factory?


Discussion:

Resolving patch:
diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py
--- a/pymodbus/server/async_io.py
+++ b/pymodbus/server/async_io.py
@@ -726,14 +726,14 @@ class ModbusSerialServer:  # pylint: disable=too-many-instance-attributes
     handler = None
 
     def __init__(
-        self, context, framer=None, identity=None, **kwargs
+        self, context, framer=ModbusRtuFramer, identity=None, **kwargs
     ):  # pragma: no cover
         """Initialize the socket server.
 
         If the identity structure is not passed in, the ModbusControlBlock
         uses its own empty structure.
         :param context: The ModbusServerContext datastore
-        :param framer: The framer strategy to use
+        :param framer: The framer strategy to use, default ModbusRtuFramer
         :param identity: An optional identify structure
         :param port: The serial port to attach to
         :param stopbits: The number of stop bits to use


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
pyserial, pyserial-asyncio should be optional in pymodbus 3
<!--
Please use the Pymodbus gitter channel at https://gitter.im/pymodbus_dev/Lobby or Stack Overflow(tag [pymodbus](https://stackoverflow.com/questions/tagged/pymodbus) for
support questions.

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://github.com/riptideio/pymodbus/issues
    * check the discussions forum https://github.com/riptideio/pymodbus/discussions
    * prepare a short, runnable example that reproduce the issue with the latest development version of Pymodbus
-->

### Versions

* Pymodbus: 3.0.0

### Description

pyserial and pyserial-asyncio are listed as optional dependencies, but importing pymodbus.client fails if they are not present.

### Code and Logs

```
>>> from pymodbus.client import ModbusUdpClient
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/pymodbus/pymodbus/client/__init__.py", line 5, in <module>
    from pymodbus.client.serial import AsyncModbusSerialClient, ModbusSerialClient
  File "/pymodbus/pymodbus/client/serial.py", line 7, in <module>
    from serial_asyncio import create_serial_connection
ModuleNotFoundError: No module named 'serial_asyncio'
```



Discussion:
Ups, that is a real bug, will fix that
> Ups, that is a real bug, will fix that

Thank you!!! 

The import of `ModbusSerialClient` module  in `pydmodbus 2.5.3` was done:

`from pymodbus.client.sync import ModbusSerialClient`

To `Pymodbus: 3.0.0`  it was changed too?.

Look at the documentation or examples.

Resolving patch:
diff --git a/pymodbus/client/serial.py b/pymodbus/client/serial.py
--- a/pymodbus/client/serial.py
+++ b/pymodbus/client/serial.py
@@ -4,9 +4,6 @@
 import time
 import logging
 
-from serial_asyncio import create_serial_connection
-import serial
-
 from pymodbus.client.base import ModbusBaseClient, ModbusClientProtocol
 from pymodbus.constants import Defaults
 from pymodbus.framer import ModbusFramer
@@ -14,6 +11,12 @@
 from pymodbus.exceptions import ConnectionException
 from pymodbus.utilities import ModbusTransactionState, hexlify_packets
 
+try:
+    import serial
+    from serial_asyncio import create_serial_connection
+except ImportError:
+    pass
+
 
 _logger = logging.getLogger(__name__)
 
diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py
--- a/pymodbus/server/async_io.py
+++ b/pymodbus/server/async_io.py
@@ -7,9 +7,6 @@
 import ssl
 from time import sleep
 
-import serial
-from serial_asyncio import create_serial_connection
-
 from pymodbus.constants import Defaults
 from pymodbus.datastore import ModbusServerContext
 from pymodbus.device import ModbusControlBlock, ModbusDeviceIdentification
@@ -24,6 +21,12 @@
 )
 from pymodbus.utilities import hexlify_packets
 
+try:
+    import serial
+    from serial_asyncio import create_serial_connection
+except ImportError:
+    pass
+
 
 # --------------------------------------------------------------------------- #
 # Logging


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
pymodbus.constants interferes with application's logging configuration
### Versions

* Python: 3.10
* OS: Ubuntu Linux
* Pymodbus: 3.0.0dev5
* Modbus Hardware (if used): 

### Description

pymodbus.constants calls logging.basicConfig() on import, overriding any logging that the application attempts to configure later on. This is unexpected and a documented anti-pattern for Python logging.

There is more discussion in PR #1106, which I will close so that someone else can suggest a solution that the maintainers can agree with.



Discussion:

Resolving patch:
diff --git a/pymodbus/__init__.py b/pymodbus/__init__.py
--- a/pymodbus/__init__.py
+++ b/pymodbus/__init__.py
@@ -17,3 +17,15 @@
 #  Block unhandled logging
 # ---------------------------------------------------------------------------#
 __logging.getLogger(__name__).addHandler(__null())
+
+
+def pymodbus_apply_logging_config():
+    """Apply basic logging configuration used by default by Pymodbus maintainers.
+
+    Please call this function to format logging appropriately when opening issues.
+    """
+    __logging.basicConfig(
+        format="%(asctime)s %(levelname)-5s %(module)s:%(lineno)s %(message)s",
+        datefmt="%H:%M:%S",
+        level=__logging.WARNING,
+    )
diff --git a/pymodbus/constants.py b/pymodbus/constants.py
--- a/pymodbus/constants.py
+++ b/pymodbus/constants.py
@@ -3,17 +3,9 @@
 This is the single location for storing default
 values for the servers and clients.
 """
-import logging
-
-from pymodbus.interfaces import Singleton
 
 
-# set logging format and default level for library.
-logging.basicConfig(
-    format="%(asctime)s %(levelname)-5s %(module)s:%(lineno)s %(message)s",
-    datefmt="%H:%M:%S",
-    level=logging.WARNING,
-)
+from pymodbus.interfaces import Singleton
 
 
 class Defaults(Singleton):  # pylint: disable=too-few-public-methods


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
No explicit timeout on client TCP/IP connections
### Versions

* Python: 3.10
* OS: MacOSX
* Pymodbus: https://github.com/riptideio/pymodbus/commit/b4f5a558254f8242fd65fb49fe10f4f255610b32
* Modbus Hardware (if used): any (I'm using a Productivity2000 PLC)

### Pymodbus Specific
* Client: TCP/IP async

### Description

The TCP/IP client connection code does not obey the `timeout` parameter inherited from `ModbusBaseClient` https://github.com/riptideio/pymodbus/blob/b4f5a558254f8242fd65fb49fe10f4f255610b32/pymodbus/client/base.py#L22-L28

This is because it relies on [`loop.create_connection()`](https://docs.python.org/3/library/asyncio-eventloop.html#opening-network-connections), which does not have any overall timeout parameter.  A failed network call will _eventually_ timeout in 45-120s, although I'm not sure which layer actually does it.  (There is only `ssl_handshake_timeout` but this is very specific)

https://github.com/riptideio/pymodbus/blob/b4f5a558254f8242fd65fb49fe10f4f255610b32/pymodbus/client/tcp.py#L82-L89

(PR incoming)



Discussion:

Resolving patch:
diff --git a/pymodbus/client/serial.py b/pymodbus/client/serial.py
--- a/pymodbus/client/serial.py
+++ b/pymodbus/client/serial.py
@@ -105,6 +105,7 @@ async def connect(self):  # pylint: disable=invalid-overridden-method
                 bytesize=self.params.bytesize,
                 stopbits=self.params.stopbits,
                 parity=self.params.parity,
+                timeout=self.params.timeout,
                 **self.params.kwargs,
             )
             await self._connected_event.wait()
diff --git a/pymodbus/client/tcp.py b/pymodbus/client/tcp.py
--- a/pymodbus/client/tcp.py
+++ b/pymodbus/client/tcp.py
@@ -83,8 +83,11 @@ async def _connect(self):
         """Connect."""
         _logger.debug("Connecting.")
         try:
-            transport, protocol = await self.loop.create_connection(
-                self._create_protocol, host=self.params.host, port=self.params.port
+            transport, protocol = await asyncio.wait_for(
+                self.loop.create_connection(
+                    self._create_protocol, host=self.params.host, port=self.params.port
+                ),
+                timeout=self.params.timeout,
             )
             return transport, protocol
         except Exception as exc:  # pylint: disable=broad-except


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
Unreachable code in AsyncModbusTcpClient
### Versions

* Pymodbus: 3.0.0

### Pymodbus Specific
* Client: tcp - async

### Description

Unreachable code in else statement due to the early return in the try statement.
This causes that there is no logging message being reported and to never reset the delay if there would be due to a temporary disconnect.

See also `_connect` function of the async TCP client 
https://github.com/riptideio/pymodbus/blob/61d9e9ac20954634a453befae50576da2333e40b/pymodbus/client/tcp.py#L82-L100



Discussion:
Pull requests are welcome.

Resolving patch:
diff --git a/pymodbus/client/tcp.py b/pymodbus/client/tcp.py
--- a/pymodbus/client/tcp.py
+++ b/pymodbus/client/tcp.py
@@ -89,7 +89,6 @@ async def _connect(self):
                 ),
                 timeout=self.params.timeout,
             )
-            return transport, protocol
         except Exception as exc:  # pylint: disable=broad-except
             txt = f"Failed to connect: {exc}"
             _logger.warning(txt)
@@ -98,6 +97,7 @@ async def _connect(self):
             txt = f"Connected to {self.params.host}:{self.params.port}."
             _logger.info(txt)
             self.reset_delay()
+            return transport, protocol
 
     def protocol_made_connection(self, protocol):
         """Notify successful connection."""


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
client.ModbusClientMixin doesn not have __init__, but ModbusBaseClient tries to call it
During its initialization class ModbusBaseClient tries to call super().\_\_init\_\_(), even though ModbusClientMixin does not have \_\_init\_\_().
Usually it is not a problem.

However, if later one tries to inherit from, for example, ModbusTcpClient and from another class which has \_\_init\_\_() - that class is being called twice, with unexpected consequences:

```python
from pymodbus.client.tcp import *

class SyncClientMixin:
    def __init__(self, **kwargs):
        print("This is gonna be called twice")

class TcpClientWrapper(ModbusTcpClient, SyncClientMixin):
    def __init__(self, **kwargs):
       super().__init__(**kwargs)
       SyncClientMixin.__init__(self, **kwargs)

wrap = TcpClientWrapper(host = 'localhost')
```

The resolution is to have an empty \_\_init\_\_ in ModbusClientMixin


Discussion:

Resolving patch:
diff --git a/pymodbus/client/mixin.py b/pymodbus/client/mixin.py
--- a/pymodbus/client/mixin.py
+++ b/pymodbus/client/mixin.py
@@ -42,6 +42,9 @@ class ModbusClientMixin:  # pylint: disable=too-many-public-methods
     last_frame_end = 0
     silent_interval = 0
 
+    def __init__(self):
+        """Initialize."""
+
     def execute(self, request: ModbusRequest) -> ModbusResponse:
         """Execute request.
 


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
3.11 deprecation: reuse_address in loop.create_datagram_endpoint

>     self.protocol, self.endpoint = await self.loop.create_datagram_endpoint(
>                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> TypeError: BaseEventLoop.create_datagram_endpoint() got an unexpected keyword argument 'reuse_address'

asyncio [docs](https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.create_datagram_endpoint):

> Changed in version 3.11: The `reuse_address` parameter, disabled since Python 3.9.0, 3.8.1, 3.7.6 and 3.6.10, has been entirely removed.


PR incoming



Discussion:

Resolving patch:
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -167,7 +167,6 @@ async def run_async_server(args):
             # custom_functions=[],  # allow custom handling
             framer=args.framer,  # The framer strategy to use
             # handler=None,  # handler for each session
-            # TBD allow_reuse_address=True,  # allow the reuse of an address
             # ignore_missing_slaves=True,  # ignore request to a missing slave
             # broadcast_enable=False,  # treat unit_id 0 as broadcast address,
             # timeout=1,  # waiting time for request to complete
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -84,7 +84,6 @@ def run_sync_server(args):
             # custom_functions=[],  # allow custom handling
             framer=args.framer,  # The framer strategy to use
             # TBD handler=None,  # handler for each session
-            # TBD allow_reuse_address=True,  # allow the reuse of an address
             # ignore_missing_slaves=True,  # ignore request to a missing slave
             # broadcast_enable=False,  # treat unit_id 0 as broadcast address,
             # timeout=1,  # waiting time for request to complete
diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py
--- a/pymodbus/server/async_io.py
+++ b/pymodbus/server/async_io.py
@@ -689,7 +689,6 @@ def __init__(
         identity=None,
         address=None,
         handler=None,
-        allow_reuse_address=False,
         allow_reuse_port=False,
         defer_start=False,  # pylint: disable=unused-argument
         backlog=20,  # pylint: disable=unused-argument
@@ -737,7 +736,6 @@ def __init__(
         self.serving = self.loop.create_future()
         self.factory_parms = {
             "local_addr": self.address,
-            "reuse_address": allow_reuse_address,
             "reuse_port": allow_reuse_port,
             "allow_broadcast": True,
         }


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
async serial server isn't explicitly started by StartAsyncSerialServer
Now my python modbus server isn't replying to the client talking to it on the serial port. It was working with 3.1.0, it fails with 3.1.1, and it's not because of the logging changes. I'll investigate...

Meanwhile, found a typo:
tcp.py line 213:
`            if self.params.host.startswith("unit:"):`

"unit" should be "unix", since it's about unix sockets...

===

I found the issue, it works now.

In 3.1.0, StartAsyncSerialServer() calls server.start()
In 3.1.1 it does not and returns the server object.

So I added .start() in my code on the return value of StartAsyncSerialServer(), and now the server serves.

I wonder if this is a bug in my code, perhaps I was supposed to call .start(), but it feels weird that a function called StartAsyncSerialServer() does not actually start the server. Hmm...

_Originally posted by @peufeu2 in https://github.com/pymodbus-dev/pymodbus/issues/1279#issuecomment-1400424302_
            


Discussion:
The call to `start()` was indeed removed in [`925660`](https://github.com/pymodbus-dev/pymodbus/pull/1256/files#diff-2b868d687ff9a33d19e875a6454786b499fb360e483cd5fa94bbd826198eb7deL1153).
hmmm seems like a real bug. Pull requests are welcome.

Resolving patch:
diff --git a/pymodbus/server/async_io.py b/pymodbus/server/async_io.py
--- a/pymodbus/server/async_io.py
+++ b/pymodbus/server/async_io.py
@@ -1263,6 +1263,7 @@ async def StartAsyncSerialServer(  # pylint: disable=invalid-name,dangerous-defa
     )
     if not defer_start:
         job = _serverList(server, custom_functions, not defer_start)
+        await server.start()
         await job.run()
     return server
 


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
REPL client Remove `unit` argument
<!--
Please use the Pymodbus gitter channel at https://gitter.im/pymodbus_dev/Lobby or Stack Overflow(tag [pymodbus](https://stackoverflow.com/questions/tagged/pymodbus) for
support questions.

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://github.com/riptideio/pymodbus/issues
    * check the discussions forum https://github.com/riptideio/pymodbus/discussions
    * prepare a short, runnable example that reproduce the issue with the latest development version of Pymodbus
-->

### Versions

* Python:
* OS:
* Pymodbus:
* Modbus Hardware (if used):

### Pymodbus Specific
* Server: tcp/rtu/ascii - NA
* Client: tcp/rtu/ascii - REPL tcp

### Description

Run REPL client to interact with modbus server

### Code and Logs

<img width="561" alt="image" src="https://user-images.githubusercontent.com/9276974/212352120-db97d9ec-feba-4a55-a72b-bf82bf383745.png">

<img width="576" alt="image" src="https://user-images.githubusercontent.com/9276974/212352174-51b45a43-ac93-49ac-9682-1e041b8d0c8e.png">




Discussion:
I think that also affects the json data being passed.

Resolving patch:
diff --git a/pymodbus/repl/client/helper.py b/pymodbus/repl/client/helper.py
--- a/pymodbus/repl/client/helper.py
+++ b/pymodbus/repl/client/helper.py
@@ -164,7 +164,7 @@ def _get_requests(members):
     )
     commands = {
         f"client.{c[0]}": Command(
-            f"client.{c[0]}", argspec(c[1]), inspect.getdoc(c[1]), unit=True
+            f"client.{c[0]}", argspec(c[1]), inspect.getdoc(c[1]), unit=False
         )
         for c in commands
         if not c[0].startswith("_")


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
Can't run pymodbus.simulator --help
<!--

Before opening a new issue, make sure you do the following:
    * check that your issue isn't already filed: https://github.com/pymodbus-dev/pymodbus/issues
    * check the discussions forum https://github.com/pymodbus-dev/pymodbus/discussions
    * prepare a short, runnable example that reproduce the issue with the latest development version of Pymodbus

    Before opening a new issue, make sure you do the following
-->

### Versions

* Python: 3.10.6
* OS: Linux
* Pymodbus: 3.1.3
* Modbus Hardware (if used):

### Description

Trying to run `pymodbus.simulator --help` fails:

```
<coroutine object main at 0x7efcc073cf90>
sys:1: RuntimeWarning: coroutine 'main' was never awaited
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
```

The `main` function used as entry point for the simulator is an async function: https://github.com/pymodbus-dev/pymodbus/blob/12859d0b82cc215a18ac757fe9319cdf1f9ec890/pymodbus/server/simulator/main.py#L113

It can't be used directly as an entry point. The entry point should be a function using `asyncio.run`.



Discussion:
Looks like a bug, but the workaround is simple. 

Resolving patch:
diff --git a/pymodbus/server/simulator/main.py b/pymodbus/server/simulator/main.py
--- a/pymodbus/server/simulator/main.py
+++ b/pymodbus/server/simulator/main.py
@@ -47,10 +47,6 @@
 from pymodbus.server.simulator.http_server import ModbusSimulatorServer
 
 
-async def run():
-    """Run simulator."""
-
-
 def get_commandline():
     """Get command line arguments."""
     parser = argparse.ArgumentParser(
@@ -110,13 +106,12 @@ def get_commandline():
     return cmd_args
 
 
-async def main():
+def main():
     """Run server."""
     cmd_args = get_commandline()
     task = ModbusSimulatorServer(**cmd_args)
-
-    await task.run_forever()
+    asyncio.run(task.run_forever(), debug=True)
 
 
 if __name__ == "__main__":
-    asyncio.run(main(), debug=True)
+    main()


Test patch:
Repository: pymodbus-dev/pymodbus

Issue:
pymodbus.simulator fails with no running event loop
### Versions

* Python: 3.9.2
* OS: Debian Bullseye
* Pymodbus: 3.1.3 latest dev branch
* Modbus Hardware (if used):

### Pymodbus Specific
* Server: tcp - sync/async
* Client: tcp - sync/async

### Description

Executing pymodbus.simulator from the commandline results in the following error:

```
$ pymodbus.simulator
10:39:28 INFO  logging:74 Start simulator
Traceback (most recent call last):
  File "/usr/local/bin/pymodbus.simulator", line 33, in <module>
    sys.exit(load_entry_point('pymodbus===3.1.x', 'console_scripts', 'pymodbus.simulator')())
  File "/usr/local/lib/python3.9/dist-packages/pymodbus/server/simulator/main.py", line 112, in main
    task = ModbusSimulatorServer(**cmd_args)
  File "/usr/local/lib/python3.9/dist-packages/pymodbus/server/simulator/http_server.py", line 134, in __init__
    server["loop"] = asyncio.get_running_loop()
RuntimeError: no running event loop
```
NOTE: I am running this from the pymodbus/server/simulator/ folder, so it picks up the example [setup.json](https://github.com/pymodbus-dev/pymodbus/blob/dev/pymodbus/server/simulator/setup.json) file.

Manually specifying available options from the commandline results in the same error as well:
```
$ pymodbus.simulator \
  --http_host 0.0.0.0 \
  --http_port 8080 \
  --modbus_server server \
  --modbus_device device \
  --json_file ~/git/pymodbus/pymodbus/server/simulator/setup.json

11:24:07 INFO  logging:74 Start simulator
Traceback (most recent call last):
  File "/usr/local/bin/pymodbus.simulator", line 33, in <module>
    sys.exit(load_entry_point('pymodbus===3.1.x', 'console_scripts', 'pymodbus.simulator')())
  File "/usr/local/lib/python3.9/dist-packages/pymodbus/server/simulator/main.py", line 112, in main
    task = ModbusSimulatorServer(**cmd_args)
  File "/usr/local/lib/python3.9/dist-packages/pymodbus/server/simulator/http_server.py", line 134, in __init__
    server["loop"] = asyncio.get_running_loop()
RuntimeError: no running event loop
```



Discussion:

Resolving patch:
diff --git a/pymodbus/server/simulator/main.py b/pymodbus/server/simulator/main.py
--- a/pymodbus/server/simulator/main.py
+++ b/pymodbus/server/simulator/main.py
@@ -106,11 +106,16 @@ def get_commandline():
     return cmd_args
 
 
-def main():
-    """Run server."""
+async def run_main():
+    """Run server async."""
     cmd_args = get_commandline()
     task = ModbusSimulatorServer(**cmd_args)
-    asyncio.run(task.run_forever(), debug=True)
+    await task.run_forever()
+
+
+def main():
+    """Run server."""
+    asyncio.run(run_main(), debug=True)
 
 
 if __name__ == "__main__":


Test patch: