bookbuilderpy package

bookbuilderpy is a package for compiling electronic books.

class bookbuilderpy.Build(input_file, output_dir, fail_without_pandoc=True)[source]

Bases: AbstractContextManager

A class to keep and access information about the build process.

build()[source]

Perform the build.

Return type:

tuple[LangResult, ...]

Returns:

the results

get_meta(key)[source]

Get a meta-data element.

Parameters:

key (str) – the key

Return type:

Any

Returns:

the meta-data element

get_meta_str(key)[source]

Get a meta-data element as a string.

Parameters:

key (str) – the key

Return type:

str

Returns:

the meta-data element

get_repo(name)[source]

Get a repository of the given name.

Parameters:

name (str) – the repository name

Return type:

Repo

Returns:

the repository structure

property input_dir: Path

Get the input directory.

Returns:

the input directory

property input_file: Path

Get the input file.

Returns:

the input file

property output_dir: Path

Get the output directory.

Returns:

the output directory

static run(input_file, output_dir, exit_on_error=False)[source]

Run a build on an input file to an output directory.

Parameters:
  • input_file (str) – the input file

  • output_dir (str) – the output directory

  • exit_on_error (bool, default: False) – should we quit Python upon error?

Return type:

tuple[LangResult, ...]

Returns:

a tuple of results

Subpackages

Submodules

bookbuilderpy.build module

The build process: The main class of the book building tool chain.

class bookbuilderpy.build.Build(input_file, output_dir, fail_without_pandoc=True)[source]

Bases: AbstractContextManager

A class to keep and access information about the build process.

build()[source]

Perform the build.

Return type:

tuple[LangResult, ...]

Returns:

the results

get_meta(key)[source]

Get a meta-data element.

Parameters:

key (str) – the key

Return type:

Any

Returns:

the meta-data element

get_meta_str(key)[source]

Get a meta-data element as a string.

Parameters:

key (str) – the key

Return type:

str

Returns:

the meta-data element

get_repo(name)[source]

Get a repository of the given name.

Parameters:

name (str) – the repository name

Return type:

Repo

Returns:

the repository structure

property input_dir: Path

Get the input directory.

Returns:

the input directory

property input_file: Path

Get the input file.

Returns:

the input file

property output_dir: Path

Get the output directory.

Returns:

the output directory

static run(input_file, output_dir, exit_on_error=False)[source]

Run a build on an input file to an output directory.

Parameters:
  • input_file (str) – the input file

  • output_dir (str) – the output directory

  • exit_on_error (bool, default: False) – should we quit Python upon error?

Return type:

tuple[LangResult, ...]

Returns:

a tuple of results

bookbuilderpy.build_result module

A collection for build results.

class bookbuilderpy.build_result.File(path)[source]

Bases: object

A single file created by a build.

path: Path

the path of the file

size: int

the size of the file

suffix: str

the file name suffix

class bookbuilderpy.build_result.LangResult(lang, lang_name, directory, results)[source]

Bases: object

All the results created for one language.

directory: Path

the directory containing the results

lang: Optional[str]

the language code

lang_name: Optional[str]

the language name

results: tuple[File, ...]

the generated files

bookbuilderpy.compress module

Routines for compressing lists of files.

bookbuilderpy.compress.can_xz_compress()[source]

Check if xz compression is available.

Return type:

bool

Returns:

True if xz compression is available, False otherwise

bookbuilderpy.compress.can_zip_compress()[source]

Check if zip compression is available.

Return type:

bool

Returns:

True if zip compression is available, False otherwise

bookbuilderpy.compress.compress_xz(source, dest)[source]

Compress a sequence of files to tar.xz.

Parameters:
Return type:

File

Returns:

the created archive

bookbuilderpy.compress.compress_zip(source, dest)[source]

Compress a sequence of files to zip.

Parameters:
Return type:

File

Returns:

the created archive

bookbuilderpy.constants module

The basic preprocessor command strings.

bookbuilderpy.constants.CMD_ABSOLUTE_CODE: Final[str] = 'abs.code'

an absolute code input to be included as a listing: abs.code{label}{caption}{path}{lines}{labels}{args} label: the label of the listing caption: the caption of the listing path: the absolute path fragment to resolve lines: the lines of the code to keep, or empty to keep all labels: the labels for selecting code pieces, or empty to keep all args: any additional arguments to pass to the code renderer

bookbuilderpy.constants.CMD_ABSOLUTE_FIGURE: Final[str] = 'abs.figure'

an absolute figure reference abs.figure{label}{caption}{path}{args}

bookbuilderpy.constants.CMD_DEFINITION: Final[str] = 'definition'

an command for formatting definitions definition{type}{label}{body}

bookbuilderpy.constants.CMD_DEF_REF: Final[str] = 'def.ref'

reference a definition def.ref{label}

bookbuilderpy.constants.CMD_GET_META: Final[str] = 'meta'

obtain a meta data element meta{id}

bookbuilderpy.constants.CMD_GET_REPO: Final[str] = 'repo'

obtain information about a repository repo{repo-id}{info-id}

bookbuilderpy.constants.CMD_GIT_CODE: Final[str] = 'git.code'

a git code include: git.code{repo}{label}{caption}{path}{lines}{labels}{args} repo: the repository ID to use label: the label of the listing caption: the caption of the listing path: the relative path fragment to resolve lines: the lines of the code to keep, or empty to keep all labels: the labels for selecting code pieces, or empty to keep all args: any additional arguments to pass to the code renderer

bookbuilderpy.constants.CMD_INPUT: Final[str] = 'rel.input'

the command for loading the input data rel.inputpath}

bookbuilderpy.constants.CMD_RELATIVE_CODE: Final[str] = 'rel.code'

