Modify 'render_to_file' function to make it operate on unicode objects

If we have non-ascii chars in rendered template we might end up with
UnicodeDecodeError exception when writing the content to a file. To
eliminate this issue io.open is used with additional 'encoding'
parameter

Change-Id: I73ee352a439d7a9d5c71033f31530a0ced68324c
Closes-Bug: #1475234
This commit is contained in:
Artem Roma 2015-09-22 14:59:17 +03:00
parent ed0f4626ee
commit be1a4bdd3a
2 changed files with 31 additions and 2 deletions

View File

@ -15,7 +15,9 @@
# under the License.
import os
import shutil
import subprocess
import tempfile
import mock
from mock import patch
@ -241,6 +243,26 @@ class TestUtils(BaseTestCase):
open_mock.assert_called_once_with(path)
yaml_mock.load.assert_called_once_with(file_mock)
def test_render_to_file_unicode_handling(self):
expected = u'тест'
params = {'vendors': expected}
template_content = "${vendors}"
temp_dir = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, temp_dir)
src_file = os.path.join(temp_dir, 'test_template')
dst_file = os.path.join(temp_dir, 'test_rendered')
with open(src_file, 'w') as f:
f.write(template_content)
utils.render_to_file(src=src_file, dst=dst_file, params=params)
with open(dst_file, 'rb') as f:
actual = f.read()
self.assertEqual(expected, actual.decode('utf-8'))
@mock.patch('fuel_plugin_builder.utils.copy_file_permissions')
@mock.patch('fuel_plugin_builder.utils.render_to_file')
@mock.patch('fuel_plugin_builder.utils.remove')

View File

@ -16,6 +16,7 @@
import datetime
import hashlib
import io
import logging
import os
import shutil
@ -172,10 +173,16 @@ def render_to_file(src, dst, params):
logger.debug(u'Render template from {0} to {1} with params: {2}'.format(
src, dst, params))
with open(src, 'r') as f:
# NOTE(aroma): we use io.open because sometimes we ended up with
# non-ascii chars in rendered template so must explicitly
# converse content to 'utf-8' encoding before writing
with io.open(src, 'r', encoding='utf-8') as f:
template_file = f.read()
with open(dst, 'w') as f:
with io.open(dst, 'w', encoding='utf-8') as f:
# NOTE(aroma): 'render' in such configuration always
# return unicode object as the result
rendered_file = Template(template_file).render(**params)
f.write(rendered_file)