summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Thiel <byronimo@gmail.com>2011-06-08 10:43:47 +0200
committerSebastian Thiel <byronimo@gmail.com>2011-06-08 11:07:47 +0200
commitb7071ce13476cae789377c280aa274e6242fd756 (patch)
tree9cabdc2dfb6dd5c9e2d5d7d7fbd22686d42dbf5c
parentfcc166d3a6e235933e823e82e1fcf6160a32a5d3 (diff)
downloadgitpython-b7071ce13476cae789377c280aa274e6242fd756.tar.gz
util: Added test for iterable list, and implemented __contains__ and __del__ functionality
-rw-r--r--doc/source/changes.rst4
-rw-r--r--git/test/test_util.py59
-rw-r--r--git/util.py34
3 files changed, 95 insertions, 2 deletions
diff --git a/doc/source/changes.rst b/doc/source/changes.rst
index 22568e3d..0cb6d065 100644
--- a/doc/source/changes.rst
+++ b/doc/source/changes.rst
@@ -11,6 +11,10 @@ Changelog
* **Blob** Type
* Added mode constants to ease the manual creation of blobs
+
+* **IterableList**
+
+ * Added __contains__ and __delitem__ methods
* **More Changes**
diff --git a/git/test/test_util.py b/git/test/test_util.py
index e55a6d15..a11c15c3 100644
--- a/git/test/test_util.py
+++ b/git/test/test_util.py
@@ -7,8 +7,8 @@
import os
import tempfile
-from git.test.lib import *
from git.util import *
+from git.test.lib import *
from git.objects.util import *
from git import *
from git.cmd import dashify
@@ -16,6 +16,15 @@ from git.cmd import dashify
import time
+class TestIterableMember(object):
+ """A member of an iterable list"""
+ __slots__ = ("name", "prefix_name")
+
+ def __init__(self, name):
+ self.name = name
+ self.prefix_name = name
+
+
class TestUtils(TestBase):
def setup(self):
self.testdict = {
@@ -107,3 +116,51 @@ class TestUtils(TestBase):
assert isinstance(Actor.committer(cr), Actor)
assert isinstance(Actor.author(cr), Actor)
#END assure config reader is handled
+
+ def test_iterable_list(self):
+ for args in (('name',), ('name', 'prefix_')):
+ l = IterableList('name')
+
+ m1 = TestIterableMember('one')
+ m2 = TestIterableMember('two')
+
+ l.extend((m1, m2))
+
+ assert len(l) == 2
+
+ # contains works with name and identity
+ assert m1.name in l
+ assert m2.name in l
+ assert m2 in l
+ assert m2 in l
+ assert 'invalid' not in l
+
+ # with string index
+ assert l[m1.name] is m1
+ assert l[m2.name] is m2
+
+ # with int index
+ assert l[0] is m1
+ assert l[1] is m2
+
+ # with getattr
+ assert l.one is m1
+ assert l.two is m2
+
+ # test exceptions
+ self.failUnlessRaises(AttributeError, getattr, l, 'something')
+ self.failUnlessRaises(IndexError, l.__getitem__, 'something')
+
+ # delete by name and index
+ self.failUnlessRaises(IndexError, l.__delitem__, 'something')
+ del(l[m2.name])
+ assert len(l) == 1
+ assert m2.name not in l and m1.name in l
+ del(l[0])
+ assert m1.name not in l
+ assert len(l) == 0
+
+ self.failUnlessRaises(IndexError, l.__delitem__, 0)
+ self.failUnlessRaises(IndexError, l.__delitem__, 'something')
+ #END for each possible mode
+
diff --git a/git/util.py b/git/util.py
index 00085ae0..71bf6977 100644
--- a/git/util.py
+++ b/git/util.py
@@ -330,7 +330,6 @@ class Actor(object):
but defaults to the committer"""
return cls._main_actor(cls.env_author_name, cls.env_author_email, config_reader)
-
class Stats(object):
"""
Represents stat information as presented by git at the end of a merge. It is
@@ -560,6 +559,21 @@ class IterableList(list):
raise ValueError("First parameter must be a string identifying the name-property. Extend the list after initialization")
# END help debugging !
+ def __contains__(self, attr):
+ # first try identy match for performance
+ rval = list.__contains__(self, attr)
+ if rval:
+ return rval
+ #END handle match
+
+ # otherwise make a full name search
+ try:
+ getattr(self, attr)
+ return True
+ except (AttributeError, TypeError):
+ return False
+ #END handle membership
+
def __getattr__(self, attr):
attr = self._prefix + attr
for item in self:
@@ -576,7 +590,25 @@ class IterableList(list):
return getattr(self, index)
except AttributeError:
raise IndexError( "No item found with id %r" % (self._prefix + index) )
+ # END handle getattr
+ def __delitem__(self, index):
+ delindex = index
+ if not isinstance(index, int):
+ delindex = -1
+ name = self._prefix + index
+ for i, item in enumerate(self):
+ if getattr(item, self._id_attr) == name:
+ delindex = i
+ break
+ #END search index
+ #END for each item
+ if delindex == -1:
+ raise IndexError("Item with name %s not found" % name)
+ #END handle error
+ #END get index to delete
+ list.__delitem__(self, delindex)
+
class Iterable(object):
"""Defines an interface for iterable items which is to assure a uniform