losalamos.documents#

Handle Documents editing, managing and builds.

Class hierarchy#

DataSet
└── Document                    (base for all document types)
    └── DocumentTeX             (base for all TeX documents)
        └── Essay               (base for essay-style documents)
            ├── Academic        (academic documents)
            │   ├── Article
            │   ├── Preprint
            │   └── PrintArticle
            └── Professional    (professional documents)
                ├── Report      (standard report; PDF/note → outputs/)
                ├── Invoice
                │   ├── Receipt
                │   └── Proposal
                │       ├── Agreement
                │       └── Contract

Template resolution#

Every new() call merges up to three template layers in priority order:

BASE_TEMPLATE  ←  VARIANT_TEMPLATE  ←  template_overlay (user)
  • BASE_TEMPLATEdefined on DocumentTeX; canonical TeX base shared

    by all document types.

  • VARIANT_TEMPLATEdefined per subclass; files that differentiate the

    document type (cover, class options, etc.).

  • template_overlayoptional user-supplied folder for private or

    client-specific files (logos, confidential covers).

Each layer wins over the one to its left. Files absent from a layer are inherited transparently from the layer below.

Functions

Classes

Academic([name, alias])

Agreement([name, alias])

Article([name, alias])

Contract([name, alias])

Document([name, alias])

Base class for all document types.

DocumentTeX([name, alias])

Base class for all TeX-based document types.

Essay([name, alias])

Invoice([name, alias])

Preprint([name, alias])

PrintArticle([name, alias])

Professional([name, alias])

Proposal([name, alias])

Receipt([name, alias])

Report([name, alias])

Exceptions

LatexCompileError(message[, source, ...])

Raised when latexmk fails or cannot be found on PATH.

losalamos.documents.escape_percent_latex(text: str) str[source]#
class losalamos.documents.Document(name='MyDocument', alias='Doc')[source]#

Bases: DataSet

Base class for all document types.

Handles generic file loading and the three-layer template merge used by new(). Subclasses specialise behaviour by overriding BASE_TEMPLATE and VARIANT_TEMPLATE.

BASE_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/txt/demo')#
VARIANT_TEMPLATE = None#
load_data(file_data)[source]#

Load data from file.

Parameters:

file_data (str) – file path to data.

new(folder, name=None, template_overlay=None, files_overlay=None)[source]#

Create a new document folder by materializing template files into a target location.

This method creates a folder named name inside folder and populates it by merging up to three template layers in the following priority order:

BASE_TEMPLATE  ←  VARIANT_TEMPLATE  ←  template_overlay

Each layer wins over the one to its left. Layers that are None are skipped transparently. The caller is responsible for ensuring the target path does not already exist; if it does, a FileExistsError is raised immediately and no files are written.

Single-layer mode (only BASE_TEMPLATE, both VARIANT_TEMPLATE and template_overlay are None):

The entire BASE_TEMPLATE directory tree is copied as-is into the target folder, preserving all subdirectories and files.

Multi-layer mode (one or both of VARIANT_TEMPLATE, template_overlay are provided):

All active layers are scanned recursively and merged into the target.

  • Files present in only one layer are copied from that layer.

  • Files present in multiple layers are resolved in favour of the highest-priority layer (right-most in the chain).

Merge example — three active layers
BASE_TEMPLATE/      VARIANT_TEMPLATE/     template_overlay/
├── main.tex        ├── main.tex           └── cover.tex
├── preamble.tex    └── cover.tex
└── refs.bib

# Resolution:
# main.tex     → VARIANT_TEMPLATE  (highest priority)
# cover.tex    → template_overlay  (highest priority)
# preamble.tex → BASE_TEMPLATE     (only source)
# refs.bib     → BASE_TEMPLATE     (only source)

