Hello community, here is the log from the commit of package python-binplist for openSUSE:Factory checked in at 2014-08-27 16:53:16 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-binplist (Old) and /work/SRC/openSUSE:Factory/.python-binplist.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-binplist" Changes: -------- --- /work/SRC/openSUSE:Factory/python-binplist/python-binplist.changes 2013-09-11 13:07:11.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-binplist.new/python-binplist.changes 2014-08-27 16:53:29.000000000 +0200 @@ -1,0 +2,8 @@ +Wed Aug 13 18:57:50 UTC 2014 - greg.freem...@gmail.com + +- update to v0.1.4 + * Per GIT log replaced JSON parser with internal code + * other minor changes +- change /usr/bin/binplist to /usr/bin/plist.py in %files section + +------------------------------------------------------------------- Old: ---- binplist-0.1.3.tar.gz New: ---- binplist-0.1.4.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-binplist.spec ++++++ --- /var/tmp/diff_new_pack.CmbxCL/_old 2014-08-27 16:53:30.000000000 +0200 +++ /var/tmp/diff_new_pack.CmbxCL/_new 2014-08-27 16:53:30.000000000 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-binplist # -# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -15,14 +15,15 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # + Name: python-binplist -Version: 0.1.3 +Version: 0.1.4 Release: 0 -License: Apache-2.0 Summary: Binary property list (plist) parser module written in python -Url: https://code.google.com/p/binplist/ +License: Apache-2.0 Group: Development/Libraries/Python -Source: https://binplist.googlecode.com/files/binplist-0.1.3.tar.gz +Url: https://code.google.com/p/binplist/ +Source: https://binplist.googlecode.com/files/binplist-0.1.4.tar.gz BuildRequires: python-devel BuildRequires: python-setuptools BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -50,7 +51,7 @@ %files %defattr(-,root,root) %doc COPYING -%{_bindir}/binplist +%{_bindir}/plist.py %{python_sitelib}/binplist-%{version}-py%{py_ver}.egg-info %{python_sitelib}/binplist ++++++ binplist-0.1.3.tar.gz -> binplist-0.1.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/PKG-INFO new/binplist-0.1.4/PKG-INFO --- old/binplist-0.1.3/PKG-INFO 2013-07-31 00:08:30.000000000 +0200 +++ new/binplist-0.1.4/PKG-INFO 2013-08-22 20:13:22.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: binplist -Version: 0.1.3 +Version: 0.1.4 Summary: A binary plist parser Home-page: http://code.google.com/p/binplist Author: Jordi Sanchez diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/binplist/__init__.py new/binplist-0.1.4/binplist/__init__.py --- old/binplist-0.1.3/binplist/__init__.py 2013-07-30 23:39:47.000000000 +0200 +++ new/binplist-0.1.4/binplist/__init__.py 2013-07-31 21:19:02.000000000 +0200 @@ -1,2 +1,2 @@ -__version__ = "0.1.3" +__version__ = "0.1.4" __feedback_email__ = "binplist.feedb...@gmail.com" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/binplist/binplist.py new/binplist-0.1.4/binplist/binplist.py --- old/binplist-0.1.3/binplist/binplist.py 2013-07-30 00:58:43.000000000 +0200 +++ new/binplist-0.1.4/binplist/binplist.py 2013-08-22 17:41:57.000000000 +0200 @@ -1,4 +1,5 @@ #!/bin/env python +# -*- coding: utf-8 -*- # # Copyright 2013 Google Inc. All Rights Reserved. # @@ -31,7 +32,7 @@ BinaryPlist class and then call the Parse() method on it, with a file-like object as an argument. - with open("myfile.plist") as fd: + with open("myfile.plist", "rb") as fd: bplist = BinaryPlist(fd) top_level_object = bplist.Parse(fd) @@ -56,12 +57,12 @@ from . import __version__ from . import __feedback_email__ -import cStringIO import datetime import logging import math import os import plistlib +import string import struct import xml.parsers.expat @@ -82,7 +83,7 @@ self.value = value def __str__(self): - return str(self.value) + return self.value def __repr__(self): return repr(self.value) @@ -90,6 +91,9 @@ def __eq__(self, other): return self.value == other + def __unicode__(self): + return u"'%s'" % ''.join([u"\\x%s" % c.encode('hex') for c in self.value]) + class CorruptReference(object): """Marks references to objects that are corrupt.""" @@ -141,7 +145,8 @@ # Length of the preview we show for each object when DEBUG logging debug_object_preview_length = 48 - def __init__(self, file_obj=None, discovery_mode=False, ultra_verbosity=True): + def __init__(self, file_obj=None, discovery_mode=False, + ultra_verbosity=False): """Constructor. Args: @@ -185,14 +190,14 @@ def Open(self, file_obj): try: - start_offset = file_obj.tell() - file_obj.seek(0, os.SEEK_END) - self._file_size = file_obj.tell() - start_offset - file_obj.seek(start_offset, os.SEEK_SET) - self._bplist_start_offset = start_offset - self.fd = file_obj + start_offset = file_obj.tell() + file_obj.seek(0, os.SEEK_END) + self._file_size = file_obj.tell() - start_offset + file_obj.seek(start_offset, os.SEEK_SET) + self._bplist_start_offset = start_offset + self.fd = file_obj except AttributeError: - raise Error("This file object doesn't support seek().") + raise Error("This file object doesn't support seek().") def Parse(self): """Parses the file descriptor at file_obj.""" @@ -371,12 +376,11 @@ finally: # Remove the index from the list of traversed objects self.objects_traversed.remove(index) - if (self.debug_object_preview_length > 0 - and len(str(obj)) > self.debug_object_preview_length): + output_string = ToDebugString(obj) + fmt = "Object %d = %s" + if len(output_string) > self.debug_object_preview_length: fmt = "Object %%d ~= %%.%ds ..." % self.debug_object_preview_length - self._LogUltraVerbose(fmt, index, obj) - else: - self._LogUltraVerbose("Object %d = %s", index, obj) + self._LogUltraVerbose(fmt, index, output_string) return obj def _ParseObject(self): @@ -587,10 +591,10 @@ return self.fd.read(strlen*char_size) def _ReadStructFromFd(self, file_obj, structure): - """Reads the given structucture from file_obj and returns the unpacked data. + """Reads the given structure from file_obj and returns the unpacked data. Raises: - IOError: When there wasn't enough data in file_obj to acommodate the + IOError: When there wasn't enough data in file_obj to accommodate the requested structure. Args: @@ -673,6 +677,7 @@ try: return utf16.decode("utf-16-be") except UnicodeDecodeError: + self._LogWarn("Invalid UTF-16 data") return RawValue(utf16) def _ParseUid(self, marker_lo): @@ -879,7 +884,7 @@ file_obj = pathOrFile except AttributeError: # Must be a path then - file_obj = open(pathOrFile) + file_obj = open(pathOrFile, "rb") bplist_start_offset = file_obj.tell() magicversion = file_obj.read(8) @@ -898,3 +903,74 @@ return plistlib.readPlist(file_obj) except xml.parsers.expat.ExpatError: raise FormatError("Invalid plist file.") + + +def ToDebugString(string): + try: + return str(string) + except UnicodeEncodeError: + return unicode(string).encode('unicode_escape') + + + +def PlistToUnicode(o, string_encoding='safeascii', encoding_options="strict", + indent=4, previous_indent=0): + """Returns the Unicode representation of a plist object. + + This is mostly just to handle displaying unicode keys or values in + dictionaries as the default dict implementation escapes them, and to try to + represent byte strings in a more human-readable form. + + Not very proud of the implementation but it is what it is. + """ + if isinstance(o, dict): + indentation = u' '*(previous_indent+indent) + indentation_join = u',\n%s' % indentation + opening_bracket = u"{\n%s" % indentation + closing_bracket = u"\n%s}" % (u' '*previous_indent) + pieces = [] + for k, v in o.iteritems(): + key = PlistToUnicode(k, string_encoding=string_encoding, + encoding_options=encoding_options, indent=indent, + previous_indent=previous_indent+indent) + value = PlistToUnicode(v, string_encoding=string_encoding, + encoding_options=encoding_options, indent=indent, + previous_indent=previous_indent+indent) + pieces.append(u"%s: %s" % (key, value)) + if not pieces: + return '{}' + return ''.join([opening_bracket, + indentation_join.join(pieces), + closing_bracket]) + elif isinstance(o, str): + try: + if string_encoding == "safeascii": + safeascii = [] + for c in o: + if c in string.printable: + safeascii.append(c) + else: + safeascii.append("\\x" + c.encode("hex")) + return u"'%s'" % (''.join(safeascii)).decode("ascii", "strict") + return u"'%s'" % o.decode(string_encoding, encoding_options) + except (UnicodeEncodeError, UnicodeDecodeError): + return u"'%s'" % ''.join([u"\\x%s" % c.encode('hex') for c in o]) + elif isinstance(o, unicode): + # Return a quote-enclosed string + return u"'%s'" % o + elif o is NullValue: + return u"NULL" + elif o is CorruptReference: + return u"##CORRUPT_REFERENCE##" + elif o is UnknownObject: + return u"##UNKNOWN_OBJECT##" + else: + try: + return u'[%s]' % u', '.join([PlistToUnicode(piece, + string_encoding, + encoding_options, + indent, + previous_indent) + for piece in o]) + except TypeError: + return unicode(o) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/binplist.egg-info/PKG-INFO new/binplist-0.1.4/binplist.egg-info/PKG-INFO --- old/binplist-0.1.3/binplist.egg-info/PKG-INFO 2013-07-31 00:08:30.000000000 +0200 +++ new/binplist-0.1.4/binplist.egg-info/PKG-INFO 2013-08-22 20:13:21.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: binplist -Version: 0.1.3 +Version: 0.1.4 Summary: A binary plist parser Home-page: http://code.google.com/p/binplist Author: Jordi Sanchez diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/binplist.egg-info/SOURCES.txt new/binplist-0.1.4/binplist.egg-info/SOURCES.txt --- old/binplist-0.1.3/binplist.egg-info/SOURCES.txt 2013-07-31 00:08:30.000000000 +0200 +++ new/binplist-0.1.4/binplist.egg-info/SOURCES.txt 2013-08-22 20:13:22.000000000 +0200 @@ -14,6 +14,6 @@ dpkg/control dpkg/copyright dpkg/rules -scripts/binplist +scripts/plist.py tests/__init__.py tests/binplist_test.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/dpkg/changelog new/binplist-0.1.4/dpkg/changelog --- old/binplist-0.1.3/dpkg/changelog 2013-07-30 23:51:35.000000000 +0200 +++ new/binplist-0.1.4/dpkg/changelog 2013-08-21 23:03:14.000000000 +0200 @@ -1,3 +1,10 @@ +binplist (0.1.4-0) unstable; urgency=low + + * Added command line options to the binplist command. + * Fixed a Unicode bug when dealing with UTF16 objects. + + -- Jordi Sanchez <binplist.feedb...@gmail.com> Wed, 21 Aug 2013 22:54:00 +0200 + binplist (0.1-3) unstable; urgency=low * Initial release diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/scripts/binplist new/binplist-0.1.4/scripts/binplist --- old/binplist-0.1.3/scripts/binplist 2013-07-30 00:22:21.000000000 +0200 +++ new/binplist-0.1.4/scripts/binplist 1970-01-01 01:00:00.000000000 +0100 @@ -1,38 +0,0 @@ -#!/bin/env python -# Copyright 2013 Google Inc. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import logging -import plistlib -import pprint -import sys - -from binplist import binplist - - -if __name__ == "__main__": - if len(sys.argv) <= 1: - print "Usage: %s <file>" % sys.argv[0] - sys.exit(-1) - - with open(sys.argv[1]) as fd: - plist = binplist.BinaryPlist(file_obj=fd) - try: - res = plist.Parse() - if plist.is_corrupt: - logging.warn("%s LOOKS CORRUPTED. You might not obtain all data!\n", - sys.argv[1]) - pprint.PrettyPrinter().pprint(res) - except binplist.FormatError, e: - pprint.PrettyPrinter().pprint(plistlib.readPlist(sys.argv[1])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/scripts/plist.py new/binplist-0.1.4/scripts/plist.py --- old/binplist-0.1.3/scripts/plist.py 1970-01-01 01:00:00.000000000 +0100 +++ new/binplist-0.1.4/scripts/plist.py 2013-08-22 17:42:00.000000000 +0200 @@ -0,0 +1,82 @@ +#!/bin/env python +# Copyright 2013 Google Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import logging +import plistlib +import sys + +from binplist import binplist + + +parser = argparse.ArgumentParser(description="A forensic plist parser.") +parser.add_argument( + "plist", default=None, action="store", + help="plist file to be parsed") +parser.add_argument( + "-V", "--version", action="version", version=binplist.__version__) +parser.add_argument("-v", "--verbose", action="append_const", const=True, + help="Turn verbose logging on. Use twice for ultra " + "verbosity.") +parser.add_argument("-e", "--string-encoding", default="safeascii", + help="Encoding of binplist strings.") +parser.add_argument("-eo", "--string-encoding-option", default="strict", + choices=['strict', 'ignore', 'replace'], + help=("What to do when encoding strings of a binary plist " + "and some characters cannot be converted.")) +parser.add_argument("-E", "--output-encoding", default="utf-8", + help="Output encoding of binplist.") +parser.add_argument("-EO", "--output-encoding-option", default="strict", + choices=['strict', 'ignore', 'replace', + 'xmlcharrefreplace', 'backslashreplace'], + help=("What to do when encoding the output of binplist " + "and some characters cannot be converted.")) +parser.add_argument("-d", "--discovery-mode", action="store_true", + help=("Will inform you when a UID or a SET is found so " + "that you can help me improve the parser.")) + + +if __name__ == "__main__": + options = parser.parse_args() + if not options.plist: + parser.print_help() + sys.exit(-1) + + ultra_verbosity = False + if options.verbose: + if len(options.verbose) == 1: + logging.basicConfig(level=logging.DEBUG) + else: + ultra_verbosity = True + logging.basicConfig(level=binplist.LOG_ULTRA_VERBOSE) + + with open(options.plist, "rb") as fd: + plist = binplist.BinaryPlist(file_obj=fd, + ultra_verbosity=ultra_verbosity, + discovery_mode=options.discovery_mode) + try: + parsed_plist = plist.Parse() + if plist.is_corrupt: + logging.warn("%s LOOKS CORRUPTED. You might not obtain all data!\n", + options.plist) + except binplist.FormatError, e: + parsed_plist = plistlib.readPlist(options.plist) + + print binplist.PlistToUnicode( + parsed_plist, + string_encoding=options.string_encoding, + encoding_options=options.string_encoding_option).encode( + options.output_encoding, + options.output_encoding_option) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/setup.py new/binplist-0.1.4/setup.py --- old/binplist-0.1.3/setup.py 2013-07-31 00:05:28.000000000 +0200 +++ new/binplist-0.1.4/setup.py 2013-08-08 00:42:03.000000000 +0200 @@ -27,6 +27,6 @@ license="Apache Software License", packages=["binplist"], test_suite = "tests", - scripts=['scripts/binplist'], + scripts=['scripts/plist.py'], install_requires=["pytz"], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/binplist-0.1.3/tests/binplist_test.py new/binplist-0.1.4/tests/binplist_test.py --- old/binplist-0.1.3/tests/binplist_test.py 2013-07-30 00:22:21.000000000 +0200 +++ new/binplist-0.1.4/tests/binplist_test.py 2013-08-22 19:22:48.000000000 +0200 @@ -1,4 +1,6 @@ #!/bin/env python +# -*- coding: utf-8 -*- +# # Copyright 2013 Google Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -28,7 +30,7 @@ class BinplistTest(unittest.TestCase): def setUp(self): - notrailer = ("bplist00") # header + notrailer = "bplist00" # header self.notrailer = StringIO.StringIO(notrailer) # A bplist of size 32, which lacks a full trailer @@ -112,7 +114,7 @@ '<plist></plist>') def testReadHeader(self): - blank_header = StringIO.StringIO("") + blank_header = StringIO.StringIO() plist = binplist.BinaryPlist(blank_header) self.assertRaises(binplist.FormatError, plist._ReadHeader) wrong_header = StringIO.StringIO("bla") @@ -128,7 +130,7 @@ self.assertEqual(plist.version, "00") def testReadTrailer(self): - blank_trailer = StringIO.StringIO("") + blank_trailer = StringIO.StringIO() plist = binplist.BinaryPlist(blank_trailer) self.assertRaises(IOError, plist._ReadTrailer) plist = binplist.BinaryPlist(self.minimal) @@ -157,7 +159,7 @@ self.assertRaises(binplist.FormatError, plist._ReadOffsetTable) def testReadPlist(self): - blank_file = StringIO.StringIO("") + blank_file = StringIO.StringIO() self.assertRaises(binplist.FormatError, binplist.readPlist, blank_file) bplist15 = StringIO.StringIO("bplist15") self.assertRaises(binplist.FormatError, binplist.readPlist, bplist15) @@ -500,14 +502,14 @@ plist = binplist.BinaryPlist(fd) # Fill objects_traversed with the current value as if we had been called # by a normal _Parse - plist.objects_traversed = set([0]) + plist.objects_traversed = {0} plist.object_ref_size = ref_size plist.object_offsets = object_offsets plist.object_count = len(object_offsets) result = plist._ParseObject() self.assertListEqual(expected_result, result) # Test that the circular reference detection helper is cleaned properly - self.assertSetEqual(plist.objects_traversed, set([0])) + self.assertSetEqual(plist.objects_traversed, {0}) def testParseDict(self): values = [ @@ -604,14 +606,131 @@ plist = binplist.BinaryPlist(fd) # Fill objects_traversed with the current value as if we had been called # by a normal _Parse - plist.objects_traversed = set([0]) + plist.objects_traversed = {0} plist.object_ref_size = ref_size plist.object_offsets = object_offsets plist.object_count = len(object_offsets) result = plist._ParseObject() self.assertEqual(expected_result, result) # Test that the circular reference detection helper is cleaned properly - self.assertSetEqual(plist.objects_traversed, set([0])) + self.assertSetEqual(plist.objects_traversed, {0}) + + + def test_ParseObjectByIndex(self): + unicode_string = ("\x6F\x00\x11\x65\xaf\x8b\xfa\x76\x7b\x90\x7f\x96\xbe" + "\x75\x33\x8b\xf7\x7e\xc8\x88\xab\x90\x1a\x8f\xc7\x00" + "\x20\x00\x2d\x00\x20\x00\x68\x00\x65\x00\x68") + actual_string = u"斯诺登避难申请终被通过 - heh" + fd = StringIO.StringIO(unicode_string) + plist = binplist.BinaryPlist(file_obj=fd) + # Make an external offset_list + offset_list = [0] + resulting_object = plist._ParseObjectByIndex(0, offset_list) + self.assertEqual(resulting_object, actual_string) + + # Second test + second_resulting_object = plist._ParseObjectByIndex(0, offset_list) + # Test that the UTF16 object was in the cache + self.assert_(second_resulting_object is resulting_object) + self.assertEqual(resulting_object, actual_string) + + # Now test for something more complex. An array that has both unicode and + # str strings. + two_element_array = ( + "\xA2" # Array of 2 objects + "\x01" # Reference to object unicode string + "\x02" # Reference to object str string + "\x61\x65\xaf" # Unicode object + "\x52\x99\xcd" # Str object + ) + fd = StringIO.StringIO(two_element_array) + plist = binplist.BinaryPlist(fd) + # Parsing with _ParseObjectByIndex requires setting up some bplist + # properties. + offset_list = [0, 3, 6] + plist.object_count = len(offset_list) + plist.object_offsets = offset_list + plist.object_ref_size = 1 + plist._file_size = len(two_element_array) + resulting_object = plist._ParseObjectByIndex(0, offset_list) + self.assertEqual(resulting_object, [u"斯", "\x99\xcd"]) + + + def test_PlistToUnicode(self): + tests = [ + # Integer tests + (3, + u'3', + u'3'), + + (-9239132913921, + u'-9239132913921', + u'-9239132913921'), + + # String tests + ('abc', # plist + u"'abc'", # with default smartascii + u"'abc'"), # with utf-8 encoding + + ('\xff\x34\x55', + u"'\\xff4U'", # smartascii handles this case "visually gracefully" + u"'\\xff\\x34\\x55'"), # invalid utf-8, so it's fully escaped + + ('\x00\x00\x00', + u"'\\x00\\x00\\x00'", # smartascii escapes non-printable characters + u"'\x00\x00\x00'"), # utf-8 actually encodes these + + # Unicode string tests + (u"斯", + u"'斯'", + u"'斯'",), + + # Array tests + ([1,2,3], + u'[1, 2, 3]', + u'[1, 2, 3]'), + + # Dictionary tests + ({'a': 3}, + u"{\n 'a': 3\n}", + u"{\n 'a': 3\n}"), + + ({'a': {'b': 3}}, + u"{\n 'a': {\n 'b': 3\n }\n}", # default indent + u"{\n 'a': {\n 'b': 3\n }\n}"), # default indent + + ({u"斯": '\xff\x61'}, + u"{\n '斯': '\\xffa'\n}", # smartascii handles a gracefully + u"{\n '斯': '\\xff\\x61'\n}"), # utf-8 fails decoding, full-escape + + # Misc values + (binplist.RawValue('abc'), + u"'\\x61\\x62\\x63'", + u"'\\x61\\x62\\x63'"), + + (binplist.CorruptReference, + u'##CORRUPT_REFERENCE##', + u'##CORRUPT_REFERENCE##'), + + (binplist.NullValue, + u'NULL', + u'NULL'), + + (binplist.UnknownObject, + u'##UNKNOWN_OBJECT##', + u'##UNKNOWN_OBJECT##'), + ] + for (plist, expected_outcome, expected_outcome_utf8) in tests: + self.assertEqual(expected_outcome, binplist.PlistToUnicode(plist)) + if expected_outcome_utf8 == UnicodeDecodeError: + self.assertRaises(UnicodeDecodeError, + binplist.PlistToUnicode, + plist, + string_encoding='utf-8') + else: + self.assertEqual(expected_outcome_utf8, + binplist.PlistToUnicode(plist, + string_encoding='utf-8')) if __name__ == "__main__": -- To unsubscribe, e-mail: opensuse-commit+unsubscr...@opensuse.org For additional commands, e-mail: opensuse-commit+h...@opensuse.org