Compare commits

..
4 Commits
Author SHA1 Message Date
LeoVasanko f483cf978c Ruff format 2026-02-10 20:56:06 +00:00
LeoVasanko 0e12e3a531 Improved error message. 2026-02-10 19:51:05 +00:00
LeoVasanko 67bea9a2a7 Remove unnecessary bool() 2026-02-10 19:46:32 +00:00
LeoVasanko a05c8236f6 Format Python modules installed with ruff to target project style. 2026-02-10 19:34:35 +00:00
4 changed files with 62 additions and 31 deletions
+1 -1
View File
@@ -276,6 +276,6 @@ def _devmode_respond(request: Request, name=""):
return JSONResponse(
status_code=409,
content={
"detail": "Frontend assets served by Vite in debug mode. You are on backend, connect to frontend instead."
"detail": "[devmode] Not serving frontend files here. Should you connect to Vite instead?"
},
)
+56 -26
View File
@@ -26,9 +26,6 @@ import tomlkit
version = importlib.metadata.version("fastapi-vue-setup")
# Track Python files written/patched for ruff formatting
_python_files_to_format: list[Path] = []
# Template directory
TEMPLATE_DIR = Path(__file__).parent / "template"
@@ -41,21 +38,49 @@ def print_boxed(text: str) -> None:
print(f"{'' * width}")
def ruff_sort_imports(files: list[Path], dry: bool = False) -> None:
"""Run ruff to sort imports in the given Python files."""
if not files:
return
py_files = [str(f) for f in files if f.suffix == ".py" and f.exists()]
if not py_files:
return
if dry:
print(f"🔧 Would run ruff import sorting on {len(py_files)} files")
return
print("🔧 Ruff isort on modified files")
def ruff_format_content(content: str, target_path: Path) -> str:
"""Format Python content using ruff with project settings.
Writes to a temp file (.new.py) next to target, runs ruff check (import sorting)
and ruff format on it, reads back the result, and cleans up.
Returns the formatted content, or original if ruff fails.
"""
temp_file = target_path.with_suffix(".new.py")
try:
temp_file.write_text(content, "UTF-8", newline="\n")
# Sort imports first
subprocess.run(
[sys.executable, "-m", "ruff", "check", "--select", "I", "--fix", *py_files],
stdout=subprocess.DEVNULL,
[
"uv",
"run",
"--with",
"ruff",
"ruff",
"check",
"--select",
"I",
"--fix",
str(temp_file),
],
cwd=target_path.parent,
capture_output=True,
)
# Then format
result = subprocess.run(
["uv", "run", "--with", "ruff", "ruff", "format", str(temp_file)],
cwd=target_path.parent,
capture_output=True,
)
if result.returncode == 0:
return temp_file.read_text("UTF-8")
except Exception:
pass
finally:
try:
temp_file.unlink(missing_ok=True)
except Exception:
pass
return content
def uv_add_packages(
@@ -655,7 +680,6 @@ def patch_app_file(
return True
path.write_text(content, "UTF-8", newline="\n")
_python_files_to_format.append(path)
print(f"✅ Patched {path}")
if not lifespan_patched:
@@ -903,13 +927,20 @@ def write_file(
the content will be written to fallback_path instead of being skipped.
If force=True, always overwrite without checking for upgrade marker.
Python files (.py) are automatically formatted using ruff with the project's
settings before writing.
"""
# Format Python content using project settings before any comparison/writing
if path.suffix == ".py":
content = ruff_format_content(content, path)
exists = path.exists()
if exists and not overwrite:
print(f"⚠️ Skipping {path} (exists)")
return False
# Check if content is the same
# Check if content is the same (new content already formatted)
if exists:
existing_content = path.read_text("UTF-8")
if existing_content == content:
@@ -935,8 +966,6 @@ def write_file(
path.write_text(content, "UTF-8", newline="\n")
if executable and sys.platform != "win32":
path.chmod(path.stat().st_mode | 0o111)
if path.suffix == ".py":
_python_files_to_format.append(path)
action = "Updated" if exists else "Created"
print(f"{action} {path}")
return True
@@ -949,10 +978,14 @@ def _write_fallback_file(
dry: bool,
executable: bool,
) -> bool:
"""Write content to a fallback .new.py file when original can't be overwritten."""
# Check if fallback already has same content
"""Write content to a fallback .new.py file when original can't be overwritten.
Note: content should already be formatted before calling this function.
"""
# Check if fallback already has same content (content already formatted)
if fallback_path.exists():
if fallback_path.read_text("UTF-8") == content:
existing_content = fallback_path.read_text("UTF-8")
if existing_content == content:
print(f"✔️ {fallback_path} (already up to date)")
return False
@@ -965,8 +998,6 @@ def _write_fallback_file(
fallback_path.write_text(content, "UTF-8", newline="\n")
if executable and sys.platform != "win32":
fallback_path.chmod(fallback_path.stat().st_mode | 0o111)
if fallback_path.suffix == ".py":
_python_files_to_format.append(fallback_path)
print(f"✅ Created {fallback_path} (original customized by user)")
_new_files_written.append((fallback_path, original_path))
return True
@@ -1440,7 +1471,6 @@ def cmd_setup(args: argparse.Namespace) -> int:
print("✅ Created .gitignore")
# === Add dependencies using uv ===
ruff_sort_imports(_python_files_to_format, dry=dry)
if dry:
print("📦 Would add: fastapi[standard], fastapi-vue, httpx (dev only)")
else:
+1 -1
View File
@@ -5,7 +5,7 @@ import os
from fastapi_vue import server
DEFAULT_PORT = TEMPLATE_DEFAULT_PORT
DEVMODE = bool(os.getenv("ENVPREFIX_DEV") == "1")
DEVMODE = os.getenv("ENVPREFIX_DEV") == "1"
def main():
+2 -1
View File
@@ -56,7 +56,8 @@ def main():
epilog=HELP_EPILOG,
)
parser.add_argument(
"-l", "--listen",
"-l",
"--listen",
metavar="host:port",
help=f"Vite (default: localhost:{DEFAULT_VITE_PORT})",
)