a relative code input to be included as a listing: rel.code{label}{caption}{path}{lines}{labels}{args} label: the label of the listing caption: the caption of the listing path: the relative path fragment to resolve lines: the lines of the code to keep, or empty to keep all labels: the labels for selecting code pieces, or empty to keep all args: any additional arguments to pass to the code renderer

bookbuilderpy.constants.CMD_RELATIVE_FIGURE: Final[str] = 'rel.figure'

a relative figure reference rel.figure{label}{caption}{path}{args}

bookbuilderpy.constants.LANG_PYTHON: Final[str] = 'python'

the Python programming language

bookbuilderpy.constants.LANG_UNDEFINED: str | None = None

the undefined programming language

bookbuilderpy.constants.META_AUTHOR: Final[str] = 'author'

A meta-data property identifying the author of a book.

bookbuilderpy.constants.META_CUR_LANG_NAME: Final[str] = 'lang.name'

The name of the current language.

bookbuilderpy.constants.META_DATE: Final[str] = 'date'

the meta data id for the current date

bookbuilderpy.constants.META_DATE_TIME: Final[str] = 'time'

the meta data id for the current date and time

bookbuilderpy.constants.META_LANGS: Final[str] = 'langs'

the languages

bookbuilderpy.constants.META_LANG_ID: Final[str] = 'id'

the language id

bookbuilderpy.constants.META_LANG_NAME: Final[str] = 'name'

the language name

bookbuilderpy.constants.META_REPOS: Final[str] = 'repos'

The key for the repository list

bookbuilderpy.constants.META_REPO_ID: Final[str] = 'id'

The key for the repository ID

bookbuilderpy.constants.META_REPO_INFO_COMMIT: Final[str] = 'repo.commit'

the key for the repository commit

bookbuilderpy.constants.META_REPO_INFO_DATE: Final[str] = 'repo.date'

the key for the repository date

bookbuilderpy.constants.META_REPO_INFO_NAME: Final[str] = 'repo.name'

the key for the repository name

bookbuilderpy.constants.META_REPO_INFO_URL: Final[str] = 'repo.url'

the key for the repository

bookbuilderpy.constants.META_REPO_URL: Final[str] = 'url'

The key for the repository url

bookbuilderpy.constants.META_TITLE: Final[str] = 'title'

A meta-data property identifying the title of a book.

bookbuilderpy.constants.META_YEAR: Final[str] = 'year'

the meta data id for the current year

bookbuilderpy.constants.PANDOC_BIBLIOGRAPHY: Final[str] = 'bibliography'

the pandoc bibliography key

bookbuilderpy.constants.PANDOC_CSL: Final[str] = 'csl'

the csl template

bookbuilderpy.constants.PANDOC_FORMAT_EPUB: Final[str] = 'epub3'

the pandoc epub format

bookbuilderpy.constants.PANDOC_FORMAT_HTML5: Final[str] = 'html5'

the pandoc html5 format

bookbuilderpy.constants.PANDOC_FORMAT_LATEX: Final[str] = 'latex'

the pandoc latex format

bookbuilderpy.constants.PANDOC_FORMAT_MARKDOWN: Final[str] = 'markdown'

the pandoc markdown format

bookbuilderpy.constants.PANDOC_TEMPLATE_EPUB: Final[str] = 'template.epub'

the pandoc epub template

bookbuilderpy.constants.PANDOC_TEMPLATE_HTML5: Final[str] = 'template.html'

the pandoc html template

bookbuilderpy.constants.PANDOC_TEMPLATE_LATEX: Final[str] = 'template.latex'

the pandoc latex template

bookbuilderpy.constants.WEBSITE_BODY_TAG_1: Final[str] = '<div id="files">'

The begin of the tag to be replaced.

bookbuilderpy.constants.WEBSITE_BODY_TAG_2: Final[str] = '</div>'

The end of the tag to be replaced.

bookbuilderpy.constants.WEBSITE_DOWNLOAD_DOWNLOAD_SPAN_ARG: Final[str] = ' class="downloadFile"'

The argument to the single file span entry.

bookbuilderpy.constants.WEBSITE_DOWNLOAD_FILE_A_ARG: Final[str] = ' class="downloadFileName"'

The argument to the single file name span entry.

bookbuilderpy.constants.WEBSITE_DOWNLOAD_FILE_DESC_SPAN_ARG: Final[str] = ' class="downloadFileDesc"'

The argument to the single file description entry.

bookbuilderpy.constants.WEBSITE_DOWNLOAD_LI_ARG: Final[str] = ' class="download"'

The argument to the single file download entry.

bookbuilderpy.constants.WEBSITE_DOWNLOAD_SIZE_SPAN_ARG: Final[str] = ' class="downloadFileSize"'

The argument to the single file size span entry.

bookbuilderpy.constants.WEBSITE_DOWNLOAD_UL_ARG: Final[str] = ' class="downloads"'

The argument to the single language file download list.

bookbuilderpy.constants.WEBSITE_LANGS_LI_ARG: Final[str] = ' class="oneLang"'

The argument to the language list item in the download files.

bookbuilderpy.constants.WEBSITE_LANGS_NAME_SPAN_ARG: Final[str] = ' class="oneLangName"'

The argument to the language name item in the download files.

bookbuilderpy.constants.WEBSITE_LANGS_UL_ARG: Final[str] = ' class="langs"'

The argument to the language list in the download files.

bookbuilderpy.constants.WEBSITE_OUTER_TAG: Final[str] = '{body}'

The outer tag of the website to be replaced with the body.

bookbuilderpy.format_python module

A formatter for python code.

bookbuilderpy.format_python.format_python(code, strip_docstrings=True, strip_comments=True, strip_hints=True)[source]

Format a python code fragment.

Parameters:
  • code (Iterable[str]) – the code fragment

  • strip_docstrings (bool, default: True) – should we delete docstrings?

  • strip_comments (bool, default: True) – should we delete comments?

  • strip_hints (bool, default: True) – should we delete type hints?

