Show software errors as web page
This commit is contained in:
		
							parent
							
								
									cf652200cd
								
							
						
					
					
						commit
						ba0eccc8d6
					
				
							
								
								
									
										32
									
								
								templates/base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								templates/base.html
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										46
									
								
								templates/navbar.html
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										30
									
								
								templates/show_error.html
									
									
									
									
									
										Normal 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 %}
 | 
				
			||||||
							
								
								
									
										19
									
								
								web_view.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								web_view.py
									
									
									
									
									
								
							| 
						 | 
					@ -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] = {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue