Coverage for application / main.py: 29%
58 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-23 05:22 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-23 05:22 +0000
1import traceback
2import requests
3from concurrent.futures import ThreadPoolExecutor, as_completed
4from json import JSONDecodeError
6from flask import flash, render_template, request, session
8from application import app
9from application.util.constants import TERM_NORMAL, TERM_RED
12@app.route('/favicon.ico')
13def favicon():
14 return app.send_static_file('img/favicon.ico')
17@app.route('/')
18def index():
19 def fetch_json(url, headers=None):
20 try:
21 res = requests.get(url, headers=headers)
22 res.raise_for_status()
23 return res.json(), None
24 except requests.exceptions.RequestException as e:
25 msg = f'Unable to connect to {url}: {e}'
26 print(f'{TERM_RED}ERROR{TERM_NORMAL}: {msg}')
27 return None, msg
28 except JSONDecodeError:
29 msg = f'Failed to parse JSON from {url}'
30 print(f'{TERM_RED}ERROR{TERM_NORMAL}: {msg}')
31 return None, msg
33 http_requests = [
34 dict(name='reviewers', url=f'{app.config["DARC_REVIEW_URL"]}/reviewer/all', headers=app.config['DARC_REVIEW_HEADERS']),
35 dict(name='stats', url=f'{app.config["DARC_REVIEW_URL"]}/stats', headers=app.config['DARC_REVIEW_HEADERS']),
36 dict(name='sequences', url=f'{app.config["VARS_VAMPIRE_SQUID_URL"]}/videosequences/names'),
37 dict(name='concepts', url=f'{app.config["VARS_KNOWLEDGE_BASE_URL"]}/concept')
38 ]
39 results = {}
40 errors = []
41 with ThreadPoolExecutor(max_workers=4) as executor:
42 future_to_name = {
43 executor.submit(fetch_json, url=item['url'], headers=item.get('headers')): item['name']
44 for item in http_requests
45 }
46 for future in as_completed(future_to_name):
47 name = future_to_name[future]
48 data, error = future.result()
49 results[name] = data
50 if error:
51 errors.append(error)
53 for error in errors:
54 flash(error, 'danger')
56 stats = results.get('stats') or {}
57 session['reviewers'] = results.get('reviewers') or []
58 session['vars_video_sequences'] = results.get('sequences') or []
59 session['vars_concepts'] = results.get('concepts') or []
61 return render_template(
62 'index.html',
63 sequences=session['vars_video_sequences'],
64 unread_comment_count=stats.get('unread_comments', 0),
65 read_comment_count=stats.get('read_comments', 0),
66 total_comment_count=stats.get('total_comments', 0),
67 active_reviewers=stats.get('active_reviewers', []),
68 )
71# video player
72@app.get('/video')
73def video():
74 data = {'link': request.args.get('link'), 'time': request.args.get('time')}
75 return render_template('video.html', data=data), 200
78@app.errorhandler(404)
79def page_not_found(e):
80 return render_template('errors/404.html', err=''), 404
83@app.errorhandler(Exception)
84def server_error(e):
85 error = f'{type(e).__name__}: {e}'
86 print('\nApplication error 😔')
87 print(error)
88 print(traceback.format_exc())
89 requests.post(
90 url=f'{app.config.get("DARC_REVIEW_URL")}/log-error',
91 headers=app.config.get('DARC_REVIEW_HEADERS'),
92 json={
93 'url': request.url,
94 'error': traceback.format_exc(),
95 },
96 )
97 return render_template('errors/500.html', err=error), 500