# Path: h11/_util.py
# def bytesify(s: Union[bytes, bytearray, memoryview, int, str]) -> bytes:
#     # Fast-path:
#     if type(s) is bytes:
#         return s
#     if isinstance(s, str):
#         s = s.encode("ascii")
#     if isinstance(s, int):
#         raise TypeError("expected bytes-like object, not int")
#     return bytes(s)
# 
# class LocalProtocolError(ProtocolError):
#     def _reraise_as_remote_protocol_error(self) -> NoReturn:
#         # After catching a LocalProtocolError, use this method to re-raise it
#         # as a RemoteProtocolError. This method must be called from inside an
#         # except: block.
#         #
#         # An easy way to get an equivalent RemoteProtocolError is just to
#         # modify 'self' in place.
#         self.__class__ = RemoteProtocolError  # type: ignore
#         # But the re-raising is somewhat non-trivial -- you might think that
#         # now that we've modified the in-flight exception object, that just
#         # doing 'raise' to re-raise it would be enough. But it turns out that
#         # this doesn't work, because Python tracks the exception type
#         # (exc_info[0]) separately from the exception object (exc_info[1]),
#         # and we only modified the latter. So we really do need to re-raise
#         # the new type explicitly.
#         # On py3, the traceback is part of the exception object, so our
#         # in-place modification preserved it and we can just re-raise:
#         raise self
# 
# class ProtocolError(Exception):
#     """Exception indicating a violation of the HTTP/1.1 protocol.
# 
#     This as an abstract base class, with two concrete base classes:
#     :exc:`LocalProtocolError`, which indicates that you tried to do something
#     that HTTP/1.1 says is illegal, and :exc:`RemoteProtocolError`, which
#     indicates that the remote peer tried to do something that HTTP/1.1 says is
#     illegal. See :ref:`error-handling` for details.
# 
#     In addition to the normal :exc:`Exception` features, it has one attribute:
# 
#     .. attribute:: error_status_hint
# 
#        This gives a suggestion as to what status code a server might use if
#        this error occurred as part of a request.
# 
#        For a :exc:`RemoteProtocolError`, this is useful as a suggestion for
#        how you might want to respond to a misbehaving peer, if you're
#        implementing a server.
# 
#        For a :exc:`LocalProtocolError`, this can be taken as a suggestion for
#        how your peer might have responded to *you* if h11 had allowed you to
#        continue.
# 
#        The default is 400 Bad Request, a generic catch-all for protocol
#        violations.
# 
#     """
# 
#     def __init__(self, msg: str, error_status_hint: int = 400) -> None:
#         if type(self) is ProtocolError:
#             raise TypeError("tried to directly instantiate ProtocolError")
#         Exception.__init__(self, msg)
#         self.error_status_hint = error_status_hint
# 
# class RemoteProtocolError(ProtocolError):
#     pass
# 
# class Sentinel(type):
#     def __new__(
#         cls: Type[_T_Sentinel],
#         name: str,
#         bases: Tuple[type, ...],
#         namespace: Dict[str, Any],
#         **kwds: Any
#     ) -> _T_Sentinel:
#         assert bases == (Sentinel,)
#         v = super().__new__(cls, name, bases, namespace, **kwds)
#         v.__class__ = v  # type: ignore
#         return v
# 
#     def __repr__(self) -> str:
#         return self.__name__
# 
# def validate(
#     regex: Pattern[bytes], data: bytes, msg: str = "malformed data", *format_args: Any
# ) -> Dict[str, bytes]:
#     match = regex.fullmatch(data)
#     if not match:
#         if format_args:
#             msg = msg.format(*format_args)
#         raise LocalProtocolError(msg)
#     return match.groupdict()


import re
import sys
import traceback
import pytest
from typing import NoReturn
from .._util import (
    bytesify,
    LocalProtocolError,
    ProtocolError,
    RemoteProtocolError,
    Sentinel,
    validate,
)




def test_ProtocolError() -> None:
    with pytest.raises(TypeError):
        ProtocolError("abstract base class")


def test_LocalProtocolError() -> None:
    try:
        raise LocalProtocolError("foo")
    except LocalProtocolError as e:
        assert str(e) == "foo"
        assert e.error_status_hint == 400

    try:
        raise LocalProtocolError("foo", error_status_hint=418)
    except LocalProtocolError as e:
        assert str(e) == "foo"
        assert e.error_status_hint == 418

    def thunk() -> NoReturn:

