home · contact · privacy
Re-structure for unittest usage.
[plomtask] / plomtask / task.py
1 #!/usr/bin/env python3
2 """plom's task manager"""
3 from http.server import BaseHTTPRequestHandler
4 from http.server import HTTPServer
5 from urllib.parse import urlparse
6 from os.path import split as path_split
7 from jinja2 import Environment as JinjaEnv, FileSystemLoader as JinjaFSLoader
8 from .days import Day
9
10 HTTP_PORT = 8082
11 TEMPLATES_DIR = 'templates'
12
13
14 class HandledException(Exception):
15     """To identify Exceptions based on expected (if faulty) user behavior."""
16
17
18 class TaskServer(HTTPServer):
19     """Variant of HTTPServer that knows .jinja as Jinja Environment."""
20
21     def __init__(self, *args, **kwargs):
22         super().__init__(self, *args, **kwargs)
23         self.jinja = JinjaEnv(loader=JinjaFSLoader(TEMPLATES_DIR))
24
25
26 class TaskHandler(BaseHTTPRequestHandler):
27     """Handles single HTTP request."""
28     server: TaskServer
29
30     def send_html(self, html: str, code: int = 200):
31         """Send HTML as proper HTTP response."""
32         self.send_response(code)
33         self.end_headers()
34         self.wfile.write(bytes(html, 'utf-8'))
35
36     def send_msg(self, msg: str, code: int = 400):
37         """Send message in HTML formatting as HTTP response."""
38         html = self.server.jinja.get_template('msg.html').render(msg=msg)
39         self.send_html(html, code)
40
41     def do_GET(self):
42         """Handle any GET request."""
43         try:
44             parsed_url = urlparse(self.path)
45             site = path_split(parsed_url.path)[1]
46             if 'calendar' == site:
47                 html = self.do_GET_calendar()
48             else:
49                 raise HandledException('Test!')
50             self.send_html(html)
51         except HandledException as error:
52             self.send_msg(error)
53
54     def do_GET_calendar(self):
55         """Show sorted Days."""
56         days = [Day('2024-01-03'), Day('2024-01-01'), Day('2024-01-02')]
57         days.sort()
58         return self.server.jinja.get_template('calendar.html').render(
59                 days=days)
60
61
62 def main():
63     """Main loop."""
64     server = TaskServer(('localhost', HTTP_PORT), TaskHandler)
65     print(f'running at port {HTTP_PORT}')
66     try:
67         server.serve_forever()
68     except KeyboardInterrupt:
69         print('aborting due to keyboard interrupt')
70     server.server_close()
71
72
73 if __name__ == '__main__':
74     from sys import exit as sys_exit
75     try:
76         main()
77     except HandledException as e:
78         print(f'Aborting due to: {e}')
79         sys_exit(1)