diff --git a/openlp/core/lib/__init__.py b/openlp/core/lib/__init__.py index 0439fc156..fe7cef4b2 100644 --- a/openlp/core/lib/__init__.py +++ b/openlp/core/lib/__init__.py @@ -90,7 +90,7 @@ def get_text_file_string(text_file): file_handle = None content = None try: - file_handle = open(text_file, 'r') + file_handle = open(text_file, 'r', encoding='utf-8') if not file_handle.read(3) == '\xEF\xBB\xBF': # no BOM was found file_handle.seek(0) diff --git a/openlp/core/ui/thememanager.py b/openlp/core/ui/thememanager.py index 0db4b12a7..9f8d0bfe0 100644 --- a/openlp/core/ui/thememanager.py +++ b/openlp/core/ui/thememanager.py @@ -354,8 +354,12 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R delete_file(os.path.join(self.path, thumb)) delete_file(os.path.join(self.thumb_path, thumb)) try: - encoding = get_filesystem_encoding() - shutil.rmtree(os.path.join(self.path, theme).encode(encoding)) + # Windows is always unicode, so no need to encode filenames + if is_win(): + shutil.rmtree(os.path.join(self.path, theme)) + else: + encoding = get_filesystem_encoding() + shutil.rmtree(os.path.join(self.path, theme).encode(encoding)) except OSError as os_error: shutil.Error = os_error self.log_exception('Error deleting theme %s' % theme) @@ -567,7 +571,7 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R check_directory_exists(os.path.dirname(full_name)) if os.path.splitext(name)[1].lower() == '.xml': file_xml = str(theme_zip.read(name), 'utf-8') - out_file = open(full_name, 'w') + out_file = open(full_name, 'w', encoding='utf-8') out_file.write(file_xml) else: out_file = open(full_name, 'wb') @@ -645,8 +649,8 @@ class ThemeManager(OpenLPMixin, RegistryMixin, QtGui.QWidget, Ui_ThemeManager, R delete_file(self.old_background_image) out_file = None try: - out_file = open(theme_file, 'w') - out_file.write(theme_pretty_xml.decode('UTF-8')) + out_file = open(theme_file, 'w', encoding='utf-8') + out_file.write(theme_pretty_xml.decode('utf-8')) except IOError: self.log_exception('Saving theme to file failed') finally: diff --git a/tests/functional/openlp_core_lib/test_lib.py b/tests/functional/openlp_core_lib/test_lib.py index 98c31d7be..9fc1fa3ff 100644 --- a/tests/functional/openlp_core_lib/test_lib.py +++ b/tests/functional/openlp_core_lib/test_lib.py @@ -176,7 +176,7 @@ class TestLib(TestCase): # THEN: None should be returned mocked_isfile.assert_called_with(filename) - mocked_open.assert_called_with(filename, 'r') + mocked_open.assert_called_with(filename, 'r', encoding='utf-8') self.assertIsNone(result, 'None should be returned if the file cannot be opened') def get_text_file_string_decode_error_test(self): diff --git a/tests/functional/openlp_core_ui/test_thememanager.py b/tests/functional/openlp_core_ui/test_thememanager.py index 85d470e4f..3dc168f77 100644 --- a/tests/functional/openlp_core_ui/test_thememanager.py +++ b/tests/functional/openlp_core_ui/test_thememanager.py @@ -29,6 +29,7 @@ from unittest import TestCase from tempfile import mkdtemp from PyQt4 import QtGui +from tempfile import mkdtemp from openlp.core.ui import ThemeManager from openlp.core.common import Registry @@ -44,6 +45,13 @@ class TestThemeManager(TestCase): Set up the tests """ Registry.create() + self.temp_folder = mkdtemp() + + def tearDown(self): + """ + Clean up + """ + shutil.rmtree(self.temp_folder) def export_theme_test(self): """ @@ -131,6 +139,27 @@ class TestThemeManager(TestCase): # THEN: The mocked_copyfile should not have been called self.assertTrue(mocked_copyfile.called, 'shutil.copyfile should be called') + def write_theme_special_char_name_test(self): + """ + Test that we can save themes with special characters in the name + """ + # GIVEN: A new theme manager instance, with mocked theme and thememanager-attributes. + theme_manager = ThemeManager(None) + theme_manager.old_background_image = None + theme_manager.generate_and_save_image = MagicMock() + theme_manager.path = self.temp_folder + mocked_theme = MagicMock() + mocked_theme.theme_name = 'theme 愛 name' + mocked_theme.extract_formatted_xml = MagicMock() + mocked_theme.extract_formatted_xml.return_value = 'fake theme 愛 XML'.encode() + + # WHEN: Calling _write_theme with a theme with a name with special characters in it + theme_manager._write_theme(mocked_theme, None, None) + + # THEN: It should have been created + self.assertTrue(os.path.exists(os.path.join(self.temp_folder, 'theme 愛 name', 'theme 愛 name.xml')), + 'Theme with special characters should have been created!') + def over_write_message_box_yes_test(self): """ Test that theme_manager.over_write_message_box returns True when the user clicks yes.