# -*- coding: utf-8 -*-
"""Base Class
================
.. module:: pcapkit.foundation.engines.engine
This is the abstract base class implementation for
all engine support functionality.
"""
import abc
from typing import TYPE_CHECKING, Generic, TypeVar, cast
__all__ = ['Engine']
if TYPE_CHECKING:
from typing import Any, Optional
from pcapkit.foundation.extraction import Extractor
_T = TypeVar('_T')
[docs]
class EngineBase(Generic[_T], metaclass=EngineMeta):
"""Base class for engine support.
Args:
extractor: :class:`~pcapkit.foundation.extraction.Extractor` instance.
Note:
This class is for internal use only. For customisation, please use
:class:`Engine` instead.
"""
if TYPE_CHECKING:
#: Engine name.
__engine_name__: 'str'
#: Engine module name.
__engine_module__: 'str'
##########################################################################
# Properties.
##########################################################################
@property
def name(self) -> 'str':
"""Engine name.
Note:
This property is not available as a class
attribute.
"""
if hasattr(self, '__engine_name__'):
return self.__engine_name__
return type(self).name # type: ignore[return-value]
@property
def module(self) -> 'str':
"""Engine module name.
Note:
This property is not available as a class
attribute.
"""
if hasattr(self, '__engine_module__'):
return self.__engine_module__
return type(self).module # type: ignore[return-value]
@property
def extractor(self) -> 'Extractor':
"""Extractor instance."""
return self._extractor
##########################################################################
# Data models.
##########################################################################
def __init__(self, extractor: 'Extractor') -> 'None':
self._extractor = extractor
def __call__(self) -> 'None':
"""Start extraction.
This method will directly call :meth:`run` to start the
extraction process.
"""
self.run()
##########################################################################
# Methods.
##########################################################################
@abc.abstractmethod
def run(self) -> 'None':
"""Start extraction.
This method is the entry point for file extraction. It is to be used
for preparing the extraction process, such as parsing the file header
and setting up the extraction engines.
"""
@abc.abstractmethod
def read_frame(self) -> '_T':
"""Read frame.
This method is to be used for reading a frame from the file. It is to
read a frame from the file using the prepared engine instance and
return the parsed frame.
"""
def close(self) -> 'None':
"""Close engine.
This method is to be used for closing the engine instance. It is to
close the engine instance after the extraction process is finished.
"""
[docs]
class Engine(EngineBase[_T], Generic[_T]):
"""Base class for engine support.
Example:
Use keyword argument ``name`` to specify the engine name at
class definition:
.. code-block:: python
class MyEngine(Engine, name='my_engine'):
...
Args:
extractor: :class:`~pcapkit.foundation.extraction.Extractor` instance.
"""
[docs]
def __init_subclass__(cls, /, name: 'Optional[str]' = None, *args: 'Any', **kwargs: 'Any') -> 'None':
"""Initialise subclass.
This method is to be used for registering the engine class to
:class:`~pcapkit.foundation.extraction.Extractor` class.
Args:
name: Engine name, default to class name.
*args: Arbitrary positional arguments.
**kwargs: Arbitrary keyword arguments.
See Also:
For more details, please refer to
:meth:`pcapkit.foundation.extraction.Extractor.register_engine`.
"""
if name is None:
name = cast('str', cls.name)
from pcapkit.foundation.extraction import Extractor
Extractor.register_engine(name.lower(), cls)
return super().__init_subclass__()