# Path: puresnmp/const.py
# MAX_VARBINDS = 2147483647
# 
# Path: puresnmp/exc.py
# class EmptyMessage(SnmpError):
#     """
#     Raised when trying to decode an SNMP-Message with no content.
#     """
# 
# class ErrorResponse(SnmpError):
#     """
#     A superclass used when the SNMP agent responded with additional error
#     information.
# 
#     Instances of ``ErrorResponse`` have two attributes concerning the error:
# 
#     * ``error_status`` the raw (int) value of the error-status as returned by
#       the SNMP agent.
#     * ``offending_oid`` the OID identified in the error message which caused
#       the error.
#     """
# 
#     DEFAULT_MESSAGE = "unknown error"
# 
#     @staticmethod
#     def construct(error_status, offending_oid, message=""):
#         # type: (int, Optional[ObjectIdentifier], str) -> ErrorResponse
#         """
#         Creates a new instance of an ErrorResponse class, using the proper
#         subclass for the given *error_status* value. The message is optional,
#         and if not specified, will use the default message for the given class.
#         """
#         if error_status == 1:
#             return TooBig(offending_oid, message)
#         if error_status == 2:
#             return NoSuchOID(offending_oid, message)
#         if error_status == 3:
#             return BadValue(offending_oid, message)
#         if error_status == 4:
#             return ReadOnly(offending_oid, message)
#         if error_status == 5:
#             return GenErr(offending_oid, message)
#         if error_status == 6:
#             return NoAccess(offending_oid, message)
#         return ErrorResponse(error_status, offending_oid, message)
# 
#     def __init__(self, error_status, offending_oid, message=""):
#         # type: (int, Optional[ObjectIdentifier], str) -> None
#         super().__init__(
#             "%s (status-code: %r) on OID %s"
#             % (
#                 message or self.DEFAULT_MESSAGE,
#                 error_status,
#                 offending_oid if offending_oid != None else "unknown",
#             )
#         )
#         self.error_status = error_status
#         self.offending_oid = offending_oid
# 
# class NoSuchOID(ErrorResponse):
#     """
#     This error is returned in any of the following cases:
# 
#     * the targeted OID does not support "snmp-set" operations
#     * the targeted OID does not exist.
#     * the targeted OID is an SMI aggregate type.
#     * the targeted OID does not precede a known name in the MIB view.
#     """
# 
#     DEFAULT_MESSAGE = "No such name/oid"
# 
#     def __init__(self, offending_oid, message=""):
#         # type: (Optional[ObjectIdentifier], str) -> None
#         super().__init__(2, offending_oid, message)
# 
# class TooManyVarbinds(SnmpError):
#     """
#     Exception which is raised when the number of VarBinds exceeds the limit
#     defined in RFC3416.
#     device.
#     """
# 
#     def __init__(self, num_oids):
#         # type: (int) -> None
#         super().__init__(
#             "Too many VarBinds (%d) in one request!"
#             " RFC3416 limits requests to %d!" % (num_oids, MAX_VARBINDS)
#         )
#         self.num_oids = num_oids
# 
# Path: puresnmp/snmp.py
# class VarBind:
#     """
#     A "VarBind" is a 2-tuple containing an object-identifier and the
#     corresponding value.
#     """
# 
#     # TODO: This class should be split in two for both the raw and pythonic
#     #       API, that would simplify the typing of both "oid" and "value"a lot
#     #       and keep things explicit
#     oid: ObjectIdentifier = ObjectIdentifier(0)
#     value: Union[PyType, Type, None] = None
# 
#     def __init__(self, oid, value):
#         # type: (Union[ObjectIdentifier, str], PyType) -> None
#         if not isinstance(oid, (ObjectIdentifier, str)):
#             raise TypeError(
#                 "OIDs for VarBinds must be ObjectIdentifier or str"
#                 " instances! Your value: %r" % oid
#             )
#         if isinstance(oid, str):
#             oid = ObjectIdentifier.from_string(oid)
#         self.oid = oid
#         self.value = value
# 
#     def __iter__(self) -> Iterator[Union[ObjectIdentifier, PyType]]:
#         return iter([self.oid, self.value])
# 
#     def __getitem__(self, idx: int) -> Union[PyType, Type, None]:
#         return list(self)[idx]
# 
#     def __lt__(self, other):
#         # type: (Any) -> bool
#         return (self.oid, self.value) < (other.oid, other.value)
# 
#     def __eq__(self, other):
#         # type: (Any) -> bool
#         return (self.oid, self.value) == (other.oid, other.value)
# 
#     def __hash__(self):
#         # type: () -> int
#         return hash((self.oid, self.value))
# 
#     def __repr__(self):
#         # type: () -> str
#         return "VarBind(%r, %r)" % (self.oid, self.value)
# 
# Path: puresnmp/typevars.py
# class SocketInfo:
#     """
#     A simple tuple containing an IP address and port number
#     """
# 
#     address: str
#     port: int