# Result in target:
folder/name/
├── main.tex        # from VARIANT_TEMPLATE
├── cover.tex       # from template_overlay
├── preamble.tex    # from BASE_TEMPLATE
└── refs.bib        # from BASE_TEMPLATE
Parameters:
  • name (str) – Name of the new document folder to be created inside folder.

  • folder (str or pathlib.Path) – Parent directory under which the new document folder is created. Must already exist as a directory on the filesystem.

  • template_overlay (str, pathlib.Path, or None) – Optional user-supplied directory whose files take priority over both BASE_TEMPLATE and VARIANT_TEMPLATE. Intended for private or client-specific files (logos, confidential covers, etc.). When None (default), only the class-level templates are used. When provided, must be a valid existing directory; otherwise NotADirectoryError is raised before any files are written.

  • files_overlay (dict, str, pathlib.Path, or None) – Optional file-level overlay applied after all template layers. Can be a dict mapping destination-relative paths to source file paths, or a path to a .json, .yaml/.yml, or .toml config file with the same structure. Keys are paths relative to the document root (e.g. "definitions/party_b.tex"); values are the source files to copy from (the destination filename is taken from the key, not the source). All source files are validated before any copying begins.

Raises:
  • FileExistsError – If the target folder folder/name already exists. No files are created or modified in this case.

  • NotADirectoryError – If template_overlay is provided but does not point to a valid directory. Validated before any files are written.

  • FileNotFoundError – If a source path in files_overlay does not exist or is not a file. Also raised if the merged template does not contain exactly one top-level main.* file to load as the document’s entry point.

Returns:

None. Acts in place: locates the merged tree’s top-level main.* file and calls load_data() on it, which updates file_data, data, and (for subclasses such as DocumentTeX) is_main to reflect the newly created document.

Return type:

None

Usage example
# Single-layer: base template only (Document base class)
doc = Document(name="MyDoc", alias="D")
doc.new("my_doc", "/home/user/documents")
# doc.file_data now points at the new document's main file

# Two-layer: base + variant (subclass sets VARIANT_TEMPLATE)
report = Report(name="AnnualReport", alias="AR")
report.new("annual_report", "/home/user/documents")

# Three-layer: base + variant + private user overlay
report.new(
    "client_report",
    "/home/user/documents",
    template_overlay="/home/user/private/client_x",
)
apply_config(config)[source]#

Apply document configuration. No-op in the base class.

Subclasses such as Invoice and Receipt override this to rewrite their services table partial from config.

Parameters:

config (dict or None) – Configuration dict. Subclasses interpret the contents.

Returns:

None

Return type:

None

exception losalamos.documents.LatexCompileError(message, source=None, returncode=-1, log_path=None)[source]#

Bases: RuntimeError

Raised when latexmk fails or cannot be found on PATH.

Parameters:
  • message (str) – Human-readable error description.

  • source (pathlib.Path or None) – Path to the .tex file being compiled, or None.

  • returncode (int) – Exit code returned by latexmk. -1 when latexmk was not found.

  • log_path (pathlib.Path or None) – Path to the .log file produced by the failed run, or None if unavailable.

class losalamos.documents.DocumentTeX(name='MyDocTeX', alias='TeX')[source]#

Bases: Document

Base class for all TeX-based document types.

Extends Document with TeX-specific behaviour: main-file detection, PDF compilation via latexmk, and document flattening. Subclasses set VARIANT_TEMPLATE to select their template layer.

BASE_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/base')#
VARIANT_TEMPLATE = None#
load_data(file_data)[source]#

Load data from a TeX file and detect whether it is a main document.

A file is considered a main document if it contains a \documentclass declaration. Partial files (chapters, sections) intended to be \input-ted by a main file will have is_main set to False.

Parameters:

file_data (str or pathlib.Path) – Path to the .tex file to load.

Returns:

None

Return type:

None

to_pdf(file_output=None, cleanup=True, command='pdf')[source]#

Compile the TeX document into a PDF using latexmk.

Only executes when is_main is True; partial files are silently skipped.

The method temporarily switches the working directory to the source file’s parent folder before invoking latexmk, ensuring that all relative paths in the document (\input, \include, figures, etc.) resolve correctly regardless of where the Python process was launched from. The original working directory is always restored, even if compilation raises an exception.

