Source code for bookbuilderpy.preprocessor_code
"""A preprocessor for loading code."""
from os.path import basename
from typing import Final
import bookbuilderpy.constants as bc
from bookbuilderpy.format_python import preprocess_python
from bookbuilderpy.logger import logger
from bookbuilderpy.path import Path
from bookbuilderpy.strings import (
enforce_non_empty_str_without_ws,
lines_to_str,
)
from bookbuilderpy.types import type_error
[docs]def get_programming_language(path: str) -> str | None:
"""
Get the programming language corresponding to a path.
:param path: the path to the source file
:return: a string identifying the programming language, or None if none
detected.
"""
_, suffix = Path.split_prefix_suffix(basename(Path.path(path)))
suffix = suffix.lower()
if suffix == "py":
return bc.LANG_PYTHON
return bc.LANG_UNDEFINED
[docs]def load_code(path: str, lines: str, labels: str, args: str) -> str:
"""
Load a piece of code from the given path.
:param path: the path
:param lines: a line definition string
:param labels: a label definition string
:param args: a string of arguments to be passed to the formatter
:return: the code
"""
src = Path.file(path)
logger(f"Now loading code from '{src}'.")
keep_lines: list[int] | None = None
if lines is not None:
if not isinstance(lines, str):
raise type_error(lines, "lines", str)
if len(lines) > 0:
keep_lines = []
for the_line in lines.split(","):
line = the_line.strip()
if "-" in line:
ab = line.split("-")
if len(ab) != 2:
raise ValueError(f"Invalid lines: {lines}.")
keep_lines.extend(range(int(ab[0]) - 1, int(ab[1])))
else:
keep_lines.append(int(line) - 1)
keep_labels: set[str] | None = None
if labels is not None:
if not isinstance(labels, str):
raise type_error(labels, "labels", str)
if len(labels) > 0:
keep_labels = set()
for label in labels.split(","):
ll = enforce_non_empty_str_without_ws(label.strip())
if ll in keep_labels:
raise ValueError(f"duplicate label: '{ll}'")
keep_labels.add(ll)
if len(keep_labels) <= 0:
raise ValueError(f"labels='{labels}'.")
arg_set: Final[set[str]] = set()
if args is not None:
if not isinstance(args, str):
raise type_error(args, "args", str)
if len(args) > 0:
for arg in args.split(","):
aa = enforce_non_empty_str_without_ws(arg.strip())
if aa in arg_set:
raise ValueError(f"duplicate argument: '{aa}'")
arg_set.add(aa)
text: Final[list[str]] = src.read_all_list()
if len(text) <= 0:
raise ValueError(f"File '{path}' is empty.")
if get_programming_language(path) == bc.LANG_PYTHON:
return preprocess_python(text, keep_lines, keep_labels, arg_set)
if keep_lines is None:
return lines_to_str([t.rstrip() for t in text])
return lines_to_str([text[i].rstrip() for i in keep_lines])