Create a redirect response type
authorDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 22 Oct 2019 19:51:56 +0000 (15:51 -0400)
committerDavid Kerkeslager <kerkeslager@gmail.com>
Tue, 22 Oct 2019 19:51:56 +0000 (15:51 -0400)
phial.py
test_phial.py

index f4da0dd..bc07b5f 100644 (file)
--- a/phial.py
+++ b/phial.py
@@ -81,9 +81,45 @@ class TextResponse(Response):
             **kwargs,
         )
 
+_RedirectResponse = collections.namedtuple(
+    'RedirectResponse',
+    (
+        'location',
+        'permanent',
+    ),
+)
+
+class RedirectResponse(_RedirectResponse):
+    def __new__(cls, location, **kwargs):
+        assert isinstance(location, str)
+
+        permanent = kwargs.pop('permanent', True)
+        assert isinstance(permanent, bool)
+        assert len(kwargs) == 0
+
+        return super().__new__(
+            cls,
+            location=location,
+            permanent=permanent,
+        )
+
+    @property
+    def status(self):
+        return 308 if self.permanent else 307
+
+    @property
+    def headers(self):
+        return (('Location', self.location),)
+
+    @property
+    def content(self):
+        return (b'',)
+
 def _get_status(response):
     return {
         200: '200 OK',
+        307: '307 Temporary Redirect',
+        308: '308 Permanent Redirect',
     }[response.status]
 
 def _get_headers(response):
index 6ff27d9..8d7498d 100644 (file)
@@ -58,9 +58,46 @@ class TextResponseTests(unittest.TestCase):
         response = phial.TextResponse('Hello, world\n')
         self.assertEqual(response.content_type, 'text/plain')
 
+class RedirectResponse(unittest.TestCase):
+    def test_takes_location_as_positional_argument(self):
+        response = phial.RedirectResponse('/location')
+        self.assertEqual(response.location, '/location')
+
+    def test_takes_location_as_keyword_argument(self):
+        response = phial.RedirectResponse(location='/location')
+        self.assertEqual(response.location, '/location')
+
+    def test_permanent_defaults_to_true(self):
+        response = phial.RedirectResponse('/location')
+        self.assertEqual(response.permanent, True)
+
+    def test_status(self):
+        self.assertEqual(
+            phial.RedirectResponse('/location', permanent=True).status,
+            308,
+        )
+        self.assertEqual(
+            phial.RedirectResponse('/location', permanent=False).status,
+            307,
+        )
+
+    def test_headers(self):
+        self.assertEqual(
+            phial.RedirectResponse('/location').headers,
+            (('Location','/location'),),
+        )
+
+    def test_content(self):
+        self.assertEqual(
+            phial.RedirectResponse('/location').content,
+            (b'',),
+        )
+
 class _get_status_Tests(unittest.TestCase):
     def test_basic(self):
         self.assertEqual(phial._get_status(mock.MagicMock(status=200)), '200 OK')
+        self.assertEqual(phial._get_status(mock.MagicMock(status=307)), '307 Temporary Redirect')
+        self.assertEqual(phial._get_status(mock.MagicMock(status=308)), '308 Permanent Redirect')
 
 class _get_content_Tests(unittest.TestCase):
     def test_bytes(self):