[PATCH 2 of 4] revset: add __length_hint__ to smart classes

Durham Goode durham at fb.com
Mon Sep 29 20:12:11 CDT 2014


# HG changeset patch
# User Durham Goode <durham at fb.com>
# Date 1412036731 25200
#      Mon Sep 29 17:25:31 2014 -0700
# Node ID 93be919300f04bfd26fd5294499fb62c96ba7f93
# Parent  c6129c781a9f11be26191e64dcebf8d539c8c76a
revset: add __length_hint__ to smart classes

This adds a __length_hint__ to the smart revset classes so we can optimize at
runtime to avoid things like iterating over the large set and checking
containment against the small set when doing 'X & Y'.

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -2204,6 +2204,9 @@ class baseset(list):
         super(baseset, self).__init__(data)
         self._set = None
 
+    def __length_hint__(self):
+        return len(self)
+
     def ascending(self):
         """Sorts the set in ascending order (in place).
 
@@ -2376,6 +2379,9 @@ class lazyset(object):
         l = baseset([r for r in self])
         return len(l)
 
+    def __length_hint__(self):
+        return self._subset.__length_hint__()
+
     def __getitem__(self, x):
         # Basic implementation to be changed in future patches.
         l = baseset([r for r in self])
@@ -2478,6 +2484,9 @@ class _addset(_orderedsetmixin):
     def __len__(self):
         return len(self._list)
 
+    def __length_hint__(self):
+        return self._r1.__length_hint__() + self._r2.__length_hint__()
+
     @util.propertycache
     def _list(self):
         if not self._genlist:
@@ -2688,6 +2697,11 @@ class _generatorset(object):
     def set(self):
         return self
 
+    def __length_hint__(self):
+        if util.safehasattr(self._gen, '__length_hint__'):
+            return self._gen.__length_hint__()
+        return sys.maxint
+
     def sort(self, reverse=False):
         if not self._finished:
             for i in self:
@@ -2800,6 +2814,9 @@ class _spanset(_orderedsetmixin):
             for r in iterrange:
                 yield r
 
+    def __length_hint__(self):
+        return abs(self._start - self._end)
+
     def __contains__(self, rev):
         start = self._start
         end = self._end


More information about the Mercurial-devel mailing list