CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pylatex

A comprehensive Python library for programmatically creating and compiling LaTeX documents and snippets.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

utilities.mddocs/

Utilities and Helper Functions

Utility functions for LaTeX escaping, file handling, and string manipulation to support document generation workflows. PyLaTeX provides essential utilities for handling special characters, file paths, text formatting, and temporary file management to ensure robust document generation.

Capabilities

String Escaping and Safety

Control how special characters are handled when converting Python strings to LaTeX.

class NoEscape(str):
    """
    String class that bypasses LaTeX character escaping.
    
    When NoEscape strings are combined:
    - NoEscape + NoEscape → NoEscape
    - NoEscape + str → str (regular string)
    
    Parameters:
    - string: str, content that should not be escaped
    """
    
def escape_latex(s):
    """
    Escape special LaTeX characters in a string.
    
    Parameters:
    - s: str, NoEscape, or convertible to string, input to escape
    
    Returns:
    - NoEscape: escaped string safe for LaTeX
    
    Special characters handled:
    - & → \\&
    - % → \\%
    - $ → \\$
    - # → \\#
    - _ → \\_
    - { → \\{
    - } → \\}
    - ~ → \\textasciitilde{}
    - ^ → \\^{}
    - \\ → \\textbackslash{}
    - newline → \\newline%
    - - → {-}
    - [ → {[}
    - ] → {]}
    """

Usage example:

from pylatex import Document, Section
from pylatex.utils import NoEscape, escape_latex

doc = Document()

with doc.create(Section('Text Handling')):
    # Automatic escaping (default behavior)
    unsafe_text = "Cost: $100, efficiency: 95% (issue #42)"
    doc.append(escape_latex(unsafe_text))
    # Produces: Cost: \$100, efficiency: 95\% (issue \#42)
    
    # Skip escaping with NoEscape
    latex_command = NoEscape(r'\textbf{Important}')
    doc.append(latex_command)
    # Produces: \textbf{Important}
    
    # Mixed content
    doc.append('Regular text with ')
    doc.append(NoEscape(r'\emph{emphasized}'))
    doc.append(' and special chars: ')
    doc.append(escape_latex('R&D costs ~$50K'))

File Path Handling

Utilities for managing file paths in LaTeX-compatible formats.

def fix_filename(path):
    """
    Fix file paths for LaTeX compatibility.
    
    Handles issues with:
    - Multiple dots in filenames
    - Special characters in paths
    - Platform-specific path separators
    - Tilde characters (~) in paths
    
    Parameters:
    - path: str, file path to fix
    
    Returns:
    - str: LaTeX-compatible file path
    
    Examples:
    - 'foo.bar.pdf' → '{foo.bar}.pdf'
    - '/path/file~name.pdf' → '\\detokenize{/path/file~name.pdf}'
    """

Usage example:

from pylatex import Document, Section
from pylatex.figure import Figure
from pylatex.utils import fix_filename

doc = Document()

with doc.create(Section('File Examples')):
    # Problematic filenames
    problematic_files = [
        'data.analysis.results.png',
        'user~documents/report.pdf',
        'file with spaces & symbols.jpg'
    ]
    
    for filename in problematic_files:
        safe_filename = fix_filename(filename)
        
        with doc.create(Figure()) as fig:
            fig.add_image(safe_filename)
            fig.add_caption(f'Fixed filename: {safe_filename}')

# Cross-platform path handling
import os
from pylatex.utils import fix_filename

if os.name == 'posix':
    # Unix/Linux/Mac paths
    image_path = '/home/user/data.set.1/results.png'
else:
    # Windows paths
    image_path = r'C:\Users\Name\data.set.1\results.png'

safe_path = fix_filename(image_path)

List and Collection Processing

Convert Python lists and collections to LaTeX-formatted strings.

def dumps_list(l, *, escape=True, token="%\n", mapper=None, as_content=True):
    """
    Convert a list to LaTeX string representation.
    
    Parameters:
    - l: list, collection to convert
    - escape: bool, whether to escape special LaTeX characters
    - token: str, separator between list items (default: newline)
    - mapper: callable or list, functions to apply to each item
    - as_content: bool, use dumps_as_content() for LatexObjects
    
    Returns:
    - NoEscape: formatted LaTeX string
    """

Usage example:

from pylatex import Document, Section, Command
from pylatex.utils import dumps_list, bold, italic

doc = Document()

with doc.create(Section('List Processing')):
    # Basic list conversion
    items = ['First item', 'Second item', 'Third item']
    formatted_list = dumps_list(items)
    doc.append(formatted_list)
    
    # With custom separator
    inline_items = ['alpha', 'beta', 'gamma']
    inline_list = dumps_list(inline_items, token=', ')
    doc.append('Greek letters: ')
    doc.append(inline_list)
    
    # With escaping for special characters
    special_items = ['Cost: $100', 'Efficiency: 95%', 'Issue #42']
    safe_list = dumps_list(special_items, escape=True)
    doc.append(safe_list)
    
    # With formatting mapper
    emphasis_items = ['Important', 'Critical', 'Urgent']
    emphasized = dumps_list(emphasis_items, mapper=bold)
    doc.append(emphasized)
    
    # Multiple mappers
    styled_items = ['Note 1', 'Note 2', 'Note 3']
    styled_list = dumps_list(styled_items, mapper=[bold, italic])
    doc.append(styled_list)

