__str__ method should return byte string, not unicode string. But as we don't have a ensure this in every KS_OBJECT.__str__ method, let's add encode("utf-8") call to the result if it is a unicode string.
Also add test for these issues.
Signed-off-by: Vratislav Podzimek vpodzime@redhat.com --- pykickstart/base.py | 10 +++++++-- tests/parser/handle_unicode.py | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 tests/parser/handle_unicode.py
diff --git a/pykickstart/base.py b/pykickstart/base.py index 4ef442c..e12b86c 100644 --- a/pykickstart/base.py +++ b/pykickstart/base.py @@ -281,10 +281,16 @@ class BaseHandler(KickstartObject):
for prio in lst: for obj in self._writeOrder[prio]: - retval += obj.__str__() + obj_str = obj.__str__() + if type(obj_str) == types.UnicodeType: + obj_str = obj_str.encode("utf-8") + retval += obj_str
for script in self.scripts: - retval += script.__str__() + script_str = script.__str__() + if type(script_str) == types.UnicodeType: + script_str = script_str.encode("utf-8") + retval += script_str
retval += self.packages.__str__()
diff --git a/tests/parser/handle_unicode.py b/tests/parser/handle_unicode.py new file mode 100644 index 0000000..22ebd10 --- /dev/null +++ b/tests/parser/handle_unicode.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +import unittest +from tests.baseclass import * + +from pykickstart import constants +from pykickstart.errors import KickstartParseError +from pykickstart import version + +class HandleUnicode_TestCase(ParserTest): + ks = """ +rootpw ááááááááá + +%post +echo áááááá +%end +""" + + def runTest(self): + unicode_str1 = u"ááááááááá" + unicode_str2 = u"áááááá" + encoded_str1 = unicode_str1.encode("utf-8") + encoded_str2 = unicode_str2.encode("utf-8") + + # parser should parse string including non-ascii characters + self.parser.readKickstartFromString(self.ks) + + # str(handler) should not cause traceback and should contain the + # original non-ascii strings as utf-8 encoded byte strings and + # str(self.handler) should not fail -- i.e. self.handler.__str__() + # should return byte string not unicode string + self.assertIn(encoded_str1, str(self.handler)) + self.assertIn(encoded_str2, str(self.handler)) + + # set root password to unicode string + self.handler.rootpw.password = unicode_str1 + + # str(handler) should not cause traceback and should contain the + # original unicode string as utf-8 encoded byte string + self.assertIn(encoded_str1, str(self.handler)) + + # set root password to encoded string + self.handler.rootpw.password = encoded_str1 + + # str(handler) should not cause traceback and should contain the + # original unicode string as utf-8 encoded byte string + self.assertIn(encoded_str1, str(self.handler)) + +if __name__ == "__main__": + unittest.main()