industrial-readers 0.1.0
Fast, cross-platform readers for .txt, .xlsx/.xls, .docx/.doc, .pptx/.ppt implemented in Rust via PyO3 and packaged with maturin.
License: MIT
Requires Python: >=3.8

# industrial_readers

**Industrial-grade document readers for Python**, implemented in Rust with [PyO3](https://pyo3.rs/) and packaged using [maturin](https://www.maturin.rs/).  
Supports:

- **Text**: `.txt`
- **Spreadsheets**: `.xlsx`, `.xls` (via `calamine`)
- **Word**: `.docx` (via `docx-parser`), `.doc` (best-effort UTF‑16LE text extraction)
- **PowerPoint**: `.pptx` (via `pptx-to-md`), `.ppt` (best-effort UTF‑16LE text extraction)
- **PDF**: `.pdf` (plain-text extraction via `pdf-extract`)
- **Images**: `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.ico`, `.tiff`, `.webp` (basic metadata via `image`)

> Legacy binary formats (`.doc` and `.ppt`) are parsed **best-effort** by scanning for UTF‑16LE text. This is robust for plain text extraction but does **not** recover full formatting or embedded objects. If you need full-fidelity parsing of legacy formats, consider first converting them to OOXML (`.docx/.pptx`).

## Install (developers)

This project builds universal **abi3** wheels for CPython ≥ 3.8 on **Windows** and **Linux**.

```bash
# 1) Create a virtualenv (recommended)
python -m venv .venv && . .venv/bin/activate  # Windows: .venv\Scripts\activate

# 2) Install maturin
pip install maturin

# 3) Build a wheel
# Linux: build manylinux-compliant wheel (requires Docker if you don't have a manylinux host)
maturin build --release --compatibility manylinux_2_28

# Windows: regular build
maturin build --release

# 4) Install the generated wheel (found in target/wheels/)
pip install target/wheels/industrial_readers-*.whl
```

See the maturin docs for additional options and platform tags.

## Python usage

```python
import industrial_readers as ir

# Read anything (format is auto-detected by signature, not just extension)
obj = ir.read_any("sample.xlsx")
print(type(obj))  # Python dicts/lists/strings depending on format

# Format-specific readers
sheets = ir.read_xlsx("sample.xlsx")     # [{'name': ..., 'nrows': ..., 'ncols': ..., 'rows': [[...], ...]}, ...]
docx   = ir.read_docx("sample.docx")     # {'markdown': '...', 'json': '...'}
pptx   = ir.read_pptx("sample.pptx")     # [{'index': 1, 'markdown': '...'}, ...]
text   = ir.read_txt("sample.txt")       # '...'

# PDF and images
pdf_text = ir.read_pdf("sample.pdf")      # plain text content
img_info = ir.read_image("sample.png")    # {'width': ..., 'height': ..., 'color_type': '...', 'format': '...'}

# Legacy formats (best-effort plain text):
doc_text = ir.read_doc("sample.doc")
ppt_text = ir.read_ppt("sample.ppt")

# Optional config (limits & legacy tuning)
cfg = ir.ReaderConfig(max_rows_per_sheet=10_000, max_cells_per_sheet=1_000_000, legacy_min_run=4)
obj = ir.read_any("big.xlsx", cfg)
```

### Additional APIs

```python
# Explicit format detection (by signatures, not just extension)
fmt = ir.detect("mystery_file.bin")   # e.g. "xlsx", "docx", "pptx", "txt", ...

# Dedicated XLS reader (same structure as read_xlsx)
xls_sheets = ir.read_xls("legacy.xls")
```

### Encryption helpers

```python
import industrial_readers as ir

# Generate a fresh random 32-byte key
key = ir.generate_key()          # bytes

# High-level helpers: .sequa files
enc_path = ir.encrypt_to_sequa("secret.txt", key)  # -> "secret.txt.sequa"
dec_path = ir.decrypt_sequa(enc_path, key)          # -> "secret.txt"

# Lower-level helpers: explicit output paths
ir.encrypt_file("secret.txt", "secret.bin", key)
ir.decrypt_file("secret.bin", "secret.txt", key)
```

## Safety & limits

- OOXML readers (`.xlsx`, `.docx`, `.pptx`) rely on well-maintained, pure-Rust crates.
- `.doc`/`.ppt` are parsed via **UTF‑16LE text scanning**; this avoids unsafe native deps and keeps wheels portable.
- `ReaderConfig` lets you cap rows/cells to prevent memory blowups.

## License

MIT