Text Formatting Utilities

Convenience functions for common text formatting operations.

def bold(s, *, escape=True):
    """
    Format text as bold using \\textbf{}.
    
    Parameters:
    - s: str, text to make bold
    - escape: bool, whether to escape special characters
    
    Returns:
    - NoEscape: bold-formatted LaTeX string
    """

def italic(s, *, escape=True):
    """
    Format text as italic using \\textit{}.
    
    Parameters:
    - s: str, text to make italic
    - escape: bool, whether to escape special characters
    
    Returns:
    - NoEscape: italic-formatted LaTeX string
    """

def verbatim(s, *, delimiter="|"):
    """
    Format text as verbatim using \\verb.
    
    Parameters:
    - s: str, text to format verbatim
    - delimiter: str, delimiter character (default: |)
    
    Returns:
    - NoEscape: verbatim-formatted LaTeX string
    """

Usage example:

from pylatex import Document, Section
from pylatex.utils import bold, italic, verbatim

doc = Document()

with doc.create(Section('Text Formatting')):
    # Basic formatting
    doc.append(bold('Important notice'))
    doc.append(' and ')
    doc.append(italic('emphasized text'))
    
    # With automatic escaping
    doc.append(bold('Cost: $1,000 (50% discount)', escape=True))
    
    # Verbatim code
    doc.append('Use the command ')
    doc.append(verbatim(r'\renewcommand{\baselinestretch}{1.5}'))
    doc.append(' to change line spacing.')
    
    # Custom verbatim delimiter
    doc.append('The expression ')
    doc.append(verbatim('x|y', delimiter='!'))
    doc.append(' uses a pipe character.')
    
    # Nested formatting
    complex_text = bold('Warning: ') + italic('System may be unstable')
    doc.append(complex_text)

Temporary File Management

Utilities for managing temporary files during document generation.

def make_temp_dir():
    """
    Create a temporary directory for document processing.
    
    Returns:
    - str: absolute path to temporary directory
    
    Note: Directory persists until rm_temp_dir() is called or program exits
    """

def rm_temp_dir():
    """
    Remove the temporary directory created by make_temp_dir().
    
    Cleans up all temporary files and directories created during processing.
    """

Usage example:

import os
from pylatex import Document
from pylatex.figure import Figure
from pylatex.utils import make_temp_dir, rm_temp_dir
import matplotlib.pyplot as plt

doc = Document()

# Create temporary directory for plots
temp_dir = make_temp_dir()

try:
    # Generate and save plots to temp directory
    plt.figure(figsize=(8, 6))
    plt.plot([1, 2, 3, 4], [1, 4, 2, 3])
    plt.title('Sample Plot')
    
    plot_path = os.path.join(temp_dir, 'sample_plot.png')
    plt.savefig(plot_path)
    
    # Use in document
    with doc.create(Figure()) as fig:
        fig.add_image(plot_path)
        fig.add_caption('Generated plot from temporary file')
    
    # Generate document
    doc.generate_pdf('document_with_temp_files')

finally:
    # Clean up temporary files
    rm_temp_dir()

Advanced Utilities

Custom String Processing

from pylatex import Document, Section
from pylatex.utils import NoEscape, escape_latex

def process_mixed_content(content_list):
    """Process list with mixed safe and unsafe content."""
    processed = []
    
    for item in content_list:
        if isinstance(item, dict):
            if item.get('safe', False):
                processed.append(NoEscape(item['text']))
            else:
                processed.append(escape_latex(item['text']))
        else:
            processed.append(escape_latex(str(item)))
    
    return processed

doc = Document()

mixed_content = [
    {'text': r'\textbf{Safe LaTeX}', 'safe': True},
    {'text': 'Unsafe: $100 & 50%', 'safe': False},
    {'text': r'\emph{Another safe command}', 'safe': True}
]

with doc.create(Section('Mixed Content')):
    for item in process_mixed_content(mixed_content):
        doc.append(item)
        doc.append(' ')

File Path Validation

import os
from pylatex.utils import fix_filename

def validate_and_fix_paths(file_paths):
    """Validate and fix multiple file paths."""
    fixed_paths = []
    
    for path in file_paths:
        if os.path.exists(path):
            fixed_path = fix_filename(path)
            fixed_paths.append(fixed_path)
        else:
            print(f"Warning: File not found: {path}")
    
    return fixed_paths

# Usage
image_files = [
    'results.data.png',
    'analysis/summary.report.pdf',
    'nonexistent.file.jpg'
]

