Skip to content

reg: retype AppType.proto to its own transport, and give register_apptype varargs instead of a proto kwarg #806

Description

@JarryShaw

Is this a bug or a feature request? A breaking design change, ruled on in #801.

Step 1 of #801's three. The maintainer's ruling, verbatim:

I feel like now that we're already using transport specific enums, we should avoid ambiguity from the enums in all sense. so... yes, go with your recommendation.

What changes

  1. AppType.proto becomes the single transport of the registry the member lives in, not the whole IANA set. TCP['http'].proto goes tcp|udp|sctp → tcp.
  2. register_apptype takes varargs instead of a proto kwarg, per the maintainer: "keeping everything singular and explicit".
def register_apptype(code: 'int | Enum_AppType', module: 'str | ModuleDescriptor[ProtocolBase] | Type[ProtocolBase]',
                     *transport: 'TransportProtocol', class_: 'str' = NULL) -> 'None':

class_ becomes keyword-only — that is deliberate and is the one divergence from the sibling register_* functions. Do NOT put *transport after class_: class_ is positional with a default, so a third positional argument binds to it and the transport is silently eaten. Measured:

(code, module, class_=NULL, *transport):  f(member, Unit, TP.udp) -> class_='TP.udp', transport=()
(code, module, *transport, class_=NULL):  f(member, Unit, TP.udp) -> transport=('TP.udp',)

Ruled sub-case: an Enum_AppType member with no explicit *transport uses the member's own proto — single-bit after this change, so it names exactly one registry. A bare int with no *transport stays an error.

Why the two are one issue: retyping removes the multi-bit value that protocols.py:833's proto = code.proto default relies on to fan out across {tcp, udp} at :846. Landing either alone leaves the other broken.

Expected behavior

Every member's proto names exactly its own registry; register_apptype requires transports to be named one at a time; no code path constructs or consumes a composite TransportProtocol.

Additional context

This is breaking for 10,625 of 12,391 members, because proto.name is folded into the member's underlying str value, not merely its display — pcapkit/vendor/reg/apptype/apptype.py:250 (temp = '%s [%d - %s]' % (name, value, proto.name), assigned to obj._value_), with __repr__ at :270 and __str__ at :273. So TCP['http'].value goes 'http [80 - tcp|udp|sctp]' → 'http [80 - tcp]'. _value_ is the live lookup key in _value2member_map_, so this must happen at generation time, never at runtime. Identity survives pickle, copy and deepcopy either way.

Verified migration surface, line numbers re-read against main (477ed00c4) — earlier citations in this thread were wrong, so trust these and re-derive rather than copying older comments:

  • pcapkit/vendor/reg/apptype/apptype.py:250 __new__, :270 __repr__, :273 __str__, :473 the docstring promising "the whole transport protocol set", :752 the emit condition if self.TRANSPORT not in record.protos.
  • The same three format strings generated into pcapkit/const/reg/apptype/apptype.py, plus the docstring duplicated into all four of const/reg/apptype/{tcp,udp,sctp,dccp}.py:21.
  • tests/const/test_const_apptype_split_unit.py:80 — assertEqual(TCP.http.proto, UDP.http.proto), which this change falsifies by design. That file is 415 lines with 15 test methods; ignore any citation above 415.
  • tests/foundation/registry/test_protocols.py:476, :484, :493, :499 — the only four register_apptype calls in the repo. :493 is the three-positional one.

Do not regenerate to verify. AppType.LINK fetches IANA's live CSV, so a regeneration is not reproducible. Hand-edit the generator and its output, then prove equivalence by rendering BASE(...) and diffing — 0 diff lines outside the intended region. BASE is a lambda returning an f-string, so braces in emitted code must be doubled.

Measurements that justify this, so they need not be redone: the multi-bit value is fully derivable — 7,054 (svc, port) groups, 0 disagreements, and 0 single-registry groups carrying a multi-bit proto. Per-registry: TCP 6147 / UDP 6143 / SCTP 91 / DCCP 10. register_apptype(TCP.http, Dummy) today displaces httpv1.HTTP from TCP and http.HTTP from UDP in one call.

Related: #801, #732, #759, #775, #804.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    breakingBreaks public-facing behaviour or API (apply alongside the type label)constRegenerated IANA or vendor constant tables; members keep their numeric valuesenhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions