Skip to content

Commit

Permalink
Added more tests, Reduced runtime type check
Browse files Browse the repository at this point in the history
  • Loading branch information
ishikawa committed Aug 4, 2008
1 parent 96181f3 commit 65f2825
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 10 deletions.
35 changes: 25 additions & 10 deletions plist_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ def startDocument(self):
self.__plist = None
self.__key = None
self.__characters = None
# For reducing runtime type checking,
# the parser caches top level object type.
self.__in_dict = False

def endDocument(self):
self._assert(self.__plist is not None, "A top level element must be <plist>.")
Expand Down Expand Up @@ -99,23 +102,31 @@ def _fixtext(self, text):
# XmlPropertyListParser private
# ------------------------------------------------
def _push_value(self, value):
if self.__plist is None:
if not self.__stack:
self._assert(self.__plist is None, "Multiple objects at top level")
self.__plist = value
else:
top = self.__stack[-1]
if isinstance(top, dict):
#assert isinstance(top, (dict, list))
if self.__in_dict:
k = self.__key
if k is None:
raise PropertyListParseError("Missing key for dictionary.")
top[k] = value
self.__key = None
elif isinstance(top, list):
top.append(value)
else:
raise PropertyListParseError("multiple objects at top level")
top.append(value)

def _pop_value(self):
def _push_stack(self, value):
self.__stack.append(value)
self.__in_dict = isinstance(value, dict)

def _pop_stack(self):
self.__stack.pop()
if self.__stack:
self.__in_dict = isinstance(self.__stack[-1], dict)
else:
self.__in_dict = False

def _start_plist(self, name, attrs):
self._assert(not self.__stack and self.__plist is None, "<plist> more than once.")
Expand All @@ -125,18 +136,20 @@ def _start_plist(self, name, attrs):
def _start_array(self, name, attrs):
v = list()
self._push_value(v)
self.__stack.append(v)
self._push_stack(v)

def _start_dict(self, name, attrs):
v = dict()
self._push_value(v)
self.__stack.append(v)
self._push_stack(v)

def _end_array(self, name):
self._pop_value()
self._pop_stack()

def _end_dict(self, name):
self._pop_value()
if self.__key is not None:
raise PropertyListParseError("Missing value for key '%s'" % self.__key)
self._pop_stack()

def _start_true(self, name, attrs):
self._push_value(True)
Expand All @@ -146,6 +159,8 @@ def _start_false(self, name, attrs):

def _parse_key(self, name, content):
self.__key = content
if not self.__in_dict:
raise PropertyListParseError("<key> element must be in <dict> element.")

def _parse_string(self, name, content):
self._push_value(content)
Expand Down
8 changes: 8 additions & 0 deletions tests/plist/invalid_key.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<key>true item</key>
<true/>
</array>
</plist>
12 changes: 12 additions & 0 deletions tests/plist/multiple_top_level.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>item 1</key>
<string>Hello</string>
</dict>
<dict>
<key>item 1</key>
<string>Hello</string>
</dict>
</plist>
10 changes: 10 additions & 0 deletions tests/runtests.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ def test_multiple_plist(self):
PropertyListParseError,
self.parsePropertyList, 'multiple_plist.plist')

def test_multiple_top_level_plist(self):
self.assertRaises(
PropertyListParseError,
self.parsePropertyList, 'multiple_top_level.plist')

def test_invalid_key_plist(self):
self.assertRaises(
PropertyListParseError,
self.parsePropertyList, 'invalid_key.plist')

def test_empty_dict_plist(self):
plist = self.parsePropertyList('empty_dict.plist')
self.assertNotNone(plist)
Expand Down

0 comments on commit 65f2825

Please sign in to comment.