Summary
MH._make_opt_mn_id documents bytes | str as accepted identifier types for
every MN-ID subtype, but each subtype's field accepts only one of the two.
Passing the other builds a schema that cannot be packed, and fails with a bare
stdlib exception rather than an in-library one.
This is the same family as #467 (which covered int) and #448 (which covered
the IPv6_Address width), but it is about bytes/str and is not fixed by
either.
Reproduction
Measured on fa128959e (current main). Identical on PR #468's branch, so
pre-existing and not a regression from that PR — I checked both trees.
from pcapkit.const.mh.option import Option
from pcapkit.const.mh.mn_id_subtype import MNIDSubtype
from pcapkit.protocols.internet.mh import MH
proto = object.__new__(MH)
# NAI's field is text, so bytes cannot be encoded
proto._make_opt_mn_id(Option.MN_ID_OPTION_TYPE,
subtype=MNIDSubtype.NAI,
identifier=b'node@example').pack()
# IMSI's field is raw octets, so str cannot be packed
proto._make_opt_mn_id(Option.MN_ID_OPTION_TYPE,
subtype=MNIDSubtype.IMSI,
identifier='12345').pack()
NAI + bytes -> AttributeError: 'bytes' object has no attribute 'encode'
IMSI + str -> struct.error: argument for 's' must be a bytes object
NAI + str -> length=13, packs 15 octets (correct)
So the defect is symmetric: bytes fails for the one text subtype, and str
fails for the octet subtypes. Only the matching pairing works.
Both failures happen at pack() rather than at construction, and neither is an
instance of pcapkit.utilities.exceptions.BaseError`, so a caller cannot catch
them with the library's own exception hierarchy.
Why it matters
The type union is documented, not accidental — _make_opt_mn_id's identifier
parameter is annotated bytes | str | IPv6Address | int, and the
Schema_MNIDOption.__init__ stub carries a matching union. So the signature
promises bytes and str interchangeably for all subtypes when in fact the
choice is fixed per subtype by whether that subtype's field is a StringField
or a BytesField.
NAI is the only text subtype; IMSI, P_TMSI, EUI_48_address,
EUI_64_address, GUTI and DUID are octet subtypes.
Suggested direction
The same shape as #467's fix: decide per subtype, then either convert (encode a
str for the octet subtypes, decode bytes for NAI — noting that an encoding
has to be chosen and named if so) or reject with a ProtocolError saying which
type that subtype takes. #467's fix already added exactly that kind of
per-subtype rejection for int, so the mechanism and message style are in
place to extend.
Whichever is chosen, the documented union should end up describing what is
actually accepted.
Provenance
Surfaced while verifying #468 (the fix for #467). Its author flagged the
bytes-for-NAI half and correctly left it out of scope; the str-for-octet-
subtypes half is mine, found while measuring the first. Both verified on main
and on the PR branch before filing.
Summary
MH._make_opt_mn_iddocumentsbytes | stras accepted identifier types forevery MN-ID subtype, but each subtype's field accepts only one of the two.
Passing the other builds a schema that cannot be packed, and fails with a bare
stdlib exception rather than an in-library one.
This is the same family as #467 (which covered
int) and #448 (which coveredthe
IPv6_Addresswidth), but it is aboutbytes/strand is not fixed byeither.
Reproduction
Measured on
fa128959e(currentmain). Identical on PR #468's branch, sopre-existing and not a regression from that PR — I checked both trees.
So the defect is symmetric:
bytesfails for the one text subtype, andstrfails for the octet subtypes. Only the matching pairing works.
Both failures happen at
pack()rather than at construction, and neither is aninstance ofpcapkit.utilities.exceptions.BaseError`, so a caller cannot catchthem with the library's own exception hierarchy.
Why it matters
The type union is documented, not accidental —
_make_opt_mn_id'sidentifierparameter is annotated
bytes | str | IPv6Address | int, and theSchema_MNIDOption.__init__stub carries a matching union. So the signaturepromises
bytesandstrinterchangeably for all subtypes when in fact thechoice is fixed per subtype by whether that subtype's field is a
StringFieldor a
BytesField.NAIis the only text subtype;IMSI,P_TMSI,EUI_48_address,EUI_64_address,GUTIandDUIDare octet subtypes.Suggested direction
The same shape as #467's fix: decide per subtype, then either convert (encode a
strfor the octet subtypes, decodebytesfor NAI — noting that an encodinghas to be chosen and named if so) or reject with a
ProtocolErrorsaying whichtype that subtype takes. #467's fix already added exactly that kind of
per-subtype rejection for
int, so the mechanism and message style are inplace to extend.
Whichever is chosen, the documented union should end up describing what is
actually accepted.
Provenance
Surfaced while verifying #468 (the fix for #467). Its author flagged the
bytes-for-NAI half and correctly left it out of scope; thestr-for-octet-subtypes half is mine, found while measuring the first. Both verified on
mainand on the PR branch before filing.