| Name | b8tex JSON |
| Version |
0.1.0
JSON |
| download |
| home_page | None |
| Summary | A high-level Python wrapper for Tectonic LaTeX compiler with project-aware compilation |
| upload_time | 2025-10-28 14:44:21 |
| maintainer | None |
| docs_url | None |
| author | None |
| requires_python | >=3.13 |
| license | MIT |
| 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"
}