Source code for arkimet.formatter.formatter

"""
This module implements a registry of Python formatters for various metadata
types, along with default implementations.
"""
# python 3.7+ from __future__ import annotations
from typing import Dict, Any, Callable, Optional
from collections import defaultdict
import logging

log = logging.getLogger("arkimet.formatter")


[docs]class Formatter: """ Registry for metadata formatters implemented in Python. This is used to register formatter implementations, and access them while formatting. Use :class:`arkimet.Formatter` to do the actual formatting: it will call either into this or in C++ implementations as needed. """ formatters = defaultdict(list)
[docs] def format(self, t: Dict[str, Any]) -> str: """ Look up and call a formatter for the given metadata item. """ # Find the formatter list for this type formatters = self.formatters.get(t["type"]) if formatters is None: return None # Try all formatters in the list, returning the result of the first # that returns not-None. # Iterate in reverse order, so that formatters loaded later (like from # /etc) can be called earlier and fall back on the shipped ones for formatter in reversed(formatters): try: res = formatter(t) except Exception: log.exception("formatter failed") res = None if res is not None: return res # Otherwise return None return None
[docs] @classmethod def register(cls, type: str, formatter: Callable[[Dict[str, Any]], Optional[str]]): """ Register a callable as a formatter for the given metadata type. A registered callable can return None to fall back on previously registered callables. This allows to add formatters for specific cases only, without losing the default handling. """ if formatter not in cls.formatters[type]: cls.formatters[type].append(formatter)