Permalink
Browse files

Implemneted IterableLists for refs, commits and remote objects includ…

…ing simple tests
  • Loading branch information...
Byron committed Oct 19, 2009
1 parent b9cb007 commit 989671780551b7587d57e1d7cb5eb1002ade75b4
Showing with 56 additions and 10 deletions.
  1. +1 −0 CHANGES
  2. +0 −2 TODO
  3. +1 −0 lib/git/objects/commit.py
  4. +1 −0 lib/git/refs.py
  5. +1 −0 lib/git/remote.py
  6. +6 −7 lib/git/repo.py
  7. +38 −1 lib/git/utils.py
  8. +3 −0 test/git/test_commit.py
  9. +1 −0 test/git/test_remote.py
  10. +3 −0 test/git/test_repo.py
  11. +1 −0 test/git/test_tag.py
View
@@ -38,6 +38,7 @@ Item Iteration
hurt performance and memory consumption and reduce response times.
iter_items method provide an iterator that will return items on demand as parsed
from a stream. This way any amount of objects can be handled.
+* list_items method returns IterableList allowing to access list members by name
objects Package
----------------
View
2 TODO
@@ -13,8 +13,6 @@ General
* Overhaul command caching - currently its possible to create many instances of
the std-in command types, as it appears they are not killed when the repo gets
deleted.
-* ReferenceList being a list that can also be accessed by name, such as rlist.HEAD
- or rlist.master, allowing repo.heads.master
* References should be parsed 'manually' to get around command invocation, but
be sure to be able to read packed refs.
@@ -23,6 +23,7 @@ class Commit(base.Object, Iterable, diff.Diffable):
type = "commit"
__slots__ = ("tree", "author", "authored_date", "committer", "committed_date",
"message", "parents")
+ _id_attribute_ = "id"
def __init__(self, repo, id, tree=None, author=None, authored_date=None,
committer=None, committed_date=None, message=None, parents=None):
View
@@ -16,6 +16,7 @@ class Reference(LazyMixin, Iterable):
"""
__slots__ = ("repo", "path")
_common_path_default = "refs"
+ _id_attribute_ = "name"
def __init__(self, repo, path, object = None):
"""
View
@@ -47,6 +47,7 @@ class Remote(LazyMixin, Iterable):
"""
__slots__ = ( "repo", "name", "_config_reader" )
+ _id_attribute_ = "name"
def __init__(self, repo, name):
"""
View
@@ -105,7 +105,7 @@ def heads(self):
this repo
Returns
- ``git.Head[]``
+ ``git.IterableList(Head, ...)``
"""
return Head.list_items(self)
@@ -127,6 +127,9 @@ def head(self,path="HEAD"):
def remotes(self):
"""
A list of Remote objects allowing to access and manipulate remotes
+
+ Returns
+ ``git.IterableList(Remote, ...)``
"""
return Remote.list_items(self)
@@ -138,19 +141,15 @@ def remote(self, name='origin'):
Raise
ValueError if no remote with such a name exists
"""
- for remote in Remote.iter_items(self):
- if remote.name == name:
- return remote
- # END for each existing remote
- raise ValueError( "Remote named %s does not exist" % name )
+ return Remote(self, name)
@property
def tags(self):
"""
A list of ``Tag`` objects that are available in this repo
Returns
- ``git.Tag[]``
+ ``git.IterableList(TagReference, ...)``
"""
return TagReference.list_items(self)
View
@@ -56,12 +56,46 @@ def _set_cache_(self, attr):
pass
+class IterableList(list):
+ """
+ List of iterable objects allowing to query an object by id or by named index::
+
+ heads = repo.heads
+ heads.master
+ heads['master']
+ heads[0]
+ """
+ __slots__ = '_id_attr'
+
+ def __new__(cls, id_attr):
+ return super(IterableList,cls).__new__(cls)
+
+ def __init__(self, id_attr):
+ self._id_attr = id_attr
+
+ def __getattr__(self, attr):
+ for item in self:
+ if getattr(item, self._id_attr) == attr:
+ return item
+ # END for each item
+ return list.__getattribute__(self, attr)
+
+ def __getitem__(self, index):
+ if isinstance(index, int):
+ return list.__getitem__(self,index)
+
+ try:
+ return getattr(self, index)
+ except AttributeError:
+ raise IndexError( "No item found with id %r" % index )
+
class Iterable(object):
"""
Defines an interface for iterable items which is to assure a uniform
way to retrieve and iterate items within the git repository
"""
__slots__ = tuple()
+ _id_attribute_ = "attribute that most suitably identifies your instance"
@classmethod
def list_items(cls, repo, *args, **kwargs):
@@ -75,7 +109,10 @@ def list_items(cls, repo, *args, **kwargs):
Returns:
list(Item,...) list of item instances
"""
- return list(cls.iter_items(repo, *args, **kwargs))
+ #return list(cls.iter_items(repo, *args, **kwargs))
+ out_list = IterableList( cls._id_attribute_ )
+ out_list.extend(cls.iter_items(repo, *args, **kwargs))
+ return out_list
@classmethod
View
@@ -67,6 +67,9 @@ def test_rev_list_bisect_all(self, git):
def test_count(self):
assert self.repo.tag('0.1.5').commit.count( ) == 141
+
+ def test_list(self):
+ assert isinstance(Commit.list_items(self.repo, '0.1.5', max_count=5)['5117c9c8a4d3af19a9958677e45cda9269de1541'], Commit)
def test_str(self):
commit = Commit(self.repo, id='abc')
View
@@ -68,6 +68,7 @@ def test_base(self):
assert num_remotes == len(remote_set)
origin = self.repo.remote('origin')
+ assert origin == self.repo.remotes.origin
def test_creation_and_removal(self):
new_name = "test_new_one"
View
@@ -39,6 +39,9 @@ def test_heads_should_populate_head_data(self):
assert head.name
assert isinstance(head.commit,Commit)
# END for each head
+
+ assert isinstance(self.repo.heads.master, Head)
+ assert isinstance(self.repo.heads['master'], Head)
@patch_object(Git, '_call_process')
def test_commits(self, git):
View
@@ -30,5 +30,6 @@ def test_tag_base(self):
# END if we have a tag object
# END for tag in repo-tags
assert tag_object_refs
+ assert isinstance(self.repo.tags['0.1.5'], TagReference)

0 comments on commit 9896717

Please sign in to comment.