diff options
| author | Piotr Kunicki <piotr.kunicki@o2.pl> | 2021-10-14 11:41:10 +0200 |
|---|---|---|
| committer | Carlton Gibson <carlton.gibson@noumenal.es> | 2021-10-14 15:05:04 +0200 |
| commit | dc724c5bf9d3b8d59c9571aa751c3cd001cdeced (patch) | |
| tree | 8f3d1079a843438a6a2f95a40a30a1528259ec5d /tests/responses | |
| parent | 3ac476439751334138edcbb9abd73f783afcec4c (diff) | |
Fixed #30509 -- Made FileResponse better handle buffers and non-zero file offsets.
Diffstat (limited to 'tests/responses')
| -rw-r--r-- | tests/responses/test_fileresponse.py | 82 |
1 files changed, 76 insertions, 6 deletions
diff --git a/tests/responses/test_fileresponse.py b/tests/responses/test_fileresponse.py index 28e6f8e48d..85350cd9f1 100644 --- a/tests/responses/test_fileresponse.py +++ b/tests/responses/test_fileresponse.py @@ -18,17 +18,71 @@ class UnseekableBytesIO(io.BytesIO): class FileResponseTests(SimpleTestCase): def test_content_length_file(self): response = FileResponse(open(__file__, 'rb')) - self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__))) response.close() + self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__))) def test_content_length_buffer(self): response = FileResponse(io.BytesIO(b'binary content')) self.assertEqual(response.headers['Content-Length'], '14') + def test_content_length_nonzero_starting_position_file(self): + file = open(__file__, 'rb') + file.seek(10) + response = FileResponse(file) + response.close() + self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__) - 10)) + + def test_content_length_nonzero_starting_position_buffer(self): + test_tuples = ( + ('BytesIO', io.BytesIO), + ('UnseekableBytesIO', UnseekableBytesIO), + ) + for buffer_class_name, BufferClass in test_tuples: + with self.subTest(buffer_class_name=buffer_class_name): + buffer = BufferClass(b'binary content') + buffer.seek(10) + response = FileResponse(buffer) + self.assertEqual(response.headers['Content-Length'], '4') + + def test_content_length_nonzero_starting_position_file_seekable_no_tell(self): + class TestFile: + def __init__(self, path, *args, **kwargs): + self._file = open(path, *args, **kwargs) + + def read(self, n_bytes=-1): + return self._file.read(n_bytes) + + def seek(self, offset, whence=io.SEEK_SET): + return self._file.seek(offset, whence) + + def seekable(self): + return True + + @property + def name(self): + return self._file.name + + def close(self): + if self._file: + self._file.close() + self._file = None + + def __enter__(self): + return self + + def __exit__(self, e_type, e_val, e_tb): + self.close() + + file = TestFile(__file__, 'rb') + file.seek(10) + response = FileResponse(file) + response.close() + self.assertEqual(response.headers['Content-Length'], str(os.path.getsize(__file__) - 10)) + def test_content_type_file(self): response = FileResponse(open(__file__, 'rb')) - self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain']) response.close() + self.assertIn(response.headers['Content-Type'], ['text/x-python', 'text/plain']) def test_content_type_buffer(self): response = FileResponse(io.BytesIO(b'binary content')) @@ -38,8 +92,14 @@ class FileResponseTests(SimpleTestCase): response = FileResponse(io.BytesIO(b'binary content'), content_type='video/webm') self.assertEqual(response.headers['Content-Type'], 'video/webm') + def test_content_type_buffer_explicit_default(self): + response = FileResponse(io.BytesIO(b'binary content'), content_type='text/html') + self.assertEqual(response.headers['Content-Type'], 'text/html') + def test_content_type_buffer_named(self): test_tuples = ( + (__file__, ['text/x-python', 'text/plain']), + (__file__ + 'nosuchfile', ['application/octet-stream']), ('test_fileresponse.py', ['text/x-python', 'text/plain']), ('test_fileresponse.pynosuchfile', ['application/octet-stream']), ) @@ -59,15 +119,16 @@ class FileResponseTests(SimpleTestCase): (False, 'inline'), (True, 'attachment'), ) - for (filename, header_filename), (as_attachment, header_disposition)\ - in itertools.product(filenames, dispositions): + for (filename, header_filename), (as_attachment, header_disposition) in itertools.product( + filenames, dispositions + ): with self.subTest(filename=filename, disposition=header_disposition): response = FileResponse(open(__file__, 'rb'), filename=filename, as_attachment=as_attachment) + response.close() self.assertEqual( response.headers['Content-Disposition'], '%s; filename="%s"' % (header_disposition, header_filename), ) - response.close() def test_content_disposition_buffer(self): response = FileResponse(io.BytesIO(b'binary content')) @@ -89,7 +150,7 @@ class FileResponseTests(SimpleTestCase): filename='custom_name.py', ) self.assertEqual( - response.headers['Content-Disposition'], '%s; filename="custom_name.py"' % header_disposition + response.headers['Content-Disposition'], '%s; filename="custom_name.py"' % header_disposition, ) def test_response_buffer(self): @@ -108,6 +169,15 @@ class FileResponseTests(SimpleTestCase): response = FileResponse(buffer) self.assertEqual(list(response), [b'tent']) + def test_buffer_explicit_absolute_filename(self): + """ + Headers are set correctly with a buffer when an absolute filename is + provided. + """ + response = FileResponse(io.BytesIO(b'binary content'), filename=__file__) + self.assertEqual(response.headers['Content-Length'], '14') + self.assertEqual(response.headers['Content-Disposition'], 'inline; filename="test_fileresponse.py"') + @skipIf(sys.platform == 'win32', "Named pipes are Unix-only.") def test_file_from_named_pipe_response(self): with tempfile.TemporaryDirectory() as temp_dir: |