A project-local latexmkrc file is expected at the root of the document folder. It is passed explicitly via -r latexmkrc so that glossaries and nomenclature are built correctly on all platforms without requiring a global latexmkrc installation.

Parameters:
  • file_output (str or pathlib.Path or None) – Desired output path for the compiled PDF. When None (default), the PDF is left next to the source .tex file.

  • cleanup (bool) – If True (default), removes auxiliary files produced by latexmk after a successful compilation (equivalent to latexmk -c).

  • command (str) – latexmk engine flag controlling the PDF backend. Common values: "pdf" (pdflatex), "pdflua" (lualatex), "pdfxe" (xelatex).

Raises:

LatexCompileError – If latexmk exits with a non-zero return code or is not found on PATH. The exception carries source, returncode, and log_path attributes.

Returns:

None

Return type:

None

clean()[source]#

Remove auxiliary files left by a previous latexmk run.

Runs latexmk -c and then sweeps for extra suffixes that latexmk -c does not track. The working directory is temporarily switched to the source file’s parent folder (matching to_pdf()) and is always restored in a finally block.

Only executes when is_main is True; partial files are silently skipped.

Returns:

None

Return type:

None

to_flat(file_output=None, compile_first=False, command='pdf')[source]#

Flatten the TeX document by recursively resolving \input / \include directives and embedding the compiled bibliography.

Delegates the flattening work to make_flat(). Only executes when is_main is True; partial files return None silently.

Parameters:
  • file_output (str or pathlib.Path or None) – Desired output path for the flattened .tex file. When None, the source file is overwritten in-place.

  • compile_first (bool) – If True (default), compiles the document before flattening so that the .bbl file reflects the current bibliography state. The intermediate PDF and .bbl are removed after flattening.

  • command (str) – latexmk engine flag passed to to_pdf() when compile_first=True.

Returns:

None

Return type:

str or None

export(folder_root, name, flatten=False, split=False, zip_export=False)[source]#

Export the TeX document to a self-contained folder.

Creates folder_root/name/ and writes the document into it according to the chosen mode:

  • Plain (flatten=False, split=False): the source file is copied as-is, retaining its original filename.

  • Flatten (flatten=True, split=False): \input / \include directives are resolved recursively and the result is written as a single file named <name>.tex. Every image (\includegraphics) and bibliography resource (\addbibresource) referenced anywhere in the document tree is also copied alongside, preserving its path relative to the original project root so the (unmodified) references in the flattened text keep resolving correctly.

  • Split (split=True): implies flattening, with the same image/bibliography-resource copying described above. The document is first flattened into a temporary file, then split into preamble.tex and main.tex. The intermediate flat file is removed after splitting.

Parameters:
  • folder_root (str or pathlib.Path) – Parent directory under which the export folder is created.

  • name (str) – Name of the export folder and, in flatten mode, stem of the output .tex file.

  • flatten (bool) – If True, resolve all \input / \include directives into a single file before exporting. Ignored when split=True (flattening is always performed in that case).

  • split (bool) – If True, flatten the document and split the result into preamble.tex and main.tex. Takes precedence over flatten.

  • zip_export (bool) – If True, additionally packages the export folder’s contents into a .zip archive at folder_root/<name>.zip. Files are placed at the archive’s root – not nested inside a <name>/ folder – so the zip can be dropped directly into Overleaf’s “Upload Project” (or any other single-archive project import) without any manual restructuring first. The uncompressed export folder is left in place alongside it either way.

Returns:

Path to the created export folder. When zip_export is True, the archive sits alongside it at folder_root/<name>.zip.

Return type:

pathlib.Path

Raises:
  • RuntimeError – If the document is not a main file (i.e. \documentclass is absent). The is_main attribute is re-evaluated from file_data before the check so stale state does not produce a false negative.

  • FileExistsError – If folder_root/name already exists.

static split_preamble(input_tex, preamble_name='preamble', main_name='main', output_folder=None)[source]#

