From 7286ba6ea9d4623c65fc99e9e960aaf1226add62 Mon Sep 17 00:00:00 2001 From: KeshavAnandCode Date: Fri, 15 May 2026 19:06:09 -0500 Subject: [PATCH] readmes and mds plus fixed ruff --- CONTRIBUTING.md | 51 +++++++++++ README.md | 89 +++++++++++++++++++ packages/foreignthon/pyproject.toml | 4 + packages/foreignthon/src/foreignthon/cli.py | 12 ++- .../foreignthon/src/foreignthon/errors.py | 2 +- 5 files changed, 153 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e69de29..c6cfe89 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -0,0 +1,51 @@ +# Contributing to ForeignThon + +## Project structure +foreignthon/ +├── packages/ +│ ├── foreignthon/ # core engine + fpy CLI +│ │ ├── src/foreignthon/ +│ │ │ ├── cli.py # fpy commands +│ │ │ ├── transpiler.py # tokenizer-based transpiler +│ │ │ ├── pack.py # language pack loader +│ │ │ └── errors.py # bilingual error hook +│ │ └── tests/ +│ └── langs/ +│ └── es/ # Spanish language pack +│ └── src/foreignthon_es/es.json + +## Setting up + +```bash +python -m venv .venv && source .venv/bin/activate +pip install -e "packages/foreignthon[dev]" +pip install -e packages/langs/es +``` + +## Running tests + +```bash +pytest packages/foreignthon/tests/ -v +``` + +## Adding a new language pack + +1. Copy `packages/langs/es/` to `packages/langs//` +2. Rename `foreignthon_es` → `foreignthon_` throughout +3. Fill in `.json` following the same schema as `es.json` +4. Validate it: `fpy pack packages/langs//src/foreignthon_/.json` +5. Add tests if the language has tricky characters or edge cases +6. Open a PR or publish independently as `foreignthon-` on PyPI + +## Language pack schema + +Every pack must have these top-level keys: +`meta`, `keywords`, `builtins`, `exceptions`, `error_messages`, `stdlib` + +See `packages/langs/es/src/foreignthon_es/es.json` as the reference. + +## Code style + +```bash +ruff check packages/foreignthon/src +``` diff --git a/README.md b/README.md index e69de29..c05d196 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,89 @@ +DME.md << 'EOF' +# ForeignThon + +Write Python in any human language. ForeignThon transpiles `.es.py`, `.ta.py` (and more) files into standard Python — keywords, builtins, exceptions, all of it. + +```python +# hola.es.py +definir saludar(nombre): + retornar f"Hola, {nombre}!" + +para i en rango(3): + imprimir(saludar(f"mundo {i}")) +``` + +```bash +fpy run hola.es.py +# Hola, mundo 0! +# Hola, mundo 1! +# Hola, mundo 2! +``` + +## Installation + +```bash +pip install foreignthon +pip install foreignthon-es # Spanish +pip install foreignthon-ta # Tamil +``` + +## Usage + +```bash +fpy run script.es.py # transpile and run +fpy compile script.es.py # output a .compiled.py file +fpy check script.es.py # validate without running +fpy pack mylang.json # validate a language pack +``` + +### Language override + +```python +# foreignthon: es +# ^ overrides the file extension +``` + +Or via CLI flag: + +```bash +fpy run script.py --lang es +``` + +## Errors + +Errors are shown in your language first, English below: +[ES] ErrorDeDivisionCero: Error: división por cero +[EN] ZeroDivisionError: division by zero + +## Language Packs + +A language pack is a JSON file + a tiny Python wrapper published as `foreignthon-xx` on PyPI. +See `packages/langs/es/` for the reference implementation. + +The JSON covers: +- **keywords** — `si → if`, `para → for`, `definir → def` … +- **builtins** — `imprimir → print`, `rango → range` … +- **exceptions** — `ErrorDeValor → ValueError` … +- **error_messages** — bilingual error output +- **stdlib** — `matematicas → math` … + +Validate your pack before publishing: + +```bash +fpy pack mylang.json +``` + +## Development + +```bash +git clone +cd foreignthon +python -m venv .venv && source .venv/bin/activate +pip install -e "packages/foreignthon[dev]" +pip install -e packages/langs/es +pytest packages/foreignthon/tests/ -v +``` + +## License + +GPL diff --git a/packages/foreignthon/pyproject.toml b/packages/foreignthon/pyproject.toml index 7a74077..c85d9f7 100644 --- a/packages/foreignthon/pyproject.toml +++ b/packages/foreignthon/pyproject.toml @@ -52,3 +52,7 @@ src = ["src"] [tool.ruff.lint] select = ["E", "F", "I"] +ignore = ["E501"] + +[tool.ruff.lint.per-file-ignores] +"pack.py" = ["E501"] diff --git a/packages/foreignthon/src/foreignthon/cli.py b/packages/foreignthon/src/foreignthon/cli.py index b2b5e82..4fa694d 100644 --- a/packages/foreignthon/src/foreignthon/cli.py +++ b/packages/foreignthon/src/foreignthon/cli.py @@ -7,7 +7,7 @@ import click from . import __version__ from .errors import activate -from .transpiler import transpile_file, run_transpiled +from .transpiler import run_transpiled, transpile_file @click.group() @@ -20,7 +20,7 @@ def main(): @main.command() @click.argument("file", type=click.Path(exists=True, path_type=Path)) @click.option("--lang", "-l", default=None, help="Override language code (e.g. es, ta)") -@click.option("--keep", is_flag=True, help="Keep the compiled .py file alongside the source") +@click.option("--keep", is_flag=True, help="Keep the compiled .py alongside the source") def run(file: Path, lang: str | None, keep: bool): """Transpile and run a foreign-language Python file.""" if lang: @@ -44,12 +44,15 @@ def run(file: Path, lang: str | None, keep: bool): @main.command() @click.argument("file", type=click.Path(exists=True, path_type=Path)) -@click.option("--output", "-o", default=None, help="Output path (default: same dir as source)") +@click.option("--output", "-o", default=None, help="Output path (default: beside source)") def compile(file: Path, output: str | None): """Transpile a file to standard Python without running it.""" transpiled = transpile_file(file) - out_path = Path(output) if output else file.with_suffix("").with_suffix(".compiled.py") + out_path = ( + Path(output) if output + else file.with_suffix("").with_suffix(".compiled.py") + ) out_path.write_text(transpiled, encoding="utf-8") click.echo(f"Compiled: {out_path}") @@ -77,6 +80,7 @@ def check(file: Path): def validate_pack(json_file: Path): """Validate a language pack JSON file.""" import json + from .pack import REQUIRED_SECTIONS with open(json_file, encoding="utf-8") as f: diff --git a/packages/foreignthon/src/foreignthon/errors.py b/packages/foreignthon/src/foreignthon/errors.py index 7f88d5a..802ef89 100644 --- a/packages/foreignthon/src/foreignthon/errors.py +++ b/packages/foreignthon/src/foreignthon/errors.py @@ -3,7 +3,7 @@ from __future__ import annotations import sys import traceback -from .pack import load_pack, PackNotFoundError +from .pack import PackNotFoundError, load_pack _active_lang: str | None = None