[PATCH 3 of 5 V2] revset: add __length_hint__ to smart classes

Durham Goode durham at fb.com
Tue Sep 30 13:02:52 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 7d4c0bc4debf9efcc673c24e880d3d831bd06ef9
# Parent  f224c6c8c7a1f0fa5a3151b1cb045367f99da28e
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
@@ -2216,6 +2216,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).
 
@@ -2388,6 +2391,9 @@ class lazyset(object):
         l = baseset([r for r in self])
         return len(l)
 
+    def __length_hint__(self):
+        return _getlengthhint(self._subset)
+
     def __getitem__(self, x):
         # Basic implementation to be changed in future patches.
         l = baseset([r for r in self])
@@ -2490,6 +2496,13 @@ class _addset(_orderedsetmixin):
     def __len__(self):
         return len(self._list)
 
+    def __length_hint__(self):
+        left = _getlengthhint(self._r1)
+        right = _getlengthhint(self._r2)
+        if left is not None and right is not None:
+            return left + right
+        return None
+
     @util.propertycache
     def _list(self):
         if not self._genlist:
@@ -2700,6 +2713,9 @@ class _generatorset(object):
     def set(self):
         return self
 
+    def __length_hint__(self):
+        return _getlengthhint(self._gen)
+
     def sort(self, reverse=False):
         if not self._finished:
             for i in self:
@@ -2812,6 +2828,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