ethereum / hexbytes

Python `bytes` subclass that decodes hex, with a readable console output
MIT License
27 stars 19 forks source link

hex() method behaves differently than the bytes type #14

Closed palkeo closed 10 months ago

palkeo commented 3 years ago

Hey,

The HexBytes type inherits from bytes, as can be seen in that code snippet:

>>> isinstance(HexBytes(b'\0'), bytes)
True

Because of that I would expect it to behave like bytes, only with added functionality but no breaking behavior. However, it does add a 0x prefix:

>>> HexBytes(b'\0').hex()
'0x00'
>>> b'\0'.hex()
'00'

So if you pass HexBytes instance to well-behaved code that use the standard practice of checking isinstance(), this code would break. I think it should either not inherit from bytes or not break existing bytes function, because this makes it confusing and likely to introduce bugs in existing code.

carver commented 1 year ago

Yeah, I'd probably do it differently if I could go back in time. It was convenient, but probably the wrong choice to break the LSP by changing the syntax of hex(). It's now a breaking change to remove the 0x, though. So I added it to that list.

XiaoHuiHui233 commented 1 year ago

Hello, I wonder when will this feature plan to release? Since hexbytes.HexBytes inherits from bytes, HexBytes can be inputted wherever bytes are required. And sometimes we don't know that the library we call uses it, which leads to some strange problems. For example, I tried to customize a data class that stores bytes, and customized its output function. For friendly printing, I manually defined the prefix 0x for the serialization of this field. However, because some libraries used HexBytes, the return type annotation for me was bytes, which caused the prefix 0x to appear twice in output like 0x0x.

from hexbytes import HexBytes

class MyClass:
    def __init__(self, value: bytes):
        self.value = value
    def to_str(self) -> None:
        return f"0x{self.value.hex()}"

# make bytes to be str
print(MyClass(b'hello').to_str())  # 0x68656c6c6f
# sometime we dont know the type is HexBytes, because HexBytes is subclass of bytes
print(MyClass(HexBytes(b'hello')).to_str())  # 0x0x68656c6c6f