Skip to content

fix(protocols): make() rejects an enum member name given as str unless a namespace is passed - #1227

Merged
JarryShaw merged 1 commit into
mainfrom
fix/1210-make-index-str
Oct 7, 2026
Merged

JarryShaw merged 1 commit into
mainfrom
fix/1210-make-index-str

Conversation

@JarryShaw

@JarryShaw JarryShaw commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner
  • Searched for similar pull requests
  • Followed the coding style (make pylint, make mypy, make isort) — ran pylint (Makefile flags), mypy and isort on protocol.py only: no new findings in the changed region
  • make test passes, and a test case covers the change — the legs listed below, not the full make test
  • Added a changelog entry — N/A, added centrally

What is the purpose of your pull request?

  • fix — corrects a defect

Description of your pull request and other information

Closes #1210

_make_index now infers the namespace when it gets a str and no namespace. It finds the calling make() / _make_* method on the class and picks the arguments whose value equals the name (==, not identity), whose <arg>_namespace is None, and whose default is an enum member. It then uses that default's enum class. When several arguments share the name, e.g. IPv4(tos_thr='HIGH', tos_rel='HIGH'), every candidate enum must have it with the same value. Otherwise it raises ProtocolNotImplemented: ... ambiguous member name ...; pass a_namespace= or b_namespace= explicitly, e.g. IPv4(tos_del='LOW', tos_thr='LOW'), since LOW is not a ToSThroughput member. No caller changed. int, enum members and explicit namespaces never reach the new code. 94 arguments across 20 modules are now inferable.

Not inferable, so these keep the old behaviour: HTTP.make(status=), HOPOPT/IPv6_Opts _make_opt_smf_dpd(tid_type=) and _make_opt_mpl(seed_type=), all of which default to None. Also the list arguments of 12 HIP _make_param_* methods (dh_group_list, hip_transform, hip_cipher, nat_traversal_mode, hit_suite_list, transport_format_list, esp_transform, hip_transport_mode, reg_info/request/response/failed). Their items are passed through a loop variable, not through a parameter with an enum default.

Before / after: Ethernet(type='Internet_Protocol_version_6') raised ProtocolNotImplemented. It now gives …86dd, the same bytes as the enum member. L2TPv2(type='Control') now gives c002000800000000.

Tests: new tests/protocols/test_make_index_str_unit.py covers link (Ethernet, L2TPv2), internet (IPv4), transport (TCP option), application (OSPF) and misc (PCAP header). Each case checks str == member == int, plus the non-default member. It also covers both ToS collisions and an ambiguous case, both a constructed one and the real LOW one. Against main it fails 8; against the first revision of this PR it fails the 2 collision tests; with the fix, 7 passed and 6 subtests passed.

  • run_unittest_leg.py protocols --exclude protocols/internet: 857 tests, 0 failures, 0 errors
  • run_unittest_leg.py protocols/internet: 503 tests, 0 failures, 0 errors
  • pytest tests/project (first revision): 389 passed, 1 skipped

@JarryShaw JarryShaw moved this to In review in PyPCAPKit Oct 7, 2026
@JarryShaw JarryShaw added fix Pull requests that fix a defect (fix: subject prefix) review: running A cross-review is in flight against the current head - no verdict yet labels Oct 7, 2026
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Coverage: 88.92% (unit tier, Python 3.14, d7c505ffd, Unit Tests run success)

Package Statements Missed Branches Partial Cover
pcapkit (top level) 104 4 20 4 93.55%
pcapkit/const 18757 1034 2342 845 90.24%
pcapkit/corekit 1878 91 580 22 94.34%
pcapkit/dumpkit 142 0 42 0 100.00%
pcapkit/foundation 2442 102 852 39 94.38%
pcapkit/interface 112 7 40 5 92.11%
pcapkit/protocols 15819 191 4064 166 98.17%
pcapkit/toolkit 487 65 144 1 85.42%
pcapkit/utilities 429 4 122 4 98.55%
pcapkit/vendor 4409 2359 1006 158 42.84%