from typing import TYPE_CHECKING, Any, Iterable, List, Tuple, Union, cast
from x690.types import (  # type: ignore
    Integer,
    Null,
    ObjectIdentifier,
    Sequence,
    Type,
    pop_tlv,
)
from x690.util import TypeInfo, encode_length, to_bytes  # type: ignore
from .const import MAX_VARBINDS
from .exc import EmptyMessage, ErrorResponse, NoSuchOID, TooManyVarbinds
from .snmp import VarBind
from .typevars import SocketInfo
    from typing import Iterator, Optional


class GetNextRequest(GetRequest):
    """
    Represents an SNMP GetNext Request.
    """

    TAG = 1


class SetRequest(PDU):
    """
    Represents an SNMP SET Request.
    """

    TAG = 3


class BulkGetRequest(Type):  # type: ignore
    """
    Represents a SNMP GetBulk request
    """

    # pylint: disable=abstract-method

    TYPECLASS = TypeInfo.CONTEXT
    TAG = 5

    def __init__(self, request_id, non_repeaters, max_repeaters, *oids):
        # type: (int, int, int, ObjectIdentifier) -> None

# Path: puresnmp/const.py
# MAX_VARBINDS = 2147483647
# 
# Path: puresnmp/exc.py
# class EmptyMessage(SnmpError):
#     """
#     Raised when trying to decode an SNMP-Message with no content.
#     """
# 
# class ErrorResponse(SnmpError):
#     """
#     A superclass used when the SNMP agent responded with additional error
#     information.
# 
#     Instances of ``ErrorResponse`` have two attributes concerning the error:
# 
#     * ``error_status`` the raw (int) value of the error-status as returned by
#       the SNMP agent.
#     * ``offending_oid`` the OID identified in the error message which caused
#       the error.
#     """
# 
#     DEFAULT_MESSAGE = "unknown error"
# 
#     @staticmethod
#     def construct(error_status, offending_oid, message=""):
#         # type: (int, Optional[ObjectIdentifier], str) -> ErrorResponse
#         """
#         Creates a new instance of an ErrorResponse class, using the proper
#         subclass for the given *error_status* value. The message is optional,
#         and if not specified, will use the default message for the given class.
#         """
#         if error_status == 1:
#             return TooBig(offending_oid, message)
#         if error_status == 2:
#             return NoSuchOID(offending_oid, message)
#         if error_status == 3:
#             return BadValue(offending_oid, message)
#         if error_status == 4:
#             return ReadOnly(offending_oid, message)
#         if error_status == 5:
#             return GenErr(offending_oid, message)
#         if error_status == 6:
#             return NoAccess(offending_oid, message)
#         return ErrorResponse(error_status, offending_oid, message)
# 
#     def __init__(self, error_status, offending_oid, message=""):
#         # type: (int, Optional[ObjectIdentifier], str) -> None
#         super().__init__(
#             "%s (status-code: %r) on OID %s"
#             % (
#                 message or self.DEFAULT_MESSAGE,
#                 error_status,
#                 offending_oid if offending_oid != None else "unknown",
#             )
#         )
#         self.error_status = error_status
#         self.offending_oid = offending_oid
# 
# class NoSuchOID(ErrorResponse):
#     """
#     This error is returned in any of the following cases:
# 
#     * the targeted OID does not support "snmp-set" operations
#     * the targeted OID does not exist.
#     * the targeted OID is an SMI aggregate type.
#     * the targeted OID does not precede a known name in the MIB view.
#     """
# 
#     DEFAULT_MESSAGE = "No such name/oid"
# 
#     def __init__(self, offending_oid, message=""):
#         # type: (Optional[ObjectIdentifier], str) -> None
#         super().__init__(2, offending_oid, message)
# 
# class TooManyVarbinds(SnmpError):
#     """
#     Exception which is raised when the number of VarBinds exceeds the limit
#     defined in RFC3416.
#     device.
#     """
# 
#     def __init__(self, num_oids):
#         # type: (int) -> None
#         super().__init__(
#             "Too many VarBinds (%d) in one request!"
#             " RFC3416 limits requests to %d!" % (num_oids, MAX_VARBINDS)
#         )
#         self.num_oids = num_oids
# 
# Path: puresnmp/snmp.py
# class VarBind:
#     """
#     A "VarBind" is a 2-tuple containing an object-identifier and the
#     corresponding value.
#     """
# 
#     # TODO: This class should be split in two for both the raw and pythonic
#     #       API, that would simplify the typing of both "oid" and "value"a lot
#     #       and keep things explicit
#     oid: ObjectIdentifier = ObjectIdentifier(0)
#     value: Union[PyType, Type, None] = None
# 
#     def __init__(self, oid, value):
#         # type: (Union[ObjectIdentifier, str], PyType) -> None
#         if not isinstance(oid, (ObjectIdentifier, str)):
#             raise TypeError(
#                 "OIDs for VarBinds must be ObjectIdentifier or str"
#                 " instances! Your value: %r" % oid
#             )
#         if isinstance(oid, str):
#             oid = ObjectIdentifier.from_string(oid)
#         self.oid = oid
#         self.value = value
# 
#     def __iter__(self) -> Iterator[Union[ObjectIdentifier, PyType]]:
#         return iter([self.oid, self.value])
# 
#     def __getitem__(self, idx: int) -> Union[PyType, Type, None]:
#         return list(self)[idx]
# 
#     def __lt__(self, other):
#         # type: (Any) -> bool
#         return (self.oid, self.value) < (other.oid, other.value)
# 
#     def __eq__(self, other):
#         # type: (Any) -> bool
#         return (self.oid, self.value) == (other.oid, other.value)
# 
#     def __hash__(self):
#         # type: () -> int
#         return hash((self.oid, self.value))
# 
#     def __repr__(self):
#         # type: () -> str
#         return "VarBind(%r, %r)" % (self.oid, self.value)
# 
# Path: puresnmp/typevars.py
# class SocketInfo:
#     """
#     A simple tuple containing an IP address and port number
#     """
# 
#     address: str
#     port: int


# Path: puresnmp/pdu.py
from typing import TYPE_CHECKING, Any, Iterable, List, Tuple, Union, cast
from x690.types import (  # type: ignore
    Integer,
    Null,
    ObjectIdentifier,
    Sequence,
    Type,
    pop_tlv,
)
from x690.util import TypeInfo, encode_length, to_bytes  # type: ignore
from .const import MAX_VARBINDS
from .exc import EmptyMessage, ErrorResponse, NoSuchOID, TooManyVarbinds
from .snmp import VarBind
from .typevars import SocketInfo
    from typing import Iterator, Optional



class GetNextRequest(GetRequest):
    """
    Represents an SNMP GetNext Request.
    """

    TAG = 1


class SetRequest(PDU):
    """
    Represents an SNMP SET Request.
    """

    TAG = 3


class BulkGetRequest(Type):  # type: ignore
    """
    Represents a SNMP GetBulk request
    """

    # pylint: disable=abstract-method

    TYPECLASS = TypeInfo.CONTEXT
    TAG = 5

    def __init__(self, request_id, non_repeaters, max_repeaters, *oids):
        # type: (int, int, int, ObjectIdentifier) -> None

        if len(oids) > MAX_VARBINDS: