Skip to content

Commit 867616b

Browse files
authored
docs: prefer Protocol over ProtocolBase in cross-references, per the owner's #1103 ruling (#2420)
ProtocolBase is the internal hidden API and Protocol is the one exposing the attributes, so a plain "here is where this member is documented" link targets Protocol. The owner then refined this: "Use the last documented override." A docstring describing what a *specific* class overrides has to name the real ancestor in that class's own chain, which is never Protocol -- Protocol has no subclasses at all, so ProtocolBase is the last documented override for every class in the tree. * Plain documentation links go to Protocol.<member>: the module-level prose and `#:` comments in protocol.py, register_protocol/_register_name in registry/protocols.py, the `register` Arguments and versionchanged clauses in internet.py, link.py, transport.py and sctp.py, and the unrelated-class references in sentinels.py, data/data.py, misc/pcap/{frame,header}.py, ipv6.py, utilities/config.py, conf.py and the mptcp test. * Override-describing links go to ProtocolBase.<member>: Internet.{register, from_data,_make_payload}, Link.register, Transport.register, IPv6_Ext.protocol, the ipv6_ext module docstring and ipv6_ext.rst, the {AH,ESP,HOPOPT,MH}.alias MRO sentences, NoPayload.protochain, PCAPNG.{length,packet}, HTTP.from_data and HTTPv2's HTTP.unpack. Each of these says "As X", "the base", "the inherited", "narrows", "sits between ... in the MRO" or "the guard this shares with", and the surrounding sentences already name ProtocolBase. * The `Raises:` clause of each `register` keeps naming ProtocolBase, unchanged: #2316/#1016 ruled that it names the class the guard's `issubclass` actually tests while the raised message names Protocol, and tests/protocols/test_register_class_guard_unit.py asserts exactly that. * Class-attribute declaration pointers stay on Protocol -- Protocol.__data__ (declared on Protocol itself), Protocol.__keywords__ and Protocol.__own_make_keywords__ -- since they name where the knob is documented rather than a method a class overrides. * ProtocolBase.__init_subclass__ references are still left alone (l2tpv2.py, c_tag.py, protocol-layer-placement.rst): Protocol does override __init_subclass__, so those name the base implementation deliberately. Verified Protocol in no class's __mro__ but its own, and that ProtocolBase defines and documents every member involved while Protocol declares only __init_subclass__ and __data__. AST-structure guard (ast.dump with docstrings stripped) confirms all 12 touched .py files are prose-only against 27c797d; ipv6_ext.rst carries no code. The mptcp test, test_docstring_contract.py, test_conventions_doc_claims.py, test_register_class_guard_unit.py and the docs xref suites pass (91 passed, 22 skipped, 444 subtests), as do tests/protocols, tests/foundation, tests/corekit and tests/utilities in full (3414 passed, 18 skipped, 60258 subtests).
1 parent 3ceb0b0 commit 867616b

19 files changed

Lines changed: 69 additions & 69 deletions

File tree

‎docs/source/conf.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,7 +890,7 @@ def sign_wrapped_function(app: 'Sphinx', obj: 'Any', bound_method: bool) -> None
890890
which for a decorated method is the wrapper. ``sphinx-autodoc-typehints``
891891
stops unwrapping at a stated ``__signature__``, so it evaluated the
892892
annotations in the decorator's module. The ``@seekset`` overload of
893-
:meth:`~pcapkit.protocols.protocol.ProtocolBase._read_packet` then rendered
893+
:meth:`~pcapkit.protocols.protocol.Protocol._read_packet` then rendered
894894
its return as the bare alias ``Data_Packet``, which only the protocol module
895895
binds (:issue:`1917`).
896896

