Generate smart defaults for some values at some places
[fwx] / phial.py
1 import collections
2
3 Request = collections.namedtuple(
4     'Request',
5     (
6         'environ',
7     )
8 )
9
10 _Response = collections.namedtuple(
11     'Response',
12     (
13         'status',
14         'content_type',
15         'extra_headers',
16         'content',
17     ),
18 )
19
20 class Response(_Response):
21     def __new__(cls, **kwargs):
22         status = kwargs.pop('status', 200)
23         assert isinstance(status, int)
24
25         content_type = kwargs.pop('content_type')
26         assert isinstance(content_type, str)
27
28         extra_headers = kwargs.pop('extra_headers', ())
29         assert isinstance(extra_headers, tuple)
30
31         content = kwargs.pop('content')
32
33         assert len(kwargs) == 0
34
35         return super().__new__(
36             cls,
37             status=status,
38             content_type=content_type,
39             extra_headers=extra_headers,
40             content=content,
41         )
42
43     @property
44     def headers(self):
45         return (
46             ('Content-Type', self.content_type),
47         )
48
49 def _get_status(response):
50     return {
51         200: '200 OK',
52     }[response.status]
53
54 def _get_headers(response):
55     return list(response.headers)
56
57 def _get_content(response):
58     content = response.content
59
60     if isinstance(content, bytes):
61         return (content,)
62
63     if isinstance(content, str):
64         return (content.encode('utf-8'),)
65
66     return content
67
68 def App(handler):
69     def app(environ, start_fn):
70         response = handler(Request(environ))
71
72         start_fn(_get_status(response), _get_headers(response))
73         return _get_content(response)
74     return app