fix(const,vendor): give Method's registered members their str payload (#870) - #871
Conversation
…#870) `Method.__new__` built every registered member with `str.__new__(cls)` (no argument), so the underlying str payload was permanently empty regardless of the declared value -- `str(Method.GET) == ''` and `Method.GET == 'GET'` was False for all 40 members, even though `_value_`/`.value` were always correct. #869 fixed the same class's *unregistered* path only, which exposed the inconsistency: after #869, `str(Method('frob')) == 'frob'` but `str(Method.GET) == ''`. - Fix `__new__` to `str.__new__(cls, value)`, mirroring `Command.__new__`, which never had this defect. Fixed in both the generator (`pcapkit/vendor/http/method.py`) and the generated module (`pcapkit/const/http/method.py`); a second regeneration is byte-identical. - Surveyed every other hand-rolled `__new__` under `pcapkit/const/`: `Command` already passes its value, `FEATCode` has no custom `__new__`, and `OptionType`/`AppType` deliberately store a formatted display string as their value -- none share this defect. - Added `tests/const/test_const_str_payload_870_unit.py`: the exact repro, a sweep of all 40 `Method` members, and a registry-wide sweep of `Command`/`FEATCode`/`Method` (`OptionType` explicitly exempted, with a comment, since its value already *is* the display string). Verified each new assertion fails on unfixed `__new__` and passes with the fix. - Updated `tests/const/test_const_enum_no_mint.py`, which had pinned the old empty-payload behavior as an accepted-but-unfixed asymmetry; it now expects the fixed behavior. Behaviour change: `Method.GET == 'GET'` is now True (was False) for all 40 public members; no code under `pcapkit/protocols` compared a Method member this way. Build and targeted tests green (315 methods across const/http/ftp suites).
|
GOOD TO GO on The fix is Generator fidelity proven, not assumed — the #866 failure mode is a const file whose generator still emits the old text. Rendering the committed The behaviour surface is wider than the body originally said, so I have updated the body. Beyond the documented No in-repo reliance on the old behaviour — the sole consumer is Tests genuinely pin it: reverting the two words fails 4 of 6 new methods (82 subTest records); the other two deliberately pin contracts the fix does not touch. The Left deliberately: a spurious Separately filed: the regeneration CLI swallows exceptions and still exits 0 — see the new issue linked below. CI on this head: 55 green, 0 failed, 3 still running; I will confirm when they land. |
Please follow the guide below
You will be asked some questions, please read them carefully and answer honestly
Put an
xinto all the boxes [ ] relevant to your pull request (like that [x])Use Preview tab to see how your pull request will actually look like
Searched for similar pull requests
Followed the coding style (
make pylint,make mypy,make isort)make testpasses, and a test case covers the changeAdded a changelog entry under
docs/source/changelog/and regeneratedCHANGELOG.md, if the change is user-visibleWhat is the purpose of your pull request?
Tick the commit type your subject line carries.
fix— corrects a defectfeat— adds a featureperf— changes performance, not behaviourrefactor— changes neither behaviour nor performancetest— tests onlydocs— documentation onlyci— workflows or build toolingchore— anything elseDescription of your pull request and other information
Fixes #870.
Method.__new__calledstr.__new__(cls)with no argument, so every one of the 40 registered members'strpayload was permanently empty regardless of its declared value:str(Method.GET) == '',Method.GET == 'GET'wasFalse._value_/.valuewere always correct. #869 fixed this class's unregistered path only, exposing the asymmetry:str(Method('frob')) == 'frob'butstr(Method.GET) == ''.Fixed to
str.__new__(cls, value), mirroringCommand.__new__(never had this defect), in both the generator (pcapkit/vendor/http/method.py) and the generated module; a second regeneration is byte-identical.Surveyed every hand-rolled
__new__underpcapkit/const/:Commandalready passes its value,FEATCodehas no custom__new__,OptionType/AppTypedeliberately store a formatted display string as their value — none share this defect.Behaviour changes, all in the correcting direction and all measured:
Method.GET == 'GET'is nowTruefor all 40 members (wasFalse);bool(Method.GET)flipsFalse→True, because an empty payload made every member falsy;json.dumps(Method.GET)emits"GET"where it emitted"";sorted()over members is now lexicographic rather than input-order-stable; and a member-keyeddict/setno longer collapses —{m: … for m in Method}has 40 entries where it had 1, sincestr.__hash__wins the MRO and all 40 members previously hashed as''and compared==to one another. Nothing underpcapkit/protocolsrelied on the old behaviour — checkedhttpv1.py/httpv2.py; the one caller only reads.valueviaMethod.get().Added
tests/const/test_const_str_payload_870_unit.py(repro, 40-member sweep, and a registry-wide sweep of Command/FEATCode/Method, with OptionType exempted and why). Verified each assertion fails on unfixed code, passes with the fix. Updatedtest_const_enum_no_mint.py, which had pinned the old empty-payload behaviour as accepted-but-unfixed.make testunchecked above: ran targeted suites instead (it OOMs locally) — the new file,test_const_enum_no_mint/get/lookup/builtin_parity,test_const_registry_protocol,test_const_apptype_split_unit(220 methods), plustests/protocols/application/test_http_unit.py,test_ftp_unit.py,test_httpv2_*(96 methods) — all green.Changelog: N/A — changelog centralised in #657.