Return type:

list[str]

Returns:

the formatted code

bookbuilderpy.format_python.preprocess_python(code, lines=None, labels=None, args=None)[source]

Preprocess Python code.

First, we select all lines of the code we want to keep. If labels are defined, then lines can be kept as ranges or as single lines. Otherwise, all lines are selected in this step.

Then, if line numbers are provided, we selected the lines based on the line numbers from the lines we have preserved.

Finally, the Python formatter is applied.

Parameters:
  • code (list[str]) – the code loaded from a file

  • lines (Optional[list[int]], default: None) – the lines to keep, or None if we keep all

  • labels (Optional[Iterable[str]], default: None) – a list of labels marking start and end of code snippets to include

  • args (Optional[set[str]], default: None) – the arguments for the code formatter

Return type:

str

Returns:

the formatted code string

bookbuilderpy.git module

Tools for interacting with git.

class bookbuilderpy.git.Repo(path, url, commit, date_time)[source]

Bases: object

An immutable record of a git repository.

commit: str

the commit

date_time: str

the date and time

static download(url, dest_dir)[source]

Download a git repository.

Parameters:
  • url (str) – the repository url

  • dest_dir (str) – the destination directory

Return type:

Repo

Returns:

the repository information

static from_local(path, url=None)[source]

Load all the information from an local repository.

Parameters:
  • path (str) – the path to the repository

  • url (Optional[str], default: None) – the url

Return type:

Repo

Returns:

the repository information

get_base_url()[source]

Get the base url of this repository.

Return type:

str

Returns:

the base url of this repository

get_name()[source]

Get the name of this repository in the form ‘user/name’.

Return type:

str

Returns:

the name of this repository in the form ‘user/name’.

make_url(relative_path)[source]

Make an url relative to this repository.

Parameters:

relative_path (str) – the relative path

Return type:

str

Returns:

the url

path: Path

the repository path

url: str

the repository url

bookbuilderpy.html module

Post-process HTML files.

bookbuilderpy.html.html_postprocess(in_file, out_file, flatten_data_uris=True, fully_evaluate_html=False, purge_scripts=False, minify=True, purge_mathjax=True, canonicalize_ids=True, overwrite=False)[source]

Post-process a html file.

Parameters:
  • in_file (str) – the input file

  • out_file (str) – the output file

  • flatten_data_uris (bool, default: True) – should we flatten data URIs?

  • fully_evaluate_html (bool, default: False) – should we use selenium to fully evaluate all html and javascript?

  • purge_scripts (bool, default: False) – should we purge all javascripts from the file?

  • minify (bool, default: True) – should we minify the HTML output?

  • purge_mathjax (bool, default: True) – purge all mathjax stuff?

  • canonicalize_ids (bool, default: True) – should we canonicalize the IDs?

  • overwrite (bool, default: False) – should the output file be overwritten if it exists?

Return type:

Path

Returns:

the output file

bookbuilderpy.logger module

The logger routine for writing a log string to stdout.

bookbuilderpy.logger.logger(message)[source]

Write a message to the log.

Parameters:

message (str) – the message

Return type:

None

bookbuilderpy.pandoc module

A routine for invoking pandoc.

bookbuilderpy.pandoc.azw3(epub_file)[source]

Convert an epub book into an azw3 one.

Parameters:

epub_file (str) – the epub file

Return type:

File

Returns:

the azw3 file

bookbuilderpy.pandoc.epub(source_file, dest_file, format_in='markdown', locale=None, standalone=True, tabstops=2, toc_print=True, toc_depth=3, crossref=True, bibliography=True, number_sections=True, get_meta=<function <lambda>>, resolve_resources=<function <lambda>>)[source]

Invoke pandoc to build epub output.

Parameters:
  • source_file (str) – the source file

  • dest_file (str) – the destination file

  • format_in (str, default: 'markdown') – the input format

  • locale (Optional[str], default: None) – the language to be used for compiling

  • standalone (bool, default: True) – should we produce a stand-alone document?

  • tabstops (Optional[int], default: 2) – the number of spaces with which we replace a tab character, or None to not replace

  • toc_print (bool, default: True) – should we print the table of contents

  • toc_depth (int, default: 3) – the depth of the table of contents

  • crossref (bool, default: True) – should we use crossref

  • bibliography (bool, default: True) – should we use a bibliography

  • number_sections (bool, default: True) – should sections be numbered?

  • get_meta (Callable, default: <function <lambda> at 0x7fa5c66f5120>) – a function to access meta-data

  • resolve_resources (Callable, default: <function <lambda> at 0x7fa5c66f51b0>) – a function to resolve resources

Return type:

File

Returns:

the Path to the generated output file and it size

bookbuilderpy.pandoc.html(source_file, dest_file, format_in='markdown', locale=None, standalone=True, tabstops=2, toc_print=True, toc_depth=3, crossref=True, bibliography=True, number_sections=True, get_meta=<function <lambda>>, resolve_resources=<function <lambda>>)[source]

Invoke pandoc to build HTML output.

Parameters:
  • source_file (str) – the source file

  • dest_file (str) – the destination file

  • format_in (str, default: 'markdown') – the input format

  • locale (Optional[str], default: None) – the language to be used for compiling

  • standalone (bool, default: True) – should we produce a stand-alone document?

  • tabstops (Optional[int], default: 2) – the number of spaces with which we replace a tab character, or None to not replace

  • toc_print (bool, default: True) – should we print the table of contents

  • toc_depth (int, default: 3) – the depth of the table of contents

  • crossref (bool, default: True) – should we use crossref

  • bibliography (bool, default: True) – should we use a bibliography

  • number_sections (bool, default: True) – should sections be numbered?

  • get_meta (Callable, default: <function <lambda> at 0x7fa5c66f4f70>) – a function to access meta-data

  • resolve_resources (Callable, default: <function <lambda> at 0x7fa5c66f5000>) – a function to resolve resources

