b8tex


Nameb8tex JSON
Version 0.1.0 PyPI version JSON
download
home_pageNone
SummaryA high-level Python wrapper for Tectonic LaTeX compiler with project-aware compilation
upload_time2025-10-28 14:44:21
maintainerNone
docs_urlNone
authorNone
requires_python>=3.13
licenseMIT
keywords compiler latex pdf tectonic typesetting
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # B8TeX

A modern, type-safe Python wrapper for the [Tectonic](https://tectonic-typesetting.github.io/) LaTeX compiler.

B8TeX provides a high-level, Pythonic interface for compiling LaTeX documents with support for:

- In-memory compilation from strings
- Custom style files and packages
- Multi-file projects with dependency tracking
- Type-safe API with comprehensive error handling
- Project-aware builds with multiple output formats

## Features

- **Modern Python**: Built for Python 3.13+ with full type hints
- **Auto-Install**: Automatically downloads the Tectonic binary on first use
- **Flexible Sources**: Compile from files, strings, or in-memory sources
- **Custom Packages**: Bundle custom `.sty`, `.cls`, and resource files with your documents
- **Project Support**: Multi-target builds with Tectonic V1 and V2 interface support
- **Type-Safe**: Comprehensive type hints and runtime validation
- **Secure**: Built-in security policies with LaTeX validation, resource limits, and configurable timeouts
- **Resilient**: Automatic retry with exponential backoff and graceful failure handling
- **Rich Results**: Structured compilation results with warnings, errors, and artifacts
- **Cross-Platform**: Supports Linux, macOS, and Windows (x86_64 and aarch64)

## Security & Resource Management

B8TeX includes comprehensive security features to protect against malicious or resource-intensive LaTeX documents:

### LaTeX Content Validation

Validates documents for security and resource constraints:

```python
from b8tex.core.validation import ContentValidator, ValidationLimits

# Configure validation limits
limits = ValidationLimits(
    max_file_size=10 * 1024 * 1024,  # 10MB per file
    max_total_size=50 * 1024 * 1024,  # 50MB total
    max_files=100,                    # Max 100 files
    allow_shell_escape=False,         # Block shell-escape packages
    dangerous_packages={"shellesc", "minted", "pythontex"}  # Block dangerous packages
)

validator = ContentValidator(limits=limits, mode="strict")
errors = validator.validate_document(document)
```

**Validation modes:**
- `strict`: Raise errors immediately on validation failure
- `permissive`: Collect warnings, only error on critical issues (default)
- `disabled`: Skip validation entirely

### Resource Limits

Control memory, CPU, and output size limits:

```python
from b8tex.core.runner import ResourceLimits, ProcessRunner

limits = ResourceLimits(
    memory_mb=1024,            # 1GB memory limit
    timeout_seconds=300.0,     # 5 minute timeout
    max_output_size_mb=100,    # Max 100MB output
    cpu_time_seconds=300       # Max 5 minutes CPU time (Unix only)
)

runner = ProcessRunner(limits=limits)
```

### Configurable Timeouts

Set different timeouts for different operations with document size-based scaling:

```python
from b8tex.core.timeouts import TimeoutConfig

timeouts = TimeoutConfig(
    compilation=600.0,          # 10 minute compilation timeout
    download=300.0,             # 5 minute download timeout
    probe=5.0,                  # 5 second probe timeout
    global_multiplier=2.0,      # Double all timeouts for slow systems
    enable_size_scaling=True,   # Scale timeout by document size
    size_scale_factor=0.1       # +0.1s per KB above base size
)

# Get effective timeout for a 500KB document
timeout = timeouts.get("compilation", document_size_kb=500)  # 640s (600 + 400*0.1)
```

### Retry Policies & Graceful Failure

Handle transient failures with automatic retry and exponential backoff:

```python
from b8tex.core.retry import RetryPolicy, retry_with_policy

policy = RetryPolicy(
    max_attempts=3,
    initial_delay=1.0,
    max_delay=30.0,
    exponential_backoff=True,
    backoff_factor=2.0,
    retryable_exceptions=(OSError, IOError, TimeoutError)
)

result = retry_with_policy(
    policy,
    lambda: compile_document(doc),
    operation_name="compilation"
)
```

### Security Configuration

All security settings can be configured via `~/.config/b8tex/config.toml`:

```toml
# Cache limits
max_cache_size_mb = 1000
max_cache_age_days = 30

[validation]
mode = "permissive"  # "strict", "permissive", or "disabled"

[validation.limits]
max_file_size = 10485760      # 10MB
max_total_size = 52428800     # 50MB
max_files = 100
allow_shell_escape = false    # Block minted, pythontex, etc.

[resource_limits]
memory_mb = 1024
timeout_seconds = 300.0
max_output_size_mb = 100

[timeouts]
compilation = 300.0
download = 300.0
global_multiplier = 1.0
enable_size_scaling = true
```

Or via environment variables:

```bash
# Validation
export B8TEX_VALIDATION_MODE=strict

# Resource limits
export B8TEX_MEMORY_LIMIT_MB=2048
export B8TEX_CPU_TIME_LIMIT=600

# Timeouts
export B8TEX_TIMEOUT_COMPILATION=600
export B8TEX_TIMEOUT_MULTIPLIER=2.0

# Cache
export B8TEX_MAX_CACHE_SIZE_MB=2000
```

## Installation

### Simple Installation (Recommended)

B8TeX will automatically download and install the Tectonic binary on first use:

```bash
# Using uv (recommended)
uv pip install b8tex

# Or with pip
pip install b8tex
```

That's it! When you first use B8TeX, it will automatically download the appropriate Tectonic binary for your platform.

### Manual Tectonic Installation (Optional)

If you prefer to manage Tectonic yourself:

```bash
# macOS
brew install tectonic

# Linux (see https://tectonic-typesetting.github.io/install.html)
# Windows (see https://tectonic-typesetting.github.io/install.html)
```

Or use the B8TeX CLI to manually install:

```bash
# Download and install Tectonic binary
b8tex install-binary

# Download a specific version
b8tex install-binary --version=0.15.0

# Force re-download
b8tex install-binary --force
```

### Configuration

B8TeX can be configured via environment variables or a configuration file.

#### Environment Variables

```bash
# Disable automatic downloads
export B8TEX_NO_AUTO_DOWNLOAD=1

# Specify Tectonic version
export B8TEX_TECTONIC_VERSION=0.15.0

# Use custom Tectonic binary
export TECTONIC_PATH=/usr/local/bin/tectonic

# Override config file location
export B8TEX_CONFIG_PATH=~/.config/b8tex/config.toml
```

#### Configuration File

Create a configuration file at `~/.config/b8tex/config.toml` (or use `b8tex init-config`):

```toml
# Binary management
auto_download = true
# tectonic_version = "0.15.0"
# binary_path = "/usr/local/bin/tectonic"

# Cache configuration
max_cache_size_mb = 1000
max_cache_age_days = 30

# Security and validation
[validation]
mode = "permissive"  # "strict", "permissive", or "disabled"

[validation.limits]
max_file_size = 10485760      # 10MB
max_total_size = 52428800     # 50MB
max_files = 100
allow_shell_escape = false

# Resource limits
[resource_limits]
memory_mb = 1024
timeout_seconds = 300.0
max_output_size_mb = 100

# Timeouts
[timeouts]
compilation = 300.0
download = 300.0
global_multiplier = 1.0
enable_size_scaling = true
```

#### CLI Commands

```bash
# Initialize default config file
b8tex init-config

# Show current configuration
b8tex config

# Install Tectonic binary
b8tex install-binary

# Show help
b8tex help
```

### For Development

```bash
git clone https://github.com/samehkamaleldin/pytex.git
cd b8tex
uv venv
source .venv/bin/activate  # or `.venv\Scripts\activate` on Windows
uv pip install -e ".[dev]"
```

## Quick Start

### Basic Usage

Compile LaTeX from a string:

```python
from b8tex import compile_string

latex = r"""
\documentclass{article}
\title{Hello B8TeX}
\begin{document}
\maketitle
Hello, world!
\end{document}
"""

result = compile_string(latex)
if result.success:
    print(f"PDF generated: {result.pdf_path}")
```

### Custom Style Files

Use custom packages and styles:

```python
from b8tex import Document, InMemorySource, Resource, compile_document

# Define a custom style
style = InMemorySource("mystyle.sty", r"""
\ProvidesPackage{mystyle}
\newcommand{\mycommand}{Custom text}
""")

# Main document
doc = Document(
    name="custom",
    entrypoint=InMemorySource("main.tex", r"""
\documentclass{article}
\usepackage{mystyle}
\begin{document}
\mycommand
\end{document}
"""),
    resources=[Resource(style)]
)

result = compile_document(doc)
```

### Project Builds

Compile multi-target projects:

```python
from b8tex import Project, Target, Document, BuildOptions, OutputFormat

project = Project.from_directory(Path("my_project"))
project.add_target(Target(
    name="pdf",
    document=Document.from_path(Path("main.tex")),
    options=BuildOptions(outfmt=OutputFormat.PDF)
))

from b8tex import TectonicCompiler
compiler = TectonicCompiler()
result = compiler.build_project(project, target="pdf")
```

## Documentation

For more examples, see the [`examples/`](examples/) directory.

### Core Concepts

- **Document**: A LaTeX document with entrypoint and resources
- **Resource**: Style files, images, bibliographies, etc.
- **BuildOptions**: Compilation settings (output format, reruns, security, etc.)
- **CompileResult**: Structured result with artifacts, warnings, and errors
- **Project**: Multi-target build configuration

### API Reference

#### Main Functions

- `compile_string(content, **options)` - Compile LaTeX source code
- `compile_document(document, **options)` - Compile a Document object
- `TectonicCompiler()` - Main compiler interface for advanced usage

#### Core Classes

- `Document` - LaTeX document representation
- `InMemorySource` - In-memory file content
- `Resource` - Additional files (styles, images, etc.)
- `BuildOptions` - Compilation configuration
- `Project` - Multi-target project
- `CompileResult` - Compilation results

## Development

### Setup

```bash
# Clone and install
git clone https://github.com/samehkamaleldin/pytex.git
cd b8tex
uv venv
source .venv/bin/activate
uv pip install -e ".[dev]"
```

### Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=b8tex --cov-report=html

# Run type checking
mypy src/b8tex

# Run linting
ruff check src tests
```

### Code Quality

This project uses:

- **mypy** for static type checking
- **ruff** for linting and formatting
- **pytest** for testing

All code must pass type checking and linting before merging.

## Requirements

- Python 3.13+
- Tectonic LaTeX compiler (automatically downloaded if not found)
- uv (recommended) or pip

### Supported Platforms

B8TeX can automatically download Tectonic for the following platforms:

- **Linux**: x86_64, aarch64
- **macOS**: x86_64 (Intel), aarch64 (Apple Silicon)
- **Windows**: x86_64

If automatic download is not available for your platform, you can install Tectonic manually following the [official installation guide](https://tectonic-typesetting.github.io/install.html).

### How Auto-Download Works

When you first use B8TeX:

1. B8TeX checks for Tectonic in the following order:
   - Custom binary path from config file
   - `TECTONIC_PATH` environment variable
   - System PATH
   - B8TeX cache directory (`~/.cache/b8tex/` or platform equivalent)

2. If Tectonic is not found and auto-download is enabled:
   - Downloads the appropriate binary from [Tectonic GitHub releases](https://github.com/tectonic-typesetting/tectonic/releases)
   - Extracts and caches it in `~/.cache/b8tex/`
   - Uses the cached binary for all future compilations

3. If auto-download is disabled or fails:
   - Provides clear instructions for manual installation
   - Suggests using `b8tex install-binary` command

You can disable auto-download by:
- Setting `B8TEX_NO_AUTO_DOWNLOAD=1` environment variable
- Setting `auto_download = false` in `~/.config/b8tex/config.toml`

## Troubleshooting

### Common Issues

#### Binary Not Found

**Problem**: `MissingBinaryError: Tectonic binary not found`

**Solutions**:
1. Enable auto-download (default): B8TeX will automatically download Tectonic
2. Manual installation: `b8tex install-binary`
3. Install Tectonic system-wide: `brew install tectonic` (macOS) or follow [official guide](https://tectonic-typesetting.github.io/install.html)
4. Set custom path: `export TECTONIC_PATH=/path/to/tectonic`

#### Compilation Fails

**Problem**: Compilation returns errors but unclear why

**Solutions**:
1. Check `result.errors` for specific error messages
2. Use `options.print_log=True` to see full Tectonic output
3. Enable `options.keep_logs=True` to preserve log files
4. Verify LaTeX syntax is valid (try with `tectonic` command directly)

#### Permission Errors

**Problem**: `PermissionError` when compiling

**Solutions**:
1. Check write permissions in output directory
2. Verify cache directory is writable: `~/.cache/b8tex/`
3. Try running with elevated permissions (not recommended)
4. Use custom output directory: `workdir=Path("/tmp/b8tex")`

#### Platform Not Supported

**Problem**: `UnsupportedPlatformError` on auto-download

**Solutions**:
1. Install Tectonic manually for your platform
2. Set `TECTONIC_PATH` to your manual installation
3. Open an issue if you think your platform should be supported

#### Slow Compilation

**Problem**: Compilation is slower than expected

**Solutions**:
1. Enable caching (on by default): `TectonicCompiler(use_cache=True)`
2. Use `only_cached=True` for offline/fast builds
3. Reduce LaTeX reruns: `BuildOptions(reruns=1)`
4. Check if cache is being invalidated unnecessarily
5. See Performance Tips section below

#### Cache Issues

**Problem**: Cache not working or corrupted

**Solutions**:
1. Clear cache: `b8tex clean-cache` or `cache.clear()`
2. Check cache stats: `cache.stats()`
3. Verify cache directory exists: `~/.cache/b8tex/build_cache.db`
4. Clean old entries: `cache.cleanup(max_age_days=30)`

## FAQ

### General

**Q: Do I need to install LaTeX?**
A: No! B8TeX uses Tectonic, which is a self-contained LaTeX distribution. You don't need TeX Live, MiKTeX, or any other LaTeX distribution.

**Q: What Python versions are supported?**
A: B8TeX requires Python 3.13 or later for modern type hints and language features.

**Q: Is B8TeX production-ready?**
A: B8TeX is currently in active development. The core API is stable, but advanced features are still being added. Check the version number and release notes.

**Q: How does B8TeX compare to other LaTeX wrappers?**
A: B8TeX focuses on modern Python features, type safety, and developer experience. It's built specifically for Tectonic and offers features like automatic binary management, build caching, and in-memory compilation.

### Usage

**Q: Can I compile LaTeX files from disk?**
A: Yes! Use `Document.from_path(Path("document.tex"))` or pass a Path object directly.

**Q: How do I include images in my document?**
A: Add images as resources:
```python
from b8tex import Document, Resource
doc = Document(
    entrypoint=Path("main.tex"),
    resources=[Resource(Path("image.png"))]
)
```

**Q: Can I compile multiple documents in parallel?**
A: Yes! Use the async API or Python's `concurrent.futures`. See `examples/04_async_compilation.py`.

**Q: How do I use custom LaTeX packages?**
A: Add them as resources with `kind="sty"`:
```python
Resource(Path("mypackage.sty"), kind="sty")
```

**Q: Can I compile without internet access?**
A: Yes! Once Tectonic is installed and packages are cached, use `BuildOptions(only_cached=True)`.

### Configuration

**Q: Where is the cache directory?**
A: Platform-dependent:
- **macOS**: `~/Library/Caches/b8tex/`
- **Linux**: `~/.cache/b8tex/`
- **Windows**: `%LOCALAPPDATA%\b8tex\cache\`

**Q: How do I disable auto-download?**
A: Set `B8TEX_NO_AUTO_DOWNLOAD=1` or `auto_download = false` in config file.

**Q: Can I use a specific Tectonic version?**
A: Yes! Set in config file:
```toml
tectonic_version = "0.15.0"
```
Or use: `b8tex install-binary --version=0.15.0`

**Q: How do I change the output directory?**
A: Use the `workdir` parameter:
```python
result = compiler.compile_document(doc, workdir=Path("/tmp/output"))
```

### Performance

**Q: Why is the first compilation slow?**
A: Tectonic downloads required LaTeX packages on first use. Subsequent compilations are much faster thanks to package caching.

**Q: Does B8TeX cache compilation results?**
A: Yes! Build caching is enabled by default. See `examples/05_cache_demo.py`.

**Q: How much space does the cache use?**
A: Check with `cache.stats()`. Typically 10-100MB depending on usage. Clean old entries with `cache.cleanup()`.

## Performance Tips

### 1. Enable Build Caching (Default)

Build caching can speed up repeated compilations by 10-100x:

```python
from b8tex import TectonicCompiler, BuildCache

# Caching is enabled by default
compiler = TectonicCompiler(use_cache=True)

# Or explicitly create cache
cache = BuildCache()
compiler = TectonicCompiler(cache=cache)
```

**When cache helps**:
- Repeated compilation of unchanged documents
- CI/CD pipelines
- Development with frequent rebuilds
- Batch processing similar documents

**Cache invalidation**: The cache automatically invalidates when:
- Document content changes
- Build options change
- Tectonic version changes
- Dependencies are modified

### 2. Use Only-Cached Mode

For fastest compilation when all packages are already downloaded:

```python
from b8tex import BuildOptions

options = BuildOptions(only_cached=True)
result = compiler.compile_document(doc, options=options)
```

This prevents Tectonic from downloading packages, ideal for offline work or CI.

### 3. Reduce Reruns

LaTeX sometimes needs multiple passes. Limit reruns for faster compilation:

```python
options = BuildOptions(reruns=1)  # Default is automatic
```

**Trade-off**: Cross-references and bibliographies may not resolve correctly.

### 4. Parallel Compilation

For batch processing, use async or parallel execution:

```python
from concurrent.futures import ThreadPoolExecutor

def compile_doc(content):
    return compile_string(content)

with ThreadPoolExecutor(max_workers=4) as executor:
    results = list(executor.map(compile_doc, documents))
```

**Speedup**: Near-linear with number of cores for independent documents.

### 5. Persistent Workspaces

Reuse workspace directories to avoid file I/O:

```python
workdir = Path("/tmp/b8tex_workspace")
workdir.mkdir(exist_ok=True)

for doc in documents:
    result = compiler.compile_document(doc, workdir=workdir)
```

### 6. In-Memory Compilation

Use in-memory sources instead of file I/O when possible:

```python
from b8tex import InMemorySource, Document

doc = Document(
    entrypoint=InMemorySource("doc.tex", latex_content),
    resources=[InMemorySource("style.sty", style_content)]
)
```

**Benefit**: Faster file operations, no disk cleanup needed.

### 7. Cache Management

Keep cache healthy with periodic cleanup:

```python
# Remove entries older than 30 days
cache.cleanup(max_age_days=30)

# Check cache size
stats = cache.stats()
print(f"Cache entries: {stats['total_entries']}")
print(f"Cache size: {stats['db_size_bytes'] / 1024 / 1024:.1f} MB")

# Clear if needed
if stats['db_size_bytes'] > 100_000_000:  # > 100 MB
    cache.clear()
```

### 8. Minimize Document Changes

The cache fingerprint includes all content. To maximize cache hits:
- Use variables/templates for changing content
- Separate frequently-changing content from static boilerplate
- Consider using LaTeX's `\input` for modular documents

### Performance Benchmarks

Typical compilation times on modern hardware:

| Scenario | First Compile | Cached | Speedup |
|----------|--------------|--------|---------|
| Simple document (1 page) | 2-5s | 0.1-0.5s | 10-20x |
| Medium document (10 pages) | 5-15s | 0.2-1s | 15-25x |
| Large document (100 pages) | 15-60s | 1-3s | 15-30x |
| With images/complex math | 10-30s | 0.5-2s | 15-20x |

**Note**: First compile includes package downloads. Subsequent first compiles (different documents) are faster as packages are cached by Tectonic.

## License

MIT License - see [LICENSE](LICENSE) file for details.

## Contributing

Contributions are welcome! Please:

1. Fork the repository
2. Create a feature branch
3. Add tests for new features
4. Ensure all tests pass and types check
5. Submit a pull request

## Acknowledgments

- Built on top of the excellent [Tectonic](https://tectonic-typesetting.github.io/) LaTeX compiler
- Inspired by modern Python packaging and type safety best practices

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "b8tex",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.13",
    "maintainer_email": null,
    "keywords": "compiler, latex, pdf, tectonic, typesetting",
    "author": null,
    "author_email": "Sameh Mohamed <sameh.kamaleldin@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/77/5c/e029e640496d9b786b3369c93b907b67f762806807bd2640fea1c212fd16/b8tex-0.1.0.tar.gz",
    "platform": null,
    "description": "# B8TeX\n\nA modern, type-safe Python wrapper for the [Tectonic](https://tectonic-typesetting.github.io/) LaTeX compiler.\n\nB8TeX provides a high-level, Pythonic interface for compiling LaTeX documents with support for:\n\n- In-memory compilation from strings\n- Custom style files and packages\n- Multi-file projects with dependency tracking\n- Type-safe API with comprehensive error handling\n- Project-aware builds with multiple output formats\n\n## Features\n\n- **Modern Python**: Built for Python 3.13+ with full type hints\n- **Auto-Install**: Automatically downloads the Tectonic binary on first use\n- **Flexible Sources**: Compile from files, strings, or in-memory sources\n- **Custom Packages**: Bundle custom `.sty`, `.cls`, and resource files with your documents\n- **Project Support**: Multi-target builds with Tectonic V1 and V2 interface support\n- **Type-Safe**: Comprehensive type hints and runtime validation\n- **Secure**: Built-in security policies with LaTeX validation, resource limits, and configurable timeouts\n- **Resilient**: Automatic retry with exponential backoff and graceful failure handling\n- **Rich Results**: Structured compilation results with warnings, errors, and artifacts\n- **Cross-Platform**: Supports Linux, macOS, and Windows (x86_64 and aarch64)\n\n## Security & Resource Management\n\nB8TeX includes comprehensive security features to protect against malicious or resource-intensive LaTeX documents:\n\n### LaTeX Content Validation\n\nValidates documents for security and resource constraints:\n\n```python\nfrom b8tex.core.validation import ContentValidator, ValidationLimits\n\n# Configure validation limits\nlimits = ValidationLimits(\n    max_file_size=10 * 1024 * 1024,  # 10MB per file\n    max_total_size=50 * 1024 * 1024,  # 50MB total\n    max_files=100,                    # Max 100 files\n    allow_shell_escape=False,         # Block shell-escape packages\n    dangerous_packages={\"shellesc\", \"minted\", \"pythontex\"}  # Block dangerous packages\n)\n\nvalidator = ContentValidator(limits=limits, mode=\"strict\")\nerrors = validator.validate_document(document)\n```\n\n**Validation modes:**\n- `strict`: Raise errors immediately on validation failure\n- `permissive`: Collect warnings, only error on critical issues (default)\n- `disabled`: Skip validation entirely\n\n### Resource Limits\n\nControl memory, CPU, and output size limits:\n\n```python\nfrom b8tex.core.runner import ResourceLimits, ProcessRunner\n\nlimits = ResourceLimits(\n    memory_mb=1024,            # 1GB memory limit\n    timeout_seconds=300.0,     # 5 minute timeout\n    max_output_size_mb=100,    # Max 100MB output\n    cpu_time_seconds=300       # Max 5 minutes CPU time (Unix only)\n)\n\nrunner = ProcessRunner(limits=limits)\n```\n\n### Configurable Timeouts\n\nSet different timeouts for different operations with document size-based scaling:\n\n```python\nfrom b8tex.core.timeouts import TimeoutConfig\n\ntimeouts = TimeoutConfig(\n    compilation=600.0,          # 10 minute compilation timeout\n    download=300.0,             # 5 minute download timeout\n    probe=5.0,                  # 5 second probe timeout\n    global_multiplier=2.0,      # Double all timeouts for slow systems\n    enable_size_scaling=True,   # Scale timeout by document size\n    size_scale_factor=0.1       # +0.1s per KB above base size\n)\n\n# Get effective timeout for a 500KB document\ntimeout = timeouts.get(\"compilation\", document_size_kb=500)  # 640s (600 + 400*0.1)\n```\n\n### Retry Policies & Graceful Failure\n\nHandle transient failures with automatic retry and exponential backoff:\n\n```python\nfrom b8tex.core.retry import RetryPolicy, retry_with_policy\n\npolicy = RetryPolicy(\n    max_attempts=3,\n    initial_delay=1.0,\n    max_delay=30.0,\n    exponential_backoff=True,\n    backoff_factor=2.0,\n    retryable_exceptions=(OSError, IOError, TimeoutError)\n)\n\nresult = retry_with_policy(\n    policy,\n    lambda: compile_document(doc),\n    operation_name=\"compilation\"\n)\n```\n\n### Security Configuration\n\nAll security settings can be configured via `~/.config/b8tex/config.toml`:\n\n```toml\n# Cache limits\nmax_cache_size_mb = 1000\nmax_cache_age_days = 30\n\n[validation]\nmode = \"permissive\"  # \"strict\", \"permissive\", or \"disabled\"\n\n[validation.limits]\nmax_file_size = 10485760      # 10MB\nmax_total_size = 52428800     # 50MB\nmax_files = 100\nallow_shell_escape = false    # Block minted, pythontex, etc.\n\n[resource_limits]\nmemory_mb = 1024\ntimeout_seconds = 300.0\nmax_output_size_mb = 100\n\n[timeouts]\ncompilation = 300.0\ndownload = 300.0\nglobal_multiplier = 1.0\nenable_size_scaling = true\n```\n\nOr via environment variables:\n\n```bash\n# Validation\nexport B8TEX_VALIDATION_MODE=strict\n\n# Resource limits\nexport B8TEX_MEMORY_LIMIT_MB=2048\nexport B8TEX_CPU_TIME_LIMIT=600\n\n# Timeouts\nexport B8TEX_TIMEOUT_COMPILATION=600\nexport B8TEX_TIMEOUT_MULTIPLIER=2.0\n\n# Cache\nexport B8TEX_MAX_CACHE_SIZE_MB=2000\n```\n\n## Installation\n\n### Simple Installation (Recommended)\n\nB8TeX will automatically download and install the Tectonic binary on first use:\n\n```bash\n# Using uv (recommended)\nuv pip install b8tex\n\n# Or with pip\npip install b8tex\n```\n\nThat's it! When you first use B8TeX, it will automatically download the appropriate Tectonic binary for your platform.\n\n### Manual Tectonic Installation (Optional)\n\nIf you prefer to manage Tectonic yourself:\n\n```bash\n# macOS\nbrew install tectonic\n\n# Linux (see https://tectonic-typesetting.github.io/install.html)\n# Windows (see https://tectonic-typesetting.github.io/install.html)\n```\n\nOr use the B8TeX CLI to manually install:\n\n```bash\n# Download and install Tectonic binary\nb8tex install-binary\n\n# Download a specific version\nb8tex install-binary --version=0.15.0\n\n# Force re-download\nb8tex install-binary --force\n```\n\n### Configuration\n\nB8TeX can be configured via environment variables or a configuration file.\n\n#### Environment Variables\n\n```bash\n# Disable automatic downloads\nexport B8TEX_NO_AUTO_DOWNLOAD=1\n\n# Specify Tectonic version\nexport B8TEX_TECTONIC_VERSION=0.15.0\n\n# Use custom Tectonic binary\nexport TECTONIC_PATH=/usr/local/bin/tectonic\n\n# Override config file location\nexport B8TEX_CONFIG_PATH=~/.config/b8tex/config.toml\n```\n\n#### Configuration File\n\nCreate a configuration file at `~/.config/b8tex/config.toml` (or use `b8tex init-config`):\n\n```toml\n# Binary management\nauto_download = true\n# tectonic_version = \"0.15.0\"\n# binary_path = \"/usr/local/bin/tectonic\"\n\n# Cache configuration\nmax_cache_size_mb = 1000\nmax_cache_age_days = 30\n\n# Security and validation\n[validation]\nmode = \"permissive\"  # \"strict\", \"permissive\", or \"disabled\"\n\n[validation.limits]\nmax_file_size = 10485760      # 10MB\nmax_total_size = 52428800     # 50MB\nmax_files = 100\nallow_shell_escape = false\n\n# Resource limits\n[resource_limits]\nmemory_mb = 1024\ntimeout_seconds = 300.0\nmax_output_size_mb = 100\n\n# Timeouts\n[timeouts]\ncompilation = 300.0\ndownload = 300.0\nglobal_multiplier = 1.0\nenable_size_scaling = true\n```\n\n#### CLI Commands\n\n```bash\n# Initialize default config file\nb8tex init-config\n\n# Show current configuration\nb8tex config\n\n# Install Tectonic binary\nb8tex install-binary\n\n# Show help\nb8tex help\n```\n\n### For Development\n\n```bash\ngit clone https://github.com/samehkamaleldin/pytex.git\ncd b8tex\nuv venv\nsource .venv/bin/activate  # or `.venv\\Scripts\\activate` on Windows\nuv pip install -e \".[dev]\"\n```\n\n## Quick Start\n\n### Basic Usage\n\nCompile LaTeX from a string:\n\n```python\nfrom b8tex import compile_string\n\nlatex = r\"\"\"\n\\documentclass{article}\n\\title{Hello B8TeX}\n\\begin{document}\n\\maketitle\nHello, world!\n\\end{document}\n\"\"\"\n\nresult = compile_string(latex)\nif result.success:\n    print(f\"PDF generated: {result.pdf_path}\")\n```\n\n### Custom Style Files\n\nUse custom packages and styles:\n\n```python\nfrom b8tex import Document, InMemorySource, Resource, compile_document\n\n# Define a custom style\nstyle = InMemorySource(\"mystyle.sty\", r\"\"\"\n\\ProvidesPackage{mystyle}\n\\newcommand{\\mycommand}{Custom text}\n\"\"\")\n\n# Main document\ndoc = Document(\n    name=\"custom\",\n    entrypoint=InMemorySource(\"main.tex\", r\"\"\"\n\\documentclass{article}\n\\usepackage{mystyle}\n\\begin{document}\n\\mycommand\n\\end{document}\n\"\"\"),\n    resources=[Resource(style)]\n)\n\nresult = compile_document(doc)\n```\n\n### Project Builds\n\nCompile multi-target projects:\n\n```python\nfrom b8tex import Project, Target, Document, BuildOptions, OutputFormat\n\nproject = Project.from_directory(Path(\"my_project\"))\nproject.add_target(Target(\n    name=\"pdf\",\n    document=Document.from_path(Path(\"main.tex\")),\n    options=BuildOptions(outfmt=OutputFormat.PDF)\n))\n\nfrom b8tex import TectonicCompiler\ncompiler = TectonicCompiler()\nresult = compiler.build_project(project, target=\"pdf\")\n```\n\n## Documentation\n\nFor more examples, see the [`examples/`](examples/) directory.\n\n### Core Concepts\n\n- **Document**: A LaTeX document with entrypoint and resources\n- **Resource**: Style files, images, bibliographies, etc.\n- **BuildOptions**: Compilation settings (output format, reruns, security, etc.)\n- **CompileResult**: Structured result with artifacts, warnings, and errors\n- **Project**: Multi-target build configuration\n\n### API Reference\n\n#### Main Functions\n\n- `compile_string(content, **options)` - Compile LaTeX source code\n- `compile_document(document, **options)` - Compile a Document object\n- `TectonicCompiler()` - Main compiler interface for advanced usage\n\n#### Core Classes\n\n- `Document` - LaTeX document representation\n- `InMemorySource` - In-memory file content\n- `Resource` - Additional files (styles, images, etc.)\n- `BuildOptions` - Compilation configuration\n- `Project` - Multi-target project\n- `CompileResult` - Compilation results\n\n## Development\n\n### Setup\n\n```bash\n# Clone and install\ngit clone https://github.com/samehkamaleldin/pytex.git\ncd b8tex\nuv venv\nsource .venv/bin/activate\nuv pip install -e \".[dev]\"\n```\n\n### Running Tests\n\n```bash\n# Run all tests\npytest\n\n# Run with coverage\npytest --cov=b8tex --cov-report=html\n\n# Run type checking\nmypy src/b8tex\n\n# Run linting\nruff check src tests\n```\n\n### Code Quality\n\nThis project uses:\n\n- **mypy** for static type checking\n- **ruff** for linting and formatting\n- **pytest** for testing\n\nAll code must pass type checking and linting before merging.\n\n## Requirements\n\n- Python 3.13+\n- Tectonic LaTeX compiler (automatically downloaded if not found)\n- uv (recommended) or pip\n\n### Supported Platforms\n\nB8TeX can automatically download Tectonic for the following platforms:\n\n- **Linux**: x86_64, aarch64\n- **macOS**: x86_64 (Intel), aarch64 (Apple Silicon)\n- **Windows**: x86_64\n\nIf automatic download is not available for your platform, you can install Tectonic manually following the [official installation guide](https://tectonic-typesetting.github.io/install.html).\n\n### How Auto-Download Works\n\nWhen you first use B8TeX:\n\n1. B8TeX checks for Tectonic in the following order:\n   - Custom binary path from config file\n   - `TECTONIC_PATH` environment variable\n   - System PATH\n   - B8TeX cache directory (`~/.cache/b8tex/` or platform equivalent)\n\n2. If Tectonic is not found and auto-download is enabled:\n   - Downloads the appropriate binary from [Tectonic GitHub releases](https://github.com/tectonic-typesetting/tectonic/releases)\n   - Extracts and caches it in `~/.cache/b8tex/`\n   - Uses the cached binary for all future compilations\n\n3. If auto-download is disabled or fails:\n   - Provides clear instructions for manual installation\n   - Suggests using `b8tex install-binary` command\n\nYou can disable auto-download by:\n- Setting `B8TEX_NO_AUTO_DOWNLOAD=1` environment variable\n- Setting `auto_download = false` in `~/.config/b8tex/config.toml`\n\n## Troubleshooting\n\n### Common Issues\n\n#### Binary Not Found\n\n**Problem**: `MissingBinaryError: Tectonic binary not found`\n\n**Solutions**:\n1. Enable auto-download (default): B8TeX will automatically download Tectonic\n2. Manual installation: `b8tex install-binary`\n3. Install Tectonic system-wide: `brew install tectonic` (macOS) or follow [official guide](https://tectonic-typesetting.github.io/install.html)\n4. Set custom path: `export TECTONIC_PATH=/path/to/tectonic`\n\n#### Compilation Fails\n\n**Problem**: Compilation returns errors but unclear why\n\n**Solutions**:\n1. Check `result.errors` for specific error messages\n2. Use `options.print_log=True` to see full Tectonic output\n3. Enable `options.keep_logs=True` to preserve log files\n4. Verify LaTeX syntax is valid (try with `tectonic` command directly)\n\n#### Permission Errors\n\n**Problem**: `PermissionError` when compiling\n\n**Solutions**:\n1. Check write permissions in output directory\n2. Verify cache directory is writable: `~/.cache/b8tex/`\n3. Try running with elevated permissions (not recommended)\n4. Use custom output directory: `workdir=Path(\"/tmp/b8tex\")`\n\n#### Platform Not Supported\n\n**Problem**: `UnsupportedPlatformError` on auto-download\n\n**Solutions**:\n1. Install Tectonic manually for your platform\n2. Set `TECTONIC_PATH` to your manual installation\n3. Open an issue if you think your platform should be supported\n\n#### Slow Compilation\n\n**Problem**: Compilation is slower than expected\n\n**Solutions**:\n1. Enable caching (on by default): `TectonicCompiler(use_cache=True)`\n2. Use `only_cached=True` for offline/fast builds\n3. Reduce LaTeX reruns: `BuildOptions(reruns=1)`\n4. Check if cache is being invalidated unnecessarily\n5. See Performance Tips section below\n\n#### Cache Issues\n\n**Problem**: Cache not working or corrupted\n\n**Solutions**:\n1. Clear cache: `b8tex clean-cache` or `cache.clear()`\n2. Check cache stats: `cache.stats()`\n3. Verify cache directory exists: `~/.cache/b8tex/build_cache.db`\n4. Clean old entries: `cache.cleanup(max_age_days=30)`\n\n## FAQ\n\n### General\n\n**Q: Do I need to install LaTeX?**\nA: No! B8TeX uses Tectonic, which is a self-contained LaTeX distribution. You don't need TeX Live, MiKTeX, or any other LaTeX distribution.\n\n**Q: What Python versions are supported?**\nA: B8TeX requires Python 3.13 or later for modern type hints and language features.\n\n**Q: Is B8TeX production-ready?**\nA: B8TeX is currently in active development. The core API is stable, but advanced features are still being added. Check the version number and release notes.\n\n**Q: How does B8TeX compare to other LaTeX wrappers?**\nA: B8TeX focuses on modern Python features, type safety, and developer experience. It's built specifically for Tectonic and offers features like automatic binary management, build caching, and in-memory compilation.\n\n### Usage\n\n**Q: Can I compile LaTeX files from disk?**\nA: Yes! Use `Document.from_path(Path(\"document.tex\"))` or pass a Path object directly.\n\n**Q: How do I include images in my document?**\nA: Add images as resources:\n```python\nfrom b8tex import Document, Resource\ndoc = Document(\n    entrypoint=Path(\"main.tex\"),\n    resources=[Resource(Path(\"image.png\"))]\n)\n```\n\n**Q: Can I compile multiple documents in parallel?**\nA: Yes! Use the async API or Python's `concurrent.futures`. See `examples/04_async_compilation.py`.\n\n**Q: How do I use custom LaTeX packages?**\nA: Add them as resources with `kind=\"sty\"`:\n```python\nResource(Path(\"mypackage.sty\"), kind=\"sty\")\n```\n\n**Q: Can I compile without internet access?**\nA: Yes! Once Tectonic is installed and packages are cached, use `BuildOptions(only_cached=True)`.\n\n### Configuration\n\n**Q: Where is the cache directory?**\nA: Platform-dependent:\n- **macOS**: `~/Library/Caches/b8tex/`\n- **Linux**: `~/.cache/b8tex/`\n- **Windows**: `%LOCALAPPDATA%\\b8tex\\cache\\`\n\n**Q: How do I disable auto-download?**\nA: Set `B8TEX_NO_AUTO_DOWNLOAD=1` or `auto_download = false` in config file.\n\n**Q: Can I use a specific Tectonic version?**\nA: Yes! Set in config file:\n```toml\ntectonic_version = \"0.15.0\"\n```\nOr use: `b8tex install-binary --version=0.15.0`\n\n**Q: How do I change the output directory?**\nA: Use the `workdir` parameter:\n```python\nresult = compiler.compile_document(doc, workdir=Path(\"/tmp/output\"))\n```\n\n### Performance\n\n**Q: Why is the first compilation slow?**\nA: Tectonic downloads required LaTeX packages on first use. Subsequent compilations are much faster thanks to package caching.\n\n**Q: Does B8TeX cache compilation results?**\nA: Yes! Build caching is enabled by default. See `examples/05_cache_demo.py`.\n\n**Q: How much space does the cache use?**\nA: Check with `cache.stats()`. Typically 10-100MB depending on usage. Clean old entries with `cache.cleanup()`.\n\n## Performance Tips\n\n### 1. Enable Build Caching (Default)\n\nBuild caching can speed up repeated compilations by 10-100x:\n\n```python\nfrom b8tex import TectonicCompiler, BuildCache\n\n# Caching is enabled by default\ncompiler = TectonicCompiler(use_cache=True)\n\n# Or explicitly create cache\ncache = BuildCache()\ncompiler = TectonicCompiler(cache=cache)\n```\n\n**When cache helps**:\n- Repeated compilation of unchanged documents\n- CI/CD pipelines\n- Development with frequent rebuilds\n- Batch processing similar documents\n\n**Cache invalidation**: The cache automatically invalidates when:\n- Document content changes\n- Build options change\n- Tectonic version changes\n- Dependencies are modified\n\n### 2. Use Only-Cached Mode\n\nFor fastest compilation when all packages are already downloaded:\n\n```python\nfrom b8tex import BuildOptions\n\noptions = BuildOptions(only_cached=True)\nresult = compiler.compile_document(doc, options=options)\n```\n\nThis prevents Tectonic from downloading packages, ideal for offline work or CI.\n\n### 3. Reduce Reruns\n\nLaTeX sometimes needs multiple passes. Limit reruns for faster compilation:\n\n```python\noptions = BuildOptions(reruns=1)  # Default is automatic\n```\n\n**Trade-off**: Cross-references and bibliographies may not resolve correctly.\n\n### 4. Parallel Compilation\n\nFor batch processing, use async or parallel execution:\n\n```python\nfrom concurrent.futures import ThreadPoolExecutor\n\ndef compile_doc(content):\n    return compile_string(content)\n\nwith ThreadPoolExecutor(max_workers=4) as executor:\n    results = list(executor.map(compile_doc, documents))\n```\n\n**Speedup**: Near-linear with number of cores for independent documents.\n\n### 5. Persistent Workspaces\n\nReuse workspace directories to avoid file I/O:\n\n```python\nworkdir = Path(\"/tmp/b8tex_workspace\")\nworkdir.mkdir(exist_ok=True)\n\nfor doc in documents:\n    result = compiler.compile_document(doc, workdir=workdir)\n```\n\n### 6. In-Memory Compilation\n\nUse in-memory sources instead of file I/O when possible:\n\n```python\nfrom b8tex import InMemorySource, Document\n\ndoc = Document(\n    entrypoint=InMemorySource(\"doc.tex\", latex_content),\n    resources=[InMemorySource(\"style.sty\", style_content)]\n)\n```\n\n**Benefit**: Faster file operations, no disk cleanup needed.\n\n### 7. Cache Management\n\nKeep cache healthy with periodic cleanup:\n\n```python\n# Remove entries older than 30 days\ncache.cleanup(max_age_days=30)\n\n# Check cache size\nstats = cache.stats()\nprint(f\"Cache entries: {stats['total_entries']}\")\nprint(f\"Cache size: {stats['db_size_bytes'] / 1024 / 1024:.1f} MB\")\n\n# Clear if needed\nif stats['db_size_bytes'] > 100_000_000:  # > 100 MB\n    cache.clear()\n```\n\n### 8. Minimize Document Changes\n\nThe cache fingerprint includes all content. To maximize cache hits:\n- Use variables/templates for changing content\n- Separate frequently-changing content from static boilerplate\n- Consider using LaTeX's `\\input` for modular documents\n\n### Performance Benchmarks\n\nTypical compilation times on modern hardware:\n\n| Scenario | First Compile | Cached | Speedup |\n|----------|--------------|--------|---------|\n| Simple document (1 page) | 2-5s | 0.1-0.5s | 10-20x |\n| Medium document (10 pages) | 5-15s | 0.2-1s | 15-25x |\n| Large document (100 pages) | 15-60s | 1-3s | 15-30x |\n| With images/complex math | 10-30s | 0.5-2s | 15-20x |\n\n**Note**: First compile includes package downloads. Subsequent first compiles (different documents) are faster as packages are cached by Tectonic.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nContributions are welcome! Please:\n\n1. Fork the repository\n2. Create a feature branch\n3. Add tests for new features\n4. Ensure all tests pass and types check\n5. Submit a pull request\n\n## Acknowledgments\n\n- Built on top of the excellent [Tectonic](https://tectonic-typesetting.github.io/) LaTeX compiler\n- Inspired by modern Python packaging and type safety best practices\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A high-level Python wrapper for Tectonic LaTeX compiler with project-aware compilation",
    "version": "0.1.0",
    "project_urls": {
        "Documentation": "https://github.com/samehkamaleldin/pytex#readme",
        "Homepage": "https://github.com/samehkamaleldin/pytex",
        "Issues": "https://github.com/samehkamaleldin/pytex/issues",
        "Repository": "https://github.com/samehkamaleldin/pytex"
    },
    "split_keywords": [
        "compiler",
        " latex",
        " pdf",
        " tectonic",
        " typesetting"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e2604b6817b8c09cb0b0aed55f9ba27c33d718f0a563fd6d8a3b6da39238652d",
                "md5": "d36e57fe209e7966a7e238d8b077a887",
                "sha256": "b7cffe4d6b1cc86da99600985763a040a3c9d26c8da20d47626a0771c318ceab"
            },
            "downloads": -1,
            "filename": "b8tex-0.1.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "d36e57fe209e7966a7e238d8b077a887",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.13",
            "size": 56587,
            "upload_time": "2025-10-28T14:44:16",
            "upload_time_iso_8601": "2025-10-28T14:44:16.424911Z",
            "url": "https://files.pythonhosted.org/packages/e2/60/4b6817b8c09cb0b0aed55f9ba27c33d718f0a563fd6d8a3b6da39238652d/b8tex-0.1.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "775ce029e640496d9b786b3369c93b907b67f762806807bd2640fea1c212fd16",
                "md5": "a810eb1b658cb24d5506d9bf560216bf",
                "sha256": "c46b930316ff925956f6ea9d36177b758c1a7c7708f2671c130d58aa02e818d3"
            },
            "downloads": -1,
            "filename": "b8tex-0.1.0.tar.gz",
            "has_sig": false,
            "md5_digest": "a810eb1b658cb24d5506d9bf560216bf",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.13",
            "size": 19663974,
            "upload_time": "2025-10-28T14:44:21",
            "upload_time_iso_8601": "2025-10-28T14:44:21.431777Z",
            "url": "https://files.pythonhosted.org/packages/77/5c/e029e640496d9b786b3369c93b907b67f762806807bd2640fea1c212fd16/b8tex-0.1.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-28 14:44:21",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "samehkamaleldin",
    "github_project": "pytex#readme",
    "github_not_found": true,
    "lcname": "b8tex"
}
        
Elapsed time: 1.19076s