Repository navigation
fix(corekit): from_dict(to_dict()) loses nested values, and Info.__len__ counts hidden keys - #1334
Conversation
|
Cross-review verdict on 1. The new test reads a capture the unit tier does not generate — CI-confirmed on every leg. 2. I confirmed on 3.14 that Verified fine, so do not redo: the new module gives 69 failures / 3 passes on a copy of Three resolver findings, none blocking: a wrong-shape mapping becomes an |
…n__ counts hidden keys ``SchemaField.pack`` now rebuilds a mapping into its declared schema, so a schema round-tripped through ``to_dict``/``from_dict`` packs instead of raising ``AttributeError: 'dict' object has no attribute 'pack'`` (#1290). ``Info.from_dict`` does the same for keys whose annotation resolves at runtime to an ``Info`` subclass, and ``to_dict`` now documents that the conversion stays one-way for every other key. ``Info.__len__`` counts only the keys ``__iter__`` yields, so ``len(info) == len(list(info))`` (#1296). Closes #1290 Closes #1296
86c1cfe to
dcb1306
Compare
|
Round-2 verdict on
Nit: the docstring's "26 of 487 Info classes" does not re-derive on 3.14 (488 subclasses, 45 with a |
Please follow the guide below
make pylint,make mypy,make isort) — ran all three on the two changedpcapkit/files; the remaining 4misc.pymypy and 3infoclass.pypylint messages are identical onmainmake testpasses, and a test case covers the change —tests/corekit/*andtests/project/*one module per process,tests/protocols/{test_option_roundtrip_unit,schema/*}, plus thecorekit,protocols/internetandprotocols --exclude protocols/internetunittest legsdocs/source/changelog/and regeneratedCHANGELOG.md— N/A, added centrally after the waveWhat is the purpose of your pull request?
fix— corrects a defectDescription of your pull request and other information
Closes #1290
Closes #1296
#1290.
SchemaField.packrebuilds aMappingintoself._schemabefore packing, so a schema flattened byto_dictand rebuilt byfrom_dictpacks.Info.from_dictdoes the same for keys whose annotation resolves at runtime to anInfosubclass (Optional[X]of one counts);to_dictdocuments that the conversion stays one-way for every other key. #1296.Info.__len__counts only the keys__iter__yields.Probe, before → after:
AttributeError: 'dict' object has no attribute 'pack'→b'\x07'; pcapng frame schemas failing 64/64 → 0/64;info.inner.xAttributeError →1;len 3 ['a']→len 1 ['a']. Over all 22 fixture captures / 1588 frames, per-Infokeys and values and per-layer packed-byte digests are identical before and after; after the fixlen == len(list(...))for 13608/13608Infoobjects. All 490 importableInfoclasses resolve andfrom_dictwithout raising.Tests:
tests/corekit/test_from_dict_roundtrip_unit.py, 14 tests + 17 subtests. Reverting both fixes fails 21 of them; restored, all pass.tests/corekit/test_infoclass.py:62pinned the oldlen(bag) == 6and is updated to3with a note — the only existing test changed.Revision 2, from review:
examples/captures/many_interfaces.pcapng, which is generated and untracked, so it failed on every CI leg. It now builds 12 blocks as octets in memory, one per block schema that claims a type code (SHB with and without options, IDB ×2, EPB, SPB, NRB, ISB, DSB, CB, SJEB, and an unclaimed type). Each assertspack() == rawas well as the round trip; verified withexamples/captures/moved aside._as_info_typeguards the resolved hint with a parametrised-generic test and aTypeErrorfallback. Below Python 3.11isinstance(list[Packet], type)isTruewhileissubclassrefuses it, sofrom_dictraised on 3.9/3.10 for 26 of 487 classes. A test pins the shape on every version by handing the resolver an object whose__class__reportstype; dropping the guard fails it here on 3.14.WeakKeyDictionaryto the class's own__dict__, read back withcls.__dict__.getso no subclass inherits its parent's map. The weak map pinned self-referential classes forever (its value strongly referenced the weak key); a class attribute makes that a collectable cycle, and agctest proves it — reinstating the weak map fails that test.Infocarrying those keys, because validating it would reject dataInfo(**kwargs)has always accepted; and an unresolvable forward reference is cached as "skip", becausefrom_dictruns per parsed packet and re-resolving every call to catch a case this package does not have costs more than it saves.Behaviour changes:
len(info)is smaller, andInfo.from_dictreturnsInfoinstances where annotated. No wire format changes.