Show software errors as web page

This commit is contained in:
Edward Betts 2022-08-15 17:56:21 +01:00
parent cf652200cd
commit ba0eccc8d6
4 changed files with 127 additions and 0 deletions

32
templates/base.html Normal file
View file

@ -0,0 +1,32 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>
{% block title %}{% endblock %}
</title>
{% block style %}{% endblock %}
</head>
{% from "navbar.html" import navbar with context %}
<body>
{% block nav %}{{ navbar() }}{% endblock %}
{% if config.SHOW_BLOCK_ALERT %}
<div class="p-2">
{{ local_block_alert() }}
{{ global_block_alert() }}
</div>
{% endif %}
{% block content %}{% endblock %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
{% block script %}{% endblock %}
</body>
</html>

46
templates/navbar.html Normal file
View file

@ -0,0 +1,46 @@
{% macro nav_item(name, label) %}
<li class="nav-item{% if name == active %} active{% endif %}">
<a class="nav-link" href="{{ url_for(name) }}">{{ label }}{% if name == active %} <span class="sr-only">(current)</span>{% endif %}</a>
</li>
{% endmacro %}
{% macro navbar() %}
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarTogglerDemo01" aria-controls="navbarTogglerDemo01" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarTogglerDemo01">
<a class="navbar-brand" href="{{ url_for('index') }}">Dab Mechanic</a>
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<ul class="navbar-nav d-flex">
{% if g.user %}
<li class="nav-item">
<a class="nav-link" href="{{ url_for('user_page', username=g.user) }}">{{ g.user }}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ url_for('oauth_disconnect', next=request.script_root + request.full_path) }}">switch user</a>
</li>
{% else %}
<li class="nav-item">
{% set login_url = url_for('start_oauth', next=request.script_root + request.full_path) %}
<a class="nav-link" href="{{ login_url }}">connect with Wikidata</a>
</li>
{% endif %}
</ul>
</div>
</div>
</nav>
{% endmacro %}

30
templates/show_error.html Normal file
View file

@ -0,0 +1,30 @@
{% extends "base.html" %}
{% block style %}
<link rel="stylesheet" href="{{url_for('static', filename='css/exception.css')}}" />
{% endblock %}
{% block content %}
<div class="p-2">
<h1>Software error: {{ tb.exception_type }}</h1>
<div>
<pre>{{ tb.exception }}</pre>
</div>
{% set body %}
URL: {{ request.url }}
{{ tb.plaintext | safe }}
{% endset %}
<p><a class="btn btn-primary btn-lg" role="button" href="https://github.com/EdwardBetts/dab-mechanic/issues/new?title={{ tb.exception + " " + request.url | urlencode }}&body={{ body | urlencode }}">Submit as an issue on GitHub</a> (requires an account with GitHub)</p>
<h2 class="traceback">Traceback <em>(most recent call last)</em></h2>
{{ tb.render_summary(include_title=False) | safe }}
<p>Error in function "{{ last_frame.function_name }}": {{ last_frame_args | pprint }}</p>
<pre>{{ last_frame.locals | pprint }}</pre>
</div>
{% endblock %}

View file

@ -1,5 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
import inspect
import json import json
import re import re
from typing import Any, Iterator, TypedDict from typing import Any, Iterator, TypedDict
@ -7,7 +8,9 @@ from typing import Any, Iterator, TypedDict
import flask import flask
import lxml.html import lxml.html
import requests import requests
import werkzeug.exceptions
from requests_oauthlib import OAuth1Session from requests_oauthlib import OAuth1Session
from werkzeug.debug.tbtools import get_current_traceback
from werkzeug.wrappers import Response from werkzeug.wrappers import Response
app = flask.Flask(__name__) app = flask.Flask(__name__)
@ -17,6 +20,22 @@ app.debug = True
api_url = "https://en.wikipedia.org/w/api.php" api_url = "https://en.wikipedia.org/w/api.php"
@app.errorhandler(werkzeug.exceptions.InternalServerError)
def exception_handler(e):
tb = get_current_traceback()
last_frame = next(frame for frame in reversed(tb.frames) if not frame.is_library)
last_frame_args = inspect.getargs(last_frame.code)
return (
flask.render_template(
"show_error.html",
tb=tb,
last_frame=last_frame,
last_frame_args=last_frame_args,
),
500,
)
def get_content(title: str) -> str: def get_content(title: str) -> str:
"""Get article text.""" """Get article text."""
params: dict[str, str | int] = { params: dict[str, str | int] = {