Core¶
Configuration models used by the LaTeX renderer.
CommonConfig
build_dir(Path | None)- Base directory for LaTeX artifacts. Provide an absolute or project-relative path to override the default export root that books inherit when they do not specify one.
mermaid_config(Path | None)- Path to a Mermaid configuration file. Point to a
.jsonor.mermaiddocument to customise diagram rendering. project_dir(Path | None)- MkDocs project root used to resolve relative paths when copying additional assets.
- BCP 47 language code forwarded to LaTeX for hyphenation, translations, and
- metadata localisation.
legacy_latex_accents(bool)- When
True, escape accented characters, ligatures, and typographic punctuation using legacy LaTeX macros. WhenFalse, keep Unicode glyphs compatible with LuaLaTeX/XeLaTeX (default). language(str | None)- BCP 47 language code forwarded to LaTeX for hyphenation, translations, and metadata localisation.
CoverConfig
name(str)- Identifier of the cover template to apply. The value must match a template declared in the cover bundle.
color(str | None)- Primary colour override applied by the cover template.
logo(str | None)- Project-relative path to a logo asset displayed on the cover.
BookConfig
root(str | None)- Navigation entry treated as the starting point for the book. Use it when the root differs from the first MkDocs page.
title(str | None)- Title displayed on the cover and in output metadata. Falls back to
site_namewhen omitted. subtitle(str | None)- Optional subtitle appended to the cover and metadata.
author(str | None)- Primary author string rendered in the book metadata.
year(int | None)- Publication year to freeze in the output when
site_dateis not supplied. email(str | None)- Contact address printed in the credits.
folder(Path | None)- Output directory for the rendered book. Defaults to a slug of the title when not provided.
frontmatter(list[str])- MkDocs page titles moved before the main matter.
backmatter(list[str])- MkDocs page titles grouped into the appendices.
base_level(int)- Heading offset applied to align section numbering with the template expectations.
copy_files(dict[str, str])- Mapping of glob patterns to destination paths for copying additional assets alongside the book.
index_is_foreword(bool)- Treat the
indexpage as a foreword, typically removing numbering. drop_title_index(bool)- Suppress the
indexpage heading when it acts as a foreword. cover(CoverConfig)- Nested configuration controlling the book cover.
LaTeXConfig
enabled(bool)- Toggle LaTeX generation without discarding configuration.
books(list[BookConfig])- Collection of books to produce, inheriting defaults from
CommonConfig. clean_assets(bool)- Remove stale assets from
build_dirto avoid accumulating unused files.
BookConfig ¶
CommonConfig ¶
Bases: BaseModel
Common configuration propagated to each book.
CoverConfig ¶
Bases: BaseModel
Metadata used to render book covers.
LaTeXConfig ¶
Bases: CommonConfig
Configuration for LaTeX taken from mkdocs.yml.
propagate ¶
propagate() -> LaTeXConfig
Propagate common values to nested book configurations.
Source code in src/texsmith/core/config.py
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | |
Rendering context primitives shared across the LaTeX pipeline.
AssetRegistry
dataclass
¶
AssetRegistry(
output_root: Path,
assets_map: MutableMapping[str, Path] = dict(),
copy_assets: bool = True,
)
Centralised registry for rendered assets.
get ¶
get(key: str) -> Path
Retrieve a previously registered artefact.
Source code in src/texsmith/core/context.py
124 125 126 127 128 129 | |
items ¶
items() -> Iterable[tuple[str, Path]]
Iterate over registered assets yielding key/path pairs.
Source code in src/texsmith/core/context.py
131 132 133 | |
latex_path ¶
latex_path(path: Path | str) -> str
Return a LaTeX-friendly path for an artefact.
Source code in src/texsmith/core/context.py
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | |
lookup ¶
lookup(key: str) -> Path | None
Return a previously registered artefact when available.
Source code in src/texsmith/core/context.py
119 120 121 122 | |
register ¶
register(key: str, artefact: Path | str) -> Path
Register a generated artefact and return its resolved path.
Source code in src/texsmith/core/context.py
111 112 113 114 115 116 117 | |
DocumentState
dataclass
¶
DocumentState(
abbreviations: dict[str, str] = dict(),
acronym_keys: dict[str, str] = dict(),
acronyms: dict[str, tuple[str, str]] = dict(),
acronym_entry_groups: dict[str, str] = dict(),
acronym_groups: list[tuple[str, str]] = list(),
has_index_entries: bool = False,
requires_shell_escape: bool = False,
bibliography: dict[str, dict[str, Any]] = dict(),
citations: list[str] = list(),
pygments_styles: dict[str, str] = dict(),
script_usage: list[dict[str, Any]] = list(),
fallback_summary: list[dict[str, Any]] = list(),
fonts_scanned: bool = False,
callouts_used: bool = False,
required_fragments: set[str] = set(),
required_packages: list[str] = list(),
index_registries: list[str] = list(),
contract_path: bool = False,
)
In-memory state accumulated while rendering a document.
record_citation ¶
record_citation(key: str) -> None
Track citation keys used throughout the document.
Source code in src/texsmith/core/context.py
95 96 97 98 99 100 | |
remember_abbreviation ¶
remember_abbreviation(
term: str,
description: str,
*,
emitter: DiagnosticEmitter | None = None,
) -> str
Track abbreviation definitions while ensuring consistency.
Source code in src/texsmith/core/context.py
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
RenderContext
dataclass
¶
RenderContext(
config: BookConfig,
document: Any,
assets: AssetRegistry,
state: DocumentState = DocumentState(),
runtime: dict[str, Any] = dict(),
)
Shared context passed to the asset helpers during a conversion.
Context objects used during document conversion.
ConversionContext
dataclass
¶
ConversionContext(
document: Document,
request: ConversionRequest,
output_dir: Path,
language: str,
generation: GenerationStrategy,
template_runtime: TemplateRuntime | None = None,
template_overrides: dict[str, Any] = dict(),
slot_requests: dict[str, str] = dict(),
bibliography_collection: BibliographyCollection
| None = None,
bibliography_map: dict[str, dict[str, Any]] = dict(),
config: BookConfig | None = None,
template_binding: TemplateBinding | None = None,
resolution: ResolutionChain | None = None,
)
Per-document resolved state for the conversion pipeline.
The context is built in two successive phases:
- :func:
resolve_conversion_context(in :mod:.conversion.execution) fills the inputs derived from the document, request and front matter. At this point :attr:configand :attr:template_bindingare stillNonebecause no template has been chosen yet. - :func:
bind_template(in :mod:.conversion.templates) resolves the selected template and populates the binding-dependent fields.
Per-slot render flags (slot_options) are read from
document.slot_options on demand rather than copied here, to avoid
duplicating state that the :class:Document already owns.
GenerationStrategy
dataclass
¶
GenerationStrategy(
copy_assets: bool = True,
convert_assets: bool = False,
hash_assets: bool = False,
)
Rendering strategy toggles shared across conversion workflows.
from_request
classmethod
¶
from_request(
request: ConversionRequest,
) -> GenerationStrategy
The asset flags of a request, as every backend must read them.
Source code in src/texsmith/core/conversion_contexts.py
29 30 31 32 33 34 35 36 | |
Shared conversion primitives exposed by the core package.
ConversionRequest
dataclass
¶
ConversionRequest(
documents: Sequence[Path] = tuple(),
bibliography_files: Sequence[Path] = list(),
front_matter: Mapping[str, Any] | None = None,
front_matter_paths: Sequence[Path] = tuple(),
slot_assignments: Mapping[
Path, Sequence[SlotAssignment]
] = dict(),
include_paths: Sequence[Path] = tuple(),
default_include_paths: Sequence[Path] = tuple(),
root_dir: Path | None = None,
base_level: int = 0,
strip_heading_all: bool = False,
strip_heading_first_document: bool = False,
promote_title: bool = True,
suppress_title: bool = False,
numbered: bool = True,
template: str | None = None,
render_dir: Path | None = None,
template_options: Mapping[str, Any] = dict(),
embed_documents: bool = False,
enable_fragments: Sequence[str] = tuple(),
disable_fragments: Sequence[str] = tuple(),
copy_assets: bool = True,
convert_assets: bool = False,
hash_assets: bool = False,
manifest: bool = False,
persist_debug_ir: bool = False,
language: str | None = None,
http_user_agent: str | None = None,
legacy_latex_accents: bool = False,
diagrams_backend: str | None = None,
emitter: DiagnosticEmitter | None = None,
)
Immutable description of conversion inputs and engine settings.
Frozen, so the docstring holds: a caller that needs a variation asks for
one with :meth:replace, which deep-copies every field but the emitter.
replace ¶
replace(**changes: Any) -> ConversionRequest
A deep copy of this request with changes applied.
The emitter is shared, not copied: it collects the run's diagnostics and a copy would collect nothing.
Source code in src/texsmith/core/conversion/models.py
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
SlotAssignment
dataclass
¶
SlotAssignment(
slot: str, selector: str | None, include_document: bool
)
Directive mapping a document onto a template slot.
SlotOptions
dataclass
¶
SlotOptions(flatten: bool = False)
Per-slot rendering flags parsed from front matter.
UnsupportedInputError ¶
Bases: Exception
Raised when a CLI input argument cannot be processed.
coerce_slot_selector ¶
coerce_slot_selector(payload: Any) -> str | None
Normalise a selector definition coming from front matter.
Source code in src/texsmith/core/conversion/inputs.py
35 36 37 38 39 40 41 42 43 44 45 | |
extract_front_matter_slots ¶
extract_front_matter_slots(
front_matter: Mapping[str, Any],
) -> tuple[dict[str, str], dict[str, SlotOptions]]
Return front-matter slot selectors alongside their per-slot options.
Source code in src/texsmith/core/conversion/inputs.py
109 110 111 112 113 114 | |
parse_slot_mapping ¶
parse_slot_mapping(
raw: Any,
) -> tuple[dict[str, str], dict[str, SlotOptions]]
Parse slot mappings together with their per-slot options.
Accepts the three front-matter shapes {name: selector},
[{target/slot: ..., label: ...}] and the bare "name:selector"
string form. Returns a (selectors, options) tuple where options
only contains entries whose values differ from the SlotOptions
defaults, so callers can ignore it when they don't care.
Source code in src/texsmith/core/conversion/inputs.py
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
Diagnostics emitters¶
texsmith.diagnostics defines the DiagnosticEmitter protocol plus a few
stock implementations. Pass any emitter into ConversionService,
convert_documents, or TemplateSession to see the findings as they happen.
An emitter is a presenter. It owns a DiagnosticSink, and the sink does
the collecting: it deduplicates, it answers strict_failed(), and it owns the
FileTable every document of the run registers in — which is why the emitter
you parse with must be the emitter you render with, or a span will name the
wrong file.
| Emitter | Description | Typical usage |
|---|---|---|
CliEmitter (texsmith.ui.cli.diagnostics) |
Rich-powered emitter used by the Typer CLI. Respects -v and --debug, paints warnings as panels, and streams structured events to the diagnostics sidebar. |
Default when running texsmith. Import it in automation scripts when you want human-friendly output. |
LoggingEmitter |
Renders each record as the path:line:col: severity code: message line and logs it at the matching level. |
Daemons, notebooks, or services that rely on existing logging policy. |
NullEmitter |
Shows nothing, and still records: the run's diagnostics stay readable on emitter.sink and on each Document. |
Unit tests, benchmarking, and any caller that reads the findings afterwards. |
To write your own, subclass SinkEmitter and implement render(diagnostic,
cause) and event(name, payload); everything else is the sink's. Emitters
expose a debug_enabled flag so downstream handlers can decide whether to
include stack traces or expensive state dumps.
Diagnostics shared by TeXSmith's Python passes and the tmark bindings.
See specs/migration/python-ir-and-passes.md §6 and docs/guide/diagnostics.md.
Diagnostic
dataclass
¶
Diagnostic(
code: str,
severity: Severity,
span: Span,
message: str,
fix: Fix | None = None,
related: tuple[tuple[Span, str], ...] = (),
origin: str = "texsmith",
)
One finding, from a Python pass or from the tmark bindings.
to_json ¶
to_json() -> dict[str, Any]
Tmark's JSON shape plus origin; fix and related only when set.
Source code in src/texsmith/diagnostics/model.py
105 106 107 108 109 110 111 112 113 114 115 116 117 118 | |
DiagnosticEmitter ¶
Bases: Protocol
What a stage may ask of the object presenting its findings.
sink is the run's collector and, through it, the run's
:class:~texsmith.diagnostics.FileTable. It is part of the interface
because the file a span names is decided by the table a record is recorded
against: a caller that could not reach it had to number its own files from
zero, and two documents then carried the same span.file.
DiagnosticSink ¶
DiagnosticSink(
files: FileTable | None = None,
*,
on_emit: OnEmit | None = None,
containers: Iterable[str] = (),
)
Collects diagnostics for one run.
files is the table spans render against; passes and the loader share
it with the sink so a record emitted in an included file prints that
file's name.
Source code in src/texsmith/diagnostics/sink.py
57 58 59 60 61 62 63 64 65 66 67 68 69 | |
declared_containers
property
¶
declared_containers: frozenset[str]
The container names the active template reads (containers).
add ¶
add(
diagnostic: Diagnostic,
*,
cause: BaseException | None = None,
) -> bool
Record diagnostic; False when it is a duplicate or a declared container.
Source code in src/texsmith/diagnostics/sink.py
89 90 91 92 93 94 95 96 97 98 99 | |
declare_containers ¶
declare_containers(names: Iterable[str]) -> None
Declare container names a template's passes consume.
solution is a construct of the template, not of the language:
tmark reports it as container-unknown when it parses the document,
long before the pass that rewrites it runs, and a pass cannot take a
record back. Declaring the name here drops that record where every
stage's findings are collected, so it is absent from the terminal,
from the counts and from --diagnostics-json — and every other name
still warns.
Source code in src/texsmith/diagnostics/sink.py
76 77 78 79 80 81 82 83 84 85 86 87 | |
emit ¶
emit(
code: str,
span: Span,
message: str,
*,
severity: Severity | None = None,
fix: Fix | None = None,
related: Iterable[tuple[Span, str]] = (),
) -> Diagnostic
Build and record a TeXSmith diagnostic, severity defaulting from the code table.
Source code in src/texsmith/diagnostics/sink.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | |
extend_from_tmark ¶
extend_from_tmark(
records: Iterable[Mapping[str, Any]],
) -> int
Record the diagnostics of a tmark result; returns how many were new.
Source code in src/texsmith/diagnostics/sink.py
123 124 125 | |
sorted ¶
sorted() -> list[Diagnostic]
The records grouped per file and ordered by position.
Source code in src/texsmith/diagnostics/sink.py
138 139 140 | |
strict_failed ¶
strict_failed() -> bool
Whether any warning or error was recorded (--strict fails the run).
Source code in src/texsmith/diagnostics/sink.py
127 128 129 | |
to_json ¶
to_json() -> list[dict[str, Any]]
The records for editors and CI: tmark's shape plus the printed location.
Source code in src/texsmith/diagnostics/sink.py
142 143 144 145 146 147 148 149 150 151 152 | |
worst ¶
worst() -> Severity | None
The highest severity recorded, None when the sink is empty.
Source code in src/texsmith/diagnostics/sink.py
131 132 133 | |
FileTable ¶
FileTable()
The files of one build, addressed by :class:FileId.
Paths are stored as given, without symlink resolution, so TeXSmith and tmark agree on the name a diagnostic prints. A file registered with an empty text (HTML input, a path only known by name) renders without a line and column.
Source code in src/texsmith/diagnostics/files.py
133 134 | |
add ¶
add(path: PurePath | str, text: str) -> FileId
Register a file and return its id (the next free one).
A PurePath already given (a PurePosixPath display name, say)
is kept as is; only a plain string is turned into a native Path,
as before. This is what lets a caller opt into a posix-stable name
without changing what every other caller gets.
Source code in src/texsmith/diagnostics/files.py
136 137 138 139 140 141 142 143 144 145 146 | |
find ¶
find(path: PurePath | str) -> FileId | None
The id of the first file registered under path, if any.
Source code in src/texsmith/diagnostics/files.py
148 149 150 151 152 153 154 | |
line_index ¶
line_index(file_id: int) -> LineIndex
The (lazily built, cached) index of a file.
Source code in src/texsmith/diagnostics/files.py
167 168 169 | |
Fix
dataclass
¶
Fix(span: Span, replacement: str)
A text edit an editor can apply: replace span with replacement.
LineCol
dataclass
¶
LineCol(line: int, col: int)
A printed position: 1-based line, 1-based byte column.
LineIndex ¶
LineIndex(text: str)
Maps byte offsets of a UTF-8 text to lines and columns and back.
Line endings are \n, \r\n and a lone \r (CommonMark). Offsets
past the end clamp to the end; an offset inside a multibyte character snaps
to that character's start, so a column never points between two bytes of
one glyph.
Source code in src/texsmith/diagnostics/files.py
44 45 46 47 48 49 50 51 52 53 54 | |
__len__ ¶
__len__() -> int
Total length in bytes.
Source code in src/texsmith/diagnostics/files.py
56 57 58 | |
line_col ¶
line_col(offset: int) -> LineCol
The printed position of a byte offset.
Source code in src/texsmith/diagnostics/files.py
86 87 88 89 90 | |
line_end ¶
line_end(line: int) -> int | None
Byte offset of the terminator of the 1-based line (the end of the text for the last one).
Source code in src/texsmith/diagnostics/files.py
72 73 74 75 76 77 | |
line_start ¶
line_start(line: int) -> int | None
Byte offset where the 1-based line starts, None past the text.
Source code in src/texsmith/diagnostics/files.py
65 66 67 68 69 70 | |
offset ¶
offset(position: LineCol) -> int
Byte offset of a printed position.
A column past the end of the line clamps to the line's end, before its terminator; a line past the text clamps to the end of the text.
Source code in src/texsmith/diagnostics/files.py
92 93 94 95 96 97 98 99 100 101 102 | |
snap ¶
snap(offset: int) -> int
Clamp offset to the text and move it back to a character boundary.
Source code in src/texsmith/diagnostics/files.py
79 80 81 82 83 84 | |
LoggingEmitter ¶
LoggingEmitter(
*,
logger_obj: Logger | None = None,
debug_enabled: bool = False,
files: FileTable | None = None,
)
Bases: SinkEmitter
Emitter that forwards diagnostics to the standard logging module.
Source code in src/texsmith/diagnostics/emitters.py
89 90 91 92 93 94 95 96 97 | |
NullEmitter ¶
NullEmitter(
*,
debug_enabled: bool = False,
files: FileTable | None = None,
)
Bases: SinkEmitter
Emitter that shows nothing.
It still collects: silence is a rendering choice, not a reason to lose the
records. Document.diagnostics is filled from this sink and the library
caller reads them after the run, which is what docs/api/high-level.md
describes.
Source code in src/texsmith/diagnostics/emitters.py
60 61 62 | |
Severity ¶
Bases: str, Enum
tmark's four severities, ordered from the mildest to the worst.
The four comparisons are spelled out: str already defines them
(alphabetically, which puts info above error), so a partial
definition would be silently completed by the string ones.
SinkEmitter ¶
SinkEmitter(
*,
debug_enabled: bool = False,
files: FileTable | None = None,
)
Base of the emitters that collect: owns the sink, renders each new record.
Subclasses implement :meth:render (and :meth:event); everything else is
the sink's. Every record goes through :meth:diagnostic, so a subclass that
filters there — the render command's --deprecated level — sees the whole
stream.
Source code in src/texsmith/diagnostics/emitters.py
60 61 62 | |
debug_enabled ¶
debug_enabled(emitter: DiagnosticEmitter | None) -> bool
Return whether debug mode is active for the given emitter.
Source code in src/texsmith/diagnostics/emitters.py
191 192 193 | |
default_severity ¶
default_severity(code: str) -> Severity
The severity a code carries when the emitter names none.
A code absent from the table (a tmark id not listed here) is a warning: tmark records arrive with their own severity anyway.
Source code in src/texsmith/diagnostics/codes.py
191 192 193 194 195 196 197 198 | |
emit_diagnostic ¶
emit_diagnostic(
emitter: DiagnosticEmitter | None,
code: str,
message: str,
*,
span: Span = NO_SPAN,
severity: Severity | None = None,
exc: BaseException | None = None,
) -> None
Record a coded finding through emitter.
The counterpart of :meth:DiagnosticSink.emit for the stages that hold an
emitter rather than a :class:~texsmith.passes.PassContext. It goes
through :meth:DiagnosticEmitter.diagnostic rather than reaching the sink
directly, so an emitter that filters sees these records too; the severity
defaults to the one the code table gives the code.
Source code in src/texsmith/diagnostics/emitters.py
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | |
ensure_emitter ¶
ensure_emitter(
emitter: DiagnosticEmitter | None,
) -> DiagnosticEmitter
Return a usable emitter, defaulting to the null implementation.
Source code in src/texsmith/diagnostics/emitters.py
186 187 188 | |
format_diagnostic ¶
format_diagnostic(
diagnostic: Diagnostic,
files: FileTable,
*,
verbosity: int = 0,
) -> str
The tmark-cli line; the fix and the related locations indented at -v.
A multi-line message keeps its first line on the header and indents the
rest, so the detail an emitter appends (-v exception notes) stays
attached to its record.
Source code in src/texsmith/diagnostics/sink.py
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | |
format_event_message ¶
format_event_message(
name: str, payload: Mapping[str, Any]
) -> str | None
Return a human-friendly summary for selected diagnostic events.
Source code in src/texsmith/diagnostics/emitters.py
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | |
from_tmark ¶
from_tmark(record: Mapping[str, Any]) -> Diagnostic
Build a :class:Diagnostic from a record returned by the tmark bindings.
The record is the serde JSON of tmark_ir::Diagnostic: fix and
related are absent when empty. origin is forced to "tmark".
Source code in src/texsmith/diagnostics/model.py
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | |
locate ¶
locate(
span: Span, files: FileTable
) -> tuple[Any, int | None, int | None] | None
(path, line, col) of a span; line and col are None without a text.
NO_SPAN names the main document without a position; an unknown file
yields None and the record prints without a path.
Source code in src/texsmith/diagnostics/sink.py
165 166 167 168 169 170 171 172 173 174 175 176 177 | |
record_event ¶
record_event(
emitter: DiagnosticEmitter | None,
event: str,
payload: Mapping[str, Any],
) -> None
Forward a structured diagnostic event.
Source code in src/texsmith/diagnostics/emitters.py
196 197 198 199 200 201 202 | |
summary_line ¶
summary_line(counts: Mapping[Severity, int]) -> str
N errors, M warnings — singular when it applies.
Source code in src/texsmith/diagnostics/sink.py
213 214 215 216 217 218 219 220 | |
unknown_container ¶
unknown_container(diagnostic: Diagnostic) -> str | None
The container name a container-unknown record names, else None.
Source code in src/texsmith/diagnostics/sink.py
39 40 41 42 43 44 | |
Custom exception hierarchy for the LaTeX rendering pipeline.
AssetMissingError ¶
Bases: LatexRenderingError
Raised when an expected asset cannot be located or generated.
ConversionError ¶
Bases: Exception
Raised when a conversion fails and cannot recover.
InvalidNodeError ¶
Bases: LatexRenderingError
Raised when a handler receives an unexpected DOM node shape.
LatexRenderingError ¶
Bases: RuntimeError
Base exception for LaTeX rendering failures.
TransformerExecutionError ¶
Bases: LatexRenderingError
Raised when an external converter fails to execute properly.
exception_hint ¶
exception_hint(exc: BaseException) -> str | None
Return the most specific message available for an exception chain.
Source code in src/texsmith/core/exceptions.py
44 45 46 47 | |
exception_messages ¶
exception_messages(exc: BaseException) -> list[str]
Return the collected message chain for an exception and its causes.
Source code in src/texsmith/core/exceptions.py
28 29 30 31 32 33 34 35 36 37 38 39 40 41 | |
format_rendering_error ¶
format_rendering_error(error: LatexRenderingError) -> str
Format a human-readable rendering failure summary.
Source code in src/texsmith/core/exceptions.py
50 51 52 53 54 55 | |
format_user_friendly_render_error ¶
format_user_friendly_render_error(
error: LatexRenderingError,
) -> str
Return a concise rendering failure summary suitable for end users.
Source code in src/texsmith/core/exceptions.py
58 59 60 61 62 63 64 65 66 67 | |
raise_conversion_error ¶
raise_conversion_error(
emitter: DiagnosticEmitter | None,
message: str,
exc: Exception,
) -> None
Record the failure that stops the run, then raise it.
Lives here rather than with the emitters: it builds a
:class:ConversionError, and the diagnostics package must not depend on
the conversion one.
Source code in src/texsmith/core/exceptions.py
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | |
LaTeX escaping — single source of truth lives in the LaTeX writer.
Escaping is a backend responsibility, so the canonical implementation moved to
:mod:texsmith.writers.latex.escaper. This module re-exports it so existing
importers (templates, fonts, extensions, legacy handler helpers) keep a stable
import path without duplicating the logic.
escape_latex_chars ¶
escape_latex_chars(
text: str, *, legacy_accents: bool = False
) -> str
Escape LaTeX special characters leveraging pylatexenc.
Source code in src/texsmith/writers/latex/escaper.py
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | |
Abstractions for invoking Docker containers safely.
DockerLimits
dataclass
¶
DockerLimits(
cpus: float | int | None = None,
memory: str | None = None,
pids_limit: int | None = None,
)
Runtime constraints for Docker containers.
DockerRunRequest
dataclass
¶
DockerRunRequest(
image: str,
args: Sequence[str] = tuple(),
mounts: Sequence[VolumeMount] = tuple(),
environment: Mapping[str, str] = dict(),
workdir: str | None = None,
user: str | None = None,
use_host_user: bool = True,
remove: bool = True,
limits: DockerLimits | None = None,
network: str | None = None,
extra_args: Sequence[str] = tuple(),
)
Full request payload for a Docker execution.
DockerRunner ¶
DockerRunner(executable: str | None = None)
Utility class encapsulating Docker invocations.
Source code in src/texsmith/adapters/docker.py
53 54 55 | |
is_available ¶
is_available() -> bool
Return True when Docker can be located.
Source code in src/texsmith/adapters/docker.py
57 58 59 60 61 62 | |
reset ¶
reset() -> None
Clear cached executable lookup results.
Source code in src/texsmith/adapters/docker.py
64 65 66 | |
run ¶
run(
request: DockerRunRequest,
*,
capture_output: bool = True,
text: bool = True,
) -> subprocess.CompletedProcess[str]
Execute Docker with the supplied request.
Source code in src/texsmith/adapters/docker.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | |
VolumeMount
dataclass
¶
VolumeMount(
source: Path | str, target: str, read_only: bool = False
)
Bind mount configuration.
is_docker_available ¶
is_docker_available() -> bool
Check if Docker can be executed.
Source code in src/texsmith/adapters/docker.py
209 210 211 | |
run_container ¶
run_container(
image: str,
args: Sequence[str] = (),
*,
mounts: Sequence[VolumeMount] = (),
environment: Mapping[str, str] | None = None,
workdir: str | None = None,
user: str | None = None,
use_host_user: bool = True,
limits: DockerLimits | None = None,
network: str | None = None,
remove: bool = True,
extra_args: Sequence[str] = (),
capture_output: bool = True,
text: bool = True,
) -> subprocess.CompletedProcess[str]
Execute Docker using the shared runner.
Source code in src/texsmith/adapters/docker.py
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | |