Deferred Packet¶
pcapkit.corekit.packet contains
DeferredPacket, the mixin that lets an
Info subclass hold its packet field as
a placeholder and resolve it on first read. The reassembled datagrams of
pcapkit.foundation.reassembly use it for a second parse of the payload,
and the traced flows of pcapkit.foundation.traceflow for a reassembly of
the stream.
A subclass is declared class X(DeferredPacket, Info), lists packet in
its __additional__, and names its placeholder class in
__deferred__;
__init_subclass__() refuses one
that does not. Listing packet in __additional__ is what makes the field
lazy: Info then stores it under a mangled
key, so reading it reaches __getattr__, while dict(x),
to_dict() and iteration still
report it as packet.
Resolution happens at most once: the placeholder is called with no arguments, and its result replaces it, so every later read returns that same object.
- class pcapkit.corekit.packet.DeferredPacket[source]¶
Bases:
objectResolves a deferred
packetfield on first read.A mixin for
Infosubclasses; seepcapkit.corekit.packetfor the contract a subclass keeps. Readingpacket– as an attribute, asx['packet'], or throughto_dict(),strorrepr()– resolves a placeholder once and keeps the result.'packet' in x,len()and iteration report the field by name without resolving it.It is shared by
pcapkit.foundation.reassembly.data.ip.Datagram,pcapkit.foundation.reassembly.data.tcp.Datagram,pcapkit.foundation.reassembly.data.dtls.Datagramandpcapkit.foundation.traceflow.data.tcp.Index, which differ only in the placeholder class each names in__deferred__(#1516).- __deferred__¶
Placeholder class the
packetfield may hold, set by each subclass. A value of this class is resolved by calling it with no arguments; an instance of any other class,Noneincluded, is not.
- classmethod __init_subclass__(*args, **kwargs)[source]¶
Refuse a subclass that does not keep the contract.
Either omission would otherwise fail silently, and only on a read. Without
packetin__additional__the field lands in__dict__under its own name,__getattr__()is never reached, and the placeholder itself comes back. Without__deferred__,__analyse__()raisesAttributeErrorfrom inside__getattr__(), whichgetattr(x, 'packet', None)takes for a missing attribute and answers withNone.- Parameters:
- Raises:
InfoError – If
clsdoes not listpacketin its__additional__, or does not name a class in its__deferred__.
- __analyse__()[source]¶
Resolve the
packetfield, at most once.A placeholder, i.e. an instance of
__deferred__, is called with no arguments and its result replaces it in__dict__. Any other value is returned as it is.
- to_dict()[source]¶
Convert the instance into
dict.- Returns:
meth:Info.to_dict <pcapkit.corekit.infoclass.Info.to_dict> exports them, with
packetresolved if it had not been read yet – an export holding the placeholder would leak an implementation detail into what is meant to be plain data.- Return type:
- __getattr__(name)[source]¶
Resolve
packeton first access; any other missing name raises.- Parameters:
name (
str) – Attribute name, reached only when it is absent from__dict__.- Return type:
- Returns:
The resolved
packet, through__analyse__().- Raises:
AttributeError – If
nameis notpacket.