Metadata-Version: 2.4
Name: go-embed-py
Version: 0.1.0
Summary: Go-style file embedding for Python — embed static files into generated Python modules at build time
Project-URL: Homepage, https://github.com/thirukguru/go-embed-py
Project-URL: Repository, https://github.com/thirukguru/go-embed-py
Project-URL: Issues, https://github.com/thirukguru/go-embed-py/issues
Project-URL: Documentation, https://github.com/thirukguru/go-embed-py#readme
Project-URL: Changelog, https://github.com/thirukguru/go-embed-py/blob/main/CHANGELOG.md
Author-email: Thiruthanikan <thirukguru@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: assets,binary,build-tool,bundle,codegen,embed,go-embed,static
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Build Tools
Classifier: Topic :: Software Development :: Code Generators
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# staticembed

[![PyPI](https://img.shields.io/pypi/v/staticembed)](https://pypi.org/project/staticembed/)
[![Python](https://img.shields.io/pypi/pyversions/staticembed)](https://pypi.org/project/staticembed/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

**Go-style file embedding for Python.** Embed static files into generated Python modules at build time. At runtime, everything is in-memory — zero filesystem access.

```
Go:     //go:embed schema.sql       →  var schema []byte
Python: # staticembed: schema.sql   →  SCHEMA: bytes
```

## Why?

Python has `importlib.resources` for accessing package data, but it still reads from the filesystem at runtime. If you want **true embedding** — data baked into your code as byte literals, no `open()`, no `Path`, no filesystem dependency — you need a code generation step. That's what `staticembed` does.

**Use cases:**
- SQL schemas, migrations, and queries
- HTML/Jinja templates
- Default config files (JSON, YAML, TOML)
- Binary assets (icons, fonts, wasm)
- Anything you'd `//go:embed` in Go

## Install

```bash
pip install staticembed
```

## Quick Start

### Option 1: One-liner API

```python
# build_embed.py — run once at build time
from staticembed import embed_files

embed_files({
    "SCHEMA": "sql/schema.sql",
    "TEMPLATES": "templates/*.html",
    "CONFIG": "static/defaults.json",
}, root_dir="assets", as_string=True)
```

Then in your application:

```python
from _embedded import SCHEMA, TEMPLATES, CONFIG

print(CONFIG)  # str — zero file I/O
```

### Option 2: Go-style Directives

Add `# staticembed:` comments to your source file:

```python
# app.py

# staticembed: sql/schema.sql
SCHEMA: bytes

# staticembed: templates/*.html
TEMPLATES: dict[str, bytes]

# staticembed: static/config.json -> CONFIG string
```

Generate the embed module:

```bash
staticembed generate --source app.py --root assets/
```

### Option 3: CLI Only

```bash
staticembed generate \
    --root ./assets \
    --output _embedded.py \
    --string \
    -f SCHEMA=sql/schema.sql \
       TEMPLATES="templates/*.html" \
       CONFIG=static/config.json
```

## Directive Syntax

```
# staticembed: <glob> [-> VAR_NAME] [string] [compress]
```

| Part | Required | Description |
|------|----------|-------------|
| `<glob>` | Yes | File path or glob pattern |
| `-> VAR_NAME` | No | Explicit variable name (auto-derived from filename otherwise) |
| `string` | No | Decode as UTF-8 `str` instead of `bytes` |
| `compress` | No | zlib compress (smaller module, tiny runtime cost) |

**Annotation style** — variable name + type hint on the next line:

```python
# staticembed: sql/schema.sql
SCHEMA: bytes

# staticembed: templates/*.html
TEMPLATES: dict[str, bytes]

# staticembed: config.json
CONFIG: str          # ← 'str' annotation enables string mode automatically
```

## Features

- **Glob support**: `*.html`, `sql/**/*.sql`, `static/*`
- **Single file → variable**, **glob → `dict[str, bytes|str]`**
- **Compression**: `--compress` flag → zlib level 9
- **String decode**: `--string` flag → UTF-8 `str`
- **Binary safe**: images, fonts, wasm, protobuf — anything
- **Manifest**: SHA-256 hashes + sizes for cache invalidation
- **AST validation**: generated code is syntax-checked before writing
- **Inspect mode**: preview what would be embedded without generating
- **Zero dependencies**: stdlib only, Python 3.9+

## CLI Reference

```bash
# Generate from source directives
staticembed generate --source app.py --root ./data

# Generate from CLI args
staticembed generate -f SCHEMA=sql/*.sql CONFIG=config.json --root .

# With compression
staticembed generate -f DATA=big_file.json --compress --root .

# As strings instead of bytes
staticembed generate -f PAGES="*.html" --string --root .

# Inspect (dry run)
staticembed inspect --source app.py --root ./data
staticembed inspect -f SCHEMA=sql/*.sql --root .

# Version
staticembed --version
```

## Integration

### Makefile

```makefile
embed:
	staticembed generate --source app.py --root assets/

build: embed
	pyinstaller --onefile app.py
```

### pyproject.toml (hatch build hook)

```toml
[tool.hatch.build.hooks.custom]
path = "build_hooks.py"
```

```python
# build_hooks.py
from staticembed import embed_files

embed_files({"SCHEMA": "sql/*.sql"}, root_dir="src/assets")
```

### Pre-commit / CI

```yaml
# .github/workflows/embed.yml
- run: pip install staticembed
- run: staticembed generate --source src/app.py --root assets/
- run: git diff --exit-code _embedded.py  # fail if stale
```

## Go ↔ Python Comparison

| Go | staticembed |
|----|-------------|
| `//go:embed schema.sql` | `# staticembed: schema.sql` |
| `var schema []byte` | `SCHEMA: bytes` |
| `//go:embed static/*` | `# staticembed: static/*` |
| `var static embed.FS` | `STATIC: dict[str, bytes]` |
| Compile-time | Build-time (pre-step) |
| In binary | In generated `.py` module |

## API Reference

### `embed_files(file_map, root_dir=".", output="_embedded.py", compress=False, as_string=False)`

One-liner API. Maps variable names to file paths/globs. Returns `Path` to the generated module.

### `embed_from_source(source_path, root_dir=None, output="_embedded.py", compress=False)`

Parses `# staticembed:` directives from a Python source file. Returns `Path`.

### `generate(spec: EmbedSpec) -> str`

Low-level: returns the generated module source as a string.

### `parse_directives(source_path: Path) -> list[EmbedDirective]`

Extract directives from a source file without generating.

### `resolve_files(root: Path, pattern: str) -> list[tuple[str, bytes]]`

Resolve a glob pattern and read matching files.

## Contributing

```bash
git clone https://github.com/thirukguru/staticembed
cd staticembed
pip install -e ".[dev]"
pytest
```

## License

MIT
