Common Utilities¶
pcapkit.dumpkit.common is the collection of common utility
functions for pcapkit.dumpkit implementation, which is
generally the customised hooks for dictdumper.Dumper
classes.
- class pcapkit.dumpkit.common.Dumper(fname, **kwargs)[source]¶
Bases:
DumperBaseBase
Dumperobject.This class is a customised
Dumperfor thepcapkit.dumpkitimplementation, which is generally customised for opt-in registration to theExtractorandTraceFlowoutput dumper registries.Example
Registration is opt-in. Pass keyword argument
fmtat class definition to register the dumper under that output format:class MyDumper(Dumper, fmt='my_format', ext='.mine'): ...
Omit it and the subclass is not registered:
class MyMixin(Dumper): # not registered ...
Such a class can still be registered later, on demand. Note this hook writes both output registries, so the equivalent manual call is the module-level one that does the same, not either class’ own method:
from pcapkit.foundation.registry.foundation import register_dumper register_dumper('my_mixin', MyMixin, '.mine')
- classmethod __init_subclass__(fmt=None, ext=None, *args, **kwargs)[source]¶
Initialise subclass.
This method is used to register the subclass to the
ExtractorandTraceFlowoutput dumper registries.- Parameters:
fmt (
str|None) – Output format to register the subclass under, lowercased.None(the default) skips registration entirely.ext (
str|None) – Output file extension;Noneinfers it fromfmt. Only meaningful alongsidefmt.*args (
Any) – Arbitrary positional arguments.**kwargs (
Any) – Arbitrary keyword arguments.
- Raises:
UnsupportedCall – If
extis given withoutfmt, or if any unrecognised class keyword is given.
Registration is opt-in: the subclass is registered if and only if
fmtis given. This is what lets a subclass decline registration rather than having to inheritDumperBaseto avoid it, and it matchesEnumSchema.__init_subclass__, which has guarded on its owncodekeyword all along.Note
The previous behaviour inferred
fmtfrom the subclass’kindproperty, which it could only read off an instance – so it constructed one against atempfile.NamedTemporaryFile()while theclassstatement was still executing. Guarding onfmtremoves that: a class definition no longer touches the filesystem.
Internal Definitions¶
- pcapkit.dumpkit.common.render_enum(o)[source]¶
Render an enumeration member as
Type::name [value].This is the spelling every dumped enumeration carries in the
json,tree,text,txt,plistandxmloutput of bothExtractorandTraceFlow, so it lives in one function rather than being spelled out at each of the three placesmake_dumper()’s hook needs it.- Parameters:
o (
Enum|Enum) – Enumeration member to render.- Return type:
- Returns:
The member’s
Type::name [value]rendering.
Note
A
Flagvalue composed entirely of undeclared bits has no name at all –nameisNone, not a string – so interpolating it unguarded put the literal four charactersNoneinto the name half and renderedFlags(0)as'Flags::None [0]'(GitHub issue #648).Two things make that worth a guard rather than a shrug.
'None'is a plausible member name, so a consumer splitting the rendering on::cannot tell it from a member genuinely so named – andNONEis a declared name elsewhere in the library. And the defect is not confined to zero:Flags(1),Flags(8)andFlags(65536)are every bit as nameless, so a guard written againstvalue == 0would fix one case and leave the rest.The fallback is the value’s own decimal spelling, which is what the enumeration libraries themselves already use for an undeclared residue:
Flags(2057).nameis'ACK|9', naming the declared bit and giving the leftovers as one number. A wholly-undeclared value is that same rendering with no declared bit to precede it, soFlags(9)becomes'Flags::9 [9]'andFlags(0)becomes'Flags::0 [0]'. It also cannot be mistaken for a member name, since a Python identifier may not begin with a digit – none of the 1867 identifiers declared underpcapkit.constis a bare decimal, and none ever can be.This is not an
aenumquirk. A stdlibenum.IntFlagbuilt from the same members answersname is Noneidentically on CPython 3.14.7, so the guard belongs here rather than in a choice of enumeration library.