# Path: h11/_util.py
# def bytesify(s: Union[bytes, bytearray, memoryview, int, str]) -> bytes:
#     # Fast-path:
#     if type(s) is bytes:
#         return s
#     if isinstance(s, str):
#         s = s.encode("ascii")
#     if isinstance(s, int):
#         raise TypeError("expected bytes-like object, not int")
#     return bytes(s)
# 
# class LocalProtocolError(ProtocolError):
#     def _reraise_as_remote_protocol_error(self) -> NoReturn:
#         # After catching a LocalProtocolError, use this method to re-raise it
#         # as a RemoteProtocolError. This method must be called from inside an
#         # except: block.
#         #
#         # An easy way to get an equivalent RemoteProtocolError is just to
#         # modify 'self' in place.
#         self.__class__ = RemoteProtocolError  # type: ignore
#         # But the re-raising is somewhat non-trivial -- you might think that
#         # now that we've modified the in-flight exception object, that just
#         # doing 'raise' to re-raise it would be enough. But it turns out that
#         # this doesn't work, because Python tracks the exception type
#         # (exc_info[0]) separately from the exception object (exc_info[1]),
#         # and we only modified the latter. So we really do need to re-raise
#         # the new type explicitly.
#         # On py3, the traceback is part of the exception object, so our
#         # in-place modification preserved it and we can just re-raise:
#         raise self
# 
# class ProtocolError(Exception):
#     """Exception indicating a violation of the HTTP/1.1 protocol.
# 
#     This as an abstract base class, with two concrete base classes:
#     :exc:`LocalProtocolError`, which indicates that you tried to do something
#     that HTTP/1.1 says is illegal, and :exc:`RemoteProtocolError`, which
#     indicates that the remote peer tried to do something that HTTP/1.1 says is
#     illegal. See :ref:`error-handling` for details.
# 
#     In addition to the normal :exc:`Exception` features, it has one attribute:
# 
#     .. attribute:: error_status_hint
# 
#        This gives a suggestion as to what status code a server might use if
#        this error occurred as part of a request.
# 
#        For a :exc:`RemoteProtocolError`, this is useful as a suggestion for
#        how you might want to respond to a misbehaving peer, if you're
#        implementing a server.
# 
#        For a :exc:`LocalProtocolError`, this can be taken as a suggestion for
#        how your peer might have responded to *you* if h11 had allowed you to
#        continue.
# 
#        The default is 400 Bad Request, a generic catch-all for protocol
#        violations.
# 
#     """
# 
#     def __init__(self, msg: str, error_status_hint: int = 400) -> None:
#         if type(self) is ProtocolError:
#             raise TypeError("tried to directly instantiate ProtocolError")
#         Exception.__init__(self, msg)
#         self.error_status_hint = error_status_hint
# 
# class RemoteProtocolError(ProtocolError):
#     pass
# 
# class Sentinel(type):
#     def __new__(
#         cls: Type[_T_Sentinel],
#         name: str,
#         bases: Tuple[type, ...],
#         namespace: Dict[str, Any],
#         **kwds: Any
#     ) -> _T_Sentinel:
#         assert bases == (Sentinel,)
#         v = super().__new__(cls, name, bases, namespace, **kwds)
#         v.__class__ = v  # type: ignore
#         return v
# 
#     def __repr__(self) -> str:
#         return self.__name__
# 
# def validate(
#     regex: Pattern[bytes], data: bytes, msg: str = "malformed data", *format_args: Any
# ) -> Dict[str, bytes]:
#     match = regex.fullmatch(data)
#     if not match:
#         if format_args:
#             msg = msg.format(*format_args)
#         raise LocalProtocolError(msg)
#     return match.groupdict()


# Path: h11/tests/test_util.py
import re
import sys
import traceback
import pytest
from typing import NoReturn
from .._util import (
    bytesify,
    LocalProtocolError,
    ProtocolError,
    RemoteProtocolError,
    Sentinel,
    validate,
)





def test_ProtocolError() -> None:
    with pytest.raises(TypeError):
        ProtocolError("abstract base class")


def test_LocalProtocolError() -> None:
    try:
        raise LocalProtocolError("foo")
    except LocalProtocolError as e:
        assert str(e) == "foo"
        assert e.error_status_hint == 400

    try:
        raise LocalProtocolError("foo", error_status_hint=418)
    except LocalProtocolError as e:
        assert str(e) == "foo"
        assert e.error_status_hint == 418

    def thunk() -> NoReturn:

        raise LocalProtocolError("a", error_status_hint=420)