Metadata-Version: 2.4
Name: EmBracePy
Version: 1.0.3
Summary: Brace-delimited Python source lowered to ordinary Python.
Author: EmBrace contributors
License-Expression: MIT
Keywords: python,bython,compiler,transpiler,braces
Classifier: Development Status :: 3 - Alpha
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Compilers
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: hypothesis; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: ruff; extra == "dev"
Requires-Dist: twine; extra == "dev"
Provides-Extra: tooling
Requires-Dist: ruff; extra == "tooling"
Requires-Dist: mypy; extra == "tooling"
Provides-Extra: jupyter
Requires-Dist: ipykernel; extra == "jupyter"
Dynamic: license-file

# EmBrace <img src="assets/embrace-logo.png" alt="" width="48" height="48" align="absmiddle">

> [!WARNING]
> **Alpha state!** This is a small experiment for scripts, demos, and the
> silly "what if Python had braces?" idea. <br>
> (Please) Do not use it as the basis for
> a serious codebase.

Python stays Python here, but EmBrace changes the visuals!<br>Statement bodies may now use `{}` instead of indents!!<br><br>
It transforms `.pybr` and legacy `.by` files into ordinary
Python, then lets CPython parse and run the result.

## Three ways to write the same code

Python:

```python
if not ready or fallback:
    print("go")
```

`strict` keeps the Python expression and puts braces around the suite:

```python
if not ready or fallback {
    print("go")
}
```

`cstyle` accepts the punctuation too:

```python
if !ready || fallback {
    print("go")
}
```

It also understands lowercase `true`, `false`, and `null`, plus
`else if` and a small set of typed declarations.

## The syntax!

```python
from __future__ import braces

def greet(name: str) {

    if name {
        return f"Hello, {name}!"
    }

    return "Hello!"
}
```

That is the whole change!

Run directly:

```console
embrace app.pybr
```

The explicit form is still available for modules, stdin, and inline source:

```console
embrace run -m package.module -- argument
embrace run -c $'if ready {\n    print("ready")\n}' --assume-braces
embrace run - --assume-braces -- input.txt < app.pybr
```

Arguments after `--` are passed to the program as separate `argv` values.

The braces marker is removed automatically. If you pass
`--assume-braces` to a file that already has `from __future__ import braces`,
EmBrace will gently point out that the braces have, in fact, arrived:

```console
embrace app.pybr --assume-braces
embrace: braces are already here; --assume-braces can take the day off
```

## Install

EmBrace targets CPython 3.11 through 3.14. It has no runtime dependencies.
Python 3.15 is an advisory prerelease target

### From PyPI (after publication)

Use a virtual environment for a normal install:

```console
python -m venv .venv
source .venv/bin/activate       # Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install EmBracePy==1.0.3
embrace --version
```

### From the repository

```console
git clone https://github.com/NotSoNymos/EmBrace.git
cd EmBrace
python -m venv .venv
source .venv/bin/activate       # Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e '.[dev]'
embrace --version
```

For a local user install, `python -m pip install -e .` is enough. The `dev`
extra adds the test, lint, type-checking, and release tools.

## Examples

For a quick check, start the brace-aware interpreter
file:

```console
embrace
embrace>>> value = 41
embrace>>> value + 1
42
embrace>>> def greet(name) {
...     return f"hello {name}"
... }
embrace>>> greet("brace")
'hello brace'
embrace>>> :quit
```

`embrace repl` does the same thing. Use `:help` for the small list of commands;
`:quit`, `exit()`, and `quit()` leave the interpreter. A blank line is not
needed to close a brace block. Type `}` on its own line.

Create `app.pybr`:

```python
from __future__ import braces

def main() {
    print("hello")
}

if __name__ == "__main__" {
    main()
}
```

Run it and pass arguments:

```console
embrace app.pybr -- input.txt --verbose
```

Check or generate ordinary Python without executing the source:

```console
embrace check src/
embrace transpile app.pybr --stdout
embrace transpile src/ --out-dir build/generated --emit-source-map
embrace transpile src/ --out-dir build/generated --check
```

Convert ordinary Python back to brace syntax:

```console
embrace reverse module.py --stdout
embrace reverse module.py --in-place
embrace reverse package/ --out-dir brace-src --style allman --profile bython
embrace format app.pybr --check
embrace format app.pybr --profile cstyle --check
```

The `bython`, `by2py`, and `py2by` commands remain available for older
projects. Use `embrace --help` for the complete option list. Project defaults
can be set in a nearby `pyproject.toml` under `[tool.embrace]`; command-line
options take precedence.

## If you really want imports

Install a scoped hook around code that imports brace modules:

```python
from embrace import install_import_hook

with install_import_hook():
    import application
```

Normal `.py` resolution wins. The hook checks `.pybr` and `.by` only when the
regular import machinery did not find a module.

## Known limits

Stock Python does not understand the future-like `braces` marker or brace
suites, so `python app.pybr` is not a supported entry point. Use `embrace
app.pybr`, the explicit `embrace run` form, the scoped import hook, or
transpile a tree to ordinary `.py` files.

EmBrace executes Python with the caller's permissions. It is not a sandbox for
untrusted code. Use a separate process or container when isolation is needed.

Formatter, LSP, Jupyter, mixed brace and indentation suites, inline suites,
and optional chaining are outside this alpha release.

## Docs

The English Starlight documentation is the primary reference.

- [Getting started](docs-site/src/content/docs/getting-started.md)
- [Language rules](docs-site/src/content/docs/language.md)
- [CLI reference](docs-site/src/content/docs/cli.md)
- [Compatibility and migration](docs-site/src/content/docs/compatibility.md)
- [Release and acceptance evidence](docs-site/src/content/docs/acceptance-evidence.md)
- [VS Code support](editors/vscode/README.md)
- [PyCharm support](editors/pycharm/README.md)

For normal PyCharm use, install the standalone plugin described in
[the PyCharm guide](editors/pycharm/README.md).

## Hacking on it

```console
python -m pytest --cov=embrace --cov-branch --cov-fail-under=95
python tools/coverage_gate.py
python tools/fuzz_smoke.py
python tools/performance_check.py
python tools/release_build.py dist --no-isolation
python -m ruff check .
python -m mypy --strict src/embrace
```

## Inspiration

The [Bython repository](https://github.com/mathialo/bython)!!!
