or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

base-classes.mdconfiguration.mddocument.mdfigures.mdindex.mdlayout.mdlists.mdmath.mdquantities.mdreferences.mdsectioning.mdtables.mdtext-formatting.mdtikz.mdutilities.md

utilities.mddocs/

0

# Utilities and Helper Functions

1

2

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.

3

4

## Capabilities

5

6

### String Escaping and Safety

7

8

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

9

10

```python { .api }

11

class NoEscape(str):

12

"""

13

String class that bypasses LaTeX character escaping.

14

15

When NoEscape strings are combined:

16

- NoEscape + NoEscape → NoEscape

17

- NoEscape + str → str (regular string)

18

19

Parameters:

20

- string: str, content that should not be escaped

21

"""

22

23

def escape_latex(s):

24

"""

25

Escape special LaTeX characters in a string.

26

27

Parameters:

28

- s: str, NoEscape, or convertible to string, input to escape

29

30

Returns:

31

- NoEscape: escaped string safe for LaTeX

32

33

Special characters handled:

34

- & → \\&

35

- % → \\%

36

- $ → \\$

37

- # → \\#

38

- _ → \\_

39

- { → \\{

40

- } → \\}

41

- ~ → \\textasciitilde{}

42

- ^ → \\^{}

43

- \\ → \\textbackslash{}

44

- newline → \\newline%

45

- - → {-}

46

- [ → {[}

47

- ] → {]}

48

"""

49

```

50

51

Usage example:

52

53

```python

54

from pylatex import Document, Section

55

from pylatex.utils import NoEscape, escape_latex

56

57

doc = Document()

58

59

with doc.create(Section('Text Handling')):

60

# Automatic escaping (default behavior)

61

unsafe_text = "Cost: $100, efficiency: 95% (issue #42)"

62

doc.append(escape_latex(unsafe_text))

63

# Produces: Cost: \$100, efficiency: 95\% (issue \#42)

64

65

# Skip escaping with NoEscape

66

latex_command = NoEscape(r'\textbf{Important}')

67

doc.append(latex_command)

68

# Produces: \textbf{Important}

69

70

# Mixed content

71

doc.append('Regular text with ')

72

doc.append(NoEscape(r'\emph{emphasized}'))

73

doc.append(' and special chars: ')

74

doc.append(escape_latex('R&D costs ~$50K'))

75

```

76

77

### File Path Handling

78

79

Utilities for managing file paths in LaTeX-compatible formats.

80

81

```python { .api }

82

def fix_filename(path):

83

"""

84

Fix file paths for LaTeX compatibility.

85

86

Handles issues with:

87

- Multiple dots in filenames

88

- Special characters in paths

89

- Platform-specific path separators

90

- Tilde characters (~) in paths

91

92

Parameters:

93

- path: str, file path to fix

94

95

Returns:

96

- str: LaTeX-compatible file path

97

98

Examples:

99

- 'foo.bar.pdf' → '{foo.bar}.pdf'

100

- '/path/file~name.pdf' → '\\detokenize{/path/file~name.pdf}'

101

"""

102

```

103

104

Usage example:

105

106

```python

107

from pylatex import Document, Section

108

from pylatex.figure import Figure

109

from pylatex.utils import fix_filename

110

111

doc = Document()

112

113

with doc.create(Section('File Examples')):

114

# Problematic filenames

115

problematic_files = [

116

'data.analysis.results.png',

117

'user~documents/report.pdf',

118

'file with spaces & symbols.jpg'

119

]

120

121

for filename in problematic_files:

122

safe_filename = fix_filename(filename)

123

124

with doc.create(Figure()) as fig:

125

fig.add_image(safe_filename)

126

fig.add_caption(f'Fixed filename: {safe_filename}')

127

128

# Cross-platform path handling

129

import os

130

from pylatex.utils import fix_filename

131

132

if os.name == 'posix':

133

# Unix/Linux/Mac paths

134

image_path = '/home/user/data.set.1/results.png'

135

else:

136

# Windows paths

137

image_path = r'C:\Users\Name\data.set.1\results.png'

138

139

safe_path = fix_filename(image_path)

140

```

