mentalisttraceur / python-macaddress

BSD Zero Clause License
19 stars 5 forks source link

Default `formats`? #5

Closed mentalisttraceur closed 2 years ago

mentalisttraceur commented 2 years ago

If a hardware address class does not specify formats, but does specify a size, we could generate at least one default format string, for example like this:

'x' * (TheClass.size // 4)

But should we?

duynhaaa commented 2 years ago

Rather than giving a default format at front, I believe it is better to provide enough classes to cover most type of hardware addresses so that users won't have to think twice about creating a new one. If they do, then they probably already have their own format. Forcing them to check their own work is better than covering for them, right?

mentalisttraceur commented 2 years ago

@ahnyud Thank you, yeah, I agree.

The other relevant considerations were:

  1. Hardware addresses with no formats at all is a legitimate and supported use-case. (If you need a custom hardware address but don't need stringification or string parsing, you shouldn't be forced to define formats.)
  2. __init__, __str__, and __repr__ as initially written let through errors like AttributeError and IndexError when a class had no formats. A broken repr is generally unacceptable since a common production use for class reprs is logging and error messages, so if a repr fails you might lose information needed to diagnose a problem, or entirely mask one error with another. For the other two, those errors are unacceptably abstraction-breaking if no-formats is supported usage. (One way to resolve this is default formats, but another is a fallback in the repr and deliberate TypeError in the other two, like I've now done in d4d3ec98f074508bcaf4a867a14cc1f67d940cd0.)
  3. A decision here has mild ramifications for #4, since a metaclass or decorator can either error out for lack of formats or generate new ones at class-definition time, and an ABC can idiomatically express that formats must be defined needed by specifying formats as an abstract property.
duynhaaa commented 2 years ago
  1. Hardware addresses with no formats at all is a legitimate and supported use-case. (If you need a custom hardware address but don't need stringification or string parsing, you shouldn't be forced to define formats.)

Would you mind telling me in which situation a hardware address does not have a human-readable format? The purpose of a hardware address for us to easily identify a piece of hardware, so a string format is definitely needed.

  1. init, str, and repr as initially written let through errors like AttributeError and IndexError when a class had no formats. A broken repr is generally unacceptable since a common production use for class reprs is logging and error messages, so if a repr fails you might lose information needed to diagnose a problem, or entirely mask one error with another. For the other two, those errors are unacceptably abstraction-breaking if no-formats is supported usage. (One way to resolve this is default formats, but another is a fallback in the repr and deliberate TypeError in the other two, like I've now done in https://github.com/mentalisttraceur/python-macaddress/commit/d4d3ec98f074508bcaf4a867a14cc1f67d940cd0.)

As for this, I think that __repr__ should not depend on __str__. For debugging, a <classname>(<arguments>) is more than enough as it contains enough information to recreate the object.

mentalisttraceur commented 2 years ago

Would you mind telling me in which situation a hardware address does not have a human-readable format? The purpose of a hardware address for us to easily identify a piece of hardware, so a string format is definitely needed.

So the most common day-to-day use-case is when quickly casually experimenting, prototyping, or testing/learning/explaining.

If I'm in the Python REPL and for whatever reason I want a non-predefined address class, it's one less piece of boilerplate to worry about:

>>> from macaddress import *
>>> class A(HWAddress):
...     size = 128
... 
>>> A(0)  # just works instead of erroring out at every moment where the repr would be shown.

On the niche but production-relevant side, I'm imagining a scenario where you have hardware with some uncommon address size, and you just need to write code that reads and writes that address at the machine level, as a byte string (like to and from some network packets or the API for that hardware).

Some code just doesn't have much reason to talk to humans and has good reason to talk in ways that are not human readable - some code is just implementing machines talking to other machines, etc.

(Of course, in those cases, humans probably have some convention or standard for writing those addresses in human-readable ways, so if I was asked to write such code, I'd probably add that to the formats of the relevant class definition anyway.)