mongo-python-driver/son.py
Mike Dirolf fcdedb47b6 doc
2009-01-08 16:12:15 -05:00

85 lines
2.4 KiB
Python

"""Tools for creating and manipulating SON, the Serialized Ocument Notation.
Regular dictionaries can be used instead of SON objects, but not when the order
of keys is important."""
import unittest
from UserDict import DictMixin
class SON(DictMixin):
"""SON data.
A subclass of dict that maintains ordering of keys and provides a few extra
niceties for dealing with SON.
"""
def __init__(self, data=None, **kwargs):
self.__keys = []
self.__data = {}
if data is not None:
if hasattr(data, 'items'):
items = data.iteritems()
else:
items = list(data)
for item in items:
if len(item) != 2:
raise ValueError("sequence elements must have length 2")
self.__keys.append(items[0])
self.__data[items[0]] = items[1]
if kwargs:
self.__merge_keys(kwargs.iterkeys())
self.update(kwargs)
def __merge_keys(self, keys):
self._keys.extend(keys)
newkeys = {}
self.__keys = [newkeys.setdefault(x, x) for x in self.__keys if x not in newkeys]
def __repr__(self):
result = []
for key in self.__keys:
result.append("(%s, %s)" % (repr(key), repr(self.__data[key])))
return "SON([%s])" % ", ".join(result)
def update(self, data):
if data is not None:
if hasattr(data, "iterkeys"):
self.__merge_keys(data.iterkeys())
else:
self.__merge_keys(data.keys())
self._data.update(data)
def __getitem__(self, key):
return self.__data[key]
def __setitem__(self, key, value):
if key not in self.__data:
self.__keys.append(key)
self.__data[key] = value
def __delitem__(self, key):
del self.__data[key]
self.__keys.remove(key)
def keys(self):
return list(self.__keys)
def copy(self):
other = SON()
other.__data = self.__data.copy()
other.__keys = self.__keys[:]
return other
class TestSON(unittest.TestCase):
def setUp(self):
pass
def test_ordered_dict(self):
a = SON()
a["hello"] = "world"
a["mike"] = "awesome"
a["hello_"] = "mike"
self.assertEqual(a.items(), [("hello", "world"), ("mike", "awesome"), ("hello_", "mike")])
if __name__ == "__main__":
unittest.main()