141

142

### List and Collection Processing

143

144

Convert Python lists and collections to LaTeX-formatted strings.

145

146

```python { .api }

147

def dumps_list(l, *, escape=True, token="%\n", mapper=None, as_content=True):

148

"""

149

Convert a list to LaTeX string representation.

150

151

Parameters:

152

- l: list, collection to convert

153

- escape: bool, whether to escape special LaTeX characters

154

- token: str, separator between list items (default: newline)

155

- mapper: callable or list, functions to apply to each item

156

- as_content: bool, use dumps_as_content() for LatexObjects

157

158

Returns:

159

- NoEscape: formatted LaTeX string

160

"""

161

```

162

163

Usage example:

164

165

```python

166

from pylatex import Document, Section, Command

167

from pylatex.utils import dumps_list, bold, italic

168

169

doc = Document()

170

171

with doc.create(Section('List Processing')):

172

# Basic list conversion

173

items = ['First item', 'Second item', 'Third item']

174

formatted_list = dumps_list(items)

175

doc.append(formatted_list)

176

177

# With custom separator

178

inline_items = ['alpha', 'beta', 'gamma']

179

inline_list = dumps_list(inline_items, token=', ')

180

doc.append('Greek letters: ')

181

doc.append(inline_list)

182

183

# With escaping for special characters

184

special_items = ['Cost: $100', 'Efficiency: 95%', 'Issue #42']

185

safe_list = dumps_list(special_items, escape=True)

186

doc.append(safe_list)

187

188

# With formatting mapper

189

emphasis_items = ['Important', 'Critical', 'Urgent']

190

emphasized = dumps_list(emphasis_items, mapper=bold)

191

doc.append(emphasized)

192

193

# Multiple mappers

194

styled_items = ['Note 1', 'Note 2', 'Note 3']

195

styled_list = dumps_list(styled_items, mapper=[bold, italic])

196

doc.append(styled_list)

197

```

198

199

### Text Formatting Utilities

200

201

Convenience functions for common text formatting operations.

202

203

```python { .api }

204

def bold(s, *, escape=True):

205

"""

206

Format text as bold using \\textbf{}.

207

208

Parameters:

209

- s: str, text to make bold

210

- escape: bool, whether to escape special characters

211

212

Returns:

213

- NoEscape: bold-formatted LaTeX string

214

"""

215

216

def italic(s, *, escape=True):

217

"""

218

Format text as italic using \\textit{}.

219

220

Parameters:

221

- s: str, text to make italic

222

- escape: bool, whether to escape special characters

223

224

Returns:

225

- NoEscape: italic-formatted LaTeX string

226

"""

227

228

def verbatim(s, *, delimiter="|"):

229

"""

230

Format text as verbatim using \\verb.

231

232

Parameters:

233

- s: str, text to format verbatim

234

- delimiter: str, delimiter character (default: |)

235

236

Returns:

237

- NoEscape: verbatim-formatted LaTeX string

238

"""

239

```

240

241

Usage example:

242

243

```python

244

from pylatex import Document, Section

245

from pylatex.utils import bold, italic, verbatim

246

247

doc = Document()

248

249

with doc.create(Section('Text Formatting')):

250

# Basic formatting

251

doc.append(bold('Important notice'))

252

doc.append(' and ')

253

doc.append(italic('emphasized text'))

254

255

# With automatic escaping

256

doc.append(bold('Cost: $1,000 (50% discount)', escape=True))

257

258

# Verbatim code

259

doc.append('Use the command ')

260

doc.append(verbatim(r'\renewcommand{\baselinestretch}{1.5}'))

261

doc.append(' to change line spacing.')

262

263

# Custom verbatim delimiter

264

doc.append('The expression ')

265

doc.append(verbatim('x|y', delimiter='!'))

266

doc.append(' uses a pipe character.')

267

268

# Nested formatting

269

complex_text = bold('Warning: ') + italic('System may be unstable')

270

doc.append(complex_text)

271

```

272

273

### Temporary File Management

274

275

Utilities for managing temporary files during document generation.

276

277

