Summary
Run into an issue with PyPCAPKit v1.3.5.post17, where its internal DictDumper (from the dictdumper project) erroneously calls .to_dict() on native Python dict objects during JSON dumping, leading to an AttributeError when using external engines like PyShark . Despite PyPCAPKit’s support for third-party engines (Scapy, DPKT, PyShark) via pcapkit.foundation.engines , the dumper lacks a guard for dict instances.
Environment
- Library: PyPCAPKit v1.3.5.post17 (released May 17, 2025)
- Python: 3.10 (any 3.6+ supported)
- OS: macOS
- External Engine: PyShark via
pyshark.FileCapture (native dict packets)
- Dumper:
dictdumper.JSON from the DictDumper project
Description
When calling:
from pcapkit import extract
extract(
fin = 'capture.pcap',
fout = 'out.json',
format = 'json',
engine = 'pyshark',
store = True,
files = True,
)
the internal dumper’s object_hook attempts:
if isinstance(o, (Info, Schema)):
return o.to_dict()
on an object o that is already a plain dict, resulting in:
AttributeError: 'dict' object has no attribute 'to_dict'
This prevents any JSON file from being produced, even though packet decoding and trace collection run correctly under the hood.
Steps to Reproduce
-
Install PyPCAPKit:
pip install pypcapkit==1.3.5.post17
([PyPI][1])
-
Install PyShark:
-
Run the above extract(...) call on any PCAP file
-
Observe the AttributeError from dictdumper/common.py when dumping JSON.
Expected Behavior
- Complete extraction, trace logging, and JSON output of all packets and trace events.
dictdumper should serialize Python dict objects directly (no .to_dict()), or wrap them appropriately.
Actual Behavior
-
extract() fails during the dumping phase with:
AttributeError: 'dict' object has no attribute 'to_dict'
-
No JSON or trace files are created, despite successful parsing and tracing
Impact
Users cannot leverage PyPCAPKit’s full trace and per-engine dumping capabilities when using JSON format with external engines, effectively breaking workflows.
Proposed Fix
In pcapkit/dumpkit/common.py, modify DictDumper.object_hook to short-circuit on dicts:
def object_hook(self, o):
if isinstance(o, (tuple, set, frozenset)):
return self.make_object(o, list(o))
+ if isinstance(o, dict):
+ return o
if isinstance(o, (Info, Schema)):
return o.to_dict()
if isinstance(o, (ipaddress.IPv4Address, ipaddress.IPv6Address)):
return str(o)
This ensures that native dict instances are passed through unmodified, preventing the .to_dict() call on plain dicts.
Summary
Run into an issue with PyPCAPKit v1.3.5.post17, where its internal DictDumper (from the
dictdumperproject) erroneously calls.to_dict()on native Pythondictobjects during JSON dumping, leading to anAttributeErrorwhen using external engines like PyShark . Despite PyPCAPKit’s support for third-party engines (Scapy, DPKT, PyShark) viapcapkit.foundation.engines, the dumper lacks a guard fordictinstances.Environment
pyshark.FileCapture(nativedictpackets)dictdumper.JSONfrom the DictDumper projectDescription
When calling:
the internal dumper’s
object_hookattempts:on an object
othat is already a plaindict, resulting in:This prevents any JSON file from being produced, even though packet decoding and trace collection run correctly under the hood.
Steps to Reproduce
Install PyPCAPKit:
([PyPI][1])
Install PyShark:
Run the above
extract(...)call on any PCAP fileObserve the
AttributeErrorfromdictdumper/common.pywhen dumping JSON.Expected Behavior
dictdumpershould serialize Pythondictobjects directly (no.to_dict()), or wrap them appropriately.Actual Behavior
extract()fails during the dumping phase with:No JSON or trace files are created, despite successful parsing and tracing
Impact
Users cannot leverage PyPCAPKit’s full trace and per-engine dumping capabilities when using JSON format with external engines, effectively breaking workflows.
Proposed Fix
In
pcapkit/dumpkit/common.py, modifyDictDumper.object_hookto short-circuit on dicts:def object_hook(self, o): if isinstance(o, (tuple, set, frozenset)): return self.make_object(o, list(o)) + if isinstance(o, dict): + return o if isinstance(o, (Info, Schema)): return o.to_dict() if isinstance(o, (ipaddress.IPv4Address, ipaddress.IPv6Address)): return str(o)This ensures that native
dictinstances are passed through unmodified, preventing the.to_dict()call on plain dicts.