plistlib replacement

45 views
Skip to first unread message

Greg Neagle

unread,
Aug 17, 2009, 11:32:05 AM8/17/09
to pymac...@googlegroups.com
Following up from a discussion last month --

Has anyone wrapped the appropriate Foundation classes to replace
plistlib?

I've been working on replacing my plistlib calls in munki with their
Foundation equivalents, but I keep running into odd errors with type
conversions to/from Objective-C/Cocoa types. I'm sure I can work
through all this, but if someone has already done the work, I'd be
happy to use it...

I'm replacing

plistlib.readPlist
plistlib.readPlistFromString
plistlib.writePlist
plistlib.writePlistToString


-Greg

Jeremy Reichman

unread,
Aug 17, 2009, 2:03:13 PM8/17/09
to pymac...@googlegroups.com

Maybe someone from the Python Mac SIG has? Has anyone asked there? If not,
it's probably worth it and if nothing else, someone might want to pitch in.
(Especially given that plistlib is included with Python.) It's a pretty
active list, and a lot of the main Mac Python developers are there.

http://mail.python.org/mailman/listinfo/pythonmac-sig

A lot of stuff there has been focused on Appscript, lately, from what I've
seen. I scan subjects when I can.


--
Jeremy

Nigel Kersten

unread,
Aug 17, 2009, 2:11:44 PM8/17/09
to pymac...@googlegroups.com
Have you got an example of a type conversion error Greg?

Greg Neagle

unread,
Aug 17, 2009, 2:20:37 PM8/17/09
to pymac...@googlegroups.com
Here's one:

Traceback (most recent call last):
File "./makepkginfo", line 257, in <module>
main()
File "./makepkginfo", line 253, in main
print plistlib.writePlistToString(catinfo)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 109, in writePlistToString
writePlist(rootObject, f)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 93, in writePlist
writer.writeValue(rootObject)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 248, in writeValue
self.writeDict(value)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 277, in writeDict
self.writeValue(value)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 254, in writeValue
self.writeArray(value)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 283, in writeArray
self.writeValue(value)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 248, in writeValue
self.writeDict(value)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 277, in writeDict
self.writeValue(value)
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/plat-mac/plistlib.py", line 256, in writeValue
raise TypeError("unsuported type: %s" % type(value))
TypeError: unsuported type: <class 'objc._pythonify.OC_PythonLong'>

I'm using Foundation to read an Info.plist from an Apple package, but
then plistlib to write another plist. Foundation is returning a long
integer for the 'IFPkgFlagInstalledSize' value, but plistlib barfs
trying to write it back out.
I'm sure this particular problem will go away once I convert the plist
writing code to use Foundation instead of plistlib, but I'm worried
that I'm going to run into all sorts of subtle errors down the line
because the types Foundation is returning are not the same as the
types plistlib is returning.

I was hoping someone else had already gone down this path.

-Greg

SABRE Robotics

unread,
Aug 17, 2009, 2:27:11 PM8/17/09
to pymac...@googlegroups.com

On 17-Aug-09, at 12:20 PM, Greg Neagle wrote:

> I'm using Foundation to read an Info.plist from an Apple package, but
> then plistlib to write another plist. Foundation is returning a long
> integer for the 'IFPkgFlagInstalledSize' value, but plistlib barfs
> trying to write it back out.
> I'm sure this particular problem will go away once I convert the plist
> writing code to use Foundation instead of plistlib, but I'm worried
> that I'm going to run into all sorts of subtle errors down the line
> because the types Foundation is returning are not the same as the
> types plistlib is returning.
>
> I was hoping someone else had already gone down this path.
>
> -Greg

Is there any reason to not just use:

NSDictionary
.dictionaryWithDictionary_(mydict).writeToFile_atomically_(myfile, True)

to output a plist, as explained here: http://stackoverflow.com/questions/879212/serializing-a-python-object-to-xml-apple-plist/1261238#1261238
?

Clinton


Greg Neagle

unread,
Aug 17, 2009, 2:31:29 PM8/17/09
to pymac...@googlegroups.com
Like I said, I will be converting all the plist writing to Foundation
calls, but I'm afraid that might side-step the issue, which is that
the types returned when reading a plist using the Foundation calls are
not the same as the types returned when reading a plist using
plistlib. This may introduce a set of issues that I'll have to work
through. It's nothing I can't handle; just hoping to avoid the grunt
work if possible.

-Greg

Preston Holmes

unread,
Aug 17, 2009, 4:29:04 PM8/17/09
to pymac...@googlegroups.com
I think there is also the angle of:

import fancyfoundationplistlib as plistlib

if it is API compatible - it lets your code remain as is

Also if fancyfoundationplistlib ends up replacing plistlib in the
standard library on the Apple provided python dist - its a win

But of course writing the wrapper comes first ;-)

given the rather finite datatypes involved, this seems like a perfect
scenario for the test code to come first.

Given what python types plist uses, and what foundation uses - a
simple conversion step in the wrapper would probably be sufficient?

Here is basically the list (from the plistlib.py file)

class PlistWriter(DumbXMLWriter):

def __init__(self, file, indentLevel=0, indent="\t",
writeHeader=1):
if writeHeader:
file.write(PLISTHEADER)
DumbXMLWriter.__init__(self, file, indentLevel, indent)

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):
self.simpleElement("real", repr(value))
elif isinstance(value, dict):
self.writeDict(value)
elif isinstance(value, Data):
self.writeData(value)
elif isinstance(value, datetime.datetime):
self.simpleElement("date", _dateToString(value))
elif isinstance(value, (tuple, list)):
self.writeArray(value)
else:
raise TypeError("unsuported type: %s" % type(value))

-Preston
Reply all
Reply to author
Forward
0 new messages