Coverage for vibefpmgui/formatter.py: 73%
27 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-01 20:51 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-01 20:51 +0000
1"""Formatting Fortran files in the editor with fprettify.
3`fprettify <https://github.com/fortran-lang/fprettify>`_ reads the editor's
4text on stdin and writes the formatted text to stdout, so unsaved changes are
5formatted too and the result is one undoable edit. It runs in the folder of
6the file, so a ``.fprettify.rc`` there (or in a parent folder, or ``~``)
7applies. Like fortitude, it only understands free-form Fortran.
8"""
10from __future__ import annotations
12import os
13import shutil
14import subprocess
15from pathlib import Path
17from .console import NO_WINDOW
18from .lint import LINT_EXTS
20FORMAT_EXTS = LINT_EXTS
23def executable() -> str | None:
24 return shutil.which("fprettify")
27def can_format(path: Path) -> bool:
28 return path.suffix.lower() in FORMAT_EXTS
31def format_text(text: str, path: Path, timeout: float = 60) -> tuple[str | None, str]:
32 """(formatted text, "") or (None, why it failed)."""
33 program = executable()
34 if program is None: 34 ↛ 35line 34 didn't jump to line 35 because the condition on line 34 was never true
35 return None, "fprettify was not found on the PATH."
36 # fprettify's own regexes trigger SyntaxWarnings on newer Pythons.
37 env = dict(os.environ, PYTHONWARNINGS="ignore")
38 try:
39 out = subprocess.run([program, "-"], input=text, capture_output=True, text=True,
40 encoding="utf-8", errors="replace", cwd=path.parent,
41 timeout=timeout, env=env, check=False, **NO_WINDOW)
42 except (OSError, subprocess.SubprocessError) as exc:
43 return None, str(exc)
44 if out.returncode != 0: 44 ↛ 45line 44 didn't jump to line 45 because the condition on line 44 was never true
45 lines = [line for line in out.stderr.splitlines() if line.strip()]
46 return None, lines[-1] if lines else f"fprettify exited with code {out.returncode}"
47 if text.strip() and not out.stdout.strip(): 47 ↛ 48line 47 didn't jump to line 48 because the condition on line 47 was never true
48 return None, "fprettify returned no text."
49 return out.stdout, ""