Returns:

the Path to the generated output file and it size

Return type:

File

bookbuilderpy.pandoc.latex(source_file, dest_file, format_in='markdown', locale=None, standalone=True, tabstops=2, toc_print=True, toc_depth=3, crossref=True, bibliography=True, number_sections=True, top_level_division='chapter', use_listings=False, get_meta=<function <lambda>>, resolve_resources=<function <lambda>>)[source]

Invoke pandoc to build LaTeX and then PDF output.

Parameters:
  • source_file (str) – the source file

  • dest_file (str) – the destination file

  • format_in (str, default: 'markdown') – the input format

  • locale (Optional[str], default: None) – the language to be used for compiling

  • standalone (bool, default: True) – should we produce a stand-alone document?

  • tabstops (Optional[int], default: 2) – the number of spaces with which we replace a tab character, or None to not replace

  • toc_print (bool, default: True) – should we print the table of contents

  • toc_depth (int, default: 3) – the depth of the table of contents

  • crossref (bool, default: True) – should we use crossref

  • bibliography (bool, default: True) – should we use a bibliography

  • number_sections (bool, default: True) – should sections be numbered?

  • top_level_division (str, default: 'chapter') – the top-level division

  • use_listings (bool, default: False) – should the listings package be used?

  • get_meta (Callable, default: <function <lambda> at 0x7fa5c66d4820>) – a function to access meta-data

  • resolve_resources (Callable, default: <function <lambda> at 0x7fa5c66f4a60>) – a function to resolve resources

Return type:

File

Returns:

the Path to the generated output file and it size

bookbuilderpy.pandoc.pandoc(source_file, dest_file, format_in='markdown', format_out='latex', locale=None, standalone=True, tabstops=2, toc_print=True, toc_depth=3, crossref=True, bibliography=True, template=None, csl=None, number_sections=True, args=None, resolve_resources=<function <lambda>>, overwrite=False)[source]

Invoke pandoc.

Parameters:
  • source_file (str) – the source file

  • dest_file (str) – the destination file

  • format_in (str, default: 'markdown') – the input format

  • format_out (str, default: 'latex') – the output format

  • standalone (bool, default: True) – should we produce a stand-alone document?

  • tabstops (Optional[int], default: 2) – the number of spaces with which we replace a tab character, or None to not replace

  • toc_print (bool, default: True) – should we print the table of contents

  • toc_depth (int, default: 3) – the depth of the table of contents

  • crossref (bool, default: True) – should we use crossref

  • bibliography (bool, default: True) – should we use a bibliography

  • template (Optional[str], default: None) – which template should we use, if any?

  • csl (Optional[str], default: None) – which csl file should we use, if any?

  • number_sections (bool, default: True) – should sections be numbered?

  • locale (Optional[str], default: None) – the language to be used for compiling

  • args (Optional[list[str]], default: None) – any additional arguments

  • resolve_resources (Callable, default: <function <lambda> at 0x7fa5c66d4430>) – a function to resolve resources

  • overwrite (bool, default: False) – should the output file be overwritten if it exists?

Return type:

File

Returns:

the Path to the generated output file and it size

bookbuilderpy.parse_metadata module

An internal package for loading metadata.

bookbuilderpy.parse_metadata.load_initial_metadata(in_file, in_dir)[source]

Load the initial metadata.

This function does not process the complete document structure but only resolves at most one include. It also does not expand other commands and it does not perform any language-based resolution. It is only there to gain access to the raw metadata which should be the same over all builds of a book. This means things such as shared source code repositories.

Parameters:
  • in_file (Path) – the input file

  • in_dir (Path) – the input directory

Return type:

dict[str, Any]

Returns:

the map with the meta-data

bookbuilderpy.parse_metadata.parse_metadata(text)[source]

Extract the metadata of a string and parse it.

Parameters:

text (str) – the text

Return type:

dict[str, Any]

Returns:

the metadata

bookbuilderpy.path module

The base class with the information of a build.

class bookbuilderpy.path.Path(value)[source]

Bases: str

An immutable representation of a path.

as_directory()[source]

Return the closest directory along this path.

Return type:

Path

Returns:

the directory: either this path if it already identifies a directory, or the parent directory if this path identifies a file.

Raises:

ValueError – if no containing directory exists

contains(other)[source]

Check whether another path is contained in this path.

Parameters:

other (str) – the other path

Return type:

bool

Returns:

True is this path contains the other path, False if not

static copy_file(source, dest)[source]

Copy one file to another one, doing gz-unzipping if necessary.

This method copies a source file to a destination file. If the source file has suffix “svgz” and the destination file has suffix “svg” OR if the source file has suffix “gz” and the destination file has not, then we will unzip the source file to the destination file. Otherwise, a normal copy is performed.

Parameters:
  • source (str) – the source file

  • dest (str) – the destination file

Return type:

Path

Returns:

the fully-qualified destination path

static copy_resource(source_dir, input_file, dest_dir)[source]

Copy an input file to an destination directory.

Parameters:
  • source_dir (str) – the source directory

  • input_file (str) – the input file

  • dest_dir (str) – the destination directory

Return type:

Path

Returns:

the path

static directory(path)[source]

Get a path identifying a directory.

Parameters:

path (str) – the path

Return type:

Path

Returns:

the file

enforce_contains(other)[source]

Raise an exception if this path does not contain the other path.

Parameters:

other (str) – the other path

Raises:

ValueError – if other is not a sub-path of this path

Return type:

None

enforce_dir()[source]

Enforce that a path references an existing directory.

Raises:

