Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ Also you can pass an opened file:
with open('file.html') as f:
pdfkit.from_file(f, 'out.pdf')

Text streams are encoded as UTF-8. Binary streams (including ``io.BytesIO``
and files opened with ``'rb'``) are passed through without changing their bytes.
The caller retains ownership of the input stream.


If you wish to further process generated PDF, you can read it to a variable:

.. code-block:: python
Expand Down
4 changes: 3 additions & 1 deletion pdfkit/pdfkit.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ def to_pdf(self, path=None):
if self.source.isString() or (self.source.isFile() and self.css):
input = self.source.to_s().encode('utf-8')
elif self.source.isFileObj():
input = self.source.source.read().encode('utf-8')
input = self.source.source.read()
if isinstance(input, str):
input = input.encode('utf-8')
else:
input = None

Expand Down
36 changes: 36 additions & 0 deletions tests/test_file_stream_input.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import io
import sys
import tempfile
import unittest
from unittest.mock import Mock, patch

import pdfkit


class FileStreamInputTests(unittest.TestCase):
def convert(self, stream, expected):
config = pdfkit.configuration(wkhtmltopdf=sys.executable)
process = Mock(returncode=0)
process.communicate.return_value = (b'%PDF-test-output', b'')
with patch('pdfkit.pdfkit.subprocess.Popen', return_value=process):
output = pdfkit.from_file(stream, configuration=config)
self.assertEqual(output, b'%PDF-test-output')
process.communicate.assert_called_once_with(input=expected)
self.assertFalse(stream.closed)

def test_binary_memory_stream(self):
data = '<p>café</p>'.encode('utf-8')
self.convert(io.BytesIO(data), data)

def test_binary_file_preserves_declared_encoding(self):
data = b'<meta charset="iso-8859-1"><p>caf\xe9</p>'
with tempfile.TemporaryFile('w+b') as stream:
stream.write(data)
stream.seek(0)
self.convert(stream, data)

def test_text_stream_is_encoded_as_utf8(self):
self.convert(io.StringIO('<p>café</p>'), '<p>café</p>'.encode('utf-8'))

def test_empty_binary_stream(self):
self.convert(io.BytesIO(b''), b'')