Pi66

merodi
A markdown-based static site generator.
git clone https://git.pi66.xyz/merodi

← back to log

refactor:simplify error handling

author: pixel
date: 2026-07-22 09:36
hash: 8419e5839c3f5205e3ed3553bde215a64e0d4b57

Diffstat:

M

src/errors.py
60 ++++++++++++++++--------------
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
diff --git a/src/errors.py b/src/errors.py
index debf659..8f94fcd 100644
--- a/src/errors.py
+++ b/src/errors.py
@@ -5,53 +5,55 @@ import traceback
 from .log import *
 from . import settings

-def get_user_frame(exc: Exception):
+def get_user_frame(exc):
     tb = traceback.extract_tb(exc.__traceback__)
     for frame in reversed(tb):
         if "site-packages" not in frame.filename and "<frozen" not in frame.filename:
             return frame
-    if not tb:
-        return None
-    return tb[-1]
+    return tb[-1] if tb else None

-def get_error_line(exc: Exception):
+def get_error_line(exc):
+    from jinja2 import TemplateSyntaxError
+    if isinstance(exc, TemplateSyntaxError) and exc.source:
+        lines = exc.source.splitlines()
+        n = exc.lineno or 1
+        if n <= len(lines):
+            return lines[n - 1].strip()
     if hasattr(exc, 'source') and exc.source:
         lines = exc.source.splitlines()
-        lineno = getattr(exc, 'lineno', 1) or 1
-        if lineno <= len(lines):
-            return lines[lineno - 1].strip()
+        n = getattr(exc, 'lineno', 1) or 1
+        if n <= len(lines):
+            return lines[n - 1].strip()
     frame = get_user_frame(exc)
-    if not frame:
-        return None
-    return frame.line.strip() if frame.line else None
+    return frame.line.strip() if frame and frame.line else None

-def term_error(exc: Exception, message: str):
+def term_error(exc, message):
     frame = get_user_frame(exc)
     if settings.VERBOSE and frame:
         print(f"{BLUE(frame.name + '()')} {GRAY('—')} {basename(frame.filename)}:{YELLOW(str(frame.lineno))}")
         print(f"{GRAY('│')}  {frame.line}\n")
     warn(message)

-def web_error(exc: Exception, message: str) -> str:
+def web_error(exc, message):
     frame = get_user_frame(exc)
     source_line = get_error_line(exc)
     line = escape(source_line) if source_line else "<i style='color:#666'>line not available</i>"
     detail = escape(str(exc.message)) if hasattr(exc, 'message') else escape(str(exc))

-    if frame is not None:
-        location_block = f"""<div style="background: #2a2a2a; border-radius: 6px; overflow: hidden;">
-                <div style="background: #333; padding: 0.5rem 1rem; display: flex; justify-content: space-between;">
-                    <span style="color: #569cd6;">{escape(frame.name)}()</span>
-                    <span style="color: #888;">{escape(basename(frame.filename))}:{frame.lineno}</span>
-                </div>
-                <pre style="margin: 0; padding: 1rem; color: #ddd; white-space: pre-wrap; border-left: 3px solid #f44; font-size: 1.1rem;">{line}</pre>
-            </div>"""
+    if frame:
+        location = f"""<div style="background: #2a2a2a; border-radius: 6px; overflow: hidden;">
+            <div style="background: #333; padding: 0.5rem 1rem; display: flex; justify-content: space-between;">
+                <span style="color: #569cd6;">{escape(frame.name)}()</span>
+                <span style="color: #888;">{escape(basename(frame.filename))}:{frame.lineno}</span>
+            </div>
+            <pre style="margin: 0; padding: 1rem; color: #ddd; white-space: pre-wrap; border-left: 3px solid #f44; font-size: 1.1rem;">{line}</pre>
+        </div>"""
     else:
-        location_block = """<div style="background: #2a2a2a; border-radius: 6px; overflow: hidden;">
-                <div style="background: #333; padding: 0.5rem 1rem;">
-                    <span style="color: #888;">no source location available</span>
-                </div>
-            </div>"""
+        location = """<div style="background: #2a2a2a; border-radius: 6px; overflow: hidden;">
+            <div style="background: #333; padding: 0.5rem 1rem;">
+                <span style="color: #888;">no source location available</span>
+            </div>
+        </div>"""

     return f"""<html>
     <head><meta charset="UTF-8"></head>
@@ -62,14 +64,14 @@ def web_error(exc: Exception, message: str) -> str:
         <div style="padding: 2rem;">
             <p style="color: #f90; font-size: 1.3rem; margin: 0 0 0.25rem;">{detail}</p>
             <p style="color: #888; font-size: 1.2rem; margin: 0 0 2rem;">{escape(message)}</p>
-            {location_block}
+            {location}
         </div>
     </body>
     </html>"""

-def fatal(exc: Exception, message: str):
+def fatal(exc, message):
     term_error(exc, message)
     die(message)

-def html_fatal(exc: Exception, message: str) -> str:
+def html_fatal(exc, message):
     return web_error(exc, message)