safe_paths = validate_and_fix_paths(image_files)

Batch Text Processing

from pylatex import Document, Section
from pylatex.utils import dumps_list, bold, italic, escape_latex

def format_bibliography_items(references):
    """Format a list of references with mixed formatting."""
    formatted_refs = []
    
    for ref in references:
        # Author in bold, title in italic
        author = bold(ref['author'], escape=True)
        title = italic(ref['title'], escape=True)
        year = escape_latex(str(ref['year']))
        
        formatted_ref = f"{author}. {title}. {year}."
        formatted_refs.append(NoEscape(formatted_ref))
    
    return formatted_refs

doc = Document()

references = [
    {'author': 'Smith, J.', 'title': 'Advanced LaTeX Techniques', 'year': 2023},
    {'author': 'Doe, A. & Brown, B.', 'title': 'Document Processing Methods', 'year': 2022}
]

with doc.create(Section('References')):
    formatted_refs = format_bibliography_items(references)
    ref_list = dumps_list(formatted_refs, token='\n\n')
    doc.append(ref_list)

Content Sanitization

from pylatex.utils import escape_latex, NoEscape
import re

def sanitize_user_input(text, allowed_commands=None):
    """Sanitize user input while allowing specific LaTeX commands."""
    if allowed_commands is None:
        allowed_commands = []
    
    # First escape everything
    safe_text = escape_latex(text)
    
    # Then selectively unescape allowed commands
    for command in allowed_commands:
        pattern = re.escape(escape_latex(command))
        safe_text = safe_text.replace(pattern, command)
    
    return NoEscape(safe_text)

# Usage
user_text = r"Use \textbf{bold} text but avoid \dangerous{commands}"
allowed = [r'\textbf', r'\textit', r'\emph']

sanitized = sanitize_user_input(user_text, allowed)
# Result: "Use \textbf{bold} text but avoid \\dangerous\{commands\}"

Error Handling and Debugging

Safe Operations

from pylatex.utils import escape_latex, NoEscape

def safe_append(container, content, escape_by_default=True):
    """Safely append content with error handling."""
    try:
        if isinstance(content, str) and escape_by_default:
            container.append(escape_latex(content))
        else:
            container.append(content)
    except Exception as e:
        print(f"Error appending content: {e}")
        container.append(f"[Content error: {str(e)}]")

# Usage with error recovery
doc = Document()

contents = [
    "Normal text",
    NoEscape(r"\textbf{Bold}"),
    None,  # This will cause an error
    "More normal text"
]

for content in contents:
    safe_append(doc, content)

Debug Utilities

from pylatex.utils import dumps_list, escape_latex

def debug_latex_output(items, show_escaping=True):
    """Debug utility to show how items will be processed."""
    print("LaTeX Processing Debug:")
    print("-" * 40)
    
    for i, item in enumerate(items):
        print(f"Item {i}: {repr(item)}")
        
        if show_escaping and isinstance(item, str):
            escaped = escape_latex(item)
            print(f"  Escaped: {escaped}")
        
        try:
            if hasattr(item, 'dumps'):
                output = item.dumps()
            else:
                output = str(item)
            print(f"  Output: {output}")
        except Exception as e:
            print(f"  Error: {e}")
        
        print()

# Usage for debugging
debug_items = [
    "Normal text with $pecial char$",
    NoEscape(r"\textbf{Bold command}"),
    42,
    ["nested", "list"]
]

debug_latex_output(debug_items)

Best Practices

Consistent Escaping Strategy

from pylatex import Document
from pylatex.utils import NoEscape, escape_latex

# Define clear policies for different content types
def add_user_content(doc, content):
    """Always escape user-provided content."""
    doc.append(escape_latex(content))

def add_template_content(doc, content):
    """Template content is pre-verified as safe."""
    doc.append(NoEscape(content))

def add_mixed_content(doc, content, is_safe=False):
    """Mixed content with explicit safety flag."""
    if is_safe:
        doc.append(NoEscape(content))
    else:
        doc.append(escape_latex(content))

Resource Management

import contextlib
from pylatex.utils import make_temp_dir, rm_temp_dir

@contextlib.contextmanager
def temp_directory():
    """Context manager for temporary directory handling."""
    temp_dir = make_temp_dir()
    try:
        yield temp_dir
    finally:
        rm_temp_dir()

# Usage
with temp_directory() as temp_dir:
    # Use temp_dir for file operations
    # Cleanup happens automatically
    pass

The utilities system in PyLaTeX provides essential tools for safe and robust document generation, handling the complexities of LaTeX character escaping, file path management, and content processing while maintaining code clarity and preventing common LaTeX compilation errors.

Install with Tessl CLI

npx tessl i tessl/pypi-pylatex

docs

base-classes.md

configuration.md

document.md

figures.md

index.md

layout.md

lists.md

math.md

quantities.md

references.md

sectioning.md

tables.md

text-formatting.md

tikz.md

utilities.md

tile.json