Patchwork [2,of,5,STABLE,v2] revset: extract common bits of _addset into abstract base class

login
register
mail settings
Submitter Gregory Szorc
Date Sept. 8, 2014, 9:59 p.m.
Message ID <3e8808bd267f9c2f6a65.1410213584@gps-mbp.local>
Download mbox | patch
Permalink /patch/5730/
State Rejected
Headers show

Comments

Gregory Szorc - Sept. 8, 2014, 9:59 p.m.
# HG changeset patch
# User Gregory Szorc <gregory.szorc@gmail.com>
# Date 1410110249 25200
#      Sun Sep 07 10:17:29 2014 -0700
# Node ID 3e8808bd267f9c2f6a650247a3a4ba926ee6c624
# Parent  eb5a18f2feaa61d48166198558035e82b8672a04
revset: extract common bits of _addset into abstract base class

An upcoming patch will introduce a _diffset class to optimize
lazyset __sub__ similarly to how _addset optimizes __add__. This
patch moves generic code useful for both classes into a new base
class which will be shared between the two.

No code was changed as part of this refactor.

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2444,20 +2444,21 @@  class orderedlazyset(_orderedsetmixin, l
     def reverse(self):
         self._subset.reverse()
         self._ascending = not self._ascending
 
-class _addset(_orderedsetmixin):
-    """Represent the addition of two sets
-
-    Wrapper structure for lazily adding two structures without losing much
-    performance on the __contains__ method
-
-    If the ascending attribute is set, that means the two structures are
-    ordered in either an ascending or descending way. Therefore, we can add
-    them maintaining the order by iterating over both at the same time
-
-    This class does not duck-type baseset and it's only supposed to be used
-    internally
+class _lazysetiteratormixin(_orderedsetmixin):
+    """Base class for representing results of a revset operation.
+
+    Operations like addition and subtraction are can only be fully optimized
+    if custom code is written. These operations effectively constitute a lazily
+    evaluated revset operations. This class is a base class to model these
+    operations.
+
+    Instances are constructed from 2 base sets (the sets being operated on) and
+    a flag saying how the result should be ordered.
+
+    Iterating over the instance triggers evaluation. The results are cached
+    locally so evaluation only occurs once.
     """
     def __init__(self, revs1, revs2, ascending=None):
         self._r1 = revs1
         self._r2 = revs2
@@ -2500,14 +2501,8 @@  class _addset(_orderedsetmixin):
         if self._ascending is not None:
             return orderedlazyset(self, filterfunc, ascending=self._ascending)
         return lazyset(self, filterfunc)
 
-    def __sub__(self, other):
-        filterfunc = lambda r: r not in other
-        if self._ascending is not None:
-            return orderedlazyset(self, filterfunc, ascending=self._ascending)
-        return lazyset(self, filterfunc)
-
     def __add__(self, other):
         """When both collections are ascending or descending, preserve the order
         """
         kwargs = {}
@@ -2517,8 +2512,59 @@  class _addset(_orderedsetmixin):
             if self.isdescending() and other.isdescending():
                 kwargs['ascending'] = False
         return _addset(self, other, **kwargs)
 
+    def __sub__(self, other):
+        filterfunc = lambda r: r not in other
+        if self._ascending is not None:
+            return orderedlazyset(self, filterfunc, ascending=self._ascending)
+        return lazyset(self, filterfunc)
+
+    def __iter__(self):
+        if self._genlist:
+            return iter(self._genlist)
+        return iter(self._iterator())
+
+    def set(self):
+        return self
+
+    def sort(self, reverse=False):
+        """Sort the added set
+
+        For this we use the cached list with all the generated values and if we
+        know they are ascending or descending we can sort them in a smart way.
+        """
+        if self._ascending is None:
+            self._list.sort(reverse=reverse)
+            self._ascending = not reverse
+        else:
+            if bool(self._ascending) == bool(reverse):
+                self.reverse()
+
+    def isascending(self):
+        return self._ascending is not None and self._ascending
+
+    def isdescending(self):
+        return self._ascending is not None and not self._ascending
+
+    def reverse(self):
+        self._list.reverse()
+        if self._ascending is not None:
+            self._ascending = not self._ascending
+
+class _addset(_lazysetiteratormixin):
+    """Represent the addition of two sets
+
+    Wrapper structure for lazily adding two structures without losing much
+    performance on the __contains__ method
+
+    If the ascending attribute is set, that means the two structures are
+    ordered in either an ascending or descending way. Therefore, we can add
+    them maintaining the order by iterating over both at the same time
+
+    This class does not duck-type baseset and it's only supposed to be used
+    internally
+    """
     def _iterator(self):
         """Iterate over both collections without repeating elements
 
         If the ascending attribute is not set, iterate over the first one and
@@ -2576,43 +2622,11 @@  class _addset(_orderedsetmixin):
             self._iter = _generatorset(gen())
 
         return self._iter
 
-    def __iter__(self):
-        if self._genlist:
-            return iter(self._genlist)
-        return iter(self._iterator())
-
     def __contains__(self, x):
         return x in self._r1 or x in self._r2
 
-    def set(self):
-        return self
-
-    def sort(self, reverse=False):
-        """Sort the added set
-
-        For this we use the cached list with all the generated values and if we
-        know they are ascending or descending we can sort them in a smart way.
-        """
-        if self._ascending is None:
-            self._list.sort(reverse=reverse)
-            self._ascending = not reverse
-        else:
-            if bool(self._ascending) == bool(reverse):
-                self.reverse()
-
-    def isascending(self):
-        return self._ascending is not None and self._ascending
-
-    def isdescending(self):
-        return self._ascending is not None and not self._ascending
-
-    def reverse(self):
-        self._list.reverse()
-        if self._ascending is not None:
-            self._ascending = not self._ascending
-
 class _generatorset(object):
     """Wrap a generator for lazy iteration
 
     Wrapper structure for generators that provides lazy membership and can