# Path: puresnmp/exc.py
# class Timeout(socket.timeout):
#     """
#     Wrapper for network timeouts.
# 
#     This wraps both "socket.timeout" and "asyncio.TimeoutError"
#     """
# 
#     def __init__(self, message: str) -> None:
#         super().__init__()
#         self.message = message
# 
# Path: puresnmp/typevars.py
# class SocketInfo:
#     """
#     A simple tuple containing an IP address and port number
#     """
# 
#     address: str
#     port: int
# 
# class SocketResponse:
#     """
#     Metadata for socket responses
#     """
# 
#     data: bytes
#     info: SocketInfo


import logging
import socket
from ipaddress import ip_address
from time import time
from typing import TYPE_CHECKING, Generator
from x690.util import visible_octets  # type: ignore
from .exc import Timeout
from .typevars import SocketInfo, SocketResponse
    from typing import Optional
            LOG.debug("Received packet:\n%s", hexdump)

        return response

    def listen(self, bind_address="0.0.0.0", port=162):  # pragma: no cover
        # type: (str, int) -> Generator[SocketResponse, None, None]
        """
        Sets up a listening UDP socket and returns a generator over recevied
        packets::

            >>> transport = Transport()
            >>> for seq, packet in enumerate(transport.listen()):
            ...     print(seq, repr(packet))
            0, b'...'
            1, b'...'
            2, b'...'

        .. note::

            This defaults to the standard SNMP Trap port 162. This is a
            privileged port so processes using this port must run as root!
        """
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
            sock.bind((bind_address, port))
            while True:
                request, addr = sock.recvfrom(self.buffer_size)
                if LOG.isEnabledFor(logging.DEBUG):
                    hexdump = visible_octets(request)
                    LOG.debug("Received packet:\n%s", hexdump)


# Path: puresnmp/exc.py
# class Timeout(socket.timeout):
#     """
#     Wrapper for network timeouts.
# 
#     This wraps both "socket.timeout" and "asyncio.TimeoutError"
#     """
# 
#     def __init__(self, message: str) -> None:
#         super().__init__()
#         self.message = message
# 
# Path: puresnmp/typevars.py
# class SocketInfo:
#     """
#     A simple tuple containing an IP address and port number
#     """
# 
#     address: str
#     port: int
# 
# class SocketResponse:
#     """
#     Metadata for socket responses
#     """
# 
#     data: bytes
#     info: SocketInfo


# Path: puresnmp/transport.py
import logging
import socket
from ipaddress import ip_address
from time import time
from typing import TYPE_CHECKING, Generator
from x690.util import visible_octets  # type: ignore
from .exc import Timeout
from .typevars import SocketInfo, SocketResponse
    from typing import Optional

            LOG.debug("Received packet:\n%s", hexdump)

        return response

    def listen(self, bind_address="0.0.0.0", port=162):  # pragma: no cover
        # type: (str, int) -> Generator[SocketResponse, None, None]
        """
        Sets up a listening UDP socket and returns a generator over recevied
        packets::

            >>> transport = Transport()
            >>> for seq, packet in enumerate(transport.listen()):
            ...     print(seq, repr(packet))
            0, b'...'
            1, b'...'
            2, b'...'

        .. note::

            This defaults to the standard SNMP Trap port 162. This is a
            privileged port so processes using this port must run as root!
        """
        with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock:
            sock.bind((bind_address, port))
            while True:
                request, addr = sock.recvfrom(self.buffer_size)
                if LOG.isEnabledFor(logging.DEBUG):
                    hexdump = visible_octets(request)
                    LOG.debug("Received packet:\n%s", hexdump)


                yield SocketResponse(request, SocketInfo(addr[0], addr[1]))