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