‎docs/source/pcapkit/protocols/internet/ipv6_ext.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ This class is reached in these ways:
141141
``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``HIP``, ``IPv6-Frag`` and ``AH`` all
142142
have dedicated classes. When one of *those* raises,
143143
:func:`~pcapkit.corekit.decorators.beholder`
144-
(:meth:`Protocol._import_next_layer <pcapkit.protocols.protocol.ProtocolBase._import_next_layer>`)
144+
(:meth:`ProtocolBase._import_next_layer <pcapkit.protocols.protocol.ProtocolBase._import_next_layer>`)
145145
would substitute plain :class:`~pcapkit.protocols.misc.raw.Raw`, which loses
146146
``next`` and crashes the walk as in path 1.
147147
:meth:`IPv6._import_next_layer <pcapkit.protocols.internet.ipv6.IPv6._import_next_layer>` catches

‎pcapkit/corekit/sentinels.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ class with no ``__eq__`` of its own does; what it lacks is a readable
472472
473473
The hazard is not theoretical elsewhere: reload staleness is a *tracked*
474474
defect class here for other constructs -- see
475-
:meth:`pcapkit.protocols.protocol.ProtocolBase._lookup_next_layer`'s own
475+
:meth:`pcapkit.protocols.protocol.Protocol._lookup_next_layer`'s own
476476
docstring note on why it declines to memoise a resolved class, and
477477
:mod:`tests.protocols.test_dispatch_default_resolution_unit`'s own
478478
``test_no_stale_class_survives_a_module_reload``, which reloads a module

‎pcapkit/foundation/registry/protocols.py‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,11 @@ def register_protocol(protocol: 'Type[ProtocolBase]') -> 'None':
166166
:class:`pcapkit.protocols.application.httpv2.HTTP` -- so they all compete
167167
for the single key ``'HTTP'``. Registering one of them replaces whichever
168168
was there, and the replacement is observable through every reader of the
169-
registry, e.g. :meth:`ProtocolBase.expand_comp
170-
<pcapkit.protocols.protocol.ProtocolBase.expand_comp>`, which resolves a
169+
registry, e.g. :meth:`Protocol.expand_comp
170+
<pcapkit.protocols.protocol.Protocol.expand_comp>`, which resolves a
171171
bare protocol name through it. Per :issue:`675` the overwrite is reported,
172-
matching :meth:`ProtocolBase.register
173-
<pcapkit.protocols.protocol.ProtocolBase.register>` and the other
172+
matching :meth:`Protocol.register
173+
<pcapkit.protocols.protocol.Protocol.register>` and the other
174174
overwrite-warning registries.
175175
176176
The guard reads "key present **and** incumbent is a different class" --
@@ -194,8 +194,8 @@ class rather than supplied by a caller, and this function is the funnel
194194
readers outside this module cannot absorb on their own -- the registry is a
195195
documented public attribute, and its readers look a bare name up and then
196196
degrade *silently* on a miss rather than raising, so a re-keying would not
197-
announce itself either. :meth:`ProtocolBase.expand_comp
198-
<pcapkit.protocols.protocol.ProtocolBase.expand_comp>` falls back to the
197+
announce itself either. :meth:`Protocol.expand_comp
198+
<pcapkit.protocols.protocol.Protocol.expand_comp>` falls back to the
199199
name as a plain string, and the ``protocol`` properties on
200200
:class:`~pcapkit.foundation.reassembly.reassembly.ReassemblyMeta` and
201201
:class:`~pcapkit.foundation.traceflow.traceflow.TraceFlowMeta` fall back to
@@ -367,7 +367,7 @@ def _register_name(protocol: 'Type[ProtocolBase]', *targets: 'tuple[type, Any]')
367367
releasing whatever each target code held before, and followed by a lease
368368
when the write changed the name, so that registering the code back undoes
369369
it (:issue:`1505`). A name already showing ``protocol`` -- shipped, defined
370-
by a :class:`~pcapkit.protocols.protocol.ProtocolBase` subclass, or
370+
by a :class:`~pcapkit.protocols.protocol.Protocol` subclass, or
371371
registered directly -- is not leased, so no restore takes it away; one
372372
showing it through a lease extends that lease to ``targets``.
373373