Split a main TeX file into a preamble fragment and a stub main file.

The preamble fragment receives everything between the \documentclass line and \begin{document} (both exclusive). The stub main file retains \documentclass, replaces the preamble block with a single \input{<preamble_name>} line, and keeps everything from \begin{document} onward intact.

Resulting structure:

% <main_name>.tex
\documentclass{...}

\input{preamble}

\begin{document}
...
\end{document}

% <preamble_name>.tex
\usepackage{...}
\newcommand{...}
...
Parameters:
  • input_tex (str or pathlib.Path) – Path to the root .tex file to split. Must be a main document containing \documentclass and \begin{document}.

  • preamble_name (str) – Stem for the preamble output file, without extension. Defaults to "preamble".

  • main_name (str) – Stem for the stub main output file, without extension. Defaults to "main".

  • output_folder (str or pathlib.Path or None) – Directory where both output files are written. When None (default), the parent directory of input_tex is used.

Returns:

Tuple of (preamble_path, main_path) as resolved pathlib.Path objects.

Return type:

tuple[pathlib.Path, pathlib.Path]

Raises:

ValueError – If input_tex does not contain a \documentclass declaration (i.e. is not a main TeX file), if \begin{document} is not found, or if the input file stem matches an output stem when both resolve to the same directory.

static make_flat(input_tex, output_tex=None, assets=None)[source]#

Flatten a TeX document by recursively resolving \input / \include directives and embedding the compiled bibliography.

This is a pure file-system operation with no dependency on any DocumentTeX instance. It can be used independently whenever a self-contained .tex file is needed (e.g. arXiv submission).

Parameters:
  • input_tex (str or pathlib.Path) – Path to the root .tex file to flatten.

  • output_tex (str or pathlib.Path or None) – Destination path for the flattened file. When None (default), the result is written back over the source file in-place.

  • assets (set or None) – Optional set, populated as a side effect with the resolved absolute paths of every image (\includegraphics) and bibliography resource (\addbibresource) referenced anywhere in the document tree. Unlike \bibliography (see below), \addbibresource references are left untouched in the flattened text – biblatex/biber still needs to read the raw .bib file after flattening – so this is the only way to learn which files must travel alongside the flattened output. When None (default), no collection is performed. Paths that can’t be found on disk (e.g. images resolved via TeX’s own search path rather than the project tree, such as the example-image-* placeholders) are never added.

Returns:

The fully flattened LaTeX source as a string.

Return type:

str

static lint_paragraphs(input_tex, output_tex=None)[source]#

Join wrapped prose paragraphs in a LaTeX file into single lines.

Reads input_tex, joins each wrapped prose paragraph in the document body into a single source line, and writes the result to output_tex.

This function performs no backup of its own. When output_tex is None (or equal to input_tex), the input file is overwritten in place; callers that want a safety copy should take one beforehand (see backup_file()).

Parameters:
  • input_tex (str or pathlib.Path) – Path to the source .tex file to read.

  • output_tex (str or pathlib.Path or None) – Path to write the linted result to. If None (the default), input_tex is overwritten in place.

Returns:

The path the linted .tex was written to (equal to input_tex if output_tex was None).

Return type:

pathlib.Path

Raises:
  • FileNotFoundError – If input_tex does not exist.

  • UnicodeDecodeError – If input_tex is not valid UTF-8.

