Skip to content

ci(deps): install the vendor extra on engine-tests, closing HAS_VENDOR_DEPS (#738) - #774

Merged
JarryShaw merged 1 commit into
mainfrom
fix-738-vendor-deps-engine-tests
Sep 25, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix-738-vendor-deps-engine-tests

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Sep 25, 2026 •

Copy link
Copy Markdown
Owner

What is the purpose of your pull request?

  • fix
  • feat
  • perf
  • refactor
  • test
  • docs
  • ci
  • chore

Description

Closes #738's remaining scope: HAS_VENDOR_DEPS' 41 methods (tests/vendor/test_request_prompt_unit.py, test_user_agent_unit.py, test_ipx_packet_unit.py, test_ftp_return_code_unit.py) were one requirement extra short of the test extra's own requests+bs4 (#507) -- html5lib, which only beautifulsoup4[html5lib] (the vendor extra) provides.

#738's ruling was to land this on a non-blocking leg rather than add it to test. engine-tests (#751) already is that leg, and is the only per-pull-request job that both reaches these gates and sits outside ruleset 23497679's 15 required checks -- gate reaches them too but never runs on a pull request, and integration's fixture-tier selection never reaches tests/vendor/. So adding vendor to engine-tests' install line was the forced choice, not merely a convenient one.

Updated tests/_dependency_gates.py's HAS_VENDOR_DEPS exclusion to drop engine-tests, per dependency_gate_gaps()'s own before/after, and to state gate's own substantive reason for staying dark instead of "also non-blocking" (which would otherwise permit adding vendor there too).

None of the 41 methods make a live network call, but not for one reason across all four files: test_user_agent_unit.py (11) and test_request_prompt_unit.py (16) gate on html5lib only as an import precondition and replace requests.get with a recorder; test_ipx_packet_unit.py (9) is a regression suite for a retired scrape (Packet.LINK is None); test_ftp_return_code_unit.py (5) is not retired -- its crawler's LINK is a live Wikipedia URL -- and is the one file where html5lib is a functional dependency: it parses an inline HTML fixture with the real parser rather than fetching anything. An independent cross-review confirmed the no-network claim directly, with socket.connect/connect_ex/getaddrinfo/create_connection all patched to raise across all 41 methods -- zero failures. Swept the same stale "skips in CI" prose this correction touches, in the four files themselves, in test_vendor_dest_path_unit.py's cross-reference to them, and in two related claims in pyproject.toml.

Added a guard test pinning the closure (shown to fail against the pre-fix workflow), and updated two falsifiability tests' hardcoded install-line strings to match the new line.

Fixes #738.

@JarryShaw JarryShaw added ci Pull requests that change CI or workflow configuration (ci: subject prefix) test Pull requests that add or correct tests (test: subject prefix) review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 25, 2026
@JarryShaw
JarryShaw force-pushed the fix-738-vendor-deps-engine-tests branch from 9502488 to 6d407e8 Compare September 25, 2026 03:52
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review: NEEDS CHANGES (opus, a different model from the author), verified at 9502488b5 and re-confirmed on the merge with 83b58ebda. The head has since rebased to 6d407e87c with an identical diff, so the findings stand. Every finding is prose — the mechanics are correct and I could not break them.

Fixes #738 is defensible. It closes one gate, but it is the last one. Re-derived per flag rather than trusting the issue: HAS_CRYPTO, HAS_PYCRATE (#740), HAS_EMOJI (#740), HAS_CRAWLER_DEPS (never dark, #507), HAS_PYSHARK (#755), HAS_PYPCAPFILE (closed but marker-limited), and HAS_VENDOR_DEPS here. No flag runs nowhere.

Verified: gaps 16 → 15, exactly the one tuple removed and every other byte-identical, no new gap. Skip delta 41 → 0 on tests/vendor, matching the PR's figure at the right scope. All 41 pass under pytest and plain unittest. And the PR's central new claim was falsified directly rather than accepted — with socket.connect, connect_ex, getaddrinfo and create_connection all patched to raise, Ran 41 tests … OK, 0 failures. None of the 41 touches the network. engine-tests is also the unique job that both reaches these gates and is absent from ruleset 23497679's 15 required checks, so the choice was forced rather than merely sensible. Added weight is ~1.4 MB of pure Python.

My own brief was wrong on one figure, and both the author and I measure the same correction: the guard is 96 passed / 511 subtests at 1a852698b, not the 105/519 I gave — that was the combined test_tier_guard.py + test_pyshark_engine.py total. After this PR: 97/512, the +1 fully attributed to test_every_extra_any_pytest_job_installs_is_declared gaining the engine-tests/vendor pair.

Six prose changes required, four of them false claims in the PR's own new text:

  1. The two new texts contradict each other on gate — the exclusion reason says it "is not part of the blocking matrix either way", the test docstring says "both remain part of it". The ruleset settles it: the exclusion is right. That also leaves the decision unjustified, so the stated reason needs to be the real one (the release path should not gain a network-parser dependency).
  2. test_ftp_return_code_unit.py is not a retired scrape — pcapkit/vendor/ftp/return_code.py:182 still carries the live Wikipedia LINK; only ipx/packet.py is retired.
  3. It mocks nothing. It builds the fixture inline and calls ReturnCode.request(text), which is bs4.BeautifulSoup(text, 'html5lib'). For those 5 methods html5lib is a functional dependency, not an import precondition. The conclusion holds; the reason given does not.
  4. A quotation attributed to two files exists in one — that exact string is only in test_user_agent_unit.py:31; the ... elision splices two different sentences.
  5. "one of the four methods" has no referent — the two files named hold 14 methods.
  6. Six stale sites left unswept, four in the very files this PR un-darks, each still telling the reader these tests skip in CI: test_user_agent_unit.py:65-67, test_request_prompt_unit.py:101-103, test_ipx_packet_unit.py:55-57, test_ftp_return_code_unit.py:50-53, test_vendor_dest_path_unit.py:96-98, plus pyproject.toml:247.

One sentence worth adding when #738 closes: HAS_PYPCAPFILE is dark on 3.12-3.14 regardless, because pypcapfile; python_version < '3.12' resolves to nothing there — a property of the dependency the guard deliberately does not model, and not something this PR could close.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 25, 2026
@JarryShaw
JarryShaw force-pushed the fix-738-vendor-deps-engine-tests branch from 6d407e8 to c9be872 Compare September 25, 2026 04:10
@JarryShaw JarryShaw added review: pending No verdict for the current head - never reviewed, or the head moved since the last one and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 25, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Final cross-review at c9be8726d: NEEDS CHANGES — one prose correction across five lines. Everything else verified green, and all six earlier findings are confirmed fixed.

Verified good. The gate contradiction is gone with one statement surviving and the docstring deferring to it. "Retired" is now correct, and the reviewer checked the mechanism rather than the prose: Vendor.LINK = None at default.py:241, 'LINK' in Packet.__dict__ is False, and _request() tests if self.LINK is None: at :569 before the requests.get at :584 — while ftp.ReturnCode.LINK is a live Wikipedia URL. test_request_makes_no_network_call exists at test_ipx_packet_unit.py:159 and replaces both requests.get and requests.Session.request, so the referent is real. The per-file counts re-derive by AST at gate scope: 11 / 16 / 9 / 5, 41 dark of 45 gated. No regression anywhere — gaps still 15 byte-identical, guard 97/512 under both runners, tests/vendor 62 passed / 186 subtests / 0 skipped. And CI now settles what the last round could not: all five Engines Python 3.10-3.14 are SUCCESS. Fixes #738. can land as-is — #776 disposed of the only caveat.

The one change. The sweep made all five un-darked files name integration as a job where these tests "skip". It never collects them. Measured:

test             reaches 7 of 7 tests/vendor modules
integration      reaches 0 of 7
engine-tests     reaches 7 of 7
pypcap-parity    reaches 0 of 7
gate             reaches 7 of 7

So four sites — test_ftp_return_code_unit.py:54, test_ipx_packet_unit.py:57, test_request_prompt_unit.py:103, test_user_agent_unit.py:67 — should drop integration. Note pypcap-parity is the same fixture-tier shape and is correctly omitted from all four, so listing one and not the other is internally inconsistent as well.

And test_vendor_dest_path_unit.py:96 now overstates: "both classes below run on every job that runs pytest at all". They run on three of five. The text it replaced — "run in CI as things stand" — was true; the replacement is not. :98 repeats the integration error in the same sentence.

This matters more than ordinary imprecision, which is why it is a change request rather than a note: "skipped" versus "never collected" is the exact distinction the #738/#745 subsystem is built on — dependency_gate_gaps() reports a gap only where a job reaches the gate, for precisely this reason. And the same PR now asserts both sides: _dependency_gates.py says "integration's fixture-tier selection never reaches tests/vendor/ in the first place", while four test files say these tests skip there.

Nothing functional argues against merging, and landing this with a follow-up sweep would be defensible. But the fix-up exists to make these comments accurate, and the correction is one word in four places plus one reworded clause.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 25, 2026
@JarryShaw
JarryShaw force-pushed the fix-738-vendor-deps-engine-tests branch from c9be872 to 1b63e98 Compare September 25, 2026 04:57
JarryShaw added a commit that referenced this pull request Sep 25, 2026
#770)

- mypy has no aenum plugin, so TransportProtocol is a plain class to it.
  undefined = 0 is a bare int literal, inferring as int, while the
  auto()-valued siblings infer as Any -- the only member that then
  disagreed with the four sites defaulting to it: the class attribute
  __transport__, and the proto parameter on __new__, get and get_all.
- Wrap the literal in typing.cast in the BASE template
  (pcapkit/vendor/reg/apptype/apptype.py) so mypy infers
  TransportProtocol instead. cast is the identity function at run
  time, so undefined stays exactly 0 and still composes, and
  regenerating from a byte-identical cached IANA fetch changes only
  this member's comment and assignment in
  pcapkit/const/reg/apptype/apptype.py -- tcp/udp/sctp/dccp.py are
  untouched, member counts (6147/6143/91/10) unchanged, and every
  member's name/port/svc/proto/value is unchanged.
- Give the member a one-line #: contract instead of the mypy rationale:
  Sphinx autodocs it with :undoc-members:, and would otherwise publish
  the cast's reasoning as the member's own rendered description.
- Add tests pinning the fix: source-text shape, a direct mypy.api.run
  check, and a runtime guard that undefined is still 0 and composes.
  The mypy check skips inline when mypy is unavailable -- it is a
  Pipfile dev-package, not a pyproject.toml extra -- rather than a
  tracked HAS_MYPY gate, which was measured to break
  tests/test_tier_guard.py's DependencyGateCoverageTests (mypy has no
  MODULE_PROVIDERS entry, and that file is #774's to change).

mypy on the whole package: 116 errors/39 files -> 112/38, matching
lint.yml's existing pin (measured at 932cb48, unaffected by this).
@JarryShaw JarryShaw added review: pending No verdict for the current head - never reviewed, or the head moved since the last one and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Sep 25, 2026
…R_DEPS (#738)

- 41 tests/vendor/*.py methods gated on HAS_VENDOR_DEPS have never run in
  CI: the test extra carries requests+bs4 (#507) but not html5lib, which
  only beautifulsoup4[html5lib] (the vendor extra) provides.
- #738's ruling was a non-blocking leg rather than adding it to `test`.
  engine-tests (#751) already is that leg -- it mirrors test's ignore-shape
  selection and is the only per-pull-request job both reaching these gates
  and outside ruleset 23497679's 15 required checks -- so adding `vendor`
  to its install line was the forced choice, not merely a convenient one.
- Updated tests/_dependency_gates.py's HAS_VENDOR_DEPS exclusion to drop
  engine-tests, state gate's own substantive reason for staying dark
  (already-covered release path, not merely "also non-blocking"), and
  correct three inaccuracies a cross-review found in the network-call
  reasoning: test_ftp_return_code_unit.py is not a retired scrape and
  needs html5lib functionally (parses an inline fixture with it); the
  other three files use html5lib only as an import precondition; and a
  quote attributed to two files was a splice of two different sentences.
- Swept the same stale "skips in CI" prose in the four un-darked test
  files, test_vendor_dest_path_unit.py's cross-reference to them, and two
  related claims in pyproject.toml, all now inaccurate now that
  engine-tests runs them. A second pass corrected those same five sites'
  job lists: `integration` and `pypcap-parity` never collect anything
  under tests/vendor/ at all, so they were never places these tests
  "skip" -- only `test` and `gate` are.
- Added a guard test pinning the closure, and updated two falsifiability
  tests' hardcoded install-line strings to match.

Verified dependency_gate_gaps() drops ('HAS_VENDOR_DEPS', 'engine-tests')
and the four newly-reachable test files (41 methods) pass for real with
html5lib installed, including under a socket-patched no-network check and
on real CI across all five Engines Python 3.10-3.14 legs.
tests/test_tier_guard.py: 97 passed / 512 subtests under both pytest and
python -m unittest.

Fixes #738.
@JarryShaw

Copy link
Copy Markdown
Owner Author

Final cross-review at 3d45a3f62 (sonnet, a different model from the author): GOOD TO GO. Every claim re-derived independently matched, and nothing was taken on trust.

Correcting my own figure first. The verification table I posted earlier said test/engine-tests/gate reach "7 of 7" tests/vendor modules. There are 8, not 7 — git ls-tree origin/main tests/vendor/ lists test_crawler_reachability_unit.py, test_ftp_return_code_unit.py, test_ipx_packet_unit.py, test_ipx_socket_unit.py, test_request_prompt_unit.py, test_user_agent_unit.py, test_vendor_dest_path_unit.py, test_vendor_reg_apptype_generator_unit.py. The denominator was wrong; the conclusion is not. pytest --collect-only tests/vendor returns 62 tests across all 8 under both the test/engine-tests ignore shape and the bare gate shape — identical sets — and fixture_tier_paths() returns zero entries mentioning "vendor", so integration and pypcap-parity reach 0 of 8. No text in this PR states "7", so the prose is unaffected.

Also correcting my own brief. I warned that the four dark files "may name a different flag set" and to verify per file. They do not: all four declare a byte-identical VENDOR_DEPS = ('requests', 'bs4', 'html5lib'), which I checked myself. So the four rewritten comments are interchangeable in mechanism, not merely in wording.

And the suspicion I raised was well placed, with the opposite answer. I said a dependency_gate_gaps() report that came back identical after un-darkening 41 methods deserved scrutiny. It is not identical: base tree 16 gaps including ('HAS_VENDOR_DEPS', 'engine-tests'), PR head 15 with that entry correctly gone. That is the right outcome rather than a red flag, and test_the_undoctored_workflow_produces_no_unexplained_gap plus test_each_exclusion_still_describes_a_gap_that_is_really_there enforce it and pass.

The new prose is true, clause by clause. Monkeypatching find_spec('html5lib') to None flips HAS_VENDOR_DEPS to False for the four dark files and leaves it True for test_vendor_dest_path_unit.py, which is exactly the skip/run split the comments claim. pyproject.toml:243 is where the vendor-extra comment begins, with requests/beautifulsoup4 plain at :264-265. The six bs4.BeautifulSoup(text, 'html5lib') call sites are exactly six files — ftp/return_code.py, pcapng/{block_type,option_type,record_type}.py, reg/linktype.py, vlan/priority_level.py — and no test in test_vendor_dest_path_unit.py constructs a Vendor or calls .context(): every instance is cls.__new__(cls) with only ._dest_path() invoked.

Counts reproduced under both runners. Per-file collection 5/9/16/11/4 sums to 41 + 4 = 45, matching the PR's breakdown; pytest 45 passed / 159 subtests, unittest 45 OK. Re-run with socket.socket.connect/connect_ex, getaddrinfo and create_connection all patched to raise: 0 failures, which independently confirms the no-network claim. tests/test_tier_guard.py 97 passed / 512 subtests under both, in agreement.

No conflict from the extra. vendor = ["requests[socks]", "beautifulsoup4[html5lib]"] is html5lib's only declared provider; dpkt/scapy/pyshark/pycrate/cryptography declare no transitive dependency on requests/bs4/html5lib/PySocks; MUTUALLY_EXCLUSIVE_IMPORTS = frozenset({'pcap'}) is unrelated. Only engine-tests' install line gained ,vendor — the other four pip install -e lines are untouched, and the step runs once per matrix leg so it survives 3.10-3.14.

Nothing went stale when #773 merged, and no comment names a PR or agent as owning a file — I asked specifically because that defect appeared twice on #777. cron-vendor.yml's post-#773 install line is still pip install -e .[all] with no pytest invocation, so the pyproject.toml comment referring to it remains true.

CI 27 success / 3 expected skips, mergeStateStatus: CLEAN, one commit, +185/−40 matching git diff --stat. Coverage: this PR touches zero pcapkit/ lines, and the applicable evidence is the new guard test shown to fail pre-fix plus CI un-darkening 41 never-executed methods across all five Engines legs.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: pending No verdict for the current head - never reviewed, or the head moved since the last one labels Sep 25, 2026
@JarryShaw
JarryShaw merged commit 35a7901 into main Sep 25, 2026
31 checks passed
@JarryShaw
JarryShaw deleted the fix-738-vendor-deps-engine-tests branch September 25, 2026 12:16
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Pull requests that change CI or workflow configuration (ci: subject prefix) test Pull requests that add or correct tests (test: subject prefix)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

tests: seven more skipUnless gates have never executed on any CI path (106 methods)

1 participant