From 34eba6fbceccc0ed3aef4e6a8ca15d9681be2df6 Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Fri, 18 Sep 2026 22:40:32 -0400 Subject: [PATCH 1/2] docs: fix Extractor exception mismatch and phantom Args: params (#490) - Extractor.__call__ documented IterableError but raises CallableError (a sibling exception class, not a subclass); fixed the docstring to name the class actually raised, since the message and semantics ("is not callable") back CallableError. - Fixed six Args: blocks documenting phantom parameters left over from copy-paste: IPv6_Route._read_data_type_rpl (length -> schema/header), PCAPNG._make_option_if_hardware/_make_option_isb_starttime/ _make_option_isb_endtime/_make_secrets_wireguard, and OSPF._make_encrypt_auth (phantom auth_type removed). - Renamed ~34 stale option: labels to options: across every _read_opt_*, make(), and _make_hopopt_options/_make_ipv6_opts in hopopt.py and ipv6_opts.py, matching each method's real parameter. - Also fixed, found via the same signature sweep: a "timestmap" typo in three PCAPNG block-maker docstrings and one summary line, and a phantom `options` param on PCAPNG._make_block_systemd. - Added a test pinning Extractor(auto=True)() to raise CallableError (and __iter__ to IterableError) against a real constructed instance, so the raise and the docstring can't drift apart unnoticed again. Verified every touched method's Args: block against inspect.signature with a standalone script; tests/foundation, test_ipv6_extension_unit and test_pcapng_unit all pass. --- pcapkit/foundation/extraction.py | 4 +-- pcapkit/protocols/internet/hopopt.py | 34 ++++++++++++------------ pcapkit/protocols/internet/ipv6_opts.py | 34 ++++++++++++------------ pcapkit/protocols/internet/ipv6_route.py | 3 ++- pcapkit/protocols/link/ospf.py | 1 - pcapkit/protocols/misc/pcapng.py | 17 ++++++------ tests/foundation/test_extraction.py | 27 +++++++++++++++++++ 7 files changed, 73 insertions(+), 47 deletions(-) diff --git a/pcapkit/foundation/extraction.py b/pcapkit/foundation/extraction.py index 45f0934370..9c35e939f6 100644 --- a/pcapkit/foundation/extraction.py +++ b/pcapkit/foundation/extraction.py @@ -1019,8 +1019,8 @@ def __call__(self) -> '_P': """Works as a simple wrapper for the iteration protocol. Raises: - IterableError: If :attr:`self._flag_a ` - is :data:`True`, as iteration is not applicable. + CallableError: If :attr:`self._flag_a ` + is :data:`True`, as such operation is not applicable. """ if not self._flag_a: diff --git a/pcapkit/protocols/internet/hopopt.py b/pcapkit/protocols/internet/hopopt.py index cf4c7c2089..eb794c191a 100644 --- a/pcapkit/protocols/internet/hopopt.py +++ b/pcapkit/protocols/internet/hopopt.py @@ -323,7 +323,7 @@ def make(self, next_default: Default value of next header type. next_namespace: Namespace of next header type. next_reversed: If the namespace of next header type is reversed. - option: Hop-by-Hop Options. + options: Hop-by-Hop Options. payload: Payload of current protocol. **kwargs: Arbitrary keyword arguments. @@ -499,7 +499,7 @@ def _read_opt_none(self, schema: 'Schema_UnassignedOption', *, options: 'Option' Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -537,7 +537,7 @@ def _read_opt_pad(self, schema: 'Schema_PadOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -594,7 +594,7 @@ def _read_opt_tun(self, schema: 'Schema_TunnelEncapsulationLimitOption', *, opti Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -628,7 +628,7 @@ def _read_opt_ra(self, schema: 'Schema_RouterAlertOption', *, options: 'Option') Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -668,7 +668,7 @@ def _read_opt_calipso(self, schema: 'Schema_CALIPSOOption', *, options: 'Option' Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -732,7 +732,7 @@ def _read_opt_smf_dpd(self, schema: 'Schema_SMFDPDOption', *, options: 'Option') Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -795,7 +795,7 @@ def _read_opt_pdm(self, schema: 'Schema_PDMOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -854,7 +854,7 @@ def _read_opt_qs(self, schema: 'Schema_QuickStartOption', *, options: 'Option') Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -917,7 +917,7 @@ def _read_opt_rpl(self, schema: 'Schema_RPLOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -961,7 +961,7 @@ def _read_opt_mpl(self, schema: 'Schema_MPLOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -1022,7 +1022,7 @@ def _read_opt_ilnp(self, schema: 'Schema_ILNPOption', *, options: 'Option') -> ' Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -1054,7 +1054,7 @@ def _read_opt_lio(self, schema: 'Schema_LineIdentificationOption', *, options: ' Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -1085,7 +1085,7 @@ def _read_opt_jumbo(self, schema: 'Schema_JumboPayloadOption', *, options: 'Opti Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -1129,7 +1129,7 @@ def _read_opt_home(self, schema: 'Schema_HomeAddressOption', *, options: 'Option Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -1167,7 +1167,7 @@ def _read_opt_ip_dff(self, schema: 'Schema_IPDFFOption', *, options: 'Option') - Args: schema: parsed parameter schema - option: extracted HOPOPT options + options: extracted HOPOPT options Returns: Parsed option data. @@ -1238,7 +1238,7 @@ def _make_hopopt_options(self, options: 'list[Schema_Option | tuple[Enum_Option, """Make options for HOPOPT. Args: - option: HOPOPT options + options: HOPOPT options Returns: Tuple of options and total length of options. diff --git a/pcapkit/protocols/internet/ipv6_opts.py b/pcapkit/protocols/internet/ipv6_opts.py index dd73be6bbd..6f5308a41f 100644 --- a/pcapkit/protocols/internet/ipv6_opts.py +++ b/pcapkit/protocols/internet/ipv6_opts.py @@ -334,7 +334,7 @@ def make(self, next_default: Default value of next header type. next_namespace: Namespace of next header type. next_reversed: If the namespace of next header type is reversed. - option: Hop-by-Hop Options. + options: Hop-by-Hop Options. payload: Payload of current protocol. **kwargs: Arbitrary keyword arguments. @@ -510,7 +510,7 @@ def _read_opt_none(self, schema: 'Schema_UnassignedOption', *, options: 'Option' Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -548,7 +548,7 @@ def _read_opt_pad(self, schema: 'Schema_PadOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -606,7 +606,7 @@ def _read_opt_tun(self, schema: 'Schema_TunnelEncapsulationLimitOption', *, opti Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -640,7 +640,7 @@ def _read_opt_ra(self, schema: 'Schema_RouterAlertOption', *, options: 'Option') Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -680,7 +680,7 @@ def _read_opt_calipso(self, schema: 'Schema_CALIPSOOption', *, options: 'Option' Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -744,7 +744,7 @@ def _read_opt_smf_dpd(self, schema: 'Schema_SMFDPDOption', *, options: 'Option') Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -807,7 +807,7 @@ def _read_opt_pdm(self, schema: 'Schema_PDMOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -866,7 +866,7 @@ def _read_opt_qs(self, schema: 'Schema_QuickStartOption', *, options: 'Option') Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -929,7 +929,7 @@ def _read_opt_rpl(self, schema: 'Schema_RPLOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -973,7 +973,7 @@ def _read_opt_mpl(self, schema: 'Schema_MPLOption', *, options: 'Option') -> 'Da Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -1034,7 +1034,7 @@ def _read_opt_ilnp(self, schema: 'Schema_ILNPOption', *, options: 'Option') -> ' Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -1066,7 +1066,7 @@ def _read_opt_lio(self, schema: 'Schema_LineIdentificationOption', *, options: ' Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -1097,7 +1097,7 @@ def _read_opt_jumbo(self, schema: 'Schema_JumboPayloadOption', *, options: 'Opti Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -1141,7 +1141,7 @@ def _read_opt_home(self, schema: 'Schema_HomeAddressOption', *, options: 'Option Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -1179,7 +1179,7 @@ def _read_opt_ip_dff(self, schema: 'Schema_IPDFFOption', *, options: 'Option') - Args: schema: parsed parameter schema - option: extracted IPv6-Opts options + options: extracted IPv6-Opts options Returns: Parsed option data. @@ -1250,7 +1250,7 @@ def _make_ipv6_opts(self, options: 'list[Schema_Option | tuple[Enum_Option, dict """Make options for IPv6-Opts. Args: - option: IPv6-Opts options + options: IPv6-Opts options Returns: Tuple of options and total length of options. diff --git a/pcapkit/protocols/internet/ipv6_route.py b/pcapkit/protocols/internet/ipv6_route.py index e836577e97..9a3345314c 100644 --- a/pcapkit/protocols/internet/ipv6_route.py +++ b/pcapkit/protocols/internet/ipv6_route.py @@ -588,7 +588,8 @@ def _read_data_type_rpl(self, schema: 'Schema_RPL', *, header: 'Schema_IPv6_Rout +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Args: - length: route data length + schema: parsed routing data schema + header: parsed IPv6-Route header schema Returns: Parsed route data. diff --git a/pcapkit/protocols/link/ospf.py b/pcapkit/protocols/link/ospf.py index a70d6afedb..309efac568 100644 --- a/pcapkit/protocols/link/ospf.py +++ b/pcapkit/protocols/link/ospf.py @@ -363,7 +363,6 @@ def _make_encrypt_auth(self, """Make Authentication field when Cryptographic Authentication is employed. Args: - auth_type: Authentication type. auth_data: Authentication data. Returns: diff --git a/pcapkit/protocols/misc/pcapng.py b/pcapkit/protocols/misc/pcapng.py index 8d316ceaff..9a57b91517 100644 --- a/pcapkit/protocols/misc/pcapng.py +++ b/pcapkit/protocols/misc/pcapng.py @@ -1276,7 +1276,7 @@ def _get_linktype(self, interface_id: 'int' = 0) -> 'Enum_LinkType': def _read_timestamp(self, timestamp_high: 'int', timestamp_low: 'int', *, interface_id: 'int' = 0) -> 'tuple[dt_type, Decimal]': - """Read timestmap. + """Read timestamp. Args: timestamp_high: Higher 32-bit integer value of timestamp. @@ -3500,7 +3500,7 @@ def _make_block_epb(self, block: 'Optional[Data_EnhancedPacketBlock]' = None, *, Args: block: Block data model. interface_id: Interface ID. - timestmap: Packet timestamp. + timestamp: Packet timestamp. captured_len: Captured length. original_len: Original length. packet_data: Payload of the block. @@ -3623,7 +3623,7 @@ def _make_block_isb(self, block: 'Optional[Data_InterfaceStatisticsBlock]' = Non Args: block: Block data model. interface_id: Interface ID. - timestmap: Block timestamp. + timestamp: Block timestamp. options: Block options. **kwargs: Arbitrary keyword arguments. @@ -3660,7 +3660,6 @@ def _make_block_systemd(self, block: 'Optional[Data_SystemdJournalExportBlock]' Args: block: Block data model. entries: :manpage:`systemd(1)` journal export entries. - options: Block options. **kwargs: Arbitrary keyword arguments. Returns: @@ -3834,7 +3833,7 @@ def _make_block_packet(self, block: 'Optional[Data_PacketBlock]' = None, *, block: Block data model. interface_id: Interface ID. drop_count: Drops count. - timestmap: Packet timestamp. + timestamp: Packet timestamp. captured_len: Captured length. original_len: Original length. packet_data: Payload of the block. @@ -4518,7 +4517,7 @@ def _make_option_if_hardware(self, type: 'Enum_OptionType', option: 'Optional[Da Args: type: Option type. option: Option data model. - os: Operating system name. + hardware: Hardware information. **kwargs: Arbitrary keyword arguments. Returns: @@ -4972,7 +4971,7 @@ def _make_option_isb_starttime(self, type: 'Enum_OptionType', option: 'Optional[ Args: type: Option type. option: Option data model. - ip: DNS server IPv6 address. + timestamp: Start time. **kwargs: Arbitrary keyword arguments. Returns: @@ -5005,7 +5004,7 @@ def _make_option_isb_endtime(self, type: 'Enum_OptionType', option: 'Optional[Da Args: type: Option type. option: Option data model. - ip: DNS server IPv6 address. + timestamp: End time. **kwargs: Arbitrary keyword arguments. Returns: @@ -5567,7 +5566,7 @@ def _make_secrets_wireguard(self, type: 'Enum_SecretsType', secrets: 'Optional[D Args: type: Secrets type. secrets: Secrets data model. - data: Secrets data. + entries: WireGuard Key Log entries. **kwargs: Arbitrary keyword arguments. Returns: diff --git a/tests/foundation/test_extraction.py b/tests/foundation/test_extraction.py index 5766caa2a2..c5782535ea 100644 --- a/tests/foundation/test_extraction.py +++ b/tests/foundation/test_extraction.py @@ -493,6 +493,33 @@ def test_constructor_initialises_without_running_when_patched(self) -> None: self.assertEqual(extractor.magic_number, b'\xa1\xb2\xc3\xd4') extractor._ifile.close() + def test_auto_mode_call_raises_the_class_the_docstring_names(self) -> None: + # #490: __call__'s docstring promises ``CallableError`` under auto mode -- + # ``__iter__``'s sibling ``Raises:`` block, one method up, promises + # ``IterableError`` for the identical condition. The two are siblings + # (both ``BaseError, TypeError``) and neither subclasses the other, so + # this pins the *actually raised* class on a real ``Extractor(auto=True)`` + # instance (not a hand-built stand-in) against both names, guarding + # against either the raise or the docstring drifting again unnoticed. + from pcapkit.foundation.extraction import Extractor + from pcapkit.utilities.exceptions import CallableError, IterableError + + self.assertFalse(issubclass(CallableError, IterableError)) + self.assertFalse(issubclass(IterableError, CallableError)) + + with tempfile.TemporaryDirectory() as tempdir: + capture = pathlib.Path(tempdir) / 'sample.pcap' + capture.write_bytes(b'\xa1\xb2\xc3\xd4payload') + with mock.patch.object(Extractor, 'run'): + extractor = Extractor(str(capture), str(pathlib.Path(tempdir) / 'out'), + format='json', auto=True, nofile=True) + self.addCleanup(extractor._ifile.close) + + with self.assertRaises(CallableError): + extractor() + with self.assertRaises(IterableError): + iter(extractor) + def test_constructor_configuration_branches_with_run_patched(self) -> None: from pcapkit.foundation.extraction import Extractor From 1aef7bdc04d3398407a92a6b99a75b5fe8169311 Mon Sep 17 00:00:00 2001 From: Jarry Shaw Date: Fri, 18 Sep 2026 22:41:05 -0400 Subject: [PATCH 2/2] docs: clarify RFC 815 vs RFC 791 framing in TCP reassembly algorithm (#490) The prose read as though RFC 815 itself uses the RCVBT bit table, when RFC 815 actually presents hole descriptors as an alternative to the RCVBT approach used by RFC 791. The eight algorithm steps were already accurate; this only fixes the historical framing sentence. --- docs/source/pcapkit/foundation/reassembly/tcp.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/source/pcapkit/foundation/reassembly/tcp.rst b/docs/source/pcapkit/foundation/reassembly/tcp.rst index 65366281f3..61ec317137 100644 --- a/docs/source/pcapkit/foundation/reassembly/tcp.rst +++ b/docs/source/pcapkit/foundation/reassembly/tcp.rst @@ -119,10 +119,11 @@ Algorithm } give up until (no entry from HDL) } -The following algorithm implement is based on **IP Datagram -Reassembly Algorithm** introduced in :rfc:`815`. It described an -algorithm dealing with ``RCVBT`` (fragment received bit table) -appeared in :rfc:`791`. And here is the process: +The following algorithm implement is based on the **IP Datagram +Reassembly Algorithm** introduced in :rfc:`815`, which presents hole +descriptors as an alternative to the ``RCVBT`` (fragment received bit +table) approach used by the reassembly procedure in :rfc:`791`. And +here is the process: 1. Select the next hole descriptor from the hole descriptor list. If there are no more entries, go to step eight.