Algorithm#

  1. Everything up to and including \begin{document}, and everything from \end{document} onward, is passed through unchanged. (The preamble’s \newcommand shorthand definitions are one-per-line by convention and must stay that way.)

  2. Within the document body, consecutive lines are grouped into “paragraphs”: maximal runs of lines that are not blank, not \begin{...}/\end{...}, not comment-only, and not inside a non-reflowable environment. Each run is joined into a single line: every line is stripped of leading/trailing whitespace, joined with a single space, and any remaining runs of spaces are collapsed to one.

  3. The following end the current paragraph and are emitted unchanged on their own line, without being joined to anything: blank lines; \begin{...}/\end{...} lines (which also push/pop an environment stack used to track non-reflowable regions, including nested ones, by scanning the whole line – e.g. a pmatrix opened and closed on the same line inside an equation/align nets to zero rather than leaking a permanently elevated non-reflowable count); a comment-only line that appears between paragraphs; and \[/\] display-math delimiters on their own line (tracked like a pseudo-environment), or inline \[ ... \] on one line.

  4. A % comment that appears inside a paragraph – either a comment-only line with real content already buffered, or a trailing % ... after real content – does not split the paragraph. The real content (if any) is kept in the paragraph, and the comment text is deferred and appended to the end of the paragraph’s joined line once it is flushed. This avoids an editorial comment in the middle of a sentence cutting it into two “paragraphs”, the second starting mid-sentence (lower-case).

  5. \item always starts a new paragraph (flush before it), but its own wrapped continuation lines still join onto it – so consecutive list items each end up on their own line.

  6. The following commands always stand alone on their own output line, never merged with the paragraph before or after them, even without a blank line in the source: \tcblower, \newpage, \clearpage, \cleardoublepage, \pagebreak, \newline, \figplaceholder, \boxfigplaceholder, \boxbiofigplaceholder, and \chapter/\section/ \subsection/\subsubsection (starred or not).

  7. Non-reflowable environments (passed through verbatim, line-by-line, including any blank lines inside them): equation, align, gather, multline, eqnarray, alignat and their starred forms; array, cases, matrix/pmatrix/bmatrix/ vmatrix/Vmatrix; tabular, tabular*, tabularx, longtable; verbatim, lstlisting, minted, Verbatim; and \[ ... \] display math.

Note

Only line breaks and runs of whitespace within a joined paragraph are changed; no other characters are altered, so the rendered PDF is unaffected.

Example#

from pathlib import Path
lint_paragraphs(Path("chapter07_T12.tex"))  # overwrite in place
lint_paragraphs("chapter07_T12.tex", "chapter07_T12_linted.tex")
static lint_decorations_remove(input_tex, output_tex=None, document_only=False, except_chars=None)[source]#

Remove decoration comments/rulers (no letter characters after %) from a LaTeX file.

Reads input_tex, strips every decorative comment (comment-only lines and trailing comment suffixes on prose lines whose comment text contains no ASCII letter), and writes the result to output_tex.

This function performs no backup of its own. When output_tex is None (or equal to input_tex), the input file is overwritten in place; callers that want a safety copy should take one beforehand (see backup_file()).

Parameters:
  • input_tex (str or pathlib.Path) – Path to the source .tex file to read.

  • output_tex (str or pathlib.Path or None) – Path to write the purged result to. If None (the default), input_tex is overwritten in place.

  • document_only (bool) – If False (the default), the purge runs over the entire file – preamble, body, and postamble alike. If True, only the lines between \begin{document} and \end{document} are processed; the preamble and postamble are passed through unchanged.

  • except_chars (list[str] or None) – Optional list of single characters. A decoration comment (one whose text after % contains no ASCII letter) is nonetheless kept if its text contains at least one character from this list. Use this to preserve specific ruler styles, e.g. except_chars=['#'] keeps % #### lines. None (the default) means no exceptions – all decoration comments are removed.

Returns:

The path the purged .tex was written to (equal to input_tex if output_tex was None).

Return type:

pathlib.Path

Raises:
  • FileNotFoundError – If input_tex does not exist.

  • UnicodeDecodeError – If input_tex is not valid UTF-8.

