Repository: XKNX/xknx
Pull request #921 (2022-04-17 20:29:47)

Purify `xknx.io` modules
<!--
  You are awesome! Thanks for contributing to our project!
  Please, DO NOT DELETE ANY TEXT from this template!.
-->
## Description
<!--
Please include a summary of the change and which issue is fixed.
Please also include relevant motivation and context.
List any dependencies that are required for this change.
-->
- Remove xknx form every class in the io.request_response package
- Remove xknx form io.transport package and io.secure_session and io.self_description modules

🧹

Fixes # (issue)

## Type of change
<!--
Please tick the applicable options.
NOTE: Ticking multiple options most likely indicates
that your change is to big and it is suggested to split it into several smaller PRs.
-->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update

## Checklist:

- [ ] I have performed a self-review of my own code
- [ ] The documentation has been adjusted accordingly
- [ ] The changes generate no new warnings
- [ ] Tests have been added that prove the fix is effective or that the feature works
- [ ] The changes are documented in the changelog
- [ ] The Homeassistant plugin has been adjusted in case of new config options


codecov[bot]: # [Codecov](https://codecov.io/gh/XKNX/xknx/pull/921?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) Report
> Merging [#921](https://codecov.io/gh/XKNX/xknx/pull/921?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) (05b4423) into [main](https://codecov.io/gh/XKNX/xknx/commit/98fd2c24ce3e58a29f3bb1c07c55eb46f4126311?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) (98fd2c2) will **decrease** coverage by `0.00%`.
> The diff coverage is `100.00%`.

> :exclamation: Current head 05b4423 differs from pull request most recent head 846867c. Consider uploading reports for the commit 846867c to get more accurate results

[![Impacted file tree graph](https://codecov.io/gh/XKNX/xknx/pull/921/graphs/tree.svg?width=650&height=150&src=pr&token=irWbIygS84&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX)](https://codecov.io/gh/XKNX/xknx/pull/921?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX)

```diff
@@            Coverage Diff             @@
##             main     #921      +/-   ##
==========================================
- Coverage   95.60%   95.59%   -0.01%     
==========================================
  Files         130      130              
  Lines        7774     7769       -5     
==========================================
- Hits         7432     7427       -5     
  Misses        342      342              
```


| [Impacted Files](https://codecov.io/gh/XKNX/xknx/pull/921?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) | Coverage Δ | |
|---|---|---|
| [xknx/io/gateway\_scanner.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9nYXRld2F5X3NjYW5uZXIucHk=) | `86.23% <ø> (ø)` | |
| [xknx/io/request\_response/connectionstate.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL2Nvbm5lY3Rpb25zdGF0ZS5weQ==) | `100.00% <ø> (ø)` | |
| [xknx/io/request\_response/request\_response.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL3JlcXVlc3RfcmVzcG9uc2UucHk=) | `100.00% <ø> (ø)` | |
| [xknx/io/routing.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yb3V0aW5nLnB5) | `64.44% <ø> (ø)` | |
| [xknx/io/request\_response/authenticate.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL2F1dGhlbnRpY2F0ZS5weQ==) | `100.00% <100.00%> (ø)` | |
| [xknx/io/request\_response/connect.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL2Nvbm5lY3QucHk=) | `100.00% <100.00%> (ø)` | |
| [xknx/io/request\_response/disconnect.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL2Rpc2Nvbm5lY3QucHk=) | `100.00% <100.00%> (ø)` | |
| [xknx/io/request\_response/session.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL3Nlc3Npb24ucHk=) | `100.00% <100.00%> (ø)` | |
| [xknx/io/request\_response/tunnelling.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9yZXF1ZXN0X3Jlc3BvbnNlL3R1bm5lbGxpbmcucHk=) | `100.00% <100.00%> (ø)` | |
| [xknx/io/secure\_session.py](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX#diff-eGtueC9pby9zZWN1cmVfc2Vzc2lvbi5weQ==) | `96.37% <100.00%> (ø)` | |
| ... and [4 more](https://codecov.io/gh/XKNX/xknx/pull/921/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=XKNX) | |


Patch:
diff --git a/changelog.md b/changelog.md
index b80c9db3..7013685c 100644
--- a/changelog.md
+++ b/changelog.md
@@ -7,6 +7,8 @@
 - Include base class in `DPTBase.parse_transcoder()` lookup
 - Move `levels` instance attribute form `GroupAddress` to `address_format` class variable
 - Remove xknx form every class in the knxip package: CEMIFrame, KNXIPFrame and KNXIPBody (and subclasses)
+- Remove xknx form every class in the io.request_response package
+- Remove xknx form io.transport package and io.secure_session and io.self_description modules
 
 ## 0.20.3 Threading fixes 2022-04-15
 
diff --git a/examples/example_disconnect.py b/examples/example_disconnect.py
index 45ecb7cc..15aae0a6 100644
--- a/examples/example_disconnect.py
+++ b/examples/example_disconnect.py
@@ -24,9 +24,7 @@ async def main():
         print("Gateway does not support tunneling")
         return
 
-    udp_transport = UDPTransport(
-        xknx, (gateway.local_ip, 0), (gateway.ip_addr, gateway.port)
-    )
+    udp_transport = UDPTransport((gateway.local_ip, 0), (gateway.ip_addr, gateway.port))
 
     await udp_transport.connect()
     local_hpai = HPAI(*udp_transport.getsockname())
@@ -34,7 +32,7 @@ async def main():
     for i in range(0, 255):
 
         conn_state = ConnectionState(
-            xknx, udp_transport, communication_channel_id=i, local_hpai=local_hpai
+            udp_transport, communication_channel_id=i, local_hpai=local_hpai
         )
 
         await conn_state.start()
@@ -42,7 +40,7 @@ async def main():
         if conn_state.success:
             print("Disconnecting ", i)
             disconnect = Disconnect(
-                xknx, udp_transport, communication_channel_id=i, local_hpai=local_hpai
+                udp_transport, communication_channel_id=i, local_hpai=local_hpai
             )
 
             await disconnect.start()
diff --git a/xknx/io/gateway_scanner.py b/xknx/io/gateway_scanner.py
index 7a31adcc..405d7d4c 100644
--- a/xknx/io/gateway_scanner.py
+++ b/xknx/io/gateway_scanner.py
@@ -225,9 +225,8 @@ class GatewayScanner:
         logger.debug("Searching on %s / %s", interface, ip_addr)
 
         udp_transport = UDPTransport(
-            self.xknx,
-            (ip_addr, 0),
-            (self.xknx.multicast_group, self.xknx.multicast_port),
+            local_addr=(ip_addr, 0),
+            remote_addr=(self.xknx.multicast_group, self.xknx.multicast_port),
             multicast=True,
         )
 
diff --git a/xknx/io/request_response/authenticate.py b/xknx/io/request_response/authenticate.py
index f260d55b..e949c8e2 100644
--- a/xknx/io/request_response/authenticate.py
+++ b/xknx/io/request_response/authenticate.py
@@ -9,7 +9,6 @@ from .request_response import RequestResponse
 
 if TYPE_CHECKING:
     from xknx.io.transport import KNXIPTransport
-    from xknx.xknx import XKNX
 
 
 class Authenticate(RequestResponse):
@@ -17,13 +16,12 @@ class Authenticate(RequestResponse):
 
     def __init__(
         self,
-        xknx: XKNX,
         transport: KNXIPTransport,
         user_id: int,
         message_authentication_code: bytes,
     ):
         """Initialize Session class."""
-        super().__init__(xknx, transport, SessionStatus, timeout_in_seconds=10)
+        super().__init__(transport, SessionStatus, timeout_in_seconds=10)
         self.user_id = user_id
         self.message_authentication_code = message_authentication_code
         self.response: SessionStatus | None = None
diff --git a/xknx/io/request_response/connect.py b/xknx/io/request_response/connect.py
index 9d39fc08..90f7dfd9 100644
--- a/xknx/io/request_response/connect.py
+++ b/xknx/io/request_response/connect.py
@@ -15,15 +15,18 @@ from .request_response import RequestResponse
 
 if TYPE_CHECKING:
     from xknx.io.transport import KNXIPTransport
-    from xknx.xknx import XKNX
 
 
 class Connect(RequestResponse):
     """Class to send a ConnectRequest and wait for ConnectResponse."""
 
-    def __init__(self, xknx: XKNX, transport: KNXIPTransport, local_hpai: HPAI):
+    def __init__(
+        self,
+        transport: KNXIPTransport,
+        local_hpai: HPAI,
+    ):
         """Initialize Connect class."""
-        super().__init__(xknx, transport, ConnectResponse)
+        super().__init__(transport, ConnectResponse)
         self.communication_channel = 0
         self.data_endpoint = HPAI()
         self.identifier = 0
diff --git a/xknx/io/request_response/connectionstate.py b/xknx/io/request_response/connectionstate.py
index 5a335bad..7e004faa 100644
--- a/xknx/io/request_response/connectionstate.py
+++ b/xknx/io/request_response/connectionstate.py
@@ -10,7 +10,6 @@ from .request_response import RequestResponse
 
 if TYPE_CHECKING:
     from xknx.io.transport import KNXIPTransport
-    from xknx.xknx import XKNX
 
 
 class ConnectionState(RequestResponse):
@@ -18,14 +17,12 @@ class ConnectionState(RequestResponse):
 
     def __init__(
         self,
-        xknx: XKNX,
         transport: KNXIPTransport,
         communication_channel_id: int,
         local_hpai: HPAI,
     ):
         """Initialize ConnectionState class."""
         super().__init__(
-            xknx,
             transport,
             ConnectionStateResponse,
             timeout_in_seconds=CONNECTIONSTATE_REQUEST_TIMEOUT,
diff --git a/xknx/io/request_response/disconnect.py b/xknx/io/request_response/disconnect.py
index e8ae1e0c..64482acc 100644
--- a/xknx/io/request_response/disconnect.py
+++ b/xknx/io/request_response/disconnect.py
@@ -9,7 +9,6 @@ from .request_response import RequestResponse
 
 if TYPE_CHECKING:
     from xknx.io.transport import KNXIPTransport
-    from xknx.xknx import XKNX
 
 
 class Disconnect(RequestResponse):
@@ -17,13 +16,12 @@ class Disconnect(RequestResponse):
 
     def __init__(
         self,
-        xknx: XKNX,
         transport: KNXIPTransport,
         communication_channel_id: int,
         local_hpai: HPAI,
     ):
         """Initialize Disconnect class."""
-        super().__init__(xknx, transport, DisconnectResponse)
+        super().__init__(transport, DisconnectResponse)
         self.communication_channel_id = communication_channel_id
         self.local_hpai = local_hpai
 
diff --git a/xknx/io/request_response/request_response.py b/xknx/io/request_response/request_response.py
index 6ac72fd5..85db907f 100644
--- a/xknx/io/request_response/request_response.py
+++ b/xknx/io/request_response/request_response.py
@@ -7,15 +7,11 @@ from __future__ import annotations
 
 import asyncio
 import logging
-from typing import TYPE_CHECKING
 
 from xknx.exceptions import CommunicationError
 from xknx.io.transport import KNXIPTransport
 from xknx.knxip import HPAI, ErrorCode, KNXIPBody, KNXIPBodyResponse, KNXIPFrame
 
-if TYPE_CHECKING:
-    from xknx.xknx import XKNX
-
 logger = logging.getLogger("xknx.log")
 
 
@@ -24,13 +20,11 @@ class RequestResponse:
 
     def __init__(
         self,
-        xknx: XKNX,
         transport: KNXIPTransport,
         awaited_response_class: type[KNXIPBody],
         timeout_in_seconds: float = 1.0,
     ):
         """Initialize RequstResponse class."""
-        self.xknx = xknx
         self.transport = transport
         self.awaited_response_class: type[KNXIPBody] = awaited_response_class
         self.response_received_event = asyncio.Event()
diff --git a/xknx/io/request_response/session.py b/xknx/io/request_response/session.py
index 1bfb03b4..66410052 100644
--- a/xknx/io/request_response/session.py
+++ b/xknx/io/request_response/session.py
@@ -9,18 +9,19 @@ from .request_response import RequestResponse
 
 if TYPE_CHECKING:
     from xknx.io.transport import KNXIPTransport
-    from xknx.xknx import XKNX
 
 
 class Session(RequestResponse):
     """Class to send a SessionRequest and wait for SessionResponse."""
 
     def __init__(
-        self, xknx: XKNX, transport: KNXIPTransport, ecdh_client_public_key: bytes
+        self,
+        transport: KNXIPTransport,
+        ecdh_client_public_key: bytes,
     ):
         """Initialize Session class."""
         # TODO: increase timeout to timeoutAuthentication: 10sec ?
-        super().__init__(xknx, transport, SessionResponse)
+        super().__init__(transport, SessionResponse)
         self.ecdh_client_public_key = ecdh_client_public_key
         # TODO: make RequestResponse generic for response class
         # maybe replace self.success with self.response None check
diff --git a/xknx/io/request_response/tunnelling.py b/xknx/io/request_response/tunnelling.py
index dd3f7b84..6c77b139 100644
--- a/xknx/io/request_response/tunnelling.py
+++ b/xknx/io/request_response/tunnelling.py
@@ -16,7 +16,6 @@ from .request_response import RequestResponse
 if TYPE_CHECKING:
     from xknx.io.transport import UDPTransport
     from xknx.telegram import IndividualAddress, Telegram
-    from xknx.xknx import XKNX
 
 
 class Tunnelling(RequestResponse):
@@ -26,7 +25,6 @@ class Tunnelling(RequestResponse):
 
     def __init__(
         self,
-        xknx: XKNX,
         transport: UDPTransport,
         data_endpoint: tuple[str, int] | None,
         telegram: Telegram,
@@ -38,7 +36,7 @@ class Tunnelling(RequestResponse):
         self.data_endpoint_addr = data_endpoint
         self.src_address = src_address
 
-        super().__init__(xknx, transport, TunnellingAck)
+        super().__init__(transport, TunnellingAck)
 
         self.telegram = telegram
         self.sequence_counter = sequence_counter
diff --git a/xknx/io/routing.py b/xknx/io/routing.py
index 487546a6..71d2a920 100644
--- a/xknx/io/routing.py
+++ b/xknx/io/routing.py
@@ -47,9 +47,8 @@ class Routing(Interface):
         self.local_ip = local_ip
 
         self.udp_transport = UDPTransport(
-            self.xknx,
-            (local_ip, 0),
-            (self.xknx.multicast_group, self.xknx.multicast_port),
+            local_addr=(local_ip, 0),
+            remote_addr=(self.xknx.multicast_group, self.xknx.multicast_port),
             multicast=True,
         )
 
diff --git a/xknx/io/secure_session.py b/xknx/io/secure_session.py
index 489b0774..a9da671f 100644
--- a/xknx/io/secure_session.py
+++ b/xknx/io/secure_session.py
@@ -3,7 +3,7 @@ from __future__ import annotations
 
 import asyncio
 import logging
-from typing import TYPE_CHECKING, Callable
+from typing import Callable
 
 from cryptography.hazmat.primitives.asymmetric.x25519 import (
     X25519PrivateKey,
@@ -38,9 +38,6 @@ from .const import SESSION_KEEPALIVE_RATE, XKNX_SERIAL_NUMBER
 from .request_response import Authenticate, Session
 from .transport import KNXIPTransport, TCPTransport
 
-if TYPE_CHECKING:
-    from xknx.xknx import XKNX
-
 logger = logging.getLogger("xknx.log")
 knx_logger = logging.getLogger("xknx.knx")
 
@@ -56,7 +53,6 @@ class SecureSession(TCPTransport):
 
     def __init__(
         self,
-        xknx: XKNX,
         remote_addr: tuple[str, int],
         user_id: int,
         user_password: str,
@@ -65,7 +61,6 @@ class SecureSession(TCPTransport):
     ) -> None:
         """Initialize SecureSession class."""
         super().__init__(
-            xknx,
             remote_addr=remote_addr,
             connection_lost_cb=connection_lost_cb,
         )
@@ -96,7 +91,6 @@ class SecureSession(TCPTransport):
         self._sequence_number = 0
         self._sequence_number_received = -1
         request_session = Session(
-            self.xknx,
             transport=self,
             ecdh_client_public_key=self.public_key,
         )
@@ -110,7 +104,6 @@ class SecureSession(TCPTransport):
         self.initialized = True
 
         request_authentication = Authenticate(
-            self.xknx,
             transport=self,
             user_id=self.user_id,
             message_authentication_code=authenticate_mac,
diff --git a/xknx/io/self_description.py b/xknx/io/self_description.py
index 9b44786e..a217fa48 100644
--- a/xknx/io/self_description.py
+++ b/xknx/io/self_description.py
@@ -15,7 +15,6 @@ from .util import find_local_ip
 
 if TYPE_CHECKING:
     from xknx.io.transport import KNXIPTransport
-    from xknx.xknx import XKNX
 
 logger = logging.getLogger("xknx.log")
 
@@ -23,7 +22,6 @@ DESCRIPTION_TIMEOUT: Final = 2
 
 
 async def request_description(
-    xknx: XKNX,
     gateway_ip: str,
     gateway_port: int = DEFAULT_MCAST_PORT,
     local_ip: str | None = None,
@@ -33,7 +31,6 @@ async def request_description(
     """Set up a UDP transport to request a description from a KNXnet/IP device."""
     _local_ip = local_ip or find_local_ip(gateway_ip)
     transport = UDPTransport(
-        xknx,
         local_addr=(_local_ip, local_port),
         remote_addr=(gateway_ip, gateway_port),
         multicast=False,
@@ -52,8 +49,7 @@ async def request_description(
         local_hpai = HPAI(*local_addr)
 
     description_query = DescriptionQuery(
-        xknx,
-        transport,
+        transport=transport,
         local_hpai=local_hpai,
     )
     await description_query.start()
@@ -64,9 +60,12 @@ async def request_description(
 class DescriptionQuery:
     """Class to send a DescriptionRequest and wait for DescriptionResponse."""
 
-    def __init__(self, xknx: XKNX, transport: KNXIPTransport, local_hpai: HPAI):
+    def __init__(
+        self,
+        transport: KNXIPTransport,
+        local_hpai: HPAI,
+    ) -> None:
         """Initialize Description class."""
-        self.xknx = xknx
         self.transport = transport
         self.local_hpai = local_hpai
 
diff --git a/xknx/io/transport/tcp_transport.py b/xknx/io/transport/tcp_transport.py
index d2df6e21..d9762409 100644
--- a/xknx/io/transport/tcp_transport.py
+++ b/xknx/io/transport/tcp_transport.py
@@ -8,16 +8,13 @@ from __future__ import annotations
 import asyncio
 import logging
 import time
-from typing import TYPE_CHECKING, Callable, cast
+from typing import Callable, cast
 
 from xknx.exceptions import CommunicationError, CouldNotParseKNXIP, IncompleteKNXIPFrame
 from xknx.knxip import HPAI, HostProtocol, KNXIPFrame
 
 from .ip_transport import KNXIPTransport
 
-if TYPE_CHECKING:
-    from xknx.xknx import XKNX
-
 raw_socket_logger = logging.getLogger("xknx.raw_socket")
 logger = logging.getLogger("xknx.log")
 knx_logger = logging.getLogger("xknx.knx")
@@ -55,12 +52,10 @@ class TCPTransport(KNXIPTransport):
 
     def __init__(
         self,
-        xknx: XKNX,
         remote_addr: tuple[str, int],
         connection_lost_cb: Callable[[], None] | None = None,
     ):
         """Initialize TCPTransport class."""
-        self.xknx = xknx
         self.remote_addr = remote_addr
         self.remote_hpai = HPAI(*remote_addr, protocol=HostProtocol.IPV4_TCP)
 
diff --git a/xknx/io/transport/udp_transport.py b/xknx/io/transport/udp_transport.py
index 3232d44a..d15bceb1 100644
--- a/xknx/io/transport/udp_transport.py
+++ b/xknx/io/transport/udp_transport.py
@@ -11,16 +11,13 @@ import logging
 import socket
 from sys import platform
 import time
-from typing import TYPE_CHECKING, Callable, cast
+from typing import Callable, cast
 
 from xknx.exceptions import CommunicationError, CouldNotParseKNXIP
 from xknx.knxip import HPAI, KNXIPFrame
 
 from .ip_transport import KNXIPTransport
 
-if TYPE_CHECKING:
-    from xknx.xknx import XKNX
-
 raw_socket_logger = logging.getLogger("xknx.raw_socket")
 logger = logging.getLogger("xknx.log")
 knx_logger = logging.getLogger("xknx.knx")
@@ -65,7 +62,6 @@ class UDPTransport(KNXIPTransport):
 
     def __init__(
         self,
-        xknx: XKNX,
         local_addr: tuple[str, int],
         remote_addr: tuple[str, int],
         multicast: bool = False,
@@ -75,7 +71,6 @@ class UDPTransport(KNXIPTransport):
             raise TypeError()
         if not isinstance(remote_addr, tuple):
             raise TypeError()
-        self.xknx = xknx
         self.local_addr = local_addr
         self.remote_addr = remote_addr
         self.multicast = multicast
diff --git a/xknx/io/tunnel.py b/xknx/io/tunnel.py
index 1ced9796..bfdf7612 100644
--- a/xknx/io/tunnel.py
+++ b/xknx/io/tunnel.py
@@ -183,7 +183,7 @@ class _Tunnel(Interface):
 
     async def _connect_request(self) -> bool:
         """Connect to tunnelling server. Set communication_channel and src_address."""
-        connect = Connect(self.xknx, self.transport, local_hpai=self.local_hpai)
+        connect = Connect(transport=self.transport, local_hpai=self.local_hpai)
         await connect.start()
         if connect.success:
             self.communication_channel = connect.communication_channel
@@ -214,8 +214,7 @@ class _Tunnel(Interface):
         if self.communication_channel is None:
             raise CommunicationError("No active communication channel.")
         conn_state = ConnectionState(
-            self.xknx,
-            self.transport,
+            transport=self.transport,
             communication_channel_id=self.communication_channel,
             local_hpai=self.local_hpai,
         )
@@ -226,8 +225,7 @@ class _Tunnel(Interface):
         """Disconnect from tunnel device. Delete communication_channel."""
         if self.communication_channel is not None:
             disconnect = Disconnect(
-                self.xknx,
-                self.transport,
+                transport=self.transport,
                 communication_channel_id=self.communication_channel,
                 local_hpai=self.local_hpai,
             )
@@ -244,8 +242,7 @@ class _Tunnel(Interface):
     async def request_description(self) -> GatewayDescriptor | None:
         """Request description from tunneling server."""
         description = DescriptionQuery(
-            self.xknx,
-            self.transport,
+            transport=self.transport,
             local_hpai=self.local_hpai,
         )
         await description.start()
@@ -437,9 +434,8 @@ class UDPTunnel(_Tunnel):
     def _init_transport(self) -> None:
         """Initialize transport transport."""
         self.transport = UDPTransport(
-            self.xknx,
-            (self.local_ip, self.local_port),
-            (self.gateway_ip, self.gateway_port),
+            local_addr=(self.local_ip, self.local_port),
+            remote_addr=(self.gateway_ip, self.gateway_port),
             multicast=False,
         )
 
@@ -460,13 +456,12 @@ class UDPTunnel(_Tunnel):
                 "Sending telegram failed. No active communication channel."
             )
         tunnelling = Tunnelling(
-            self.xknx,
-            self.transport,
-            self._data_endpoint_addr,
-            telegram,
-            self._src_address,
-            self.sequence_number,
-            self.communication_channel,
+            transport=self.transport,
+            data_endpoint=self._data_endpoint_addr,
+            telegram=telegram,
+            src_address=self._src_address,
+            sequence_counter=self.sequence_number,
+            communication_channel_id=self.communication_channel,
         )
         await self._wait_for_tunnelling_request_confirmation(
             send_tunneling_request_aw=tunnelling.start(), telegram=telegram
@@ -530,7 +525,6 @@ class TCPTunnel(_Tunnel):
     def _init_transport(self) -> None:
         """Initialize transport transport."""
         self.transport = TCPTransport(
-            self.xknx,
             remote_addr=(self.gateway_ip, self.gateway_port),
             connection_lost_cb=self._tunnel_lost,
         )
@@ -598,7 +592,6 @@ class SecureTunnel(TCPTunnel):
     def _init_transport(self) -> None:
         """Initialize transport transport."""
         self.transport = SecureSession(
-            self.xknx,
             remote_addr=(self.gateway_ip, self.gateway_port),
             user_id=self._user_id,
             user_password=self._user_password,


Test patch:
diff --git a/test/io_tests/request_response_tests/authenticate_test.py b/test/io_tests/request_response_tests/authenticate_test.py
index 6794c00a..ea0d2a48 100644
--- a/test/io_tests/request_response_tests/authenticate_test.py
+++ b/test/io_tests/request_response_tests/authenticate_test.py
@@ -1,7 +1,6 @@
 """Unit test for KNX/IP Authenticate Request/Response."""
 from unittest.mock import Mock, patch
 
-from xknx import XKNX
 from xknx.io.request_response import Authenticate
 from xknx.knxip import (
     HPAI,
@@ -18,12 +17,10 @@ class TestAuthenticate:
 
     async def test_authenticate(self):
         """Test authenticating to secure KNX device."""
-        xknx = XKNX()
         transport_mock = Mock()
         user_id = 123
         mac = bytes(16)
         authenticate = Authenticate(
-            xknx,
             transport_mock,
             user_id=user_id,
             message_authentication_code=mac,
diff --git a/test/io_tests/request_response_tests/connect_test.py b/test/io_tests/request_response_tests/connect_test.py
index 5f98a730..49997e22 100644
--- a/test/io_tests/request_response_tests/connect_test.py
+++ b/test/io_tests/request_response_tests/connect_test.py
@@ -1,7 +1,6 @@
 """Unit test for KNX/IP Connect Request/Response."""
 from unittest.mock import patch
 
-from xknx import XKNX
 from xknx.io.request_response import Connect
 from xknx.io.transport import UDPTransport
 from xknx.knxip import (
@@ -20,10 +19,9 @@ class TestConnect:
 
     async def test_connect(self):
         """Test connecting from KNX bus."""
-        xknx = XKNX()
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         local_hpai = HPAI(ip_addr="192.168.1.3", port=4321)
-        connect = Connect(xknx, udp_transport, local_hpai=local_hpai)
+        connect = Connect(udp_transport, local_hpai=local_hpai)
         connect.timeout_in_seconds = 0
 
         assert connect.awaited_response_class == ConnectResponse
@@ -76,10 +74,9 @@ class TestConnect:
 
     async def test_connect_route_back_true(self):
         """Test connecting from KNX bus."""
-        xknx = XKNX()
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         local_hpai = HPAI()  # route_back: No IP address, no port, UDP
-        connect = Connect(xknx, udp_transport, local_hpai=local_hpai)
+        connect = Connect(udp_transport, local_hpai=local_hpai)
         connect.timeout_in_seconds = 0
 
         assert connect.awaited_response_class == ConnectResponse
diff --git a/test/io_tests/request_response_tests/connectionstate_test.py b/test/io_tests/request_response_tests/connectionstate_test.py
index 84cb5408..49d8d462 100644
--- a/test/io_tests/request_response_tests/connectionstate_test.py
+++ b/test/io_tests/request_response_tests/connectionstate_test.py
@@ -1,7 +1,6 @@
 """Unit test for KNX/IP ConnectionState Request/Response."""
 from unittest.mock import patch
 
-from xknx import XKNX
 from xknx.io.request_response import ConnectionState
 from xknx.io.transport import UDPTransport
 from xknx.knxip import (
@@ -19,12 +18,11 @@ class TestConnectionState:
 
     async def test_connectionstate(self):
         """Test connectionstateing from KNX bus."""
-        xknx = XKNX()
         communication_channel_id = 23
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         local_hpai = HPAI(ip_addr="192.168.1.3", port=4321)
         connectionstate = ConnectionState(
-            xknx, udp_transport, communication_channel_id, local_hpai=local_hpai
+            udp_transport, communication_channel_id, local_hpai=local_hpai
         )
         connectionstate.timeout_in_seconds = 0
 
@@ -73,12 +71,11 @@ class TestConnectionState:
 
     async def test_connectionstate_route_back_true(self):
         """Test connectionstateing from KNX bus."""
-        xknx = XKNX()
         communication_channel_id = 23
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         local_hpai = HPAI()
         connectionstate = ConnectionState(
-            xknx, udp_transport, communication_channel_id, local_hpai=local_hpai
+            udp_transport, communication_channel_id, local_hpai=local_hpai
         )
         connectionstate.timeout_in_seconds = 0
 
diff --git a/test/io_tests/request_response_tests/disconnect_test.py b/test/io_tests/request_response_tests/disconnect_test.py
index 860bb6b5..e693fc0c 100644
--- a/test/io_tests/request_response_tests/disconnect_test.py
+++ b/test/io_tests/request_response_tests/disconnect_test.py
@@ -1,7 +1,6 @@
 """Unit test for KNX/IP Disconnect Request/Response."""
 from unittest.mock import patch
 
-from xknx import XKNX
 from xknx.io.request_response import Disconnect
 from xknx.io.transport import UDPTransport
 from xknx.knxip import (
@@ -19,12 +18,11 @@ class TestDisconnect:
 
     async def test_disconnect(self):
         """Test disconnecting from KNX bus."""
-        xknx = XKNX()
         communication_channel_id = 23
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         local_hpai = HPAI(ip_addr="192.168.1.3", port=4321)
         disconnect = Disconnect(
-            xknx, udp_transport, communication_channel_id, local_hpai=local_hpai
+            udp_transport, communication_channel_id, local_hpai=local_hpai
         )
         disconnect.timeout_in_seconds = 0
 
@@ -73,12 +71,11 @@ class TestDisconnect:
 
     async def test_disconnect_route_back_true(self):
         """Test disconnecting from KNX bus."""
-        xknx = XKNX()
         communication_channel_id = 23
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         local_hpai = HPAI()
         disconnect = Disconnect(
-            xknx, udp_transport, communication_channel_id, local_hpai=local_hpai
+            udp_transport, communication_channel_id, local_hpai=local_hpai
         )
         disconnect.timeout_in_seconds = 0
 
diff --git a/test/io_tests/request_response_tests/request_response_test.py b/test/io_tests/request_response_tests/request_response_test.py
index 77d07420..25de914f 100644
--- a/test/io_tests/request_response_tests/request_response_test.py
+++ b/test/io_tests/request_response_tests/request_response_test.py
@@ -4,7 +4,6 @@ from unittest.mock import AsyncMock, MagicMock, patch
 
 import pytest
 
-from xknx import XKNX
 from xknx.io.request_response import RequestResponse
 from xknx.io.transport import UDPTransport
 from xknx.knxip import DisconnectResponse, KNXIPBody
@@ -15,9 +14,8 @@ class TestConnectResponse:
 
     async def test_create_knxipframe_err(self):
         """Test if create_knxipframe of base class raises an exception."""
-        xknx = XKNX()
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
-        request_response = RequestResponse(xknx, udp_transport, DisconnectResponse)
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
+        request_response = RequestResponse(udp_transport, DisconnectResponse)
         request_response.timeout_in_seconds = 0
 
         with pytest.raises(NotImplementedError):
@@ -31,9 +29,8 @@ class TestConnectResponse:
         self, _send_request_mock, logger_debug_mock
     ):
         """Test RequestResponse: timeout. No callback shall be left."""
-        xknx = XKNX()
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
-        requ_resp = RequestResponse(xknx, udp_transport, KNXIPBody)
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
+        requ_resp = RequestResponse(udp_transport, KNXIPBody)
         requ_resp.response_received_event.wait = MagicMock(
             side_effect=asyncio.TimeoutError()
         )
@@ -52,9 +49,8 @@ class TestConnectResponse:
     )
     async def test_request_response_cancelled(self, _send_request_mock):
         """Test RequestResponse: task cancelled. No callback shall be left."""
-        xknx = XKNX()
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
-        requ_resp = RequestResponse(xknx, udp_transport, KNXIPBody)
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
+        requ_resp = RequestResponse(udp_transport, KNXIPBody)
         requ_resp.response_received_event.wait = MagicMock(
             side_effect=asyncio.CancelledError()
         )
diff --git a/test/io_tests/request_response_tests/session_test.py b/test/io_tests/request_response_tests/session_test.py
index 8f8a4eb7..c00f2e83 100644
--- a/test/io_tests/request_response_tests/session_test.py
+++ b/test/io_tests/request_response_tests/session_test.py
@@ -1,7 +1,6 @@
 """Unit test for KNX/IP Session Request/Response."""
 from unittest.mock import Mock, patch
 
-from xknx import XKNX
 from xknx.io.request_response import Session
 from xknx.knxip import (
     HPAI,
@@ -17,11 +16,9 @@ class TestSession:
 
     async def test_session(self):
         """Test authenticating to secure KNX device."""
-        xknx = XKNX()
         transport_mock = Mock()
         ecdh_public_key = bytes(16)
         session = Session(
-            xknx,
             transport_mock,
             ecdh_client_public_key=ecdh_public_key,
         )
diff --git a/test/io_tests/request_response_tests/tunnelling_test.py b/test/io_tests/request_response_tests/tunnelling_test.py
index 2120f785..49e6afe6 100644
--- a/test/io_tests/request_response_tests/tunnelling_test.py
+++ b/test/io_tests/request_response_tests/tunnelling_test.py
@@ -1,7 +1,6 @@
 """Unit test for KNX/IP Tunnelling Request/Response."""
 from unittest.mock import patch
 
-from xknx import XKNX
 from xknx.dpt import DPTArray
 from xknx.io.request_response import Tunnelling
 from xknx.io.transport import UDPTransport
@@ -22,10 +21,9 @@ class TestTunnelling:
 
     async def test_tunnelling(self):
         """Test tunnelling from KNX bus."""
-        xknx = XKNX()
         communication_channel_id = 23
         data_endpoint = ("192.168.1.2", 4567)
-        udp_transport = UDPTransport(xknx, ("192.168.1.1", 0), ("192.168.1.2", 1234))
+        udp_transport = UDPTransport(("192.168.1.1", 0), ("192.168.1.2", 1234))
         telegram = Telegram(
             destination_address=GroupAddress("1/2/3"),
             payload=GroupValueWrite(DPTArray((0x1, 0x2, 0x3))),
@@ -33,7 +31,6 @@ class TestTunnelling:
         sequence_counter = 42
         src_address = IndividualAddress("2.2.2")
         tunnelling = Tunnelling(
-            xknx,
             udp_transport,
             data_endpoint,
             telegram,
diff --git a/test/io_tests/secure_session_test.py b/test/io_tests/secure_session_test.py
index 12b54ba4..b92b3876 100644
--- a/test/io_tests/secure_session_test.py
+++ b/test/io_tests/secure_session_test.py
@@ -5,7 +5,6 @@ from unittest.mock import Mock, patch
 from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey
 import pytest
 
-from xknx import XKNX
 from xknx.exceptions import CommunicationError, CouldNotParseKNXIP
 from xknx.io.const import SESSION_KEEPALIVE_RATE
 from xknx.io.secure_session import SecureSession
@@ -57,9 +56,7 @@ class TestSecureSession:
         )
         self.patch_message_tag.start()
 
-        self.xknx = XKNX()
         self.session = SecureSession(
-            self.xknx,
             remote_addr=self.mock_addr,
             user_id=self.mock_user_id,
             user_password=self.mock_user_password,
diff --git a/test/io_tests/self_description_test.py b/test/io_tests/self_description_test.py
index 4f0e0538..c7bd8e24 100644
--- a/test/io_tests/self_description_test.py
+++ b/test/io_tests/self_description_test.py
@@ -2,7 +2,6 @@
 import asyncio
 from unittest.mock import Mock, patch
 
-from xknx import XKNX
 from xknx.io.self_description import DescriptionQuery, request_description
 from xknx.io.transport.udp_transport import UDPTransport
 from xknx.knxip import HPAI, DescriptionRequest, KNXIPFrame
@@ -13,12 +12,9 @@ class TestSelfDescription:
 
     async def test_description_query(self, time_travel):
         """Test DescriptionQuery class."""
-        xknx = XKNX()
         local_addr = ("127.0.0.1", 12345)
         remote_addr = ("127.0.0.2", 54321)
-        transport_mocked = UDPTransport(
-            xknx, local_addr=local_addr, remote_addr=remote_addr
-        )
+        transport_mocked = UDPTransport(local_addr=local_addr, remote_addr=remote_addr)
         transport_mocked.getsockname = Mock(return_value=local_addr)
         transport_mocked.send = Mock()
 
@@ -33,7 +29,7 @@ class TestSelfDescription:
             "0c 02 02 02 03 02 04 02 05 02 07 01",
         )
         description_query = DescriptionQuery(
-            xknx, transport=transport_mocked, local_hpai=HPAI(*local_addr)
+            transport=transport_mocked, local_hpai=HPAI(*local_addr)
         )
         task = asyncio.create_task(description_query.start())
         await time_travel(0)
@@ -48,7 +44,6 @@ class TestSelfDescription:
 
     async def test_request_description(self, time_travel):
         """Test request_description function."""
-        xknx = XKNX()
         local_addr = ("127.0.0.1", 12345)
         remote_addr = ("127.0.0.2", 54321)
 
@@ -61,7 +56,7 @@ class TestSelfDescription:
         ) as transport_stop_mock, patch(
             "xknx.io.self_description.DescriptionQuery.start"
         ) as description_query_start_mock:
-            await request_description(xknx, remote_addr[0])
+            await request_description(remote_addr[0])
             transport_connect_mock.assert_called_once_with()
             transport_getsockname_mock.assert_called_once_with()
             transport_stop_mock.assert_called_once_with()