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

login
register
mail settings
Submitter Durham Goode
Date Sept. 30, 2014, 6:02 p.m.
Message ID <7d4c0bc4debf9efcc673.1412100172@dev2000.prn2.facebook.com>
Download mbox | patch
Permalink /patch/6042/
State Changes Requested
Headers show

Comments

Durham Goode - Sept. 30, 2014, 6:02 p.m.
# HG changeset patch
# User Durham Goode <durham@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'.

Patch

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