User Defined Exceptions¶
pcapkit.utilities.exceptions refined built-in exceptions.
Make it possible to show only user error stack information [*],
when exception raised on user’s operation.
Loud and Quiet Errors¶
Raising a BaseError is, by default, a
loud act: the error is logged once at logging.CRITICAL on the
logger logger, and outside development mode
an exception hook is installed on sys.excepthook and
threading.excepthook, the first time a loud error needs it, so the user
sees the exception line rather than a walk through pcapkit’s internals.
That hook only shortens the printing of a
BaseError itself; every other exception
is handed on to whichever hook was previously installed, unchanged.
quiet=True marks an error that pcapkit raises as internal control
flow and expects to catch itself – the
MissingKeyError behind
MultiDict.get is the archetype.
Such an error emits nothing on any channel and touches no process-global state.
It is still an ordinary exception carrying its message, so except clauses and
repr() are unaffected.
Changed in version 1.5.0: In 1.4.x, quiet=True logged at ERROR instead of CRITICAL rather
than not logging, and sys.tracebacklimit was set on both paths. A
single MultiDict.get() miss therefore produced an ERROR record – one
per frame when parsing unfragmented IPv6 with reassembly enabled – and
truncated the tracebacks of unrelated exceptions for the rest of the process.
Those records never corresponded to a fault; to observe internal lookup
misses, catch the exception rather than read the log (#362).
- exception pcapkit.utilities.exceptions.BaseError(*args, quiet=False, **kwargs)[source]¶
Bases:
ExceptionBase error class of all kinds.
A loud error – the default – is reported once, at
logging.CRITICALlevel, on theloggerlogger. Outside development mode it also installs_excepthook()assys.excepthookand_threading_excepthook()asthreading.excepthook, the first time a loud error needs them, so that error – and every loud error reaching the top level after it, on the main thread or any other – prints its one-line exception message rather than a walk throughpcapkit’s internals.A quiet error (
quiet=True) is onepcapkitraises as internal control flow and expects to catch itself, such as theMissingKeyErrorbehindMultiDict.get. It is therefore silent and free of side effects: nothing is logged, and neithersys.excepthooknorthreading.excepthookis touched. It is still a perfectly ordinary exception, carrying its message for whoever catches it.Important
The terseness is deliberately not done by setting
sys.tracebacklimitto0: that is process-global, so one loud error would truncate the tracebacks of every other, unrelated exception for the rest of the process. Each of the two hooks here shortens the printing of aBaseErroronly, and hands every other exception, unchanged, to whatever hookpcapkitfound installed before it first needed its own.Both hooks are installed lazily, from here, rather than at import time, so a program that imports
pcapkitbut never raises one of its errors never hassys.excepthookorthreading.excepthooktouched.The two hooks still do not cover every path an exception can take. A traceback a caller formats itself with
traceback– rather than letting it reach the top level uncaught – passes through neither. See GitHub issue #719.The
stacklevelof the log record is the relative levelstacklevel()computes, so the record is attributed to the caller whose operation failed rather than to this module. It must not be negated:logging.Logger.findCaller()reads that as “do not walk out at all” and would blameloggingitself for every error.
Changed in version 1.5.0: A quiet error logs nothing, where 1.4.x logged it at
ERROR, and no error setssys.tracebacklimit(#362).- Parameters:
quiet – If
True, the error is neither logged nor allowed to install the exception hook; it is raised silently, as internal control flow.*args – Arbitrary positional arguments.
**kwargs – Arbitrary keyword arguments.
TypeError Category¶
- exception pcapkit.utilities.exceptions.DigitError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be (a) number(s).
- exception pcapkit.utilities.exceptions.IntError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be integral.
- exception pcapkit.utilities.exceptions.RealError(*args, quiet=False, **kwargs)[source]¶
-
The function is not defined for real number.
- exception pcapkit.utilities.exceptions.ComplexError(*args, quiet=False, **kwargs)[source]¶
-
The function is not defined for complex instance.
- exception pcapkit.utilities.exceptions.BoolError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
booltype.
- exception pcapkit.utilities.exceptions.BytesError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
bytestype.
- exception pcapkit.utilities.exceptions.StringError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
strtype.
- exception pcapkit.utilities.exceptions.BytearrayError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
bytearraytype.
- exception pcapkit.utilities.exceptions.DictError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
dicttype.
- exception pcapkit.utilities.exceptions.ListError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
listtype.
- exception pcapkit.utilities.exceptions.TupleError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
tupletype.
- exception pcapkit.utilities.exceptions.IterableError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be iterable.
- exception pcapkit.utilities.exceptions.IOObjError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be file-like object.
- exception pcapkit.utilities.exceptions.ProtocolUnbound(*args, quiet=False, **kwargs)[source]¶
-
Protocol slice unbound.
- exception pcapkit.utilities.exceptions.CallableError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be callable.
- exception pcapkit.utilities.exceptions.InfoError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be
Infoinstance.
- exception pcapkit.utilities.exceptions.IPError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be IP address.
- exception pcapkit.utilities.exceptions.EnumError(*args, quiet=False, **kwargs)[source]¶
-
The argument(s) must be enumeration protocol type.
- exception pcapkit.utilities.exceptions.ComparisonError(*args, quiet=False, **kwargs)[source]¶
-
Rich comparison not supported between instances.
AttributeError Category¶
- exception pcapkit.utilities.exceptions.FormatError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,AttributeErrorUnknown format(s).
- exception pcapkit.utilities.exceptions.UnsupportedCall(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,AttributeErrorUnsupported function or property call.
IOError Category¶
FileExistsError Category¶
- exception pcapkit.utilities.exceptions.FileExists(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,FileExistsError[Errno 17] File already exists.
FileNotFoundError Category¶
- exception pcapkit.utilities.exceptions.FileNotFound(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,FileNotFoundError[Errno 2] File not found.
IndexError Category¶
- exception pcapkit.utilities.exceptions.ProtocolNotFound(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,IndexErrorProtocol not found in ProtoChain.
ValueError Category¶
- exception pcapkit.utilities.exceptions.VersionError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorUnknown IP version.
- exception pcapkit.utilities.exceptions.IndexNotFound(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorProtocol not in ProtoChain.
- exception pcapkit.utilities.exceptions.ProtocolError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorInvalid protocol format.
- exception pcapkit.utilities.exceptions.EndianError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorInvalid endian (byte order).
- exception pcapkit.utilities.exceptions.KeyExists(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorKey already exists.
- exception pcapkit.utilities.exceptions.NoDefaultValue(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorNo default value.
- exception pcapkit.utilities.exceptions.EnumValueError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorNo member of an enumeration carries this value.
The value-miss half of the pair whose name-miss half is
EnumKeyError; see that one for the stdlibEnumshape both follow, and for why the two halves derive from different builtins.
- exception pcapkit.utilities.exceptions.FieldValueError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorInvalid field value.
- exception pcapkit.utilities.exceptions.SchemaError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorInvalid schema.
- exception pcapkit.utilities.exceptions.SeekError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorInvalid seek position.
- exception pcapkit.utilities.exceptions.TruncateError(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorInvalid truncate size.
- exception pcapkit.utilities.exceptions.VendorPathNotFound(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ValueErrorCrawler module is not inside the
vendorpackage root.
NotImplementedError Category¶
- exception pcapkit.utilities.exceptions.ProtocolNotImplemented(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,NotImplementedErrorProtocol not implemented.
- exception pcapkit.utilities.exceptions.VendorNotImplemented(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,NotImplementedErrorVendor not implemented.
struct.error Category¶
EOFError Category¶
- exception pcapkit.utilities.exceptions.StreamEOFError(*args, quiet=False, **kwargs)[source]¶
-
Underlying stream exhausted; no data left to read.
Raised by
prepare()when the length of a schema’s read was derived by measuring what is actually left in the stream – rather than declared by the caller – and that measurement came back zero. This is the frame reader’s “no more packets” signal, so it subclassesEOFErrorrather than replacing it: existingexcept (EOFError, StopIteration)handlers keep working unchanged, and a caller that wants to be more specific can catch this instead.A declared zero length – a nested schema legitimately sized to have nothing to read – is a different situation and does not raise this.
FrameandPCAPNGraise it too, quietly, when fewer octets are left than a record header or a block needs.Note
prepare()always raises this withquiet=True: reaching end of stream is the frame reader’s ordinary way of finding out there is nothing left to parse, not a fault to log – the same conventionStructErrorfollows for the same situation via its owneof=True.
KeyError Category¶
- exception pcapkit.utilities.exceptions.MissingKeyError(*args, quiet=False, **kwargs)[source]¶
-
Key not found.
- exception pcapkit.utilities.exceptions.FragmentError(*args, quiet=False, **kwargs)[source]¶
-
Invalid fragment dict.
- exception pcapkit.utilities.exceptions.PacketError(*args, quiet=False, **kwargs)[source]¶
-
Invalid packet dict.
- exception pcapkit.utilities.exceptions.EnumKeyError(*args, quiet=False, **kwargs)[source]¶
-
No member of an enumeration carries this name.
The name-miss half of the pair whose value-miss half is
EnumValueError, and the split between them follows stdlibEnumrather than this package’s own taste:E['nosuch']raisesKeyErrorandE(999)raisesValueError, so a lookup that misses by name isKeyError-derived and one that misses by value isValueError-derived. That is a ruling given in review of #877’s phase-2 re-parenting, carried out by GitHub issue #923: raise whichever of the two stdlibEnumwould raise in the same circumstances, and raise it from this module rather than as a builtin.Deriving from
KeyErroris what makes that ruling cheap to carry out: six in-library call sites catchget()’s name miss asKeyError–get()catches it in order to build an unregistered member, so for that one a failed name lookup is part of a successful call – and every one of them keeps catching.Note
Distinct from
MissingKeyError, which is deliberately not reused here: that one reports an absent mapping key, asMultiDictand thepcapkit.toolkitextractors raise it, and conflating the two would leave a caller unable to tell a registry that has no such member from a packet dict that has no such field.Added in version 1.5.0.
ModuleNotFoundError Category¶
- exception pcapkit.utilities.exceptions.ModuleNotFound(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,ModuleNotFoundErrorModule not found.
io.UnsupportedOperation Category¶
- exception pcapkit.utilities.exceptions.UnsupportedOperation(*args, quiet=False, **kwargs)[source]¶
Bases:
BaseError,UnsupportedOperationUnsupported operation.
Error Handling Utilities¶
- pcapkit.utilities.exceptions.stacklevel()[source]¶
Stack level of the innermost frame outside
pcapkit.The value is a relative level, in the sense both
warnings.warn()and theloggingmodule use: level1is the frame that calledstacklevel(), level2its caller, and so on outwards. Handing it to either of them attributes the complaint to the caller who reached intopcapkit, rather than to whicheverpcapkitinternal happened to notice the problem – which is the whole point of the function, since the internal frames are noise to the user reading the report.The arithmetic, since it is easy to get backwards. Number the frames outwards from this one, so that a number is the relative level a consumer wants:
level 0 stacklevel() itself level 1 whoever called stacklevel() ... level boundary the outermost frame inside pcapkit ... level outermost the interpreter entry point
The frame to name is the first one past the boundary, hence
boundary + 1.boundaryis measured from the inside out: it depends only on how deep thepcapkitframes run, never on how deep the caller’s own stack is. Numbering from the outside in would grow with the outer stack, so the frame named would drift one further out for every extra frame above the boundary – under pytest, dozens of them.Both bounds are enforced, as neither consumer copes with a level outside them:
Never below
1.0and negative values mean “do not walk out at all” tologging.Logger.findCaller(), which then attributes the record tologgingitself;warnings.warn()treats them as1.Never above
outermost. That bound is reached when the whole stack is insidepcapkit, e.g. running the package as a script, and walking past the outermost frame makeswarnings.warn()fall back to blaming thesysmodule.
The walk goes through
inspect.currentframe()andf_backrather thantraceback.extract_stack(): it skips building theFrameSummaryobjects and thelinecachelookupstraceback.extract_stack()does for every frame, which is worth avoiding on a function called once per warning. It is also immune tosys.tracebacklimit, whichtraceback.StackSummary.extract()honours: a limit of0would makeextract_stack()return an empty list and silently break the attribution of every warning.BaseErrordoes not set that limit (it prints its terse line through an exception hook instead), but user code may.Important
The level is relative to the caller of
stacklevel(). A function that forwards it towarnings.warn()on its caller’s behalf has to add one for its own frame – seepcapkit.utilities.warnings.warn(), which does exactly that.- Return type:
- Returns:
Number of frames from the caller of
stacklevel()outwards to the innermost frame whose path does not contain/pcapkit/.
Footnotes