__all__ = ['dictproxy', 'make_dictproxy'] from ctypes import pythonapi, py_object from _ctypes import PyObj_FromPtr PyDictProxy_New = pythonapi.PyDictProxy_New PyDictProxy_New.argtypes = (py_object,) PyDictProxy_New.rettype = py_object def make_dictproxy(obj): assert isinstance(obj,dict) return PyObj_FromPtr(PyDictProxy_New(obj)) ## make_dictproxy = lambda dictobj: type('',(),dictobj).__dict__ # for isinstance() check dictproxy = type(make_dictproxy({})) if __name__ == '__main__': import unittest class DictProxyTestCase(unittest.TestCase): def test_instance(self): d = make_dictproxy({}) self.assertTrue(isinstance(d,dictproxy)) self.assertFalse(isinstance(d.copy(),dictproxy)) def test_get(self): d = make_dictproxy({'a': 'b', 'c': 'd'}) self.assertEqual('b', d.get('a')) self.assertEqual('d', d.get('c')) def test_set(self): d = make_dictproxy({}) def _test_item_assignment(): d['a'] = 10 self.assertRaises(TypeError, _test_item_assignment) def test_copy(self): d1 = make_dictproxy({'a': 'b', 'c': 'd'}) d2 = d1.copy() self.assertEqual(d1, d2) self.assertTrue(isinstance(d2,dict)) d2['a'] = 'z' self.assertNotEqual(d1, d2) self.assertEqual('z', d2['a']) def test_not_immutable(self): a = dict(val=20) b = make_dictproxy(a) a['val'] = 10 self.assertEqual(10, b['val']) # This is ok, correct behavior. # So ... can/should not use dictproxy as immutable dict. # dictproxy just hide the interface. unittest.main()