# -*- coding: utf-8 -*-
# pylint: disable=protected-access
"""decorator functions
:mod:`pcapkit.utilities.decorators` contains several useful
decorators, including :func:`~pcapkit.utilities.decorators.seekset`
and :func:`~pcapkit.utilities.decorators.beholder`.
"""
import functools
import io
import os
import traceback
###############################################################################
# from pcapkit.foundation.analysis import analyse
# from pcapkit.protocols.raw import Raw
###############################################################################
__all__ = ['seekset', 'seekset_ng', 'beholder', 'beholder_ng']
[docs]def seekset(func):
"""Read file from start then set back to original.
Important:
This decorator function is designed for decorating *class methods*.
The decorator will keep the current offset of :attr:`self._file`, then
call the decorated function. Afterwards, it will rewind the offset of
:attr:`self._file` to the original and returns the return value from
the decorated function.
Note:
The decorated function should have following signature::
func(self, *args, **kw)
See Also:
:meth:`pcapkit.protocols.protocol.Protocol._read_packet`
:meta decorator:
"""
@functools.wraps(func)
def seekcur(self, *args, **kw):
seek_cur = self._file.tell()
self._file.seek(self._seekset, os.SEEK_SET)
return_ = func(self, *args, **kw)
self._file.seek(seek_cur, os.SEEK_SET)
return return_
return seekcur
[docs]def seekset_ng(func):
"""Read file from start then set back to original.
Important:
This decorator function is designed for decorating *plain functions*.
The decorator will rewind the offset of ``file`` to ``seekset``, then
call the decorated function and returns its return value.
Note:
The decorated function should have following signature::
func(file, *args, seekset=os.SEEK_SET, **kw)
See Also:
:mod:`pcapkit.foundation.analysis`
:meta decorator:
"""
@functools.wraps(func)
def seekcur(file, *args, seekset=os.SEEK_SET, **kw): # pylint: disable=redefined-outer-name
# seek_cur = file.tell()
file.seek(seekset, os.SEEK_SET)
return_ = func(file, *args, seekset=seekset, **kw)
# file.seek(seek_cur, os.SEEK_SET)
return return_
return seekcur
[docs]def beholder(func):
"""Behold extraction procedure.
Important:
This decorator function is designed for decorating *class methods*.
This decorate first keep the current offset of
:attr:`self._file <pcapkit.protocols.protocol.Protocol._file>`, then
try to call the decorated function. Should any exception raised, it will
re-parse the :attr:`self._file <pcapkit.protocols.protocol.Protocol._file>`
as :class:`~pcapkit.protocols.raw.Raw` protocol.
Note:
The decorated function should have following signature::
func(self, proto, length, *args, **kwargs)
See Also:
:meth:`pcapkit.protocols.protocol.Protocol._decode_next_layer`
:meta decorator:
"""
@functools.wraps(func)
def behold(self, proto, length, *args, **kwargs):
seek_cur = self._file.tell()
try:
return func(proto, length, *args, **kwargs)
except Exception:
from pcapkit.protocols.raw import Raw # pylint: disable=import-outside-toplevel
error = traceback.format_exc(limit=1).strip().split(os.linesep)[-1]
# error = traceback.format_exc()
self._file.seek(seek_cur, os.SEEK_SET)
next_ = Raw(io.BytesIO(self._read_fileng(length)), length, error=error)
return next_
return behold
[docs]def beholder_ng(func):
"""Behold analysis procedure.
Important:
This decorator function is designed for decorating *plain functions*.
This decorate first keep the current offset of ``file``, then try to call
the decorated function. Should any exception raised, it will re-parse the
``file`` as :class:`~pcapkit.protocols.raw.Raw` protocol.
Note:
The decorated function should have following signature::
func(file, length, *args, **kwargs)
See Also:
:meth:`pcapkit.protocols.transport.transport.Transport._import_next_layer`
:meta decorator:
"""
@functools.wraps(func)
def behold(file, length, *args, **kwargs):
seek_cur = file.tell()
try:
return func(file, length, *args, **kwargs)
except Exception:
# from pcapkit.foundation.analysis import analyse
from pcapkit.protocols.raw import Raw # pylint: disable=import-outside-toplevel
error = traceback.format_exc(limit=1).strip().split(os.linesep)[-1]
# error = traceback.format_exc()
file.seek(seek_cur, os.SEEK_SET)
# raw = Raw(file, length, error=str(error))
# return analyse(raw.info, raw.protochain, raw.alias)
next_ = Raw(file, length, error=error)
return next_
return behold