```python { .api }

278

def make_temp_dir():

279

"""

280

Create a temporary directory for document processing.

281

282

Returns:

283

- str: absolute path to temporary directory

284

285

Note: Directory persists until rm_temp_dir() is called or program exits

286

"""

287

288

def rm_temp_dir():

289

"""

290

Remove the temporary directory created by make_temp_dir().

291

292

Cleans up all temporary files and directories created during processing.

293

"""

294

```

295

296

Usage example:

297

298

```python

299

import os

300

from pylatex import Document

301

from pylatex.figure import Figure

302

from pylatex.utils import make_temp_dir, rm_temp_dir

303

import matplotlib.pyplot as plt

304

305

doc = Document()

306

307

# Create temporary directory for plots

308

temp_dir = make_temp_dir()

309

310

try:

311

# Generate and save plots to temp directory

312

plt.figure(figsize=(8, 6))

313

plt.plot([1, 2, 3, 4], [1, 4, 2, 3])

314

plt.title('Sample Plot')

315

316

plot_path = os.path.join(temp_dir, 'sample_plot.png')

317

plt.savefig(plot_path)

318

319

# Use in document

320

with doc.create(Figure()) as fig:

321

fig.add_image(plot_path)

322

fig.add_caption('Generated plot from temporary file')

323

324

# Generate document

325

doc.generate_pdf('document_with_temp_files')

326

327

finally:

328

# Clean up temporary files

329

rm_temp_dir()

330

```

331

332

## Advanced Utilities

333

334

### Custom String Processing

335

336

```python

337

from pylatex import Document, Section

338

from pylatex.utils import NoEscape, escape_latex

339

340

def process_mixed_content(content_list):

341

"""Process list with mixed safe and unsafe content."""

342

processed = []

343

344

for item in content_list:

345

if isinstance(item, dict):

346

if item.get('safe', False):

347

processed.append(NoEscape(item['text']))

348

else:

349

processed.append(escape_latex(item['text']))

350

else:

351

processed.append(escape_latex(str(item)))

352

353

return processed

354

355

doc = Document()

356

357

mixed_content = [

358

{'text': r'\textbf{Safe LaTeX}', 'safe': True},

359

{'text': 'Unsafe: $100 & 50%', 'safe': False},

360

{'text': r'\emph{Another safe command}', 'safe': True}

361

]

362

363

with doc.create(Section('Mixed Content')):

364

for item in process_mixed_content(mixed_content):

365

doc.append(item)

366

doc.append(' ')

367

```

368

369

### File Path Validation

370

371

```python

372

import os

373

from pylatex.utils import fix_filename

374

375

def validate_and_fix_paths(file_paths):

376

"""Validate and fix multiple file paths."""

377

fixed_paths = []

378

379

for path in file_paths:

380

if os.path.exists(path):

381

fixed_path = fix_filename(path)

382

fixed_paths.append(fixed_path)

383

else:

384

print(f"Warning: File not found: {path}")

385

386

return fixed_paths

387

388

# Usage

389

image_files = [

390

'results.data.png',

391

'analysis/summary.report.pdf',

392

'nonexistent.file.jpg'

393

]

394

395

safe_paths = validate_and_fix_paths(image_files)

396

```

397

398

### Batch Text Processing

399

400

```python

401

from pylatex import Document, Section

402

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

403

404

def format_bibliography_items(references):

405

"""Format a list of references with mixed formatting."""

406

formatted_refs = []

407

408

for ref in references:

409

# Author in bold, title in italic

410

author = bold(ref['author'], escape=True)

411

title = italic(ref['title'], escape=True)

412

year = escape_latex(str(ref['year']))

413

414

formatted_ref = f"{author}. {title}. {year}."

415

formatted_refs.append(NoEscape(formatted_ref))

416

417

return formatted_refs

418

419

doc = Document()

420

421

references = [

422

{'author': 'Smith, J.', 'title': 'Advanced LaTeX Techniques', 'year': 2023},

423

{'author': 'Doe, A. & Brown, B.', 'title': 'Document Processing Methods', 'year': 2022}

424

]

425

426

with doc.create(Section('References')):

427

formatted_refs = format_bibliography_items(references)

428

ref_list = dumps_list(formatted_refs, token='\n\n')

429

doc.append(ref_list)

430

```

