Rev 131: implement some more properties. in http://bazaar.launchpad.net/~jameinel/meliae/mem-object-collection

John Arbash Meinel john at arbash-meinel.com
Mon Dec 28 04:13:52 GMT 2009


At http://bazaar.launchpad.net/~jameinel/meliae/mem-object-collection

------------------------------------------------------------
revno: 131
revision-id: john at arbash-meinel.com-20091228041337-3588e2grxelu0l3a
parent: john at arbash-meinel.com-20091228033001-vwjof7itsddctrua
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: mem-object-collection
timestamp: Sun 2009-12-27 22:13:37 -0600
message:
  implement some more properties.
-------------- next part --------------
=== modified file 'meliae/_loader.pyx'
--- a/meliae/_loader.pyx	2009-12-28 03:30:01 +0000
+++ b/meliae/_loader.pyx	2009-12-28 04:13:37 +0000
@@ -53,6 +53,8 @@
     """
     cdef PyObject *tmp
 
+    # TODO: Note that using _lookup directly would remove the need to ever do a
+    #       double-lookup to set the value
     tmp = PyDict_GetItem(d, val)
     if tmp == NULL:
         PyDict_SetItem(d, val, val)
@@ -133,8 +135,10 @@
     # """The raw C structure, used to minimize memory allocation size."""
     PyObject *address
     PyObject *type_str
+    # Consider making this unsigned long
     long size
     RefList *ref_list
+    # TODO: Scheduled for removal
     int length
     PyObject *value
     PyObject *name
@@ -159,12 +163,10 @@
     """
 
     cdef MemObjectCollection collection
-    cdef public object address
     cdef _MemObject *_obj
     cdef object __weakref__
 
-    def __init__(self, address, collection):
-        self.address = address
+    def __init__(self, collection):
         self.collection = collection
         self._obj = NULL
 
@@ -178,6 +180,11 @@
             return False
         return True
 
+    property address:
+        def __get__(self):
+            self._ensure_obj()
+            return <object>(self._obj.address)
+
     property type_str:
         """The type of this object."""
         def __get__(self):
@@ -194,12 +201,40 @@
             self._ensure_obj()
             self._obj.size = value
 
+    property value:
+        """Value for this object (for strings and ints)"""
+        def __get__(self):
+            self._ensure_obj()
+            return <object>self._obj.value
+
+        def __set__(self, value):
+            cdef PyObject *new_val
+            self._ensure_obj()
+            new_val = <PyObject *>value
+            # INCREF first, just in case value is self._obj.value
+            Py_INCREF(new_val)
+            Py_DECREF(self._obj.value)
+            self._obj.value = new_val
+
     def __len__(self):
         self._ensure_obj()
         if self._obj.ref_list == NULL:
             return 0
         return self._obj.ref_list.size
 
+    def _intern_from_cache(self, cache):
+        self._ensure_obj()
+        address = _set_default(cache, <object>self._obj.address)
+        if (<PyObject *>address) != self._obj.address:
+            Py_DECREF(self._obj.address)
+            self._obj.address = <PyObject *>address
+            Py_INCREF(self._obj.address)
+        type_str = _set_default(cache, <object>self.type_str)
+        if (<PyObject *>type_str) != self._obj.type_str:
+            Py_DECREF(self._obj.type_str)
+            self._obj.type_str = <PyObject *>type_str
+            Py_INCREF(self._obj.type_str)
+
     # def __getitem__(self, offset):
     #     cdef _MemObject *slot
     #     cdef PyObject *item_addr
@@ -324,7 +359,7 @@
             if address in self._proxies:
                 proxy = self._proxies[address]
             else:
-                proxy = _MemObjectProxy(address, self)
+                proxy = _MemObjectProxy(self)
                 proxy._obj = slot[0]
                 self._proxies[address] = proxy
         return proxy
@@ -427,6 +462,7 @@
             value=None, name=None, referrer_list=(), total_size=0):
         """Add a new MemObject to this collection."""
         cdef _MemObject **slot, *new_entry
+        cdef _MemObjectProxy proxy
         cdef PyObject *addr
 
         slot = self._lookup(address)
@@ -455,7 +491,11 @@
         Py_INCREF(new_entry.type_str)
         new_entry.size = size
         new_entry.ref_list = _list_to_ref_list(ref_list)
-        new_entry.length = length
+        # TODO: Scheduled for removal
+        if length is None:
+            new_entry.length = -1
+        else:
+            new_entry.length = length
         new_entry.value = <PyObject *>value
         Py_INCREF(new_entry.value)
         new_entry.name = <PyObject *>name