‎pcapkit/protocols/application/http.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class HTTP(Application[_PT, _ST], Generic[_PT, _ST]):
215215
#: the 24-octet HTTP/2 connection preface, when :meth:`_guess_version`
216216
#: identified one and parsed the frame that follows it. They belong to this
217217
#: packet's header rather than to its payload, so :meth:`read` adds them to
218-
#: :attr:`length`; otherwise :meth:`ProtocolBase.__init__ <pcapkit.protocols.protocol.ProtocolBase.__init__>`'s
218+
#: :attr:`length`; otherwise :meth:`Protocol.__init__ <pcapkit.protocols.protocol.Protocol.__init__>`'s
219219
#: ``self._info.__update__(packet=self.packet.payload)`` would slice the
220220
#: payload from octet 9 of a buffer whose frame starts at octet 24 and report
221221
#: the tail of the preface as packet payload.
@@ -228,8 +228,8 @@ class HTTP(Application[_PT, _ST], Generic[_PT, _ST]):
228228
#: :meth:`HTTPv2.make <pcapkit.protocols.application.httpv2.HTTP.make>`
229229
#: according to that value, so the correct set of names depends on an
230230
#: argument. :obj:`None` therefore opts out of the construction keyword check
231-
#: that :meth:`ProtocolBase.__init__
232-
#: <pcapkit.protocols.protocol.ProtocolBase.__init__>` performs; the
231+
#: that :meth:`Protocol.__init__
232+
#: <pcapkit.protocols.protocol.Protocol.__init__>` performs; the
233233
#: versioned classes are checked normally when constructed directly.
234234
__keywords__ = None
235235

