Patchwork revset: added generatorset class with cached __contains__ method

login
register
mail settings
Submitter Lucas Moscovicz
Date Feb. 18, 2014, 10:29 p.m.
Message ID <7dfddd4a822ee7e5a3ce.1392762568@dev1037.prn2.facebook.com>
Download mbox | patch
Permalink /patch/3690/
State Accepted
Headers show

Comments

Lucas Moscovicz - Feb. 18, 2014, 10:29 p.m.
# HG changeset patch
# User Lucas Moscovicz <lmoscovicz@fb.com>
# Date 1391642591 28800
#      Wed Feb 05 15:23:11 2014 -0800
# Node ID 7dfddd4a822ee7e5a3ce6f39a0bdf9c533cd76ff
# Parent  c29948fed40a2d9755ecaa01ec05bfa542f65670
revset: added generatorset class with cached __contains__ method
Pierre-Yves David - Feb. 18, 2014, 10:32 p.m.
On 02/18/2014 02:29 PM, Lucas Moscovicz wrote:
> # HG changeset patch
> # User Lucas Moscovicz <lmoscovicz@fb.com>
> # Date 1391642591 28800
> #      Wed Feb 05 15:23:11 2014 -0800
> # Node ID 7dfddd4a822ee7e5a3ce6f39a0bdf9c533cd76ff
> # Parent  c29948fed40a2d9755ecaa01ec05bfa542f65670
> revset: added generatorset class with cached __contains__ method
>
> diff --git a/mercurial/revset.py b/mercurial/revset.py
> --- a/mercurial/revset.py
> +++ b/mercurial/revset.py
> @@ -2131,6 +2131,37 @@
>       def set(self):
>           return set([r for r in self])
>
> +class generatorset(object):
> +    """Wrapper structure for generators that provides lazy membership."""

Could use more doc about all its behavior.

> +    def __init__(self, gen):
> +        self._gen = gen
> +        self._iter = iter(gen)
> +        self._cache = {}
> +
> +    def __contains__(self, x):
> +        if x in self._cache:
> +            return self._cache[x]
> +
> +        while True:
> +            try:
> +                l = self._iter.next()
> +                self._cache[l] = True
> +                if l == x:
> +                    return True
> +            except (StopIteration):
> +                break
> +
> +        self._cache[x] = False
> +        return False
> +
> +    def __iter__(self):
> +        for item in self._gen:
> +            self._cache[item] = True
> +            yield item
> +
> +    def set(self):
> +        return self

Sounds wrong to me, is there precendence of a set() method returning a 
non set object?
Matt Mackall - Feb. 19, 2014, 11:20 p.m.
On Tue, 2014-02-18 at 14:29 -0800, Lucas Moscovicz wrote:
> # HG changeset patch
> # User Lucas Moscovicz <lmoscovicz@fb.com>
> # Date 1391642591 28800
> #      Wed Feb 05 15:23:11 2014 -0800
> # Node ID 7dfddd4a822ee7e5a3ce6f39a0bdf9c533cd76ff
> # Parent  c29948fed40a2d9755ecaa01ec05bfa542f65670
> revset: added generatorset class with cached __contains__ method

Queued for default, thanks.
Matt Mackall - Feb. 20, 2014, 10:07 p.m.
On Tue, 2014-02-18 at 14:29 -0800, Lucas Moscovicz wrote:
> # HG changeset patch
> # User Lucas Moscovicz <lmoscovicz@fb.com>
> # Date 1391642591 28800
> #      Wed Feb 05 15:23:11 2014 -0800
> # Node ID 7dfddd4a822ee7e5a3ce6f39a0bdf9c533cd76ff
> # Parent  c29948fed40a2d9755ecaa01ec05bfa542f65670
> revset: added generatorset class with cached __contains__ method

Queued for default, thanks.

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2131,6 +2131,37 @@ 
     def set(self):
         return set([r for r in self])
 
+class generatorset(object):
+    """Wrapper structure for generators that provides lazy membership."""
+    def __init__(self, gen):
+        self._gen = gen
+        self._iter = iter(gen)
+        self._cache = {}
+
+    def __contains__(self, x):
+        if x in self._cache:
+            return self._cache[x]
+
+        while True:
+            try:
+                l = self._iter.next()
+                self._cache[l] = True
+                if l == x:
+                    return True
+            except (StopIteration):
+                break
+
+        self._cache[x] = False
+        return False
+
+    def __iter__(self):
+        for item in self._gen:
+            self._cache[item] = True
+            yield item
+
+    def set(self):
+        return self
+
 class spanset(object):
     """Duck type for baseset class which represents a range of revisions and
     can work lazily and without having all the range in memory