Per-file detail: the coverage-html artifact of this run.

@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review verdict on bb5c9a881: NEEDS CHANGES (Sonnet reviewed; the author ran on Opus).

  • Must fix: _make_index_namespace matches the caller's argument by identity (values.get(arg) is name). When two enum arguments receive the same literal, both match. Inference then gives up and raises ProtocolNotImplemented. Examples: IPv4(tos_del='NORMAL', tos_thr='NORMAL') and IPv4(tos_thr='HIGH', tos_rel='HIGH'). Whether it fails depends on string interning: 'NOR'+'MAL' works. main also raises here, so this is not a regression, but the gap is neither tested nor documented.
  • Confirmed: across 376 classes, the default make() output is byte-identical to main. So is member/int output for 6 members of every enum argument. 111/111 string names build the same bytes as their members. Invalid names still raise or fall back as before. There is no measurable slowdown on the non-str path. Both test legs are clean (498/0 and 855/0).
  • Count: 21 modules call _make_index, not 22.

@JarryShaw JarryShaw added review: needs-changes Cross-review at the current head says changes are required; see the verdict comment and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 7, 2026
…s a namespace is passed

Protocol._make_index now infers the namespace for a str member name when
none is given: it finds the calling make() method on the class, picks the
arguments whose value equals the name, whose *_namespace companion is
None, and whose default is an enum member, and uses that default's enum
class. If several arguments match, every candidate enum must have the
name with the same value; otherwise ProtocolNotImplemented asks for an
explicit *_namespace. int, enum members and explicit namespaces take the
same path as before.

Arguments whose default is not an enum member (None defaults and loop
variables over list arguments) keep the old behaviour.

Closes #1210
@JarryShaw
JarryShaw force-pushed the fix/1210-make-index-str branch from bb5c9a8 to d7c505f Compare October 7, 2026 18:08
@JarryShaw JarryShaw added review: running A cross-review is in flight against the current head - no verdict yet and removed review: needs-changes Cross-review at the current head says changes are required; see the verdict comment labels Oct 7, 2026
@JarryShaw

Copy link
Copy Markdown
Owner Author

Cross-review verdict on d7c505ffd: GOOD TO GO (Sonnet, round 2; author Opus).

  • Fixed: IPv4(tos_del='NORMAL', tos_thr='NORMAL') now builds the same bytes as the enum form, and so does a non-interned 'NOR'+'MAL'. tos_thr/tos_rel='HIGH' matches too.
  • No other output changed: default make() output is byte-identical to main across every protocol class.
  • Tests: the new tests fail on main. The legs give 503/0 and 857/0.
  • Follow-up, not a regression (filed separately): the strict rule over-raises. tos_thr='LOW', tos_thr_default=1 falls back as it does on main, but adding tos_del='LOW' makes the same call raise "ambiguous". No two enum arguments currently share a name with different values, so the value-conflict branch never fires. The fix is to resolve each _make_index call against its own argument, which all 111 call sites name plainly. The hint in the error message also points at tos_thr_namespace=, which could not help in that case.

@JarryShaw JarryShaw added review: good-to-go Cross-review at the current head says ready; CI state is separate and removed review: running A cross-review is in flight against the current head - no verdict yet labels Oct 7, 2026
@JarryShaw
JarryShaw merged commit a265fa3 into main Oct 7, 2026
40 checks passed
@JarryShaw
JarryShaw deleted the fix/1210-make-index-str branch October 7, 2026 19:06
@JarryShaw JarryShaw removed the review: good-to-go Cross-review at the current head says ready; CI state is separate label Oct 7, 2026
@JarryShaw JarryShaw added this to the PyPCAPKit v1.5 milestone Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Pull requests that fix a defect (fix: subject prefix)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

fix(protocols): make() rejects an enum member name given as str unless a namespace is passed

1 participant