jumeaux/addons/res2dict/block.py
# -*- coding:utf-8 -*-
import re
from owlmixin import OwlMixin
from jumeaux.addons.res2dict import Res2DictExecutor
from jumeaux.logger import Logger
from jumeaux.models import DictOrList, Res2DictAddOnPayload
logger: Logger = Logger(__name__)
LOG_PREFIX = "[res2dict/block]"
class Config(OwlMixin):
force: bool = False
header_regexp: str
record_regexp: str
def config_generator(blockstr: str, header_regexp: str, record_regexp: str):
key = None
d: dict = {}
# XXX: [""] means for the case which last line break is nothing
for line in blockstr.splitlines() + [""]:
if not line:
if d:
yield key, d
d = {}
continue
r = re.findall(header_regexp, line)
if r and len(r) == 1:
key = r[0]
continue
b = re.findall(record_regexp, line)
if b and len(b) == 1:
d[b[0][0]] = b[0][1] if len(b[0]) > 1 else None
def to_dict(blockstr: str, header_regexp: str, record_regexp: str) -> dict:
return {k: v for k, v in config_generator(blockstr, header_regexp, record_regexp)}
class Executor(Res2DictExecutor):
def __init__(self, config: dict) -> None:
self.config: Config = Config.from_dict(config or {})
def exec(self, payload: Res2DictAddOnPayload) -> Res2DictAddOnPayload:
if not payload.result.is_none() and not self.config.force:
logger.debug(f"{LOG_PREFIX} Skipped because result is already existed.")
return payload
result: DictOrList # type: ignore
if self.config.force:
logger.debug(f"{LOG_PREFIX} Force to convert to dict as block")
result = to_dict(
payload.response.text,
self.config.header_regexp,
self.config.record_regexp,
)
else:
logger.debug(f"{LOG_PREFIX} Convert to dict as block")
result = to_dict(
payload.response.text,
self.config.header_regexp,
self.config.record_regexp,
)
return Res2DictAddOnPayload.from_dict(
{"response": payload.response, "result": result}
)