66 lines
1.7 KiB
Python
66 lines
1.7 KiB
Python
import sys
|
|
from typing import (
|
|
TYPE_CHECKING,
|
|
Type,
|
|
Union,
|
|
cast,
|
|
overload,
|
|
)
|
|
|
|
from ._utils import (
|
|
to_bytes,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from typing import (
|
|
SupportsIndex,
|
|
)
|
|
|
|
BytesLike = Union[bool, bytearray, bytes, int, str, memoryview]
|
|
|
|
|
|
class HexBytes(bytes):
|
|
"""
|
|
HexBytes is a *very* thin wrapper around the python built-in :class:`bytes` class.
|
|
|
|
It has these three changes:
|
|
1. Accepts more initializing values, like hex strings, non-negative integers,
|
|
and booleans
|
|
2. Returns hex with prefix '0x' from :meth:`HexBytes.hex`
|
|
3. The representation at console is in hex
|
|
"""
|
|
|
|
def __new__(cls: Type[bytes], val: BytesLike) -> "HexBytes":
|
|
bytesval = to_bytes(val)
|
|
return cast(HexBytes, super().__new__(cls, bytesval)) # type: ignore # https://github.com/python/typeshed/issues/2630 # noqa: E501
|
|
|
|
def hex(
|
|
self, sep: Union[str, bytes] = None, bytes_per_sep: "SupportsIndex" = 1
|
|
) -> str:
|
|
"""
|
|
Output hex-encoded bytes, with an "0x" prefix.
|
|
|
|
Everything following the "0x" is output exactly like :meth:`bytes.hex`.
|
|
"""
|
|
return "0x" + super().hex()
|
|
|
|
@overload
|
|
def __getitem__(self, key: "SupportsIndex") -> int: # noqa: F811
|
|
...
|
|
|
|
@overload # noqa: F811
|
|
def __getitem__(self, key: slice) -> "HexBytes": # noqa: F811
|
|
...
|
|
|
|
def __getitem__( # noqa: F811
|
|
self, key: Union["SupportsIndex", slice]
|
|
) -> Union[int, bytes, "HexBytes"]:
|
|
result = super().__getitem__(key)
|
|
if hasattr(result, "hex"):
|
|
return type(self)(result)
|
|
else:
|
|
return result
|
|
|
|
def __repr__(self) -> str:
|
|
return f"HexBytes({self.hex()!r})"
|