2020
2121from pcapkit .corekit .module import ModuleDescriptor
2222from pcapkit .dumpkit .common import make_dumper
23+ from pcapkit .protocols import __proto__ as protocol_registry
24+ from pcapkit .protocols .misc .raw import Raw
2325from pcapkit .utilities .exceptions import FileExists , RegistryError , stacklevel
2426from pcapkit .utilities .warnings import FileWarning , FormatWarning , RegistryWarning , warn
2527
4143Packet = TypeVar ('Packet' , bound = 'Info' )
4244
4345
44- class TraceFlow (Generic [BufferID , Buffer , Index , Packet ], metaclass = abc .ABCMeta ):
46+ class TraceFlowMeta (abc .ABCMeta ):
47+ """Meta class to add dynamic support to :class:`TraceFlow`.
48+
49+ This meta class is used to generate necessary attributes for the
50+ :class:`TraceFlow` class. It can be useful to reduce unnecessary
51+ registry calls and simplify the customisation process.
52+
53+ """
54+ if TYPE_CHECKING :
55+ #: Protocol name of current reassembly object.
56+ __protocol_name__ : 'str'
57+ #: Protocol of current reassembly object.
58+ __protocol_type__ : 'Type[Protocol]'
59+
60+ @property
61+ def name (cls ) -> 'str' :
62+ """Protocol name of current reassembly object."""
63+ if hasattr (cls , '__protocol_name__' ):
64+ return cls .__protocol_name__
65+ return cls .__name__
66+
67+ @property
68+ def protocol (cls ) -> 'Type[Protocol]' :
69+ """Protocol of current reassembly object."""
70+ if hasattr (cls , '__protocol_type__' ):
71+ return cls .__protocol_type__
72+ return protocol_registry .get (cls .name .upper (), Raw )
73+
74+
75+ class TraceFlowBase (Generic [BufferID , Buffer , Index , Packet ], metaclass = TraceFlowMeta ):
4576 """Base flow tracing class.
4677
4778 Arguments:
@@ -52,7 +83,16 @@ class TraceFlow(Generic[BufferID, Buffer, Index, Packet], metaclass=abc.ABCMeta)
5283 *args: Arbitrary positional arguments.
5384 **kwargs: Arbitrary keyword arguments.
5485
86+ Note:
87+ This class is for internal use only. For customisation, please use
88+ :class:`TraceFlow` instead.
89+
5590 """
91+ if TYPE_CHECKING :
92+ #: Protocol name of current reassembly object.
93+ __protocol_name__ : 'str'
94+ #: Protocol of current reassembly object.
95+ __protocol_type__ : 'Type[Protocol]'
5696
5797 # Internal data storage for cached properties.
5898 __cached__ : 'dict[str, Any]'
@@ -86,16 +126,6 @@ class TraceFlow(Generic[BufferID, Buffer, Index, Packet], metaclass=abc.ABCMeta)
86126 # Properties.
87127 ##########################################################################
88128
89- @property
90- @abc .abstractmethod
91- def name (self ) -> 'str' :
92- """Protocol name of current reassembly object."""
93-
94- @property
95- @abc .abstractmethod
96- def protocol (self ) -> 'Type[Protocol]' :
97- """Protocol of current reassembly object."""
98-
99129 @property
100130 def index (self ) -> 'tuple[Index, ...]' :
101131 """Index table for traced flow."""
@@ -278,3 +308,51 @@ def __call__(self, packet: 'Packet') -> 'None':
278308 """
279309 # trace frame record
280310 self .dump (packet )
311+
312+
313+ class TraceFlow (TraceFlowBase [BufferID , Buffer , Index , Packet ], Generic [BufferID , Buffer , Index , Packet ]):
314+ """Base flow tracing class.
315+
316+ Example:
317+
318+ Use keyword argument ``protocol`` to specify the protocol
319+ name at class definition:
320+
321+ .. code-block:: python
322+
323+ class MyProtocol(TraceFlow, protocol='my_protocol'):
324+ ...
325+
326+ Arguments:
327+ fout: output path
328+ format: output format
329+ byteorder: output file byte order
330+ nanosecond: output nanosecond-resolution file flag
331+ *args: Arbitrary positional arguments.
332+ **kwargs: Arbitrary keyword arguments.
333+
334+ """
335+
336+ def __init_subclass__ (cls , / , protocol : 'Optional[str]' = None , * args : 'Any' , ** kwargs : 'Any' ) -> 'None' :
337+ """Initialise subclass.
338+
339+ This method is to be used for registering the engine class to
340+ :class:`~pcapkit.foundation.extraction.Extractor` class.
341+
342+ Args:
343+ name: Protocol name, default to class name.
344+ *args: Arbitrary positional arguments.
345+ **kwargs: Arbitrary keyword arguments.
346+
347+ See Also:
348+ For more details, please refer to
349+ :meth:`~pcapkit.foundation.extraction.Extractor.register_traceflow`.
350+
351+ """
352+ if protocol is None :
353+ protocol = cls .name
354+
355+ from pcapkit .foundation .extraction import Extractor
356+ Extractor .register_traceflow (protocol .lower (), cls )
357+
358+ return super ().__init_subclass__ ()
0 commit comments