@@ -466,6 +506,10 @@
         if self._filled * 3 > (self._table_mask + 1) * 2:
             # We need to grow
             self._resize(self._active * 2)
+        proxy = _MemObjectProxy(self)
+        proxy._obj = new_entry
+        self._proxies[address] = proxy
+        return proxy
 
     def __dealloc__(self):
         cdef long i
@@ -510,6 +554,7 @@
     #       not just point to the final object anyway...
     cdef RefList *_ref_list # An array of addresses that this object
                             # referenced. May be NULL if len() == 0
+    # TODO: Scheduled for removal
     cdef readonly int length # Object length (ob_size), aka len(object)
     cdef public object value    # May be None, a PyString or a PyInt
     cdef readonly object name     # Name of this object (only valid for

=== modified file 'meliae/loader.py'
--- a/meliae/loader.py	2009-12-23 16:55:05 +0000
+++ b/meliae/loader.py	2009-12-28 04:13:37 +0000
@@ -488,7 +488,8 @@
             cleanup()
 
 
-def iter_objs(source, using_json=False, show_prog=False, input_size=0, objs=None):
+def iter_objs(source, using_json=False, show_prog=False, input_size=0,
+              objs=None, factory=None):
     """Iterate MemObjects from json.
 
     :param source: A line iterator.
@@ -497,6 +498,8 @@
     :param input_size: The size of the input if known (in bytes) or 0.
     :param objs: Either None or a dict containing objects by address. If not
         None, then duplicate objects will not be parsed or output.
+    :param factory: Use this to create new instances, if None, use
+        _loader.MemObject
     :return: A generator of MemObjects.
     """
     # TODO: cStringIO?
@@ -513,6 +516,8 @@
         decoder = _from_json
     else:
         decoder = _from_line
+    if factory is None:
+        factory = _loader.MemObject
     for line_num, line in enumerate(source):
         bytes_read += len(line)
         if line in ("[\n", "]\n"):
@@ -527,7 +532,7 @@
             address = int(m.group('address'))
             if address in objs:
                 continue
-        yield decoder(_loader.MemObject, line, temp_cache=temp_cache)
+        yield decoder(factory, line, temp_cache=temp_cache)
         if show_prog and (line_num - last > 5000):
             last = line_num
             mb_read = bytes_read / 1024. / 1024
@@ -544,8 +549,11 @@
 
 
 def _load(source, using_json, show_prog, input_size):
+    #objs = _loader.MemObjectCollection()
     objs = {}
-    for memobj in iter_objs(source, using_json, show_prog, input_size, objs):
+    for memobj in iter_objs(source, using_json, show_prog, input_size, objs,
+                            ):#factory=objs.add):
+        # objs.add automatically adds the object as it is created
         objs[memobj.address] = memobj
     # _fill_total_size(objs)
     return ObjManager(objs, show_progress=show_prog)

=== modified file 'meliae/tests/test__loader.py'
--- a/meliae/tests/test__loader.py	2009-12-28 03:30:01 +0000
+++ b/meliae/tests/test__loader.py	2009-12-28 04:13:37 +0000
@@ -231,3 +231,32 @@
         self.assertRaises(RuntimeError, lambda: mop.type_str)
         self.assertRaises(RuntimeError, lambda: mop.size)
         self.assertRaises(RuntimeError, len, mop)
+
+    def test_value(self):
+        mop = self.moc.add(1234, 'type', 256, value='testval')
+        self.assertEqual('testval', mop.value)
+        mop.value = None
+        self.assertEqual(None, mop.value)
+        mop.value = 'a str'
+        self.assertEqual('a str', mop.value)
+        mop.value = 'a str'
+        self.assertEqual('a str', mop.value)
+
+    def test__intern_from_cache(self):
+        cache = {}
+        addr = 1234567
+        mop = self.moc.add(addr, 'my ' + ' type', 256)
+        mop._intern_from_cache(cache)
+        self.assertTrue(addr in cache)
+        # TODO: ref_list and referrers
+        self.assertTrue(mop.address is addr)
+        self.assertTrue(cache[addr] is addr)
+        t = cache['my  type']
+        self.assertTrue(mop.type_str is t)
+        del self.moc[addr]
+        mop = self.moc.add(1234566+1, 'my ' + ' ty' + 'pe', 256)
+        self.assertFalse(mop.address is addr)
+        self.assertFalse(mop.type_str is t)
+        mop._intern_from_cache(cache)
+        self.assertTrue(mop.address is addr)
+        self.assertTrue(mop.type_str is t)



More information about the bazaar-commits mailing list