Algorithm#

  1. When document_only=True, everything up to and including \begin{document}, and everything from \end{document} onward, is passed through unchanged. When document_only=False (default), all lines – including the preamble – are processed uniformly.

  2. Within the processed region each line is classified as one of:

    1. Blank – passed through unchanged.

    2. Comment-only decoration – the entire line’s non-whitespace content is a % whose following text (stripped) contains no ASCII letter and no except_chars character. The line is dropped; if the previous output line was blank, that blank is also removed (blank-line collapse).

    3. Comment-only kept – comment-only but preserved because the text contains a letter or an except_chars character. Passed through unchanged.

    4. Prose with trailing decoration comment – the % suffix qualifies as decoration. The suffix (and any whitespace before it) is stripped; the prose remainder is kept.

    5. Prose with trailing real comment – kept verbatim.

    6. Prose without any comment – kept verbatim.

  3. The % position is found via _find_comment_pos, which correctly handles escaped percent signs (\%).

  4. Non-reflowable environments (equation, align, tabular, verbatim, etc.) receive no special treatment here: comment lines inside math or table environments are still subject to the same rule.

Note

Only comment text is removed; no other characters are altered, so the rendered PDF is unaffected.

static lint_decorations_add(input_tex, output_tex=None, ruler_chars=None, ruler_len=60)[source]#

Inject decoration rulers above section headings in a LaTeX file.

Reads input_tex, inserts a comment ruler (% `` + N repetitions of a level-specific character) on the line immediately before every ``\chapter, \section, \subsection, and \subsubsection command found inside the document body, then writes the result to output_tex.

The preamble (everything up to and including \begin{document}) and the postamble (\end{document} and everything after) are passed through unchanged.

If a ruler with the correct character already exists on the line immediately before a heading, it is replaced rather than duplicated, making the function safe to call multiple times on the same file (idempotent with respect to ruler content; ruler length is always normalised to the current ruler_len).

This function performs no backup of its own. When output_tex is None (or equal to input_tex), the input file is overwritten in place; callers that want a safety copy should take one beforehand (see backup_file()).

Parameters:
  • input_tex (str or pathlib.Path) – Path to the source .tex file to read.

  • output_tex (str or pathlib.Path or None) – Path to write the result to. If None (the default), input_tex is overwritten in place.

  • ruler_chars (str or list[str] or None) – Sequence of up to four characters, one per heading level (chapter, section, subsection, subsubsection). Missing positions fall back to the defaults ('#', '*', '=', '-'). May be a string (each character is used positionally) or any sequence of single characters. None uses all defaults.

  • ruler_len (int) – Number of times the ruler character is repeated after the % `` prefix.  Defaults to ``60.

Returns:

The path the result was written to.

Return type:

pathlib.Path

Raises:
  • FileNotFoundError – If input_tex does not exist.

  • UnicodeDecodeError – If input_tex is not valid UTF-8.

  • ValueError – If ruler_len is less than 1.

Algorithm#

  1. Split the file into preamble, body lines, and postamble at \begin{document} / \end{document}. Only the body is processed.

  2. Resolve the four ruler strings from ruler_chars and ruler_len.

  3. Walk body lines. When a line matches a heading command, look at the previous output line:

    • If it is already a ruler whose dominant character matches the current level’s character, replace it with the freshly built ruler (normalises length on re-runs).

    • Otherwise insert the ruler as a new line before the heading.

  4. Reassemble preamble + processed body + postamble and write.

Note

A “ruler line” for replacement detection is defined as a line whose stripped content matches % <char><char>... with at least one repetition of char – the same format this function produces. Any other comment line is left untouched even if it precedes a heading.

static lint_blank_lines(input_tex, output_tex=None)[source]#

Normalize blank-line spacing in a LaTeX file.

Reads input_tex and enforces two rules throughout the document body:

  • Paragraph separation – any run of two or more consecutive blank lines in prose is collapsed to exactly one blank line.

  • Environment padding – every \begin{...} is preceded by exactly two blank lines, and every \end{...} is followed by exactly two blank lines. The interior of every environment (everything between its \begin and \end) is left completely untouched.

Schematically, the target layout is:

<prose>

<blank>
<blank>
\begin{equation}
  ...            <- interior: never touched
\end{equation}
<blank>
<blank>
<prose>

Nested environments produce nested padding:

<blank>
<blank>
\begin{subequations}

  <blank>
  <blank>
  \begin{align}
    ...
  \end{align}
  <blank>
  <blank>

