Const-Vendor Pairing¶
Every module under pcapkit.const is generated by a matching crawler
under pcapkit.vendor, with no exception. A registry copied from an IANA,
IETF or similar web-published table is never hand-maintained – the crawler
re-scrapes the source and regenerates the module, so a hand edit to the generated
file is silently discarded on the next run. Raised in cross-review of #2441,
which deferred the TLS crawlers; ruled on #2495, where the owner allowed no
exception and pointed a hand-maintained registry at the DATA attribute below.
The DATA Attribute, for a Registry With No Web Source¶
A source that is not a web-crawlable table does not excuse a module from this
pairing – it changes what the crawler fetches. Vendor
reads its registry two ways: _request() either
GETs LINK, or, when a subclass overrides
request() to take no arguments, returns a
module-level DATA literal instead and never touches the network.
pcapkit.vendor.ipx.packet and pcapkit.vendor.ipx.socket are the
precedent: both read a hand-transcribed DATA dict because their source,
Novell’s and Xerox’s own IPX socket/packet-type tables, went offline (#507,
#518).
ARPHRD follows this pattern: its source is the
Linux kernel header <linux/if_arp.h>, C source
under the kernel’s own versioning rather than an IANA page, so
pcapkit.vendor.linux.arphrd reads a DATA dict of
{code: (name, description)} transcribed from the header instead of fetching a
URL. The crawler’s process() renders that dict
into the same enumeration members, the same FLAG bound and the same
_missing_ body the committed pcapkit.const.linux.arphrd carries –
running it is a no-op against the file in the tree, exactly as a web-scraped
crawler’s run is. The explanatory prose that once lived in the hand-maintained
const module – which values are listed and why, the cross-reference to
Hardware – now lives in the crawler’s own
module docstring and comments, alongside the DATA literal it documents; the
generated const module carries only the plain, templated docstring every
other generated module does.
Where the primary source is paywalled, a pinned secondary revision is an acceptable
DATA source once its values are cross-checked against independent implementations,
ruled in review of #2607 (#2575). pcapkit.vendor.ipx is the earlier
example, and the pcapkit.vendor.ieee802_11 crawlers check theirs against the
Linux kernel’s header and Wireshark.
LINK-and-Scrape Pairing: TLS Content Types and HandshakeType¶
ContentType and
HandshakeType, which came with the TLS
record layer, have matching crawlers – pcapkit.vendor.tls.content_type and
pcapkit.vendor.tls.handshake_type, exported as TLS_ContentType and
TLS_HandshakeType – closing the gap #2495 tracked. Both take the
normal LINK-and-scrape shape against IANA’s tls-parameters-5.csv and
tls-parameters-7.csv, as this doc said the eventual crawler would; unlike
ARPHRD, TLS’s source is a live, web-published table, so neither reads a
DATA literal.
Running either crawler is a true no-op against the committed const
modules: regenerating both reproduces the tree byte-for-byte, the same
guarantee ARPHRD and the sslv2 restack carry. Getting there meant
regenerating the const modules committed with the TLS record layer, which
predated the crawler and had drifted from it in the ways cross-review of
#2503 (#2495) caught:
the committed
ContentTyperesolved values 32-63 toUnassignedvia a flat_missing_fallback, while IANA’s registry – and the crawler – call that bandReserved(RFC 9147); the committed docstring already said “Reserved”, the code did not. Regenerating fixes the resolved name for that band.the committed
ContentTypecarried aninvalid = 0sentinel with no IANA counterpart and no reference anywhere in the codebase (IANA leaves 0 inside its 0-19Unassignedband, unnamed); it is dropped, and value 0 now resolves toUnassignedlike the rest of that band.SSLnever checked this member by name – its wire-type allowlist already excluded value 0 by construction – so the sentinel’s removal is behaviourally a no-op there too.the committed
HandshakeTypecited RFC 5246, 6066 and 4680 for several members where IANA’s registry now cites RFC 9846, and left IANA’s two single-rowUnassignedentries (values 7 and 255) to_missing_rather than naming them; the crawler renders both as explicit members (unassigned_7,unassigned_255), matching the registry.
The protocol-specific prose the hand-curated modules carried – the
record-layer header citations, the Unassigned/Reserved band rationale, the
_RESERVED-suffix handling – moved into the crawlers’ own module
docstrings and comments, the way pcapkit.vendor.linux.arphrd already
does for ARPHRD; the generated const modules carry only the plain,
templated docstring every other generated module does.
Lazy Package Imports¶
A pcapkit.const package imports its enumerations on first use, not with
itself. Ruled by the owner in session and recorded on #2729. Its
__init__.py names each export in an import under if TYPE_CHECKING:, for
the type checkers, and binds the __getattr__ and __dir__ that
lazy_exports() returns; pcapkit.const re-exports
its subpackages’ __all__ the same way. The one real import is of
AppType and
TransportProtocol, which
pcapkit.const.reg.apptype builds
AppType.__registries__
on. A crawler writes the enumeration module and never a package’s
__init__.py, so regenerating keeps the laziness, and a module a crawler adds
takes its export there by hand, in both places.
tests/const/test_const_lazy_exports_2729_unit.py fails on an export imported
outside TYPE_CHECKING, or one that does not resolve to what its import names, and
tests/const/test_const_apptype_lazy_1538_unit.py on a package that loads an
enumeration with itself.