Skip to content

Commit

Permalink
Merge pull request #14 from normanyahq/master
Browse files Browse the repository at this point in the history
Add peek_first_item() and peek_last_item()
  • Loading branch information
amitdev authored Jul 7, 2016
2 parents ee61aea + 300e84b commit 220b787
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 3 deletions.
8 changes: 7 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ This can be used to build a LRU cache. Usage is almost like a dict.
from lru import LRU
l = LRU(5) # Create an LRU container that can hold 5 items
print l.peek_first_item(), l.peek_last_item() #return the MRU key and LRU key
# Would print None None
for i in range(5):
l[i] = str(i)
print l.items() # Prints items in MRU order
# Would print [(4, '4'), (3, '3'), (2, '2'), (1, '1'), (0, '0')]
print l.peek_first_item(), l.peek_last_item() #return the MRU key and LRU key
# Would print (4, '4') (0, '0')
l[5] = '5' # Inserting one more item should evict the old item
print l.items()
# Would print [(5, '5'), (4, '4'), (3, '3'), (2, '2'), (1, '1')]
Expand Down Expand Up @@ -87,4 +94,3 @@ be similar with other python implementations as well).
Time : 3.31 s, Memory : 453672 Kb
$ python bench.py lru.LRU
Time : 0.23 s, Memory : 124328 Kb

36 changes: 34 additions & 2 deletions lru.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ static void
lru_delete_last(LRU *self)
{
Node* n = self->last;

if (!self->last)
return;

Expand Down Expand Up @@ -238,7 +238,7 @@ LRU_get(LRU *self, PyObject *args)

if (!PyArg_ParseTuple(args, "O|O", &key, &instead))
return NULL;

result = lru_subscript(self, key);
PyErr_Clear(); /* GET_NODE sets an exception on miss. Shut it up. */
if (result)
Expand Down Expand Up @@ -332,6 +332,34 @@ get_key(Node *node)
return node->key;
}

static PyObject *
LRU_peek_first_item(LRU *self)
{
if (self->first) {
PyObject *tuple = PyTuple_New(2);
Py_INCREF(self->first->key);
PyTuple_SET_ITEM(tuple, 0, self->first->key);
Py_INCREF(self->first->value);
PyTuple_SET_ITEM(tuple, 1, self->first->value);
return tuple;
}
else Py_RETURN_NONE;
}

static PyObject *
LRU_peek_last_item(LRU *self)
{
if (self->last) {
PyObject *tuple = PyTuple_New(2);
Py_INCREF(self->last->key);
PyTuple_SET_ITEM(tuple, 0, self->last->key);
Py_INCREF(self->last->value);
PyTuple_SET_ITEM(tuple, 1, self->last->value);
return tuple;
}
else Py_RETURN_NONE;
}

static PyObject *
LRU_keys(LRU *self) {
return collect(self, get_key);
Expand Down Expand Up @@ -451,6 +479,10 @@ static PyMethodDef LRU_methods[] = {
PyDoc_STR("L.clear() -> clear LRU")},
{"get_stats", (PyCFunction)LRU_get_stats, METH_NOARGS,
PyDoc_STR("L.get_stats() -> returns a tuple with cache hits and misses")},
{"peek_first_item", (PyCFunction)LRU_peek_first_item, METH_NOARGS,
PyDoc_STR("L.peek_first_item() -> returns the MRU item (key,value) without changing key order")},
{"peek_last_item", (PyCFunction)LRU_peek_last_item, METH_NOARGS,
PyDoc_STR("L.peek_last_item() -> returns the LRU item (key,value) without changing key order")},
{NULL, NULL},
};

Expand Down
14 changes: 14 additions & 0 deletions test/test_lru.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ def test_access(self):
self.assertEqual(l[i], str(i))
self.assertEqual(l.get(i,None), str(i))

def test_peek_first_item(self):
l = LRU(2)
self.assertEqual(None, l.peek_first_item())
l[1] = '1'
l[2] = '2'
self.assertEqual((2, '2'), l.peek_first_item())

def test_peek_last_item(self):
l = LRU(2)
self.assertEqual(None, l.peek_last_item())
l[1] = '1'
l[2] = '2'
self.assertEqual((1, '1'), l.peek_last_item())

def test_overwrite(self):
l = LRU(1)
l[1] = '2'
Expand Down

0 comments on commit 220b787

Please sign in to comment.