ValueError – if path does not reference an existing directory

Return type:

None

enforce_file()[source]

Enforce that a path references an existing file.

Raises:

ValueError – if path does not reference an existing file

Return type:

None

enforce_neither_contains(other)[source]

Enforce that neither path contains another one.

Parameters:

other (str) – the other path

Raises:

ValueError – if other is contained in this path or vice versa

Return type:

None

ensure_dir_exists()[source]

Make sure that the directory exists, create it otherwise.

Return type:

None

ensure_file_exists()[source]

Atomically ensure that the file exists and create it otherwise.

Return type:

bool

Returns:

True if the file already existed and False if it was newly and atomically created.

Raises:

ValueError if anything goes wrong during the file creation

static file(path)[source]

Get a path identifying a file.

Parameters:

path (str) – the path

Return type:

Path

Returns:

the file

static path(path)[source]

Get a canonical path.

Parameters:

path (str) – the path to canonicalize

Return type:

Path

Returns:

the Path instance

read_all_list()[source]

Read all the lines in a file.

Return type:

list[str]

Returns:

the list of strings of text

read_all_str()[source]

Read a file as a single string.

Return type:

str

Returns:

the single string of text

relative_to(base_path)[source]

Compute a relative path of this path towards the given base path.

Parameters:

base_path (str) – the string

Return type:

str

Returns:

a relative path

Raises:

ValueError – if this path is not inside base_path

resolve_input_file(relative_path, lang=None)[source]

Resolve a path to an input file relative to this path.

Parameters:
  • relative_path (str) – the relative path to resolve

  • lang (Optional[str], default: None) – the language to use

Return type:

Path

Returns:

the resolved path

Raises:

ValueError – if the path cannot be resolved to a file

resolve_inside(relative_path)[source]

Resolve a relative path to an absolute path inside this path.

Parameters:

relative_path (str) – the path to resolve

Return type:

Path

Returns:

the resolved child path

Raises:

ValueError – If the path would resolve to something outside of this path and/or if it is empty.

static split_prefix_suffix(name, enforce_suffix=True)[source]

Split the file name ‘name’ into a prefix and a suffix.

Parameters:
  • name (str) – the file name

  • enforce_suffix (bool, default: True) – crash if no suffix?

Return type:

tuple[str, str]

Returns:

a tuple of [prefix, suffix]

write_all(contents)[source]

Read all the lines in a file.

Parameters:

contents (Union[str, Iterable[str]]) – the contents to write

Return type:

None

bookbuilderpy.path.UTF8: Final[str] = 'utf-8-sig'

the UTF-8 encoding

bookbuilderpy.path.copy_pure(path_in, path_out)[source]

Perform the internal method to copy a file.

Parameters:
  • path_in (str) – the path to the input file

  • path_out (str) – the path to the output file

Return type:

Path

Returns:

the path to the new file

bookbuilderpy.path.move_pure(path_in, path_out)[source]

Copy a file.

Parameters:
  • path_in (str) – the path to the input file

  • path_out (str) – the path to the output file

Return type:

Path

Returns:

the path to the new file

bookbuilderpy.pdf module

Post-process PDF files.

bookbuilderpy.pdf.pdf_postprocess(in_file, out_file, overwrite=False)[source]

Post-process a pdf file.

Parameters:
  • in_file (str) – the input file

  • out_file (str) – the output file

  • overwrite (bool, default: False) – should the output file be overwritten if it exists?

Return type:

Path

Returns:

the output file

bookbuilderpy.preprocessor module

The preprocessor commands to be applied once the text has been loaded.

bookbuilderpy.preprocessor.preprocess(text, input_dir, get_meta, get_repo, repo, output_dir)[source]

Apply all the preprocessor commands to the given text.

Parameters:
  • text (str) – the text of the book to be preprocessed.

  • input_dir (str) – the input director

  • get_meta (Callable) – a command for obtaining meta information.

  • get_repo (Callable) – a command for obtaining a repository

  • repo (Optional[Repo]) – the root repository of the project

  • output_dir (str) – the output directory

Return type:

str

bookbuilderpy.preprocessor_code module

A preprocessor for loading code.

bookbuilderpy.preprocessor_code.get_programming_language(path)[source]

Get the programming language corresponding to a path.

Parameters:

path (str) – the path to the source file

Return type:

Optional[str]

Returns:

a string identifying the programming language, or None if none detected.

bookbuilderpy.preprocessor_code.load_code(path, lines, labels, args)[source]

Load a piece of code from the given path.

Parameters:
  • path (str) – the path

  • lines (str) – a line definition string

  • labels (str) – a label definition string

  • args (str) – a string of arguments to be passed to the formatter

Return type:

str

Returns:

the code

bookbuilderpy.preprocessor_commands module

Regular-expression based command generation and invocation.

bookbuilderpy.preprocessor_commands.create_preprocessor(name, func, n=1, strip_white_space=False, wrap_in_newlines=0)[source]

Create a preprocessor command.

A LaTeX-style command can be defined as an (recursive) regular expression. The start of the command is indicated by name. It then has n arguments with n>=0. Each argument is wrapped into a { and a }. Example: sub{1}{2}.

This function returns a function f which can be applied an arbitrary string s. The function f will iteratively process all invocations of name that appear in s, pass the extracted parameter values to func, and replace the whole matched string with the return value of func.

The command can appear nested in its arguments. In this case, the preprocessor f will resolve the inner-most occurences first.

Parameters:
  • name (str) – the command name

  • func (Callable) – the function to call

  • n (int, default: 1) – the number of arguments to pass to func

  • strip_white_space (bool, default: False) – should surrounding white space be stripped?

  • wrap_in_newlines (int, default: 0) – the number of newlines into which the output should be wrapped

Return type:

Callable

Returns:

