Source code for timelink.kleio.utilities

""".. module:: utilities
   :synopsis: Various utilities for handling Kleio groups and elements

.. moduleauthor: Joaquim Ramos de Carvalho

Kleio Groups are the building blocks for transcription of historical sources.
"""
import json
import textwrap
from os import linesep as nl


[docs] def kleio_escape(v: str) -> str: """ Checks for Kleio special characters and quotes if needed:: >>> print(kleio_escape('normal string')) normal string >>> print(kleio_escape('oops we have a / in the middle')) "oops we have a / in the middle" """ if v is None: return None # test if v is already quoted if v.startswith('"') and v.endswith('"'): return v s = str(v) if any(i in s for i in "/;=$#%\n"): return '"' + s + '"' else: return s
[docs] def quote_long_text(txt, initial_indent=" " * 4, indent=" " * 2, width=2048) -> str: """Surround long text with triple quotes, wraps and indents lines if needed. Some of the parameters are passed on to :py:func:`textwrap.fill`. Sphynx style markup :param txt: The text to be transformed :type txt: str :param initial_indent: string to ident the first line of paragraphs. Default is 4 spaces. See :py:func:`textwrap.fill`. :type initial_indent: str :param indent: string to ident the wrap lines of paragraphs (after the first). Default is 2 spaces. See :py:func:`textwrap.fill`. :type indent: str :param width: width of line for wrapping. See :py:func:`textwrap.fill`. :type width: int :rtype: str """ if txt is None: return None if width is None: width = 80 # check if text already is triple quoted, starts with """ and end with """ if txt.startswith('"""') and txt.endswith('"""'): return txt if len(txt) > width or len(txt.splitlines()) > 1: s = '"""' + nl for line in txt.splitlines(): w = textwrap.fill(line, width=width, initial_indent=initial_indent) s = s + textwrap.indent(w, indent) + nl s = s + indent + '"""' elif '"' in txt: s = '"""' + txt + '"""' else: s = kleio_escape(txt) return s
[docs] def get_extra_info(obs_text: str) -> tuple[str, dict]: """ Extracts the extra information from the extra_info string and returns a tuple with the cleaned string and a dictionary :param obs_text: The string with extra information (can have other text before) :type obs_text: str :rtype: tuple[str,dict] """ if obs_text is None: return "", {} if "extra_info:" in obs_text: extra_info = obs_text.split("extra_info:")[1].strip() s = obs_text.split("extra_info:")[0].strip() if len(extra_info) > 0: extra_info_dict = json.loads(extra_info) else: extra_info_dict = {} else: s = obs_text extra_info_dict = {} return s, extra_info_dict
[docs] def render_with_extra_info(element_name, element_value, extra_info, **kwargs) -> str: """ Renders a Kleio element with extra information :param element_name: The name of the element :type element_name: str :param element_value: The value of the element from the db :type element_value: str :param extra_info: The extra information dictionary :type extra_info: dict :param kwargs: Additional parameters for :py:func:`quote_long_text` :rtype: str """ element_value = quote_long_text(element_value, **kwargs) extras = extra_info.get(element_name, {}) element_comment = extras.get("comment", None) element_original = extras.get("original", None) if element_comment is not None: element_value = f"{element_value}#{quote_long_text(element_comment, **kwargs)}" if element_original is not None: element_value = f"{element_value}%{quote_long_text(element_original, **kwargs)}" return element_value