Coverage for application / main.py: 29%

58 statements  

« 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 

5 

6from flask import flash, render_template, request, session 

7 

8from application import app 

9from application.util.constants import TERM_NORMAL, TERM_RED 

10 

11 

12@app.route('/favicon.ico') 

13def favicon(): 

14 return app.send_static_file('img/favicon.ico') 

15 

16 

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 

32 

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) 

52 

53 for error in errors: 

54 flash(error, 'danger') 

55 

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 [] 

60 

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 ) 

69 

70 

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 

76 

77 

78@app.errorhandler(404) 

79def page_not_found(e): 

80 return render_template('errors/404.html', err=''), 404 

81 

82 

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