added source maps
This commit is contained in:
@@ -1,15 +1,13 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import runpy
|
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import click
|
import click
|
||||||
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from .errors import activate
|
from .errors import activate
|
||||||
from .transpiler import transpile_file
|
from .transpiler import transpile_file, run_transpiled
|
||||||
|
|
||||||
|
|
||||||
@click.group()
|
@click.group()
|
||||||
@@ -26,15 +24,13 @@ def main():
|
|||||||
def run(file: Path, lang: str | None, keep: bool):
|
def run(file: Path, lang: str | None, keep: bool):
|
||||||
"""Transpile and run a foreign-language Python file."""
|
"""Transpile and run a foreign-language Python file."""
|
||||||
if lang:
|
if lang:
|
||||||
# Inject shebang override so transpiler picks it up
|
|
||||||
source = file.read_text(encoding="utf-8")
|
source = file.read_text(encoding="utf-8")
|
||||||
if not source.startswith("# foreignthon:"):
|
if not source.startswith("# foreignthon:"):
|
||||||
source = f"# foreignthon: {lang}\n" + source
|
source = f"# foreignthon: {lang}\n" + source
|
||||||
file.write_text(source, encoding="utf-8")
|
file.write_text(source, encoding="utf-8")
|
||||||
|
|
||||||
transpiled = transpile_file(file)
|
transpiled = transpile_file(file)
|
||||||
|
|
||||||
# Detect lang for error hook
|
|
||||||
detected_lang = lang or _lang_from_file(file)
|
detected_lang = lang or _lang_from_file(file)
|
||||||
activate(detected_lang)
|
activate(detected_lang)
|
||||||
|
|
||||||
@@ -43,17 +39,7 @@ def run(file: Path, lang: str | None, keep: bool):
|
|||||||
out_path.write_text(transpiled, encoding="utf-8")
|
out_path.write_text(transpiled, encoding="utf-8")
|
||||||
click.echo(f"Compiled: {out_path}")
|
click.echo(f"Compiled: {out_path}")
|
||||||
|
|
||||||
# Write to a temp file and run it — runpy keeps __file__ correct
|
run_transpiled(file, transpiled)
|
||||||
with tempfile.NamedTemporaryFile(
|
|
||||||
suffix=".py", mode="w", encoding="utf-8", delete=False
|
|
||||||
) as tmp:
|
|
||||||
tmp.write(transpiled)
|
|
||||||
tmp_path = tmp.name
|
|
||||||
|
|
||||||
try:
|
|
||||||
runpy.run_path(tmp_path, run_name="__main__")
|
|
||||||
finally:
|
|
||||||
Path(tmp_path).unlink(missing_ok=True)
|
|
||||||
|
|
||||||
|
|
||||||
@main.command()
|
@main.command()
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ def transpile(source: str, lang_code: str) -> str:
|
|||||||
|
|
||||||
def transpile_file(path: Path) -> str:
|
def transpile_file(path: Path) -> str:
|
||||||
"""
|
"""
|
||||||
Detect language from file extension (.es.py → es),
|
Detect language from file extension (.es.py -> es),
|
||||||
read the file, and return transpiled Python source.
|
read the file, and return transpiled Python source.
|
||||||
"""
|
"""
|
||||||
lang_code = _detect_lang(path)
|
lang_code = _detect_lang(path)
|
||||||
@@ -64,8 +64,33 @@ def transpile_file(path: Path) -> str:
|
|||||||
return transpile(source, lang_code)
|
return transpile(source, lang_code)
|
||||||
|
|
||||||
|
|
||||||
|
def run_transpiled(original_path: Path, transpiled: str) -> None:
|
||||||
|
"""
|
||||||
|
Execute transpiled source while making tracebacks point
|
||||||
|
to the original .es.py file, not a temp file.
|
||||||
|
"""
|
||||||
|
import linecache
|
||||||
|
|
||||||
|
filename = str(original_path.resolve())
|
||||||
|
|
||||||
|
# Register original source lines so traceback displays them correctly
|
||||||
|
original_lines = original_path.read_text(encoding="utf-8").splitlines(keepends=True)
|
||||||
|
linecache.cache[filename] = (
|
||||||
|
len(original_lines),
|
||||||
|
None,
|
||||||
|
original_lines,
|
||||||
|
filename,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Compile with original filename — this is what sets it in the traceback
|
||||||
|
code = compile(transpiled, filename, "exec")
|
||||||
|
|
||||||
|
glob = {"__file__": filename, "__name__": "__main__"}
|
||||||
|
exec(code, glob)
|
||||||
|
|
||||||
|
|
||||||
def _detect_lang(path: Path) -> str:
|
def _detect_lang(path: Path) -> str:
|
||||||
"""Extract lang code from extension, e.g. script.es.py → es."""
|
"""Extract lang code from extension, e.g. script.es.py -> es."""
|
||||||
suffixes = path.suffixes # e.g. ['.es', '.py']
|
suffixes = path.suffixes # e.g. ['.es', '.py']
|
||||||
if len(suffixes) >= 2 and suffixes[-1] == ".py":
|
if len(suffixes) >= 2 and suffixes[-1] == ".py":
|
||||||
return suffixes[-2].lstrip(".")
|
return suffixes[-2].lstrip(".")
|
||||||
|
|||||||
Reference in New Issue
Block a user