From patchwork Tue Sep 30 18:02:52 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [3,of,5,V2] revset: add __length_hint__ to smart classes From: Durham Goode X-Patchwork-Id: 6042 Message-Id: <7d4c0bc4debf9efcc673.1412100172@dev2000.prn2.facebook.com> To: Date: Tue, 30 Sep 2014 11:02:52 -0700 # HG changeset patch # User Durham Goode # 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