a function that can be invoked on a string and which replaces all the occurences of the command with the results of corresponding func invocations

>>> f = lambda a, b: a + "-" + b
>>> cmd = create_preprocessor("sub", f, 2)
>>> cmd("x \\sub{7}{3} y \\sub{\\sub{8}{5}}{\\sub{4}{3}}")
'x 7-3 y 8-5-4-3'
>>> cmd = create_preprocessor("mm", lambda: "Z", 0, True)
>>> cmd("a\\mm\\mm\\mmb")
'aZZZb'
>>> cmd = create_preprocessor("swp", lambda a, b: "("+b+","+a+")", 2)
>>> cmd("\\swp{1}{2}")
'(2,1)'
>>> cmd("\\swp{\\swp{1}{2}}{3}")
'(3,(2,1))'
>>> cmd("\\swp{\\swp{\\swp{1}{2}}{3}}{\\swp{4}{5}}")
'((5,4),(3,(2,1)))'
>>> cmd = create_preprocessor("y", lambda x: str(int(x)*2), 1)
>>> cmd("12\\y{3}4")
'1264'
>>> cmd = create_preprocessor("y", lambda x: f"a{x}b", 1,
...     wrap_in_newlines=2)
>>> cmd("12\\y{3}4")
'12\n\na3b\n\n4'

bookbuilderpy.preprocessor_input module

A preprocessor that loads one root file and resolves are relative inputs.

bookbuilderpy.preprocessor_input.load_input(input_file, input_dir, lang_id)[source]

Recursively load an input file.

Parameters:
  • input_file (str) – the input file

  • input_dir (str) – the base directory

  • lang_id (Optional[str]) – the language to use

Return type:

str

Returns:

the fully-resolved input

bookbuilderpy.shell module

The tool for invoking shell commands.

bookbuilderpy.shell.shell(command, timeout=3600, cwd=None, wants_stdout=False, exit_code_to_str=None, check_stderr=<function <lambda>>)[source]

Execute a text-based command on the shell.

The command is executed and its stdout and stderr and return code are captured. If the command had a non-zero exit code, an exception is thrown. The command itself, as well as the parameters are logged via the logger. If wants_stdout is True, the command’s stdout is returned. Otherwise, None is returned.

Parameters:
  • command (Union[str, Iterable[str]]) – the command to execute

  • timeout (int, default: 3600) – the timeout

  • cwd (Optional[str], default: None) – the directory to run inside

  • wants_stdout (bool, default: False) – if True, the stdout is returned, if False, None is returned

  • exit_code_to_str (Optional[dict[int, str]], default: None) – an optional map converting erroneous exit codes to strings

  • check_stderr (Callable[[str], Optional[BaseException]], default: <function <lambda> at 0x7fa5bfcac700>) – an optional callable that is applied to the std_err string and may raise an exception if need be

Return type:

Optional[str]

bookbuilderpy.source_tools module

In this file, we put some shared tools for rendering source codes.

bookbuilderpy.source_tools.format_empty_lines(lines, empty_before=<function <lambda>>, no_empty_after=<function <lambda>>, force_no_empty_after=<function <lambda>>, max_consecutive_empty_lines=1)[source]

Obtain a generator that strips any consecutive empty lines.

Parameters:
  • lines (Iterable[str]) – the original line iterable

  • empty_before (Callable, default: <function <lambda> at 0x7fa5bf211630>) – a function checking whether an empty line is required before a certain string

  • no_empty_after (Callable, default: <function <lambda> at 0x7fa5bf2116c0>) – a function checking whether an empty line is prohibited after a string

  • force_no_empty_after (Callable, default: <function <lambda> at 0x7fa5bf211750>) – a function checking whether an empty line is prohibited after a string

  • max_consecutive_empty_lines (int, default: 1) – the maximum number of permitted consecutive empty lines

Return type:

list[str]

Returns:

the generation

>>> code = ["", "a", "", "b", "", "", "c", "", "", "", "d", "e", ""]
>>> format_empty_lines(code, max_consecutive_empty_lines=3)
['a', '', 'b', '', '', 'c', '', '', '', 'd', 'e']
>>> format_empty_lines(code, max_consecutive_empty_lines=2)
['a', '', 'b', '', '', 'c', '', '', 'd', 'e']
>>> format_empty_lines(code, max_consecutive_empty_lines=1)
['a', '', 'b', '', 'c', '', 'd', 'e']
>>> format_empty_lines(code, max_consecutive_empty_lines=0)
['a', 'b', 'c', 'd', 'e']
>>> format_empty_lines(code, max_consecutive_empty_lines=2,
...                    no_empty_after=lambda s: s == "b")
['a', '', 'b', 'c', '', '', 'd', 'e']
>>> format_empty_lines(code, max_consecutive_empty_lines=2,
...                    no_empty_after=lambda s: s == "b",
...                    empty_before=lambda s: s == "e")
['a', '', 'b', 'c', '', '', 'd', '', 'e']
>>> format_empty_lines(code, max_consecutive_empty_lines=2,
...                    no_empty_after=lambda s: s == "b",
...                    empty_before=lambda s: s == "e",
...                    force_no_empty_after=lambda s: s == "d")
['a', '', 'b', 'c', '', '', 'd', 'e']
bookbuilderpy.source_tools.select_lines(code, lines=None, labels=None, line_comment_start='#', max_consecutive_empty_lines=1)[source]

Select lines of source code based on labels and line indices.

First, we select all lines of the code we want to keep. If labels are defined, then lines are kept as ranges or as single lines for all pre-defined labels. Ranges may overlap and/or intersect. Otherwise, all lines are selected in this step.

Then, if line numbers are provided, we selected the lines based on the line numbers from the lines we have preserved.

Finally, leading and trailing empty lines as well as superfluous empty lines are removed.

