summaryrefslogtreecommitdiffstats
path: root/Lib/plat-mac/plistlib.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/plat-mac/plistlib.py')
-rw-r--r--Lib/plat-mac/plistlib.py648
1 files changed, 324 insertions, 324 deletions
diff --git a/Lib/plat-mac/plistlib.py b/Lib/plat-mac/plistlib.py
index 9c914d2..40e2675 100644
--- a/Lib/plat-mac/plistlib.py
+++ b/Lib/plat-mac/plistlib.py
@@ -33,29 +33,29 @@ The <date> plist data has (limited) support through the Date class.
Generate Plist example:
- pl = Plist(
- aString="Doodah",
- aList=["A", "B", 12, 32.1, [1, 2, 3]],
- aFloat = 0.1,
- anInt = 728,
- aDict=Dict(
- anotherString="<hello & hi there!>",
- aUnicodeValue=u'M\xe4ssig, Ma\xdf',
- aTrueValue=True,
- aFalseValue=False,
- ),
- someData = Data("<binary gunk>"),
- someMoreData = Data("<lots of binary gunk>" * 10),
- aDate = Date(time.mktime(time.gmtime())),
- )
- # unicode keys are possible, but a little awkward to use:
- pl[u'\xc5benraa'] = "That was a unicode key."
- pl.write(fileName)
+ pl = Plist(
+ aString="Doodah",
+ aList=["A", "B", 12, 32.1, [1, 2, 3]],
+ aFloat = 0.1,
+ anInt = 728,
+ aDict=Dict(
+ anotherString="<hello & hi there!>",
+ aUnicodeValue=u'M\xe4ssig, Ma\xdf',
+ aTrueValue=True,
+ aFalseValue=False,
+ ),
+ someData = Data("<binary gunk>"),
+ someMoreData = Data("<lots of binary gunk>" * 10),
+ aDate = Date(time.mktime(time.gmtime())),
+ )
+ # unicode keys are possible, but a little awkward to use:
+ pl[u'\xc5benraa'] = "That was a unicode key."
+ pl.write(fileName)
Parse Plist example:
- pl = Plist.fromFile(pathOrFile)
- print pl.aKey
+ pl = Plist.fromFile(pathOrFile)
+ print pl.aKey
"""
@@ -71,40 +71,40 @@ INDENT = "\t"
class DumbXMLWriter:
- def __init__(self, file):
- self.file = file
- self.stack = []
- self.indentLevel = 0
+ def __init__(self, file):
+ self.file = file
+ self.stack = []
+ self.indentLevel = 0
- def beginElement(self, element):
- self.stack.append(element)
- self.writeln("<%s>" % element)
- self.indentLevel += 1
+ def beginElement(self, element):
+ self.stack.append(element)
+ self.writeln("<%s>" % element)
+ self.indentLevel += 1
- def endElement(self, element):
- assert self.indentLevel > 0
- assert self.stack.pop() == element
- self.indentLevel -= 1
- self.writeln("</%s>" % element)
+ def endElement(self, element):
+ assert self.indentLevel > 0
+ assert self.stack.pop() == element
+ self.indentLevel -= 1
+ self.writeln("</%s>" % element)
- def simpleElement(self, element, value=None):
- if value:
- value = _encode(value)
- self.writeln("<%s>%s</%s>" % (element, value, element))
- else:
- self.writeln("<%s/>" % element)
+ def simpleElement(self, element, value=None):
+ if value:
+ value = _encode(value)
+ self.writeln("<%s>%s</%s>" % (element, value, element))
+ else:
+ self.writeln("<%s/>" % element)
- def writeln(self, line):
- if line:
- self.file.write(self.indentLevel * INDENT + line + "\n")
- else:
- self.file.write("\n")
+ def writeln(self, line):
+ if line:
+ self.file.write(self.indentLevel * INDENT + line + "\n")
+ else:
+ self.file.write("\n")
def _encode(text):
- text = text.replace("&", "&amp;")
- text = text.replace("<", "&lt;")
- return text.encode("utf-8")
+ text = text.replace("&", "&amp;")
+ text = text.replace("<", "&lt;")
+ return text.encode("utf-8")
PLISTHEADER = """\
@@ -114,323 +114,323 @@ PLISTHEADER = """\
class PlistWriter(DumbXMLWriter):
- def __init__(self, file):
- file.write(PLISTHEADER)
- DumbXMLWriter.__init__(self, file)
-
- def writeValue(self, value):
- if isinstance(value, (str, unicode)):
- self.simpleElement("string", value)
- elif isinstance(value, bool):
- # must switch for bool before int, as bool is a
- # subclass of int...
- if value:
- self.simpleElement("true")
- else:
- self.simpleElement("false")
- elif isinstance(value, int):
- self.simpleElement("integer", str(value))
- elif isinstance(value, float):
- # should perhaps use repr() for better precision?
- self.simpleElement("real", str(value))
- elif isinstance(value, (dict, Dict)):
- self.writeDict(value)
- elif isinstance(value, Data):
- self.writeData(value)
- elif isinstance(value, Date):
- self.simpleElement("date", value.toString())
- elif isinstance(value, (tuple, list)):
- self.writeArray(value)
- else:
- assert 0, "unsuported type: %s" % type(value)
-
- def writeData(self, data):
- self.beginElement("data")
- for line in data.asBase64().split("\n"):
- if line:
- self.writeln(line)
- self.endElement("data")
-
- def writeDict(self, d):
- self.beginElement("dict")
- items = d.items()
- items.sort()
- for key, value in items:
- assert isinstance(key, (str, unicode)), "keys must be strings"
- self.simpleElement("key", key)
- self.writeValue(value)
- self.endElement("dict")
-
- def writeArray(self, array):
- self.beginElement("array")
- for value in array:
- self.writeValue(value)
- self.endElement("array")
+ def __init__(self, file):
+ file.write(PLISTHEADER)
+ DumbXMLWriter.__init__(self, file)
+
+ def writeValue(self, value):
+ if isinstance(value, (str, unicode)):
+ self.simpleElement("string", value)
+ elif isinstance(value, bool):
+ # must switch for bool before int, as bool is a
+ # subclass of int...
+ if value:
+ self.simpleElement("true")
+ else:
+ self.simpleElement("false")
+ elif isinstance(value, int):
+ self.simpleElement("integer", str(value))
+ elif isinstance(value, float):
+ # should perhaps use repr() for better precision?
+ self.simpleElement("real", str(value))
+ elif isinstance(value, (dict, Dict)):
+ self.writeDict(value)
+ elif isinstance(value, Data):
+ self.writeData(value)
+ elif isinstance(value, Date):
+ self.simpleElement("date", value.toString())
+ elif isinstance(value, (tuple, list)):
+ self.writeArray(value)
+ else:
+ assert 0, "unsuported type: %s" % type(value)
+
+ def writeData(self, data):
+ self.beginElement("data")
+ for line in data.asBase64().split("\n"):
+ if line:
+ self.writeln(line)
+ self.endElement("data")
+
+ def writeDict(self, d):
+ self.beginElement("dict")
+ items = d.items()
+ items.sort()
+ for key, value in items:
+ assert isinstance(key, (str, unicode)), "keys must be strings"
+ self.simpleElement("key", key)
+ self.writeValue(value)
+ self.endElement("dict")
+
+ def writeArray(self, array):
+ self.beginElement("array")
+ for value in array:
+ self.writeValue(value)
+ self.endElement("array")
class Dict:
- """Dict wrapper for convenient access of values through attributes."""
+ """Dict wrapper for convenient access of values through attributes."""
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
+ def __init__(self, **kwargs):
+ self.__dict__.update(kwargs)
- def __cmp__(self, other):
- if isinstance(other, self.__class__):
- return cmp(self.__dict__, other.__dict__)
- elif isinstance(other, dict):
- return cmp(self.__dict__, other)
- else:
- return cmp(id(self), id(other))
+ def __cmp__(self, other):
+ if isinstance(other, self.__class__):
+ return cmp(self.__dict__, other.__dict__)
+ elif isinstance(other, dict):
+ return cmp(self.__dict__, other)
+ else:
+ return cmp(id(self), id(other))
- def __str__(self):
- return "%s(**%s)" % (self.__class__.__name__, self.__dict__)
- __repr__ = __str__
+ def __str__(self):
+ return "%s(**%s)" % (self.__class__.__name__, self.__dict__)
+ __repr__ = __str__
- def copy(self):
- return self.__class__(**self.__dict__)
+ def copy(self):
+ return self.__class__(**self.__dict__)
- def __getattr__(self, attr):
- """Delegate everything else to the dict object."""
- return getattr(self.__dict__, attr)
+ def __getattr__(self, attr):
+ """Delegate everything else to the dict object."""
+ return getattr(self.__dict__, attr)
class Plist(Dict):
- """The main Plist object. Basically a dict (the toplevel object
- of a plist is a dict) with two additional methods to read from
- and write to files.
- """
-
- def fromFile(cls, pathOrFile):
- didOpen = 0
- if not hasattr(pathOrFile, "write"):
- pathOrFile = open(pathOrFile)
- didOpen = 1
- p = PlistParser()
- plist = p.parse(pathOrFile)
- if didOpen:
- pathOrFile.close()
- return plist
- fromFile = classmethod(fromFile)
-
- def write(self, pathOrFile):
- if not hasattr(pathOrFile, "write"):
- pathOrFile = open(pathOrFile, "w")
- didOpen = 1
- else:
- didOpen = 0
-
- writer = PlistWriter(pathOrFile)
- writer.writeln("<plist version=\"1.0\">")
- writer.writeDict(self.__dict__)
- writer.writeln("</plist>")
-
- if didOpen:
- pathOrFile.close()
+ """The main Plist object. Basically a dict (the toplevel object
+ of a plist is a dict) with two additional methods to read from
+ and write to files.
+ """
+
+ def fromFile(cls, pathOrFile):
+ didOpen = 0
+ if not hasattr(pathOrFile, "write"):
+ pathOrFile = open(pathOrFile)
+ didOpen = 1
+ p = PlistParser()
+ plist = p.parse(pathOrFile)
+ if didOpen:
+ pathOrFile.close()
+ return plist
+ fromFile = classmethod(fromFile)
+
+ def write(self, pathOrFile):
+ if not hasattr(pathOrFile, "write"):
+ pathOrFile = open(pathOrFile, "w")
+ didOpen = 1
+ else:
+ didOpen = 0
+
+ writer = PlistWriter(pathOrFile)
+ writer.writeln("<plist version=\"1.0\">")
+ writer.writeDict(self.__dict__)
+ writer.writeln("</plist>")
+
+ if didOpen:
+ pathOrFile.close()
class Data:
- """Wrapper for binary data."""
+ """Wrapper for binary data."""
- def __init__(self, data):
- self.data = data
+ def __init__(self, data):
+ self.data = data
- def fromBase64(cls, data):
- import base64
- return cls(base64.decodestring(data))
- fromBase64 = classmethod(fromBase64)
+ def fromBase64(cls, data):
+ import base64
+ return cls(base64.decodestring(data))
+ fromBase64 = classmethod(fromBase64)
- def asBase64(self):
- import base64
- return base64.encodestring(self.data)
+ def asBase64(self):
+ import base64
+ return base64.encodestring(self.data)
- def __cmp__(self, other):
- if isinstance(other, self.__class__):
- return cmp(self.data, other.data)
- elif isinstance(other, str):
- return cmp(self.data, other)
- else:
- return cmp(id(self), id(other))
+ def __cmp__(self, other):
+ if isinstance(other, self.__class__):
+ return cmp(self.data, other.data)
+ elif isinstance(other, str):
+ return cmp(self.data, other)
+ else:
+ return cmp(id(self), id(other))
- def __repr__(self):
- return "%s(%s)" % (self.__class__.__name__, repr(self.data))
+ def __repr__(self):
+ return "%s(%s)" % (self.__class__.__name__, repr(self.data))
class Date:
- """Primitive date wrapper, uses time floats internally, is agnostic
- about time zones.
- """
+ """Primitive date wrapper, uses time floats internally, is agnostic
+ about time zones.
+ """
- def __init__(self, date):
- if isinstance(date, str):
- from xml.utils.iso8601 import parse
- date = parse(date)
- self.date = date
+ def __init__(self, date):
+ if isinstance(date, str):
+ from xml.utils.iso8601 import parse
+ date = parse(date)
+ self.date = date
- def toString(self):
- from xml.utils.iso8601 import tostring
- return tostring(self.date)
+ def toString(self):
+ from xml.utils.iso8601 import tostring
+ return tostring(self.date)
- def __cmp__(self, other):
- if isinstance(other, self.__class__):
- return cmp(self.date, other.date)
- elif isinstance(other, (int, float)):
- return cmp(self.date, other)
- else:
- return cmp(id(self), id(other))
+ def __cmp__(self, other):
+ if isinstance(other, self.__class__):
+ return cmp(self.date, other.date)
+ elif isinstance(other, (int, float)):
+ return cmp(self.date, other)
+ else:
+ return cmp(id(self), id(other))
- def __repr__(self):
- return "%s(%s)" % (self.__class__.__name__, repr(self.toString()))
+ def __repr__(self):
+ return "%s(%s)" % (self.__class__.__name__, repr(self.toString()))
class PlistParser:
- def __init__(self):
- self.stack = []
- self.currentKey = None
- self.root = None
-
- def parse(self, file):
- from xml.parsers.expat import ParserCreate
- parser = ParserCreate()
- parser.StartElementHandler = self.handleBeginElement
- parser.EndElementHandler = self.handleEndElement
- parser.CharacterDataHandler = self.handleData
- parser.ParseFile(file)
- return self.root
-
- def handleBeginElement(self, element, attrs):
- self.data = []
- handler = getattr(self, "begin_" + element, None)
- if handler is not None:
- handler(attrs)
-
- def handleEndElement(self, element):
- handler = getattr(self, "end_" + element, None)
- if handler is not None:
- handler()
-
- def handleData(self, data):
- self.data.append(data)
-
- def addObject(self, value):
- if self.currentKey is not None:
- self.stack[-1][self.currentKey] = value
- self.currentKey = None
- elif not self.stack:
- # this is the root object
- assert self.root is value
- else:
- self.stack[-1].append(value)
-
- def getData(self):
- data = "".join(self.data)
- try:
- data = data.encode("ascii")
- except UnicodeError:
- pass
- self.data = []
- return data
-
- # element handlers
-
- def begin_dict(self, attrs):
- if self.root is None:
- self.root = d = Plist()
- else:
- d = Dict()
- self.addObject(d)
- self.stack.append(d)
- def end_dict(self):
- self.stack.pop()
-
- def end_key(self):
- self.currentKey = self.getData()
-
- def begin_array(self, attrs):
- a = []
- self.addObject(a)
- self.stack.append(a)
- def end_array(self):
- self.stack.pop()
-
- def end_true(self):
- self.addObject(True)
- def end_false(self):
- self.addObject(False)
- def end_integer(self):
- self.addObject(int(self.getData()))
- def end_real(self):
- self.addObject(float(self.getData()))
- def end_string(self):
- self.addObject(self.getData())
- def end_data(self):
- self.addObject(Data.fromBase64(self.getData()))
- def end_date(self):
- self.addObject(Date(self.getData()))
+ def __init__(self):
+ self.stack = []
+ self.currentKey = None
+ self.root = None
+
+ def parse(self, file):
+ from xml.parsers.expat import ParserCreate
+ parser = ParserCreate()
+ parser.StartElementHandler = self.handleBeginElement
+ parser.EndElementHandler = self.handleEndElement
+ parser.CharacterDataHandler = self.handleData
+ parser.ParseFile(file)
+ return self.root
+
+ def handleBeginElement(self, element, attrs):
+ self.data = []
+ handler = getattr(self, "begin_" + element, None)
+ if handler is not None:
+ handler(attrs)
+
+ def handleEndElement(self, element):
+ handler = getattr(self, "end_" + element, None)
+ if handler is not None:
+ handler()
+
+ def handleData(self, data):
+ self.data.append(data)
+
+ def addObject(self, value):
+ if self.currentKey is not None:
+ self.stack[-1][self.currentKey] = value
+ self.currentKey = None
+ elif not self.stack:
+ # this is the root object
+ assert self.root is value
+ else:
+ self.stack[-1].append(value)
+
+ def getData(self):
+ data = "".join(self.data)
+ try:
+ data = data.encode("ascii")
+ except UnicodeError:
+ pass
+ self.data = []
+ return data
+
+ # element handlers
+
+ def begin_dict(self, attrs):
+ if self.root is None:
+ self.root = d = Plist()
+ else:
+ d = Dict()
+ self.addObject(d)
+ self.stack.append(d)
+ def end_dict(self):
+ self.stack.pop()
+
+ def end_key(self):
+ self.currentKey = self.getData()
+
+ def begin_array(self, attrs):
+ a = []
+ self.addObject(a)
+ self.stack.append(a)
+ def end_array(self):
+ self.stack.pop()
+
+ def end_true(self):
+ self.addObject(True)
+ def end_false(self):
+ self.addObject(False)
+ def end_integer(self):
+ self.addObject(int(self.getData()))
+ def end_real(self):
+ self.addObject(float(self.getData()))
+ def end_string(self):
+ self.addObject(self.getData())
+ def end_data(self):
+ self.addObject(Data.fromBase64(self.getData()))
+ def end_date(self):
+ self.addObject(Date(self.getData()))
# cruft to support booleans in Python <= 2.3
import sys
if sys.version_info[:2] < (2, 3):
- # Python 2.2 and earlier: no booleans
- # Python 2.2.x: booleans are ints
- class bool(int):
- """Imitation of the Python 2.3 bool object."""
- def __new__(cls, value):
- return int.__new__(cls, not not value)
- def __repr__(self):
- if self:
- return "True"
- else:
- return "False"
- True = bool(1)
- False = bool(0)
+ # Python 2.2 and earlier: no booleans
+ # Python 2.2.x: booleans are ints
+ class bool(int):
+ """Imitation of the Python 2.3 bool object."""
+ def __new__(cls, value):
+ return int.__new__(cls, not not value)
+ def __repr__(self):
+ if self:
+ return "True"
+ else:
+ return "False"
+ True = bool(1)
+ False = bool(0)
else:
- # Bind the boolean builtins to local names
- True = True
- False = False
- bool = bool
+ # Bind the boolean builtins to local names
+ True = True
+ False = False
+ bool = bool
if __name__ == "__main__":
- from StringIO import StringIO
- import time
- if len(sys.argv) == 1:
- pl = Plist(
- aString="Doodah",
- aList=["A", "B", 12, 32.1, [1, 2, 3]],
- aFloat = 0.1,
- anInt = 728,
- aDict=Dict(
- anotherString="<hello & hi there!>",
- aUnicodeValue=u'M\xe4ssig, Ma\xdf',
- aTrueValue=True,
- aFalseValue=False,
- ),
- someData = Data("<binary gunk>"),
- someMoreData = Data("<lots of binary gunk>" * 10),
- aDate = Date(time.mktime(time.gmtime())),
- )
- elif len(sys.argv) == 2:
- pl = Plist.fromFile(sys.argv[1])
- else:
- print "Too many arguments: at most 1 plist file can be given."
- sys.exit(1)
-
- # unicode keys are possible, but a little awkward to use:
- pl[u'\xc5benraa'] = "That was a unicode key."
- f = StringIO()
- pl.write(f)
- xml = f.getvalue()
- print xml
- f.seek(0)
- pl2 = Plist.fromFile(f)
- assert pl == pl2
- f = StringIO()
- pl2.write(f)
- assert xml == f.getvalue()
- #print repr(pl2)
+ from StringIO import StringIO
+ import time
+ if len(sys.argv) == 1:
+ pl = Plist(
+ aString="Doodah",
+ aList=["A", "B", 12, 32.1, [1, 2, 3]],
+ aFloat = 0.1,
+ anInt = 728,
+ aDict=Dict(
+ anotherString="<hello & hi there!>",
+ aUnicodeValue=u'M\xe4ssig, Ma\xdf',
+ aTrueValue=True,
+ aFalseValue=False,
+ ),
+ someData = Data("<binary gunk>"),
+ someMoreData = Data("<lots of binary gunk>" * 10),
+ aDate = Date(time.mktime(time.gmtime())),
+ )
+ elif len(sys.argv) == 2:
+ pl = Plist.fromFile(sys.argv[1])
+ else:
+ print "Too many arguments: at most 1 plist file can be given."
+ sys.exit(1)
+
+ # unicode keys are possible, but a little awkward to use:
+ pl[u'\xc5benraa'] = "That was a unicode key."
+ f = StringIO()
+ pl.write(f)
+ xml = f.getvalue()
+ print xml
+ f.seek(0)
+ pl2 = Plist.fromFile(f)
+ assert pl == pl2
+ f = StringIO()
+ pl2.write(f)
+ assert xml == f.getvalue()
+ #print repr(pl2)