'How to force plistlib in Python to save escaped special characters?
I am having a kind of a problem with module plistlib. It works fine, except when saving plists. It doesn't save apostrophe as special character. It does save & as & which is fine, but it saves apostrophe as ' (instead of ') which is not fine. I have a lot of plists with a lot of text and when I change something (batch change with script) it gives me a headache with git diff, because every single ' will become '.
How to force plistlib to save plist with all special characters escaped (after all, there is only 5 of them)?
Solution 1:[1]
I will answer my own question since I dug around and found answer.
Problem is with function _escape(text) in module plistlib. It escapes only &, < and > although Xcode with its plist reader escapes all five characters (&, <, >, ' and "), that is why I think this module should also. It would also be a good addition to module plistlib something like ElementTree's parameter entities in function escape(). That parameter is a dict with additional characters to replace. Similar addition to plistlib's function save_plist() would be a good idea so that we can escape additional characters.
My solution is based on so called monkey patching. Basically, I copied whole function _escape(text) and just added additional escapes (' and "):
from plistlib import _controlCharPat
def patched_escape(text):
m = _controlCharPat.search(text)
if m is not None:
raise ValueError("strings can't contains control characters; "
"use bytes instead")
text = text.replace("\r\n", "\n") # convert DOS line endings
text = text.replace("\r", "\n") # convert Mac line endings
text = text.replace("&", "&") # escape '&'
text = text.replace("<", "<") # escape '<'
text = text.replace(">", ">") # escape '>'
text = text.replace("'", "'") # escape '''
text = text.replace("\"", """) # escape '"'
return text
And now in my script I replaced plistlib's function _escape(text) with mine:
plistlib._escape = patched_escape
Now plistlib correctly escapes and saves plists. Usual warnings regarding monkey patching apply also here. I don't have other callers, just this script so it is fine to do this.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | dosvarog |