Parameters:
  • code (Iterable[str]) – the code loaded from a file

  • lines (Optional[Iterable[int]], default: None) – the lines to keep, or None if we keep all

  • labels (Optional[Iterable[str]], default: None) – a list of labels marking start and end of code snippets to include

  • line_comment_start (str, default: '#') – the string marking the line comment start

  • max_consecutive_empty_lines (int, default: 1) – the maximum number of permitted consecutive empty lines

Return type:

list[str]

Returns:

the list of selected lines

>>> select_lines(["def a():", "    b=c", "    return x"])
['def a():', '    b=c', '    return x']
>>> pc = ["# start x", "def a():", " b=c # -x", "    return x", "# end x"]
>>> select_lines(pc, labels={"x"})
['def a():', '    return x']
bookbuilderpy.source_tools.strip_common_whitespace_prefix(lines)[source]

Strip a common whitespace prefix from a list of strings and merge them.

Parameters:

lines (Iterable[str]) – the lines

Return type:

list[str]

Returns:

the code with the white space prefix stripped

>>> strip_common_whitespace_prefix([" a", "  b"])
['a', ' b']
>>> strip_common_whitespace_prefix([" a", " b"])
['a', 'b']
>>> strip_common_whitespace_prefix(["  a", "  b"])
['a', 'b']
>>> strip_common_whitespace_prefix(["  a", "  b", "c"])
['  a', '  b', 'c']
>>> strip_common_whitespace_prefix([" a", "  b", "c"])
[' a', '  b', 'c']
>>> strip_common_whitespace_prefix(["  a", "  b", "    c"])
['a', 'b', '  c']

bookbuilderpy.strings module

Some utility methods for string processing.

bookbuilderpy.strings.datetime_to_date_str(date)[source]

Convert a datetime object to a date string.

Parameters:

date (datetime) – the date

Return type:

str

Returns:

the date string

bookbuilderpy.strings.datetime_to_datetime_str(date)[source]

Convert a datetime object to a date-time string.

Parameters:

date (datetime) – the date

Return type:

str

Returns:

the date-time string

bookbuilderpy.strings.enforce_non_empty_str(text)[source]

Enforce that a text is a non-empty string.

Parameters:

text (str) – the text

Return type:

str

Returns:

the text

Raises:
bookbuilderpy.strings.enforce_non_empty_str_without_ws(text)[source]

Enforce that a text is a non-empty string without white space.

Parameters:

text (str) – the text

Return type:

str

Returns:

the text

Raises:
  • TypeError – if text is not a str

  • ValueError – if text is empty or contains any white space characters

bookbuilderpy.strings.enforce_url(url)[source]

Enforce that a string is a valid url.

Parameters:

url (str) – the url

Return type:

str

Returns:

the url

bookbuilderpy.strings.file_size(size)[source]

Convert a file size to a string.

Parameters:

size (int) – the size

Return type:

str

Returns:

the string

bookbuilderpy.strings.get_prefix_str(str_list)[source]

Compute the common prefix string.

Parameters:

str_list (tuple[str, ...] | list[str]) – the list of strings

Return type:

str

Returns:

the common prefix

>>> get_prefix_str(["abc", "acd"])
'a'
>>> get_prefix_str(["xyz", "gsdf"])
''
>>> get_prefix_str([])
''
>>> get_prefix_str(["abx"])
'abx'
>>> get_prefix_str(("\\relative.path", "\\relative.figure",
...     "\\relative.code"))
'\\relative.'
bookbuilderpy.strings.lang_to_locale(lang)[source]

Convert a language ID to a locale.

Parameters:

lang (str) – the language id

Return type:

str

Returns:

the locale

bookbuilderpy.strings.lines_to_str(lines, trailing_newline=True)[source]

Convert an iterable of strings to a single string.

Parameters:
  • lines (Iterable[str]) – the lines

  • trailing_newline (bool, default: True) – should the re be a newline at the end?

Return type:

str

Returns:

the single string

>>> lines_to_str(["a", "b", "", "c", ""], trailing_newline=True)
'a\nb\n\nc\n'
>>> lines_to_str(["a", "b", "", "c"], trailing_newline=True)
'a\nb\n\nc\n'
>>> lines_to_str(["a", "b", "", "c"], trailing_newline=False)
'a\nb\n\nc'
>>> lines_to_str(["a", "b", "", "c", ""], trailing_newline=False)
'a\nb\n\nc'
bookbuilderpy.strings.regex_sub(search, replace, inside)[source]

Replace all occurrences of ‘search’ in ‘inside’ with ‘replace’.

Parameters:
  • search (Union[str, Pattern]) – the regular expression to search

  • replace (Union[Callable, str]) – the regular expression to replace it with

  • inside (str) – the string in which to search/replace

Return type:

str

Returns:

the new string after the recursive replacement

>>> regex_sub('[ \t]+\n', '\n', ' bla \nxyz\tabc\t\n')
' bla\nxyz\tabc\n'
>>> regex_sub('[0-9]A', 'X', '23A7AA')
'2XXA'
bookbuilderpy.strings.str_to_lines(text)[source]

Convert a string to an iterable of lines.

Parameters:

text (str) – the original text string

Return type:

list[str]

Returns:

the lines

>>> str_to_lines("\n123\n  456\n789 \n 10\n\n")
['', '123', '  456', '789 ', ' 10', '', '']
bookbuilderpy.strings.to_string(obj, locale=None, use_seq_and=True)[source]

Convert any object to a string, try to use a proper locale.

Parameters:
  • obj – the input object

  • locale (Optional[str], default: None) – the locale

  • use_seq_and (bool, default: True) – should we use “and” in sequences?

Return type:

str

Returns:

the string representation

bookbuilderpy.temp module

A set of utilities interactions with the file system.

class bookbuilderpy.temp.TempDir(value)[source]

