Repository navigation
const: generalise register_alias from AppType to every pcapkit.const enum #842
Description
Split out of #838 at the maintainer's direction. His framing, verbatim:
register_aliasis an API on each Enum, and it only touches the concrete Enum
class it serves; AppType is the exception where it must goes to the underlying
transport protocol registry Enum class.In this case,
ETHwill become an alias to IANA's defaultETHERNETname and is
onlyregister_alias'ed when PyShark being used. We might also check other PDML
attributes to extend other Wireshark's display-filter names as well.
Today it is bespoke to one registry. register_alias exists only on
AppType (pcapkit/const/reg/apptype/apptype.py, from #807). Its docstring scopes
itself deliberately to the per-transport port registry: TCP.register_alias(...) must
never touch UDP, so an alias registered on one transport cannot leak onto a transport
IANA never assigned it. It mints through extend_enum, which is the caller-named path
#775 deliberately preserves.
The design questions this has to answer:
- What does "this registry alone" mean for an enum that is not per-transport? On
AppTypethe boundary is the transport class; elsewhere there is no analogue, so
the generalised contract needs stating rather than inheriting. - Does a generalised
register_aliasbelong in the shared template
(pcapkit/vendor/default.py), giving all 105 generated registries the method, or
only where a caller needs it? The shared template reaches 26 registries directly;
the other 79 carry their ownprocess()or template — see Registries mint a permanent member for every unrecognised value: 1,169 extend_enum sites across 113 registries #775's census. AppType's override routes to the underlying transport registry. What is the hook
that lets one registry opt into different routing without the template knowing
about it?- Lazy registration:
ETHshould only exist while pyshark is in use. What registers
it, when, and does anything unregister it — a process-wide alias that outlives the
engine that wanted it is the same class of surprise Registries mint a permanent member for every unrecognised value: 1,169 extend_enum sites across 113 registries #775 removed. - Which other Wireshark display-filter names are worth aliasing, and from which PDML
attribute are they read?pyshark/packet/layers/xml_layer.pytakes the layer name
from<proto name=…>; the maintainer suggests other attributes may carry more.
Not blocking #838, which carries a trivial local fix for the eth case per the
same ruling.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsDone
Activity
JarryShaw commentedon Sep 27, 2026
EhterType.register_aliaswill only touchEtherTypeitself, whilstAppType.register_aliaswill touch one ofTCP/UDP/SCTP/DDCP/etc. depending on the*transportargument.pcapkit.vendorclass who maintains their own template override.AppTyperegistry,register_aliasonly happens to the caller Enum class itself, no routing needed.pcapkit.toolkit.pysharkwhen we do theimport pysharkcall.JarryShaw commentedon Sep 27, 2026
Recorded, verbatim:
That settles 1-3 as a template question rather than a design one: the shared method in
pcapkit/vendor/default.pydoes the no-routing case,AppTypekeeps its override, andthe cost is the same shared-vs-bespoke split #775 measured — the bespoke vendor modules
each need the method too.
One consequence of (4) worth stating once, since you have ruled and I am not
re-opening it.
extend_enummutates the class permanently for the process, so analias registered at
import pysharktime is not unregistered when the engine goesaway: a program that runs the pyshark engine and then the scapy one will still have
LinkType.ETHpresent. That is probably harmless — it resolves to the right memberrather than a minted
-1— but it means "only when PyShark being used" is true ofregistration, not of lifetime.
Worth knowing about the timing, and it helps:
pcapkit/foundation/engines/pyshark.py:236imports
pcapkit.toolkit.pysharklazily inside the run method, not at packageimport. So registration happens the first time the pyshark engine actually runs, not
when someone imports
pcapkit— which is closer to engine-scoped than the phrasingsuggests.
(5) is in flight. A read-only investigation is enumerating what a PDML
<proto>element actually carries and which filter names can be justified against Wireshark's
dissector registrations. #838 meanwhile lands only the two that are unambiguous —
eth→ETHERNETandtr→IEEE802_5— and deliberately omitssll,fr,ipand
ipv6, each of which is shared by two or three DLTs. I will post the fullenumeration here when it lands.
JarryShaw commentedon Sep 27, 2026
for this, it is expected and accepted by me. it's like
import pysharkwill load the module into cache and memory anyways, so having its aliases registered as permanent members ofpcapkit.constis just part of the import's setup process. we dont have to overthink/overdesign on the lifecycle management thingy.JarryShaw commentedon Sep 27, 2026
Design measurements in. Two findings change the plan, both verified by me.
1.
register_aliasdoes not dispatch today — generalising means adding that, notpreserving it. Your (1) says
AppType.register_alias"will touch one ofTCP/UDP/SCTP/DDCPdepending on the*transportargument". Measured:It refuses on the base and works only when called on a subclass.
get/get_all/_dispatchdo takeprotoand delegate;register_aliasnever did.2. "Alias" means two structurally different things, and that is the real design
risk. On a plain
IntEnuman alias is a second name for the same member; onAppTypeit is a new member. Measured onLinkType:versus
TCP.register_alias, which grewlen(list(TCP))by one. One name over twosemantics invites callers to assume they match.
Also measured: aenum already enforces the safety boundary —
extend_enumwith acolliding name raises
TypeErrorfor both same-value and different-value cases andleaves nothing partial (
9999 in _value2member_map_→False). So the generic methodneeds
ValueErrortranslation for consistency, not new protection. And a runtime aliasis indistinguishable from a shipped one:
LinkTypealready shipsI2C_LINUXas analias of
IPMB_LINUXat 209, so__members__ − _member_names_was non-empty beforeanyone called anything.
On your (2), the split is better than I told the investigation. A single edit to
LINEinpcapkit/vendor/default.pyreaches 105 of 121 const modules; 16 needper-module work — the bespoke-
context()set, which isftp/{command,return_code},http/{method,status_code},ipv6/extension_header, the fourmh/*_flag,pcapng/option_type,tcp/flags, and the fivereg/apptype/*. I had briefed 26/95,which is the
process()axis — that governs member generation, not which helpermethods get emitted. Wrong axis, my error. And the override vehicle already exists:
today's
register_aliastext lives inpcapkit/vendor/reg/apptype/apptype.py:544,inside its bespoke
BASEtemplate.On your (4) and (5) — one hypothesis does not survive. pyshark reads only
xml_obj.attrib['name']from a PDML<proto>and discards the element(
pyshark/packet/layers/xml_layer.py:16-32; the comment says the lxml objects are toomemory-inefficient to keep). So "check other PDML attributes" would require parsing
PDML in pcapkit rather than using pyshark's
Packet. I could not enumerate the real<proto>attribute set — notsharkon this host and pyshark ships no sample — so thatstays unverified; Wireshark's
epan/print.cis where to read it.Justifiable to map:
eth,sll/sll2,wlan/radiotap. Not justifiable:ipand
ipv6, because a capture rooted there came fromRAW,IPV4,IPV6orNULLandthe filter name cannot say which — mapping it is what the original ruling refused. And a
trap for "register them all": 20 of 50 candidate filter names uppercase straight onto
an existing
LinkTypemember name by coincidence, includingMPLSandNETLINK,which are Wireshark protocol dissectors that merely share a name with a DLT. There is
no derivable rule — only a curated table.
Three calls that are yours: whether the generic
register_aliasrequires an existingmember at the value (AppType does,
registerdoes not — this decides whether it is"alias" or just "second name"); whether both operations keep the same method name given
they differ structurally; and whether those 20 coincidental matches get blessed, mapped
explicitly, or refused.
JarryShaw commentedon Sep 27, 2026
Recorded, verbatim: "for this, it is expected and accepted by me. it's like
import pysharkwill load the module into cache and memory anyways, so having its aliasesregistered as permanent members of
pcapkit.constis just part of the import's setupprocess. we dont have to overthink/overdesign on the lifecycle management thingy."
That closes question (4) — the one the investigation called hardest. Option (a):
register once on the pyshark import path, never undone, no teardown machinery. Noting
for the record that the investigation's own preference was (c), resolve through a plain
table and never touch the enum; your ruling overrides it and I am not re-arguing it. The
measurement that makes (a) defensible is already on this issue: on a plain
IntEnumanalias adds a name to
__members__and changes nothing else —_member_names_,iteration,
_value2member_map_and everyreprare untouched — so the residue isconfined to name lookup, which is precisely what you want it for.
One sequencing consequence, no decision needed: #838 ships the curated table form for
the two unambiguous names (
eth,tr) because it must not wait for this design. Onceregister_aliaslands here,Enum_LinkType.get('ETH')will resolve on its own andFILTER_NAME_TO_LINKTYPEbecomes redundant for whatever it covers — so this issueshould delete the entries it supersedes rather than leave two sources of truth. Worth
doing in the same PR that adds the aliases.
Still open from your (5), and the only thing blocking a full alias table: which
Wireshark filter names to register. The measured constraints are above —
ip/ipv6cannot be mapped at all, and 20 of 50 candidates uppercase onto an existing member name
by coincidence, so the set has to be curated rather than derived.
JarryShaw commentedon Sep 27, 2026
okay, then
register_aliason AppType should also have thisprotoand delegate convention.JarryShaw commentedon Sep 27, 2026
Recorded, verbatim: "okay, then
register_aliason AppType should also have thisprotoand delegate convention."So the design is now specified apart from one item:
register_alias(value, name)inpcapkit/vendor/default.py'sLINE,reaching 105 of 121 const modules from one edit. Validate the value already
carries a member; translate aenum's
TypeErroron a colliding name toValueErrorfor consistency with the rest of the package.
AppTypeoverrides it inBASE/TRANSPORT, gainingprotoand delegatingthrough the existing
_dispatch— matchingget/get_all. This is the part thatdoes not exist today, per the measurement above.
AppTyperegistries: no routing, the caller class itself.16 modules need the method by hand beyond the template edit:
ftp/command,ftp/return_code,http/method,http/status_code,ipv6/extension_header, the fourmh/*_flag,pcapng/option_type,tcp/flags, and the fivereg/apptype/*.Checkable blocker for implementation: #838 merged.
Not a preference — a file conflict. This work edits
pcapkit/vendor/default.pyandregenerates the const tree, and #838 currently rewrites 117 files including all 105
of those const modules. Starting before it merges guarantees conflicts and a re-derivation.
Labelled
blockedaccordingly;wipremoved since no PR covers it yet.The design record above is complete enough to implement from the moment #838 lands and
(5) is answered.
JarryShaw commentedon Sep 27, 2026
For non-
AppTyperegistries, "Alias" is custom/caller-opt-in names, which are not recorded in IANA registrars, unlikeAppType.check PyShark/WireShark documentation then? they should have the names documented somewhere I believe.
actually i think it should always be for an existing member - unless AppType (and concrete enums) requires to call it on non-existing members.
same name for same convention - i think my ruling above makes them eseentially the same.
so if the filter is same name as an existing enum, that's good, no alias needed.
JarryShaw commentedon Sep 27, 2026
Recorded, verbatim — all four judgement calls answered:
So the contract is: always require an existing member, one method name, and the
plain-enum case is explicitly the caller-opt-in, non-IANA half. That framing resolves
the structural asymmetry I raised — the two operations differ in mechanism but share the
convention, which is what the name is for.
On the last one, I want to check rather than agree straight away. "If the filter is
same name as an existing enum, that's good, no alias needed" is already how #838
behaves — the table is consulted first, then
Enum_LinkType.getcatches anything thatuppercases onto a member. The risk is that some of those 20 matches are coincidence,
not identity:
mplsandnetlinkare Wireshark protocol dissectors that happen toshare a name with a DLT, so the rule would silently accept them for a capture whose link
layer is something else.
My prior is that it is harmless — pyshark strips
geninfo/frame, solayers[0]is thefirst dissected protocol, and
mplsappearing there implies MPLS is the link layer.But that is reasoning, not measurement, and a wrong DLT is silent corruption rather than
a raise. Dispatching a read-only check of exactly that: for each of the 20, whether the
filter name is reachable as
layers[0]only from the DLT sharing its name.Same investigation takes your documentation pointer — Wireshark's protocol-abbreviation
reference and
epan/print.cfor the real PDML<proto>attribute set, which I could notenumerate here (no
tsharkon the host, no sample in the pyshark distribution). That isthe last open input for the alias list.
fix(vendor): stop get() minting; _missing_ fixed for 21 of 105 (#775)
39 remaining items
docs(corekit): state the enum.py rulings as statements, not quotations
docs(corekit): drop an alias exception that no registry implements
docs(corekit): scope the four-method contract to the registry tier
docs(corekit): state the enum.py rulings as statements, not quotations
docs(corekit): drop an alias exception that no registry implements
docs(corekit): scope the four-method contract to the registry tier
docs(corekit): render #842's AppType hedge instead of denying it
docs(corekit): state the enum.py rulings as statements, not quotations
docs(corekit): drop an alias exception that no registry implements
docs(corekit): scope the four-method contract to the registry tier
docs(corekit): render #842's AppType hedge instead of denying it
docs(corekit): name the real exception set, and stop narrowing #842's…
docs(corekit,tests): state what the enum tiers actually declare and d…