Patchwork revset: added stopiterating condition to generatorset

login
register
mail settings
Submitter Lucas Moscovicz
Date Feb. 25, 2014, 9:16 p.m.
Message ID <e1b82805679d24f3de89.1393363007@dev1037.prn2.facebook.com>
Download mbox | patch
Permalink /patch/3771/
State Changes Requested
Headers show

Comments

Lucas Moscovicz - Feb. 25, 2014, 9:16 p.m.
# HG changeset patch
# User Lucas Moscovicz <lmoscovicz@fb.com>
# Date 1391796950 28800
#      Fri Feb 07 10:15:50 2014 -0800
# Node ID e1b82805679d24f3de891162d780971da4e8e151
# Parent  f4d57e463ca01c39ea60703c378025ff86c6ab18
revset: added stopiterating condition to generatorset

This will be used for when the generated content is known to be sorted and a
condition can be set to stop iterating without going through all the values.
Matt Mackall - Feb. 27, 2014, 10:15 p.m.
On Tue, 2014-02-25 at 13:16 -0800, Lucas Moscovicz wrote:
> # HG changeset patch
> # User Lucas Moscovicz <lmoscovicz@fb.com>
> # Date 1391796950 28800
> #      Fri Feb 07 10:15:50 2014 -0800
> # Node ID e1b82805679d24f3de891162d780971da4e8e151
> # Parent  f4d57e463ca01c39ea60703c378025ff86c6ab18
> revset: added stopiterating condition to generatorset
> 
> This will be used for when the generated content is known to be sorted and a
> condition can be set to stop iterating without going through all the values.
> 
> diff --git a/mercurial/revset.py b/mercurial/revset.py
> --- a/mercurial/revset.py
> +++ b/mercurial/revset.py
> @@ -2191,14 +2191,16 @@
>      """Wrapper structure for generators that provides lazy membership and can
>      be iterated more than once.
>      When asked for membership it generates values until either it finds the
> -    requested one or has gone through all the elements in the generator
> +    requested one, the stopiter condition returns true or it has gone through
> +    all the elements in the generator
>      """
> -    def __init__(self, gen):
> +    def __init__(self, gen, stopiter=None):

Took me a long time to figure out what stopiter does, due to naming (not
an iterator) and lack of docs about its arguments.

I'd call it:

 stopcheck(current, target)
 returns True if current is past target, stopping search

But really, I think I'd prefer two classes that inherit from
generatorset, but define their own __contains__ using > and <.

>          self._gen = gen
>          self._iter = iter(gen)
>          self._cache = {}
>          self._genlist = baseset([])
>          self._iterated = False
> +        self._stopiter = stopiter
>  
>      def _nextitem(self):
>          l = self._iter.next()
> @@ -2211,13 +2213,26 @@
>              return self._cache[x]
>  
>          self._iterated = True
> -        while True:
> -            try:
> -                l = self._nextitem()
> -                if l == x:
> -                    return True
> -            except (StopIteration):
> -                break
> +        if self._stopiter:
> +            stop = self._stopiter
> +            while True:
> +                try:
> +                    l = self._nextitem()
> +                    if l == x:
> +                        return True
> +                    if stop(l, x):
> +                        self._cache[x] = False
> +                        return False
> +                except (StopIteration):
> +                    break
> +        else:
> +            while True:
> +                try:
> +                    l = self._nextitem()
> +                    if l == x:
> +                        return True
> +                except (StopIteration):
> +                    break
>  
>          self._cache[x] = False
>          return False
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2191,14 +2191,16 @@ 
     """Wrapper structure for generators that provides lazy membership and can
     be iterated more than once.
     When asked for membership it generates values until either it finds the
-    requested one or has gone through all the elements in the generator
+    requested one, the stopiter condition returns true or it has gone through
+    all the elements in the generator
     """
-    def __init__(self, gen):
+    def __init__(self, gen, stopiter=None):
         self._gen = gen
         self._iter = iter(gen)
         self._cache = {}
         self._genlist = baseset([])
         self._iterated = False
+        self._stopiter = stopiter
 
     def _nextitem(self):
         l = self._iter.next()
@@ -2211,13 +2213,26 @@ 
             return self._cache[x]
 
         self._iterated = True
-        while True:
-            try:
-                l = self._nextitem()
-                if l == x:
-                    return True
-            except (StopIteration):
-                break
+        if self._stopiter:
+            stop = self._stopiter
+            while True:
+                try:
+                    l = self._nextitem()
+                    if l == x:
+                        return True
+                    if stop(l, x):
+                        self._cache[x] = False
+                        return False
+                except (StopIteration):
+                    break
+        else:
+            while True:
+                try:
+                    l = self._nextitem()
+                    if l == x:
+                        return True
+                except (StopIteration):
+                    break
 
         self._cache[x] = False
         return False