Revision: 596 http://rpy.svn.sourceforge.net/rpy/?rev=596&view=rev Author: lgautier Date: 2008-07-27 14:24:07 +0000 (Sun, 27 Jul 2008)
Log Message: ----------- New class TaggedList Modified Paths: -------------- branches/rpy_nextgen/NEWS branches/rpy_nextgen/rpy/rlike/container.py branches/rpy_nextgen/rpy/rlike/tests/test_container.py Modified: branches/rpy_nextgen/NEWS =================================================================== --- branches/rpy_nextgen/NEWS 2008-07-26 09:14:58 UTC (rev 595) +++ branches/rpy_nextgen/NEWS 2008-07-27 14:24:07 UTC (rev 596) @@ -1,6 +1,6 @@ -SVN -=== +Release 2.0.0a2 +=============== New features ------------ @@ -9,9 +9,12 @@ - package for R-like features in Python -- module :mod:`rpy2.rlike.container` with the class :class:`ArgsDict`. +- module :mod:`rpy2.rlike.container` +- class :class:`ArgsDict` in :mod:`rpy2.rlike.container` +- class :class:`TaggedList` in :mod:`rpy2.rlike.container` + :mod:`rpy2.rinterface`: - method :meth:`named`, corresponding to R's C-level NAMED Modified: branches/rpy_nextgen/rpy/rlike/container.py =================================================================== --- branches/rpy_nextgen/rpy/rlike/container.py 2008-07-26 09:14:58 UTC (rev 595) +++ branches/rpy_nextgen/rpy/rlike/container.py 2008-07-27 14:24:07 UTC (rev 596) @@ -1,3 +1,5 @@ +import itertools + class ArgsDict(dict): """ Implements the Ordered Dict API defined in PEP 372. When `odict` becomes part of collections, this class @@ -15,6 +17,9 @@ def __init__(self, c=[]): + if isinstance(c, TaggedList): + c = c.items() + if isinstance(c, dict): #FIXME: allow instance from ArgsDict ? raise ValueError('A regular dictionnary does not ' +\ @@ -92,7 +97,7 @@ def items(self): """ Return an ordered list of all key/value pairs """ res = [self.byindex(i) for i in xrange(len(self.__l))] - return res + return tuple(res) def iteritems(self): return iter(self.__l) @@ -117,3 +122,125 @@ raise(Exception("Not yet implemented.")) +class TaggedList(list): + """ A list for which each item has a 'tag'. """ + + def __add__(self, tl): + try: + tags = tl.tags() + except AttributeError, ae: + raise ValueError('Can only concatenate TaggedLists.') + res = TaggedList(list(self) + list(tl), + tags = self.tags() + tl.tags()) + return res + + def __delitem__(self, y): + super(TaggedList, self).__delitem__(y) + self.__tags.__delitem__(y) + + def __delslice__(self, i, j): + super(TaggedList, self).__delslice__(i, j) + self.__tags.__delslice__(i, j) + + def __iadd__(self, y): + super(TaggedList, self).__iadd__(y) + if isinstance(y, TaggedList): + self.__tags.__iadd__(y.tags()) + else: + self.__tags.__iadd__([None, ] * len(y)) + return self + + def __imul__(self, y): + restags = self.__tags.__imul__(y) + resitems = super(TaggedList, self).__imul__(y) + return self + + def __init__(self, l, tags = None): + + super(TaggedList, self).__init__(l) + + if tags is None: + tags = [None, ] * len(l) + tags = list(tags) + + if isinstance(tags, list): + if len(tags) != len(l): + raise ValueError("When a list, the parameter 'tags' must be of same length as the given list.") + self.__tags = tags + else: + raise ValueError("Parameter 'tags' must be either a list or 'None'.") + + def __setslice__(self, i, j, y): + #FIXME: implement + raise Exception("Not yet implemented.") + + def append(self, obj, tag = None): + super(TaggedList, self).append(obj) + self.__tags.append(tag) + + def extend(self, iterable): + if isinstance(iterable, TaggedList): + itertags = iterable.itertags() + else: + itertags = [None, ] * len(iterable) + + for tag, item in itertools.izip(itertags, iterable): + self.append(item, tag=tag) + + + def insert(self, index, obj, tag=None): + super(TaggedList, self).insert(index, obj) + self.__tags.insert(index, tag) + + def items(self): + """ Return a tuple of all pairs (tag, item). """ + res = [(tag, item) for tag, item in itertools.izip(self.__tags, self)] + return tuple(res) + + def iterontag(self, tag): + """ iterate on items marked with one given tag. """ + i = 0 + for onetag in self.__tags: + if tag == onetag: + yield self[i] + i += 1 + + def itertags(self): + """ iterate on tags. """ + for tag in self.__tags: + yield tag + + def pop(self, index=None): + if index is None: + index = len(self) - 1 + + super(TaggedList, self).pop(index) + self.__tags.pop(index) + + def remove(self, value): + found = False + for i in xrange(len(self)): + if self[i] == value: + found = True + break + if found: + self.pop(i) + + def reverse(self): + super(TaggedList, self).reverse() + self.__tags.reverse() + + def sort(self): + #FIXME: implement + raise Exception("Not yet implemented.") + + + def tags(self): + """ Return a tuple of all tags """ + res = [x for x in self.__tags] + return tuple(res) + + + def settag(self, i, t): + """ Set tag 't' for item 'i'. """ + self.__tags[i] = t Modified: branches/rpy_nextgen/rpy/rlike/tests/test_container.py =================================================================== --- branches/rpy_nextgen/rpy/rlike/tests/test_container.py 2008-07-26 09:14:58 UTC (rev 595) +++ branches/rpy_nextgen/rpy/rlike/tests/test_container.py 2008-07-27 14:24:07 UTC (rev 596) @@ -83,9 +83,159 @@ self.assertEquals(ki[0], ko[0]) self.assertEquals(ki[1], ko[1]) +class TaggedListTestCase(unittest.TestCase): + + def test__add__(self): + tn = ['a', 'b', 'c'] + tv = [1,2, 3] + tl = rlc.TaggedList(tv, tags = tn) + tl = tl + tl + self.assertEquals(6, len(tl)) + self.assertEquals(('a', 'b', 'c', 'a', 'b', 'c'), tl.tags()) + self.assertEquals((1,2,3,1,2,3), tuple(tl)) + + def test__delitem__(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals(3, len(tl)) + del tl[1] + self.assertEquals(2, len(tl)) + self.assertEquals(tl.tags(), ('a', 'c')) + self.assertEquals(tuple(tl), (1, 3)) + + def test__delslice__(self): + self.assertTrue(False) # no test (yet) + + def test__iadd__(self): + tn = ['a', 'b', 'c'] + tv = [1, 2, 3] + tl = rlc.TaggedList(tv, tags = tn) + tl += tl + self.assertEquals(6, len(tl)) + self.assertEquals(('a', 'b', 'c', 'a', 'b', 'c'), tl.tags()) + self.assertEquals((1,2,3,1,2,3), tuple(tl)) + + def test__imul__(self): + tn = ['a', 'b'] + tv = [1,2] + tl = rlc.TaggedList(tv, tags = tn) + tl *= 3 + self.assertEquals(6, len(tl)) + self.assertEquals(('a', 'b', 'a', 'b', 'a', 'b'), tl.tags()) + self.assertEquals((1,2,1,2,1,2), tuple(tl)) + + def test__init__(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + + self.assertRaises(TypeError, rlc.TaggedList, tv, tags=123) + self.assertRaises(ValueError, rlc.TaggedList, tv, tags=('a', 'b')) + + + def test__setslice__(self): + self.assertTrue(False) # no test (yet) + + def testappend(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals(3, len(tl)) + tl.append(4, tag='a') + self.assertEquals(4, len(tl)) + self.assertEquals(4, tl[3]) + self.assertEquals(('a', 'b', 'c', 'a'), tl.tags()) + + def testextend(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + tl.extend([4, 5]) + self.assertEquals(('a', 'b', 'c', None, None), tuple(tl.itertags())) + self.assertEquals((1, 2, 3, 4, 5), tuple(tl)) + + def testinsert(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + tl.insert(1, 4, tag = 'd') + self.assertEquals(('a', 'd', 'b', 'c'), tuple(tl.itertags())) + self.assertEquals((1, 4, 2, 3), tuple(tl)) + + def testitems(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals((('a', 1), ('b', 2), ('c', 3)), + tl.items()) + + def testiterontag(self): + tn = ['a', 'b', 'a', 'c'] + tv = [1,2,3,4] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals((1, 3), tuple(tl.iterontag('a'))) + + def testitertags(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals(('a', 'b', 'c'), tuple(tl.itertags())) + + def testpop(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals(3, len(tl)) + tl.pop() + self.assertEquals(2, len(tl)) + self.assertEquals(tl.tags(), ('a', 'b')) + self.assertEquals(tuple(tl), (1, 2)) + + tl.pop(0) + self.assertEquals(1, len(tl)) + self.assertEquals(tl.tags(), ('b', )) + + def testremove(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + self.assertEquals(3, len(tl)) + tl.remove(2) + self.assertEquals(2, len(tl)) + self.assertEquals(tl.tags(), ('a', 'c')) + self.assertEquals(tuple(tl), (1, 3)) + + def testreverse(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + tl.reverse() + self.assertEquals(3, len(tl)) + self.assertEquals(tl.tags(), ('c', 'b', 'a')) + self.assertEquals(tuple(tl), (3, 2, 1)) + + def testsort(self): + self.assertTrue(False) # no test (yet) + def testtags(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + tags = tl.tags() + self.assertTrue(isinstance(tags, tuple)) + self.assertEquals(tags, ('a', 'b', 'c')) + + def testsettag(self): + tn = ['a', 'b', 'c'] + tv = [1,2,3] + tl = rlc.TaggedList(tv, tags = tn) + tl.settag(1, 'z') + self.assertEquals(tl.tags(), ('a', 'z', 'c')) + def suite(): suite = unittest.TestLoader().loadTestsFromTestCase(ArgsDictTestCase) + suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TaggedListTestCase)) return suite if __name__ == '__main__': This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- This SF.Net email is sponsored by the Moblin Your Move Developer's challenge Build the coolest Linux based applications with Moblin SDK & win great prizes Grand prize is a trip for two to an Open Source event anywhere in the world http://moblin-contest.org/redirect.php?banner_id=100&url=/ _______________________________________________ rpy-list mailing list rpy-list@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/rpy-list