docs: correct documentation that stated untrue things (#546) - #550
Conversation
|
✅ GOOD TO MERGE — verified all three flagged owner decisions were handled correctly rather than left ambiguous: |
Detailed review (independent verification, falsify-not-bless)Head sha reviewed: The three owner decisions -- each checked directly, not read and trustedSECURITY.md. Read the actual file rather than grepping for a placeholder marker that might not exist under that name. It does not invent an email address: the primary channel is GitHub's private vulnerability reporting ( The secondary route says "email the project contact listed in
The four dead
|
* `no_eof` was documented backwards on `Extractor` -- "if raise EOFError" where the flag suppresses the EOF stop. Matched to `interface/core.py` and to the `if self._flag_n: continue` branch that decides the behaviour. * `register_extractor_engine` documented a parameter `engine`; the signature reads `name`, so the only documented spelling raised `TypeError`. The other 34 `register_*` functions were audited and carry no such defect. * `SECURITY.md` was GitHub's unedited template, listing 1.0.x/0.x.x and offering no disclosure channel. Replaced with the real supported lines and the repository's already-enabled private vulnerability reporting. * `pyproject.toml` claimed the project floor was `>=3.10` while `requires-python` reads `>=3.6, <4`. The comment was wrong, not the packaging, and the `PCAP_CT` marker is load-bearing rather than decorative as a result. * `ext.rst` omitted NGAP from its table of all protocol classes; it was the only concrete class missing. * `changelog/1.5.0.rst` said 70 of 71 MH options with CGA Parameters outstanding. All 71 are registered with a dedicated handler, so `pep.rst` was the correct copy. `CHANGELOG.md` regenerated. * `deploy-pages.yml` carried npm boilerplate over a step that runs Sphinx. * `reassembly/data/tcp.py` stacked two `#:` comments on one field, which Sphinx concatenated. * `conf.py` held four handlers whose `app.connect` calls were all commented out; deleted, with the reason recorded in their place. * 29 dead cross-reference targets fixed, each verified against the built `objects.inv` rather than guessed. Unit suite green (1039 passed, 8 skipped). Sphinx warnings unchanged at 50; nitpicky dead `pcapkit.*` targets 81 -> 50, with no new warnings.
d4a4fca to
0ffbda9
Compare
… closed one (#611) `SECURITY.md` was rewritten from GitHub's template in #550 and its facts still check out, so this is the one gap that review found rather than a rework. * The threat model promised that parse errors "are supposed to arrive as" `pcapkit.utilities.exceptions` types. `MemoryError` appears nowhere in `pcapkit/`, so the hierarchy demonstrably does not cover it and the sentence over-claimed. Reworded to intent plus a known shortfall, keeping the class in scope for reports. * Added "Handling untrusted captures", giving callers the advice the threat model implied but never stated: bound memory and time out of process, expect built-in exception types the hierarchy misses, and revalidate any parsed field that carries a security decision. A short read can pad to a value instead of raising, so the last one is not hypothetical. Deliberately non-specific: no amplification figures, capture shapes or issue numbers. The open vectors stay described where they already are, in `docs/source/changelog/1.5.0.rst`, which is a record of what was measured; this file only needs to stop implying the work is finished. No changelog bullet, following #550, which rewrote this file wholesale and added none -- repository policy documents are not a release note here.
Closes #546.
Ten places where the documentation stated something untrue. Every item was
confirmed from its cited
file:linebefore being touched; two turned out differentlyfrom the issue's description and are called out as such, and two could not be fixed
here because their files are owned by other open work.
Rebased onto
d656b09f1. One commit.What was confirmed and fixed
1.
no_eofdocumented backwards —extraction.py:787said "if raiseEOFErrorwhen EOF";interface/core.py:136said "if not raise". The codesettles it:
extraction.py:699-700isif self._flag_n: continue, so the flag meanskeep going. Corroborated by
__main__.py:121, which setsno_eof = args.fin == '-'so a stdin stream does not stop at a transient EOF.
extraction.pynow matches.Tested.
2.
register_extractor_enginedocumented a nonexistent parameter —enginewhere the signature reads
name, so the only documented spelling raisedTypeError.Fixed. I audited all 35
register_*functions inpcapkit/foundation/registry/(99 documented parameter entries) and this was the only mismatch — contrary to
the reasonable expectation that a copy-paste defect would have spread.
No new test was needed:
tests/test_docstring_contract.pyalready checks thisproperty project-wide and carried the defect as a
KNOWN_DEFECTSentry reading"owned by the registry docstring change". Deleting that entry is what turns the
existing check on. Tested, by an existing test.
4.
pyproject.tomlcontradicted itself on the Python floor — the comment waswrong, not the packaging.
requires-python = ">=3.6, <4"is deliberate andjustified at length at
:22-48via thebpc-*source conversion, and theclassifiers list 3.6. So
:187's "This project's own floor is now>=3.10" is thefalse statement. Correcting it changes the meaning of the line around it: because the
project floor really is
>=3.6, thepython_version >= '3.10'marker onPCAP_CTisload-bearing, not "belt-and-braces" — without it,
pip install pypcapkit[PCAP_CT]on 3.6–3.9 would try to resolve two distributions that excludethat interpreter and fail the whole install.
5.
ext.rstomitted NGAP. Checked programmatically against everyProtocolsubclass in the tree — 44 shipped, 37 tabled — and NGAP was the only concrete class
missing; the other six are abstract bases the table names in its "Protocol Type"
column instead. Added, and verified rendered inside the real table in the built HTML
rather than assumed.
6. The MH option count — the changelog was stale,
pep.rstwas right. Settled bycounting, not by picking:
pcapkit.const.mh.option.Optionhas 71 members (0–70),MH.__option__has 71 entries, and CGA Parameters resolves to a dedicatedcga_paramhandler rather than a generic one. So "all 71 registered options" iscorrect and "70 of the 71 … Only the CGA Parameters option remains" is stale.
CHANGELOG.mdregenerated withutil/changelog_md.py;--checkpasses.7.
deploy-pages.ymlnpm boilerplate over a Sphinx step — replaced with a commentdescribing what the step does. I verified what
PCAPKIT_DEVMODEactually does (DEBUGlogging on stderr plus untrimmed tracebacks) before writing it down, rather than
inferring from the name.
8. Two stacked
#:comments on one field —reassembly/data/tcp.py:106-108. Thesibling
reassembly/data/ip.pycarries a single coherent comment for the same field,so the stale first line is dropped and the wording brought into line with it.
10. Dead cross-reference targets — 31 fixed. Measured with a nitpicky
sphinx-build, and every replacement spelling was verified present in the baselinebuild's
objects.invrather than inferred. That mattered: my first pass retargetedProtocol._fileand friends ontoProtocolBase, and the inventory showed theopposite is true —
Protocol.*is what Sphinx documents andProtocolBase.*isabsent. That pass was reverted, and the 13 dead
ProtocolBase.*references weremoved the other way.
Also fixed:
engins→engines(twice, one of them in a type comment that arole-based search cannot see),
Secrets_Type→SecretsType,Extraction→Extractor,StatusCode→DNSStatusCode,:mod:pcapkit.exceptions``→pcapkit.utilities.exceptions, `Data_Raw`/`Schema_Raw`onto their real modules, `PadOption.length`→`Option.length` where the field is
actually documented, `_read_ani_geo`→`_read_ani_suboptions`, and a stray `>` that
broke three `MH` roles in `registry/protocols.py`.
Three of these turned out to be real documentation gaps rather than typos:
Extractor._flag_ris set atextraction.py:824and read by every engine but was theone flag missing from the
if TYPE_CHECKING:block documenting its eight siblings;and
Extractor._exctx,Protocol._data/_exctxwere missing from the explicitautoattributelists their.rstfiles use under:no-members:. All now documented._flag_ris tested.Two references had no addressable target at all and were demoted to literals
rather than papered over:
dumpkit/common.py'sdefault/_append_fallbackaremethods of a class defined inside
make_dumper(), so no dotted path can reachthem; and
Frame._fnum/PCAPNG._fnumare instance-only attributes thatautoattributecannot import — I tried adding them and it produced two new buildwarnings, so I reverted that and demoted the references instead.
Measurements
Baseline is
d656b09f1— re-measured after the rebase rather than carried over,since
mainmoved by three commits while this was in progress.nitpicky)pcapkit.*targetsThe plain warning sets are identical — diffed as sets, not just counted: no
warning added, none removed. Dead cross-references do not warn outside
nitpickymode, which is exactly why they accumulated. The 3 pre-existing duplicate-object
warnings (
Info.__post_init__,reassembly.data.tcp.BufferID,pcap.header.Header.__post_init__) are untouched.All four builds ran with
PYTHONPATHpinned to the tree under test, and each printedthe
pcapkit.__file__it imported. That is not ceremony:sphinx-buildruns fromdocs/,conf.pydoes not add the repository root tosys.path, and so without itthe build imports
pcapkitfrom the editable install — a different checkoutentirely. Measured: with
PYTHONPATHunset the import resolves outside the tree.Testing
tests/project/test_documentation_claims.pyis new (3 tests); theregister_*checkreuses the existing contract test. Each assertion was proved to fail without its fix
by running the same files against a pristine snapshot — pytest's exit code read
from a file, because a wrapper's status is not pytest's and pytest 9.1.1 reports a
failing subtest's parent as
PASSED:no_eofdisagreement, theno_eofsense-vs-code check, the missing
_flag_rdeclaration, andtest_documented_parameters_existnamingregister_extractor_engine documents 'engine'.The pristine run was confirmed to have imported the snapshot's own
pcapkit, and itsfailure text quotes the old docstring verbatim (
'no_eof: if raise :exc:EOFErrorwhen EOF').Checked on Python 3.10 as well, since #547 is currently red on that axis only:
both test files compile under 3.10.21, and the
ast-only test class (the one needingno
pcapkitimport) passes there. The new tests construct no classes and use no classkeywords, so the
ABCMeta.__new__() got multiple values for argument 'name'failuremode in #547 cannot arise from them.
Items 3, 4, 6, 7, 8, 9 are untested and cannot be — they are prose, a TOML
comment, a YAML comment and a deletion of unreachable code. Item 5 is verified by
inspecting the built HTML, not by a test. This change also cannot raise library
coverage, and I am not claiming it does: every source edit is a docstring or
comment, and the one added statement (
_flag_r: 'bool') sits insideif TYPE_CHECKING:and never executes.Three decisions I left to you
1. The
SECURITY.mddisclosure channel (item 3). The file was GitHub's uneditedtemplate —
1.0.xsupported,0.x.xnot, placeholder prose, and no disclosurechannel at all, which for a published PyPI package is the one item here with an
outside-facing consequence.
I did not invent an email address. Two verified facts made that unnecessary:
GitHub private vulnerability reporting is already enabled on this repository
(
gh api repos/JarryShaw/PyPCAPKit/private-vulnerability-reporting→{"enabled":true}), sosecurity/advisories/newis a real channel you have alreadyturned on, and it is the primary route in the new file. The secondary route points at
the contact in
CODE_OF_CONDUCT.mdby reference rather than repeating theaddress, so there is exactly one place to change it.
The open question is yours: if you would rather security reports did not arrive in
the same inbox as conduct reports, that is the one line to change — or delete, leaving
the GitHub advisory route as the only channel. Supported versions come from the
release list (1.4.x stable, latest
v1.4.1.post2; 1.5.x pre-release), and Ideliberately did not pin the exact beta, because the automated
Vendor Updatejobbumps it — it moved from
b3tob4while this PR was being prepared. The responseexpectation ("best-effort", single maintainer) and the threat model section are my
drafting and are yours to soften or cut.
2.
nitpicky— measured, and I recommend not enabling it. The issue calls it"arguably the real fix". It is, but the cost is now known rather than speculative:
turning it on takes the build from 50 warnings to 1035, because nitpicky flags
every unresolvable reference including builtins and stdlib types with no intersphinx
coverage. Only ~150 of those are
pcapkit.*. Enabling it as-is therefore buries thesignal it exists to surface, so
conf.pyis left unchanged. If you want it, theroute is
nitpicky = Trueplus anitpick_ignore_regexexcluding the non-pcapkitnamespaces — its own change, with its own review, and a judgement about which
namespaces to trust.
3.
conf.py(item 9) — I deleted the four dead functions rather than restoring thehooks, and here is why. The deciding argument is that deletion is provably
output-neutral — they were never connected, so nothing rendered from them — whereas
restoring changes rendered output, which is your call and not mine. On the merits:
remove_module_docstringandprocess_docstringwere two attempts at the same thing,flipping
typing.TYPE_CHECKINGand reloading each module so autodoc could see guardednames, and
bind_type_checking_namesnow does that properly, per module and withoutmutating a global mid-build.
process_fieldsonly everprinted — thelines.appendthat was its point was itself commented out.
source_readprinted every document'sentire source, which here is thousands of pages of build log. The reasoning is left as
a comment where they were, so the next reader need not re-derive it. Their now-unused
sys,typingandListimports went with them. If you wanted any of them live,this is the commit to object to.
Two things I could not fix, and why
cga_type→cga_extension, the example Documentation states untrue things in ten places, including no_eof documented backwards and a nonexistent parameter name #546 names, lives inpcapkit/const/mh/__init__.py:92andpcapkit/vendor/mh/__init__.py:92. Package__init__.pyfiles underpcapkit/are owned by concurrent work, so I left themalone rather than clobber it. The diagnosis is confirmed:
cga_extension.CGAExtensionis present in the inventory under bothconstandvendor, andcga_typedefinesCGAType. A one-word change whenever those filesare free.
data.internet.mh.PadOption.lengthis the sameOption.lengthfix applied hereto hopopt and ipv6_opts, but it lives in
pcapkit/protocols/internet/mh.py, alsoowned by another change.
pcapkit/protocols/internet/ipv4.py:18-27(the staleip.dsfield.dscp/ip.frag_offset/ip.protodocstring) was left alone as #546 directs, since #543still owns that file. This PR touches no file owned by an open PR.
50 dead
pcapkit.*targets remain, and they are not more copy-paste typos — theyneed individual judgement (
pcapkit.protocols.internet.AH,const.ftp.command.CommandType,ReassemblyBase.timeout, several_AT/_PT/_STtype variables, a truncated
pcapkit.protocols.), and several sit in the off-limitsfiles above. Worth its own pass.
CI
CI has not run on this branch yet — it was pushed without waiting. Locally: the
unit tier is green (exit code read from a file), both Sphinx builds exit 0, and the
3.10 checks above pass. A red mark here should be treated as real rather than a queue
artefact.