431

432

### Content Sanitization

433

434

```python

435

from pylatex.utils import escape_latex, NoEscape

436

import re

437

438

def sanitize_user_input(text, allowed_commands=None):

439

"""Sanitize user input while allowing specific LaTeX commands."""

440

if allowed_commands is None:

441

allowed_commands = []

442

443

# First escape everything

444

safe_text = escape_latex(text)

445

446

# Then selectively unescape allowed commands

447

for command in allowed_commands:

448

pattern = re.escape(escape_latex(command))

449

safe_text = safe_text.replace(pattern, command)

450

451

return NoEscape(safe_text)

452

453

# Usage

454

user_text = r"Use \textbf{bold} text but avoid \dangerous{commands}"

455

allowed = [r'\textbf', r'\textit', r'\emph']

456

457

sanitized = sanitize_user_input(user_text, allowed)

458

# Result: "Use \textbf{bold} text but avoid \\dangerous\{commands\}"

459

```

460

461

## Error Handling and Debugging

462

463

### Safe Operations

464

465

```python

466

from pylatex.utils import escape_latex, NoEscape

467

468

def safe_append(container, content, escape_by_default=True):

469

"""Safely append content with error handling."""

470

try:

471

if isinstance(content, str) and escape_by_default:

472

container.append(escape_latex(content))

473

else:

474

container.append(content)

475

except Exception as e:

476

print(f"Error appending content: {e}")

477

container.append(f"[Content error: {str(e)}]")

478

479

# Usage with error recovery

480

doc = Document()

481

482

contents = [

483

"Normal text",

484

NoEscape(r"\textbf{Bold}"),

485

None, # This will cause an error

486

"More normal text"

487

]

488

489

for content in contents:

490

safe_append(doc, content)

491

```

492

493

### Debug Utilities

494

495

```python

496

from pylatex.utils import dumps_list, escape_latex

497

498

def debug_latex_output(items, show_escaping=True):

499

"""Debug utility to show how items will be processed."""

500

print("LaTeX Processing Debug:")

501

print("-" * 40)

502

503

for i, item in enumerate(items):

504

print(f"Item {i}: {repr(item)}")

505

506

if show_escaping and isinstance(item, str):

507

escaped = escape_latex(item)

508

print(f" Escaped: {escaped}")

509

510

try:

511

if hasattr(item, 'dumps'):

512

output = item.dumps()

513

else:

514

output = str(item)

515

print(f" Output: {output}")

516

except Exception as e:

517

print(f" Error: {e}")

518

519

print()

520

521

# Usage for debugging

522

debug_items = [

523

"Normal text with $pecial char$",

524

NoEscape(r"\textbf{Bold command}"),

525

42,

526

["nested", "list"]

527

]

528

529

debug_latex_output(debug_items)

530

```

531

532

## Best Practices

533

534

### Consistent Escaping Strategy

535

536

```python

537

from pylatex import Document

538

from pylatex.utils import NoEscape, escape_latex

539

540

# Define clear policies for different content types

541

def add_user_content(doc, content):

542

"""Always escape user-provided content."""

543

doc.append(escape_latex(content))

544

545

def add_template_content(doc, content):

546

"""Template content is pre-verified as safe."""

547

doc.append(NoEscape(content))

548

549

def add_mixed_content(doc, content, is_safe=False):

550

"""Mixed content with explicit safety flag."""

551

if is_safe:

552

doc.append(NoEscape(content))

553

else:

554

doc.append(escape_latex(content))

555

```

556

557

### Resource Management

558

559

```python

560

import contextlib

561

from pylatex.utils import make_temp_dir, rm_temp_dir

562

563

@contextlib.contextmanager

564

def temp_directory():

565

"""Context manager for temporary directory handling."""

566

temp_dir = make_temp_dir()

567

try:

568

yield temp_dir

569

finally:

570

rm_temp_dir()

571

572

# Usage

573

with temp_directory() as temp_dir:

574

# Use temp_dir for file operations

575

# Cleanup happens automatically

576

pass

577

```

578

579

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.