Bases: Path, AbstractContextManager

A scoped temporary directory to be used in a ‘with’ block.

The directory and everything in it will be deleted upon exiting the ‘with’ block.

static create(directory=None)[source]

Create the temporary directory.

Parameters:

directory (Optional[str], default: None) – an optional root directory

Raises:

TypeError – if directory is not None but also no str

Return type:

TempDir

class bookbuilderpy.temp.TempFile(value)[source]

Bases: Path, AbstractContextManager

A scoped temporary file to be used in a ‘with’ block.

This file will be deleted upon exiting the ‘with’ block.

static create(directory=None, prefix=None, suffix=None)[source]

Create a temporary file.

Parameters:
  • directory (Optional[str], default: None) – a root directory or TempDir instance

  • prefix (Optional[str], default: None) – an optional prefix

  • suffix (Optional[str], default: None) – an optional suffix, e.g., .txt

Raises:

TypeError – if any of the parameters does not fulfill the type contract

Return type:

TempFile

bookbuilderpy.types module

Some basic type handling routines.

bookbuilderpy.types.type_error(obj, name, expected=None, call=False)[source]

Create an error to raise if a type did not fit.

Parameters:
  • obj (Any) – the object that is of the wrong type

  • name (str) – the name of the object

  • expected (Union[None, type, Iterable[type]], default: None) – the expected types (or None)

  • call (bool, default: False) – the object should have been callable?

Return type:

ValueError | TypeError

Returns:

a TypeError with a descriptive information

>>> type_error(1.3, "var", int)
TypeError("var should be an instance of int but is float, namely '1.3'.")
>>> type_error("x", "z", (int, float)).args[0]
"z should be an instance of any in {float, int} but is str, namely 'x'."
>>> type_error("f", "q", call=True).args[0]
"q should be a callable but is str, namely 'f'."
>>> type_error("1", "2", bool, call=True).args[0]
"2 should be an instance of bool or a callable but is str, namely '1'."
>>> type_error(None, "x", str)
TypeError('x should be an instance of str but is None.')
bookbuilderpy.types.type_name(tpe)[source]

Convert a type to a string.

Parameters:

tpe (type) – the type

Return type:

str

Returns:

the string

>>> type_name(type(None))
'None'
>>> type_name(int)
'int'
>>> from bookbuilderpy.path import Path
>>> type_name(Path)
'bookbuilderpy.path.Path'
bookbuilderpy.types.type_name_of(obj)[source]

Get the fully-qualified class name of an object.

Parameters:

obj – the object

Return type:

str

Returns:

the fully-qualified class name of the object

>>> from bookbuilderpy.path import Path
>>> type_name_of(Path.path("/tmp"))
'bookbuilderpy.path.Path'

bookbuilderpy.url module

Loading of data from urls.

bookbuilderpy.url.load_binary_from_url(url)[source]

Load all the binary data from one url.

Parameters:

url (str) – the url

Return type:

tuple[str, bytes]

Returns:

a tuple of the file name and the binary data that was loaded

bookbuilderpy.url.load_text_from_url(url)[source]

Load all the text from one url.

Parameters:

url (str) – the url

Return type:

tuple[str, str]

Returns:

a tuple of the file name and the text that was loaded

bookbuilderpy.version module

An internal file with the version of the bookbuilderpy package.

bookbuilderpy.versions module

Get the versions of all involved libraries and tools.

bookbuilderpy.versions.TOOL_CALIBRE: Final[str] = 'calibre'

the name of the calibre executable tool

bookbuilderpy.versions.TOOL_FIREFOX: Final[str] = 'firefox'

the name of the firefox browser executable tool

bookbuilderpy.versions.TOOL_FIREFOX_DRIVER: Final[str] = 'geckodriver'

the name of the firefox driver tool

bookbuilderpy.versions.TOOL_GHOSTSCRIPT: Final[str] = 'gs'

the name of the ghostscript executable tool

bookbuilderpy.versions.TOOL_GIT: Final[str] = 'git'

the name of the git executable tool

bookbuilderpy.versions.TOOL_PANDOC: Final[str] = 'pandoc'

the name of the pandoc executable tool

bookbuilderpy.versions.TOOL_PDFLATEX: Final[str] = 'pdflatex'

the name of the pdflatex executable tool

bookbuilderpy.versions.TOOL_RSVG_CONVERT: Final[str] = 'rsvg-convert'

the name of the rsvg-convert executable tool

bookbuilderpy.versions.TOOL_TAR: Final[str] = 'tar'

the name of the tar executable tool

bookbuilderpy.versions.TOOL_XELATEX: Final[str] = 'xelatex'

the name of the xelatex executable tool

bookbuilderpy.versions.TOOL_XZ: Final[str] = 'xz'

the name of the xz executable tool

bookbuilderpy.versions.TOOL_ZIP: Final[str] = 'zip'

the name of the zip executable tool

bookbuilderpy.versions.get_versions()[source]

Get the versions of all involved libraries and tools.

Return type:

str

Returns:

a string with version information of all libraries and tools

bookbuilderpy.versions.has_tool(tool)[source]

Check if the given tool is installed.

Parameters:

tool (str) – the tool executable

Return type:

bool

Returns:

True if the tool is installed, False otherwise.

bookbuilderpy.website module

The routine for building the website for the book.

bookbuilderpy.website.build_website(docs, outer_file, body_file, dest_dir, input_dir, get_meta)[source]

Build a website linking to all the generated documents.

Parameters:
  • docs (Iterable[LangResult]) – the per-language results

  • outer_file (str) – the wrapper file

  • body_file (Optional[str]) – the body file

  • dest_dir (str) – the destination directory

  • input_dir (str) – the base input directory

  • get_meta (Callable) – a callable used to get the results

Return type:

File

Returns:

the file record to the generated website