Repository navigation
refactor(ipv6): rename IPv6_GenericExt to IPv6_Ext and make it the base for all 8 extension headers #917
Description
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 # MERGEDLanding 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.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Activity
JarryShaw commentedon Sep 29, 2026
Unblocked — #904 merged as
b3551cb63, andpcapkit/protocols/internet/ipv6_generic_ext.pyis now onmain, which is the file this renames.Removing
blocked, markingwip, worker dispatched. Nothing in the design above changes; the required test — everyIPv6_Extsubclass overridesname,aliasand__index__, and__index__returns a realEnum_TransType— is what makes the one-class-two-roles merge safe rather than merely tidy, and it is not optional.Landing this discharges #895's blocker in turn: once
ESP(IPsec, IPv6_Ext)subclasses the base, ESP gains the extension-mode contract by construction rather than by hand-writing the three_extfguards.refactor(ipv6): rename IPv6_GenericExt to IPv6_Ext and make it the sh…
refactor(ipv6): rename IPv6_GenericExt to IPv6_Ext and make it the sh…
refactor(ipv6): rename IPv6_GenericExt to IPv6_Ext and make it the sh…
docs(pcapkit,ci): cite the issue a defect belongs to, not the pull re…
docs(pcapkit,ci): cite the issue a defect belongs to, not the pull re…