‎pcapkit/protocols/application/httpv2.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ def unpack(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_HTTP'
234234
235235
``length`` is resolved against :func:`len` only for *this*
236236
method's own check, and the *original* argument -- ``None``
237-
included -- is what is forwarded to :meth:`Protocol.unpack
237+
included -- is what is forwarded to :meth:`ProtocolBase.unpack
238238
<pcapkit.protocols.protocol.ProtocolBase.unpack>`. Collapsing
239239
``None`` to a concrete ``0`` would change what
240240
:meth:`Schema.unpack <pcapkit.protocols.schema.schema.Schema.unpack>`'s own
@@ -251,7 +251,7 @@ def unpack(self, length: 'Optional[int]' = None, **kwargs: 'Any') -> 'Data_HTTP'
251251
if length is None:
252252
# ``0 < ... < 9`` rather than ``... < 9``: an exhausted stream
253253
# (``len(self) == 0``) is left alone, so ``length`` reaches
254-
# :meth:`Protocol.unpack <pcapkit.protocols.protocol.ProtocolBase.unpack>`
254+
# :meth:`ProtocolBase.unpack <pcapkit.protocols.protocol.ProtocolBase.unpack>`
255255
# still ``None`` and its ``prepare`` decorator raises
256256
# :exc:`StreamEOFError` as documented above; only a *non-empty*
257257
# short stream is rejected as malformed here.

‎pcapkit/protocols/data/data.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Data(Info):
1919
The ``__next_name__``, ``__next_type__`` and ``__short_read__`` keys are
2020
metadata, listed in :attr:`~pcapkit.corekit.infoclass.Info.__included__`
2121
and :attr:`~pcapkit.corekit.infoclass.Info.__excluded__`:
22-
:meth:`Protocol.from_data <pcapkit.protocols.protocol.ProtocolBase.from_data>`
22+
:meth:`Protocol.from_data <pcapkit.protocols.protocol.Protocol.from_data>`
2323
dispatches the payload on the first two and on nothing else, and cuts a
2424
short read back on the third. :meth:`to_dict` carries them, so that
2525
``from_data(info.to_dict())`` rebuilds as ``from_data(info)`` does, while

‎pcapkit/protocols/internet/internet.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ def register(cls, code: 'Enum_TransType', protocol: 'ModuleDescriptor[ProtocolBa
182182
Arguments:
183183
code: protocol code as in :class:`~pcapkit.const.reg.transtype.TransType`
184184
protocol: module descriptor or a
185-
:class:`~pcapkit.protocols.protocol.ProtocolBase` subclass
185+
:class:`~pcapkit.protocols.protocol.Protocol` subclass
186186
187187
Raises:
188188
pcapkit.utilities.exceptions.RegistryError: If ``protocol`` is not a

‎pcapkit/protocols/internet/ipv6.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ def _exthdr_key(alias: 'str') -> 'str':
447447
"""Key an extension header's info is written under in :class:`Data_IPv6`.
448448
449449
Args:
450-
alias: :attr:`~pcapkit.protocols.protocol.ProtocolBase.alias` of
450+
alias: :attr:`~pcapkit.protocols.protocol.Protocol.alias` of
451451
the extension header's parser.
452452
453453
Returns:

‎pcapkit/protocols/internet/ipv6_ext.py‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ class for that code instead (see the bottom of the module), so dispatch
108108
``IPv6-Route``, ``IPv6-Opts``, ``MH``, ``HIP``, ``IPv6-Frag`` and ``AH`` all
109109
have dedicated classes. When one of *those* raises,
110110
:func:`~pcapkit.corekit.decorators.beholder`
111-
(:meth:`Protocol._import_next_layer <pcapkit.protocols.protocol.ProtocolBase._import_next_layer>`)
111+
(:meth:`ProtocolBase._import_next_layer <pcapkit.protocols.protocol.ProtocolBase._import_next_layer>`)
112112
would substitute plain :class:`~pcapkit.protocols.misc.raw.Raw`, which loses
113113
``next`` and crashes the walk as in path 1.
114114
:meth:`IPv6._import_next_layer <pcapkit.protocols.internet.ipv6.IPv6._import_next_layer>`
@@ -299,7 +299,7 @@ def protocol(self) -> 'Optional[Enum_ExtensionHeader] | Optional[str]':
299299
300300
In the *fallback* role (this instance parsed this module's own schema)
301301
this is **not** the base
302-
:attr:`Protocol.protocol <pcapkit.protocols.protocol.ProtocolBase.protocol>`
302+
:attr:`ProtocolBase.protocol <pcapkit.protocols.protocol.ProtocolBase.protocol>`
303303
meaning ("name of next layer protocol"). On the owner's ruling for
304304
GitHub issue :issue:`891` it is deliberately repointed at this
305305
instance's *own* identity, i.e. which header's format it parsed, such as
@@ -324,7 +324,7 @@ class sits between them and
324324
data model with no such field (``AttributeError``).
325325
326326
The discriminator is the *class-level*
327-
:attr:`~pcapkit.protocols.protocol.ProtocolBase.__data__` rather than an
327+
:attr:`~pcapkit.protocols.protocol.Protocol.__data__` rather than an
328328
:func:`isinstance` test on ``self._info``, because a ``make``-only
329329
instance has no ``_info`` at all. Reading it would turn
330330
:attr:`ProtocolBase.protocol <pcapkit.protocols.protocol.ProtocolBase.protocol>`,
@@ -510,8 +510,8 @@ def make(self, *,
510510
there is unioned down the MRO, so every subclass would accept
511511
these names and drop them. A ``make`` signature can be kept from
512512
subclasses instead: this class sets
513-
:attr:`ProtocolBase.__own_make_keywords__
514-
<pcapkit.protocols.protocol.ProtocolBase.__own_make_keywords__>`,
513+
:attr:`Protocol.__own_make_keywords__
514+
<pcapkit.protocols.protocol.Protocol.__own_make_keywords__>`,
515515
so a subclass that overrides ``make`` accepts ``len`` or ``data``
516516
only where its own ``make`` declares it (:issue:`2286`).
517517

0 commit comments

Comments
 (0)