\end{subequations}
<blank>
<blank>

The preamble (everything up to and including \begin{document}) and the document environment boundary itself are exempt from padding.

This function performs no backup of its own. When output_tex is None (or equal to input_tex), the input file is overwritten in place; callers that want a safety copy should take one beforehand.

Parameters:
  • input_tex (str or pathlib.Path) – Path to the source .tex file to read.

  • output_tex (str or pathlib.Path or None) – Path to write the result to. If None (the default), input_tex is overwritten in place.

Returns:

(output_path, stats) where stats is a dict with keys collapsed (excess blank lines removed) and padded (blank lines inserted).

Return type:

tuple[pathlib.Path, dict]

Raises:
  • FileNotFoundError – If input_tex does not exist.

  • UnicodeDecodeError – If input_tex is not valid UTF-8.

Algorithm#

A single forward pass over the lines maintains:

  • env_depth – nesting depth of padded environments (0 = prose).

  • pending_pad – number of blank lines still to be emitted after an \end{...} before the next non-blank content.

When a \begin{...} is encountered (outside the preamble and outside the document environment): any trailing blank lines in the output buffer are stripped, exactly two blank lines are inserted, and then the \begin line itself is emitted. env_depth is incremented, and all subsequent lines (including blank ones) are passed through verbatim until the matching \end{...} is reached. On \end{...}: env_depth is decremented, the \end line is emitted, and pending_pad is set to 2. The next non-blank line flushes those two blank lines first. Any blank lines in the source between \end and the next content are discarded (replaced by the controlled padding).

class losalamos.documents.Essay(name='MyDocTeX', alias='TeX')[source]#

Bases: DocumentTeX

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/essay')#
class losalamos.documents.Academic(name='MyDocTeX', alias='TeX')[source]#

Bases: Essay

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/academic/base')#
class losalamos.documents.Article(name='MyDocTeX', alias='TeX')[source]#

Bases: Academic

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/academic/article')#
class losalamos.documents.Preprint(name='MyDocTeX', alias='TeX')[source]#

Bases: Article

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/academic/preprint')#
class losalamos.documents.PrintArticle(name='MyDocTeX', alias='TeX')[source]#

Bases: Article

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/academic/base')#
class losalamos.documents.Professional(name='MyDocTeX', alias='TeX')[source]#

Bases: Essay

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/base')#
class losalamos.documents.Report(name='MyDocTeX', alias='TeX')[source]#

Bases: Professional

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/report')#
class losalamos.documents.Invoice(name='MyDocTeX', alias='TeX')[source]#

Bases: Professional

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/invoice')#
apply_config(config)[source]#

Rewrite partials/services-invoice.tex from a config dict.

Parameters:

config (dict or None) –

Dict with a services list and optional invoice settings. Keys:

  • services: list of dicts with description (str), quantity (float), and unit_price (float).

  • invoice.currency_symbol: LaTeX currency prefix (default r"\texteuro\;").

  • invoice.tax_rate: fraction applied to the subtotal (default 0.0).

Returns:

None

Return type:

None

class losalamos.documents.Receipt(name='MyDocTeX', alias='TeX')[source]#

Bases: Invoice

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/receipt')#
apply_config(config)[source]#

Rewrite partials/services-receipt.tex from a config dict.

Identical structure to Invoice.apply_config(), but appends a PAID row to the table.

Parameters:

config (dict or None) – Same structure as Invoice.apply_config().

Returns:

None

Return type:

None

class losalamos.documents.Proposal(name='MyDocTeX', alias='TeX')[source]#

Bases: Invoice

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/proposal')#
class losalamos.documents.Agreement(name='MyDocTeX', alias='TeX')[source]#

Bases: Proposal

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/agreement')#
class losalamos.documents.Contract(name='MyDocTeX', alias='TeX')[source]#

Bases: Agreement

VARIANT_TEMPLATE = PosixPath('/home/runner/work/losalamos/losalamos/src/losalamos/data/templates/documents/tex/professional/contract')#