Follow-up to #904, on the owner's ruling. Verbatim:
My initial thought was to directly rename IPv6_GenericExt to IPv6_Ext, and use it as the base class and the unknown extension header's fallback parser.
and, approving the plan to do it here rather than inside #904:
Go
The change
Rename IPv6_GenericExt to IPv6_Ext (pcapkit/protocols/internet/ipv6_generic_ext.py → ipv6_ext.py), and make the one class serve both roles: the base every IPv6 extension header subclasses, and the concrete fallback parser for an RFC 6564-conforming header this library does not implement.
Re-parent all 8 members of the family, per the owner's earlier ruling on #891 that ESP joins because IANA marks it Y in the IPv6 Extension Header column:
IPv6_Route IPv6_Frag IPv6_Opts HIP MH -> subclass IPv6_Ext
AH -> AH(IPsec, IPv6_Ext)
ESP -> ESP(IPsec, IPv6_Ext)
Why one class is viable — measured, not assumed
The obvious objection is that IPv6_GenericExt.__index__ raises UnsupportedCall, because one instance stands in for many extension-header codes and a @classmethod has nowhere to put a per-instance value. That would be fatal for a base of six numbered headers — except every one of them defines __index__ on itself:
IPv6_Route 43 IPv6_Frag 44 IPv6_Opts 60
HIP 139 MH 135 AH 51 each `defined on` itself
So the raising member is shadowed everywhere and harms nothing. Same for name and alias, which each header declares as its own Literal. The class already carries the extension contract too: its payload and protochain return ... | NoReturn, the _extf guard shape AH has at ah.py:75,87,99.
What the merge costs, and the required mitigation
It removes a safety net for anything added later. A seventh extension header that forgets to override inherits concrete values and silently reports itself as "Generic IPv6 Extension Header" with alias IPv6-GenericExt, and __index__ raising instead of returning its number. Today's six are correct only because all six happen to shadow everything; nothing enforces it.
So this change must ship a test asserting that every IPv6_Ext subclass overrides name, alias and __index__, and that __index__ returns a real Enum_TransType rather than raising. That converts an invariant currently held by luck into one held by CI, and is the reason the merge is safe rather than merely tidy.
Blocked on #904
#904 adds the very file this renames, and holds esp.py and mh.py besides. Unblocks with:
gh pr view 904 -R JarryShaw/PyPCAPKit --json state -q .state # MERGED
Landing this also unblocks #895, whose blocked label names the IPv6_Ext base as its blocker: ESP gains the extension-mode contract by construction once it subclasses the base, rather than by hand-writing the three _extf guards.
Follow-up to #904, on the owner's ruling. Verbatim:
and, approving the plan to do it here rather than inside #904:
The change
Rename
IPv6_GenericExttoIPv6_Ext(pcapkit/protocols/internet/ipv6_generic_ext.py→ipv6_ext.py), and make the one class serve both roles: the base every IPv6 extension header subclasses, and the concrete fallback parser for an RFC 6564-conforming header this library does not implement.Re-parent all 8 members of the family, per the owner's earlier ruling on #891 that
ESPjoins because IANA marks itYin theIPv6 Extension Headercolumn:Why one class is viable — measured, not assumed
The obvious objection is that
IPv6_GenericExt.__index__raisesUnsupportedCall, because one instance stands in for many extension-header codes and a@classmethodhas nowhere to put a per-instance value. That would be fatal for a base of six numbered headers — except every one of them defines__index__on itself:So the raising member is shadowed everywhere and harms nothing. Same for
nameandalias, which each header declares as its ownLiteral. The class already carries the extension contract too: itspayloadandprotochainreturn... | NoReturn, the_extfguard shapeAHhas atah.py:75,87,99.What the merge costs, and the required mitigation
It removes a safety net for anything added later. A seventh extension header that forgets to override inherits concrete values and silently reports itself as "Generic IPv6 Extension Header" with alias
IPv6-GenericExt, and__index__raising instead of returning its number. Today's six are correct only because all six happen to shadow everything; nothing enforces it.So this change must ship a test asserting that every
IPv6_Extsubclass overridesname,aliasand__index__, and that__index__returns a realEnum_TransTyperather than raising. That converts an invariant currently held by luck into one held by CI, and is the reason the merge is safe rather than merely tidy.Blocked on #904
#904 adds the very file this renames, and holds
esp.pyandmh.pybesides. Unblocks with:gh pr view 904 -R JarryShaw/PyPCAPKit --json state -q .state # MERGEDLanding this also unblocks #895, whose
blockedlabel names theIPv6_Extbase as its blocker:ESPgains the extension-mode contract by construction once it subclasses the base, rather than by hand-writing the three_extfguards.