Patchwork [3,of,3,hglib] client: implement __iter__ (issue4511)

login
register
mail settings
Submitter Gregory Szorc
Date July 6, 2016, 9:40 p.m.
Message ID <36e8e8f994eb6783de29.1467841214@ubuntu-vm-main>
Download mbox | patch
Permalink /patch/15761/
State Changes Requested
Headers show

Comments

Gregory Szorc - July 6, 2016, 9:40 p.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1467840878 25200
#      Wed Jul 06 14:34:38 2016 -0700
# Node ID 36e8e8f994eb6783de296c23f4ea0f1d058af37f
# Parent  04badaecb6343ca09230b9a8e80ee9e3388e748d
client: implement __iter__ (issue4511)

The client is a container-like class for changesets. It makes sense
to implement __iter__ as a way of iterating over every changeset in
the repo.

The implementation in this patch isn't ideal in terms of performance.
But it gets the job done.
Yuya Nishihara - July 8, 2016, 12:42 p.m.
On Wed, 06 Jul 2016 14:40:14 -0700, Gregory Szorc wrote:
> # HG changeset patch
> # User Gregory Szorc <gregory.szorc@gmail.com>
> # Date 1467840878 25200
> #      Wed Jul 06 14:34:38 2016 -0700
> # Node ID 36e8e8f994eb6783de296c23f4ea0f1d058af37f
> # Parent  04badaecb6343ca09230b9a8e80ee9e3388e748d
> client: implement __iter__ (issue4511)
> 
> The client is a container-like class for changesets. It makes sense
> to implement __iter__ as a way of iterating over every changeset in
> the repo.
> 
> The implementation in this patch isn't ideal in terms of performance.
> But it gets the job done.
> 
> diff --git a/hglib/client.py b/hglib/client.py
> --- a/hglib/client.py
> +++ b/hglib/client.py
> @@ -1641,8 +1641,19 @@ class hgclient(object):
>          check if changeid, which can be either a local revision number or a
>          changeset id, matches a changeset in the client.
>          """
>          try:
>              context.changectx(self, changeid)
>              return True
>          except ValueError:
>              return False
> +
> +    def __iter__(self):
> +        # We query all available nodes up front then obtain a context
> +        # for each. This isn't optimal because we have to run a command
> +        # for every context.
> +        # FUTURE: turn self.log() directly into context instances.
> +        args = cmdbuilder(b('log'), template='{node}\\0', r='0:tip')

Needs hidden=self.hidden ?

Other than that, the series LGTM.
Matt Mackall - July 11, 2016, 10:51 p.m.
On Fri, 2016-07-08 at 21:42 +0900, Yuya Nishihara wrote:
> On Wed, 06 Jul 2016 14:40:14 -0700, Gregory Szorc wrote:
> > 
> > # HG changeset patch
> > # User Gregory Szorc <gregory.szorc@gmail.com>
> > # Date 1467840878 25200
> > #      Wed Jul 06 14:34:38 2016 -0700
> > # Node ID 36e8e8f994eb6783de296c23f4ea0f1d058af37f
> > # Parent  04badaecb6343ca09230b9a8e80ee9e3388e748d
> > client: implement __iter__ (issue4511)
> > 
> > The client is a container-like class for changesets. It makes sense
> > to implement __iter__ as a way of iterating over every changeset in
> > the repo.
> > 
> > The implementation in this patch isn't ideal in terms of performance.
> > But it gets the job done.
> > 
> > diff --git a/hglib/client.py b/hglib/client.py
> > --- a/hglib/client.py
> > +++ b/hglib/client.py
> > @@ -1641,8 +1641,19 @@ class hgclient(object):
> >          check if changeid, which can be either a local revision number or a
> >          changeset id, matches a changeset in the client.
> >          """
> >          try:
> >              context.changectx(self, changeid)
> >              return True
> >          except ValueError:
> >              return False
> > +
> > +    def __iter__(self):
> > +        # We query all available nodes up front then obtain a context
> > +        # for each. This isn't optimal because we have to run a command
> > +        # for every context.
> > +        # FUTURE: turn self.log() directly into context instances.
> > +        args = cmdbuilder(b('log'), template='{node}\\0', r='0:tip')
> Needs hidden=self.hidden ?
> 
> Other than that, the series LGTM.

Seems so. I've pushed the first two, thanks.

-- 
Mathematics is the supreme nostalgia of our time.

Patch

diff --git a/hglib/client.py b/hglib/client.py
--- a/hglib/client.py
+++ b/hglib/client.py
@@ -1641,8 +1641,19 @@  class hgclient(object):
         check if changeid, which can be either a local revision number or a
         changeset id, matches a changeset in the client.
         """
         try:
             context.changectx(self, changeid)
             return True
         except ValueError:
             return False
+
+    def __iter__(self):
+        # We query all available nodes up front then obtain a context
+        # for each. This isn't optimal because we have to run a command
+        # for every context.
+        # FUTURE: turn self.log() directly into context instances.
+        args = cmdbuilder(b('log'), template='{node}\\0', r='0:tip')
+        out = self.rawcommand(args)
+        nodes = out.split(b('\0'))[:-1]
+        for node in nodes:
+            yield context.changectx(self, node)
diff --git a/tests/test-log.py b/tests/test-log.py
--- a/tests/test-log.py
+++ b/tests/test-log.py
@@ -15,16 +15,27 @@  class test_log(common.basetest):
         self.assertTrue(len(revs) == 2)
         self.assertEquals(revs[1].node, node1)
 
         self.assertEquals(revs[0], self.client.log(b('0'))[0])
         self.assertEquals(self.client.log(), self.client.log(files=[b('a')]))
 
         self.assertEquals(self.client.log(), self.client.log(hidden=True))
 
+    def test_iter(self):
+        self.append('a', 'a')
+        rev0, node0 = self.client.commit(b('first'), addremove=True)
+        self.append('a', 'a')
+        rev1, node1 = self.client.commit(b('second'))
+
+        revs = list(c for c in self.client)
+        self.assertEquals(len(revs), 2)
+        self.assertEquals(revs[0].node(), node0)
+        self.assertEquals(revs[1].node(), node1)
+
     # def test_errors(self):
     #     self.assertRaisesRegexp(CommandError, 'abort: unknown revision',
     #                             self.client.log, 'foo')
     #     self.append('a', 'a')
     #     self.client.commit('first', addremove=True)
     #     self.assertRaisesRegexp(CommandError,
     #                             'abort: unknown revision',
     #                             self.client.log, 'bar')