Source code for moptipy.utils.text_format

"""Infrastructure to created structured text, like Markdown and LaTeX."""

from io import TextIOBase
from typing import Final

from pycommons.io.path import Path, directory_path
from pycommons.types import type_error

from moptipy.utils.lang import Lang

#: indicates a normal row or cell
MODE_NORMAL: Final[int] = 0
#: indicates a row or cell in the table header
MODE_TABLE_HEADER: Final[int] = 1
#: indicates a row or cell in the section header
MODE_SECTION_HEADER: Final[int] = 2


[docs] class TextFormatDriver: """ A base class for text format drivers. Table drivers allow us to render the structured text. It used, for example, by instances of :class:`~moptipy.utils.table.Table` to write tabular data to a text format stream. """
[docs] def begin_table_body(self, stream: TextIOBase, cols: str) -> None: """ Write the beginning of the table body. :param stream: the stream to write to :param cols: the column definition """
[docs] def end_table_body(self, stream: TextIOBase, cols: str) -> None: """ Write the ending of the table body. :param stream: the stream to write to :param cols: the column definition """
[docs] def begin_table_header(self, stream: TextIOBase, cols: str) -> None: """ Begin the header row of the table. :param stream: the stream to write to :param cols: the column definition """
[docs] def end_table_header(self, stream: TextIOBase, cols: str) -> None: """ End the header row of the table. :param stream: the stream to write to :param cols: the column definition """
[docs] def begin_table_section(self, stream: TextIOBase, cols: str, section_index: int) -> None: """ Begin a new section of the table. :param stream: the stream to write to :param cols: the column definition :param section_index: the index of the section, `0` for the first section """
[docs] def end_table_section(self, stream: TextIOBase, cols: str, section_index: int, n_rows: int) -> None: """ End a section of the table. :param stream: the stream to write to :param cols: the column definition :param section_index: the index of the section, `0` for the first section :param n_rows: the number of rows that were written in the section """
[docs] def begin_table_section_header(self, stream: TextIOBase, cols: str, section_index: int) -> None: """ Begin the header row of a section. :param stream: the stream to write to :param cols: the column definition :param section_index: the index of the section, `0` for the first section """
[docs] def end_table_section_header(self, stream: TextIOBase, cols: str, section_index: int) -> None: """ End the header row of a section. :param stream: the stream to write to :param cols: the column definition :param section_index: the index of the section, `0` for the first section """
[docs] def begin_table_row(self, stream: TextIOBase, cols: str, section_index: int, row_index: int, row_mode: int) -> None: """ Begin a table header row, section row, or normal row in a section. :param stream: the stream to write to :param cols: the column definition :param section_index: the index of the current section, `-1` if we are in the table header :param row_index: the row index in the section or header :param row_mode: the mode of the row, will be one of `MODE_NORMAL`, `MODE_TABLE_HEADER`, or `MODE_SECTION_HEADER` """
[docs] def end_table_row(self, stream: TextIOBase, cols: str, section_index: int, row_index: int) -> None: """ End a table header row, section row, or normal row in a section. :param stream: the stream to write to :param cols: the column definition :param section_index: the index of the current section :param row_index: the row index in the section or header """
[docs] def begin_table_cell(self, stream: TextIOBase, cols: str, section_index: int, row_index: int, col_index: int, cell_mode: int) -> None: """ Begin a header cell, section header cell, or normal cell. :param stream: the stream to write to :param cols: the column definitions :param section_index: the index of the current section, `-1` if this is a table header cell :param row_index: the row index in the section or header :param col_index: the column index, `0` for the first column :param cell_mode: the mode of the cell, will be one of `MODE_NORMAL`, `MODE_TABLE_HEADER`, or `MODE_SECTION_HEADER` """
[docs] def end_table_cell(self, stream: TextIOBase, cols: str, section_index: int, row_index: int, col_index: int, cell_mode: int) -> None: """ End a header cell, section header cell, or normal cell. :param stream: the stream to write to :param cols: the column definitions :param section_index: the index of the current section, `-1` if this is a table header cell :param row_index: the row index in the section or header :param col_index: the column index, `0` for the first column :param cell_mode: the mode of the cell, will be one of `MODE_NORMAL`, `MODE_TABLE_HEADER`, or `MODE_SECTION_HEADER` """
[docs] def text(self, stream: TextIOBase, text: str, bold: bool, italic: bool, code: bool, mode: int) -> None: """ Write a chunk of text. :param stream: the stream to write to :param text: the text to write :param bold: is the text in bold face? :param italic: is the text in italic face? :param code: is the text in code face? :param mode: the mode of a formatted text piece, see the attribute :attr:`~moptipy.utils.formatted_string.FormattedStr.mode` of :class:`~moptipy.utils.formatted_string.FormattedStr` """
[docs] def filename(self, file_name: str = "file", dir_name: str = ".", use_lang: bool = True) -> Path: """ Get the right filename for this text driver. :param file_name: the base file name :param dir_name: the base directory :param use_lang: should we use the language to define the filename? :returns: the path to the file to generate """ if not isinstance(dir_name, str): raise type_error(dir_name, "dir_name", str) if len(dir_name) <= 0: raise ValueError(f"invalid dir_name: {dir_name!r}.") if not isinstance(file_name, str): raise type_error(file_name, "file_name", str) if len(file_name) <= 0: raise ValueError(f"invalid file_name: {file_name!r}.") if not isinstance(use_lang, bool): raise type_error(use_lang, "use_lang", bool) out_dir = directory_path(dir_name) suffix = str(self) if not isinstance(suffix, str): raise type_error(suffix, "result of str(table driver)", str) if len(suffix) <= 0: raise ValueError(f"invalid driver suffix: {suffix!r}") if use_lang: file_name = Lang.current().filename(file_name) file: Final[Path] = out_dir.resolve_inside(f"{file_name}.{suffix}") file.ensure_file_exists() return file