Python API
Everything the command line does is available from Python. The library never prints or exits: results are returned, and failures are raised.
Example
from dataclasses import replace
from word2html import Limits, UnsafeDocumentError, WordToHtmlError, convert_to_html
limits = replace(Limits(), timeout=30, max_memory=512 * 1024 * 1024)
try:
result = convert_to_html("report.docx", strict=True, limits=limits)
except UnsafeDocumentError as exc:
print("refused:", exc)
for finding in exc.findings:
print(" -", finding.kind, finding.message)
except (WordToHtmlError, FileNotFoundError) as exc:
print("failed:", exc)
else:
print("wrote", result.output_path)
for finding in result.warnings:
print(" -", finding.kind, finding.message)
convert_to_html
convert_to_html(
filename: str | os.PathLike[str],
*,
strict: bool = False,
limits: Limits | None = None,
) -> ConversionResult
Converts a document and writes the HTML next to it, replacing any existing file with that name.
| Argument | Description |
|---|---|
filename | Path to the .docx file. |
strict | Raise UnsafeDocumentError for unsafe links or hidden text, instead of returning them as warnings. |
limits | Resource limits, or None for the defaults. |
ConversionResult
| Attribute | Type | Description |
|---|---|---|
output_path | pathlib.Path | The HTML file that was written. |
warnings | tuple[Finding, ...] | Things to know about the document. Empty if there are none. |
Limits
A frozen dataclass. Use dataclasses.replace() to change individual values.
| Field | Default | Description |
|---|---|---|
max_file_size | 200 MiB | Largest input file, in bytes. |
max_total_uncompressed | 1 GiB | Largest total uncompressed size, in bytes. |
max_xml_part_size | 64 MiB | Largest single XML part, in bytes. |
max_zip_entries | 10,000 | Most files in the archive. |
max_xml_depth | 256 | Deepest XML nesting. |
max_memory | 2 GiB | pandoc memory limit, in bytes. |
timeout | 120.0 | pandoc time limit, in seconds. |
Finding and FindingKind
A Finding has a kind and a message. Messages are already escaped, so they're safe to print to a terminal.
FindingKind | Value | Meaning | Handling |
|---|---|---|---|
UNSAFE_LINK | unsafe-link | A link with a scheme that isn't allowed | Warning; refused with strict=True |
HIDDEN_TEXT | hidden-text | Text hidden in Word that'll be visible | Warning; refused with strict=True |
ACTIVE_CONTENT | active-content | Content that could run in a browser | Always refused |
LINKED_IMAGE | linked-image | An image that isn't stored in the document | Warning only |
PANDOC | pandoc | A message from pandoc itself | Warning only |
Check for a specific kind like this:
from word2html import FindingKind, convert_to_html
result = convert_to_html("report.docx")
has_hidden_text = any(f.kind is FindingKind.HIDDEN_TEXT for f in result.warnings)
Exceptions
Everything word2html raises deliberately derives from WordToHtmlError, except FileNotFoundError for a missing input. If any of these is raised, no output was written.
| Exception | Raised when |
|---|---|
WordToHtmlError | The base class. Catch this for any deliberate failure. |
InvalidDocumentError | The input isn't a usable .docx. Also a ValueError. |
ResourceLimitError | The input, or converting it, exceeded a limit. |
UnsafeDocumentError | The document was refused. Its findings attribute says why. |
PandocNotFoundError | pandoc isn't installed or isn't on PATH. |
PandocError | pandoc is too old, or failed for a reason other than the document. |
OutputError | The HTML couldn't be written. |
FileNotFoundError | The input doesn't exist. This is Python's built-in exception. |
Version
import word2html
print(word2html.__version__)
Threads and processes
Each call starts its own pandoc process and keeps no shared state, so separate documents can be converted at the same time. Two calls converting the same document will both write the same output path, and whichever finishes last wins.