diff -r 87918218da70 -r 12a46ad67a3c mercurial/smartset.py --- a/mercurial/smartset.py Wed Dec 27 13:53:21 2017 -0600 +++ b/mercurial/smartset.py Wed Dec 27 11:08:32 2017 -0700 @@ -772,6 +772,16 @@ >>> xs.last() # cached 4 """ + def __new__(cls, gen, iterasc=None): + if iterasc is None: + typ = cls + elif iterasc: + typ = _generatorsetasc + else: + typ = _generatorsetdesc + + return super(generatorset, cls).__new__(typ) + def __init__(self, gen, iterasc=None): """ gen: a generator producing the values for the generatorset. @@ -782,13 +792,6 @@ self._genlist = [] self._finished = False self._ascending = True - if iterasc is not None: - if iterasc: - self.fastasc = self._iterator - self.__contains__ = self._asccontains - else: - self.fastdesc = self._iterator - self.__contains__ = self._desccontains def __nonzero__(self): # Do not use 'for r in self' because it will enforce the iteration @@ -814,36 +817,6 @@ self._cache[x] = False return False - def _asccontains(self, x): - """version of contains optimised for ascending generator""" - if x in self._cache: - return self._cache[x] - - # Use new values only, as existing values would be cached. - for l in self._consumegen(): - if l == x: - return True - if l > x: - break - - self._cache[x] = False - return False - - def _desccontains(self, x): - """version of contains optimised for descending generator""" - if x in self._cache: - return self._cache[x] - - # Use new values only, as existing values would be cached. - for l in self._consumegen(): - if l == x: - return True - if l < x: - break - - self._cache[x] = False - return False - def __iter__(self): if self._ascending: it = self.fastasc @@ -947,7 +920,45 @@ def __repr__(self): d = {False: '-', True: '+'}[self._ascending] - return '<%s%s>' % (type(self).__name__, d) + return '<%s%s>' % (type(self).__name__.lstrip('_'), d) + +class _generatorsetasc(generatorset): + """Special case of generatorset optimized for ascending generators.""" + + fastasc = generatorset._iterator + + def __contains__(self, x): + if x in self._cache: + return self._cache[x] + + # Use new values only, as existing values would be cached. + for l in self._consumegen(): + if l == x: + return True + if l > x: + break + + self._cache[x] = False + return False + +class _generatorsetdesc(generatorset): + """Special case of generatorset optimized for descending generators.""" + + fastdesc = generatorset._iterator + + def __contains__(self, x): + if x in self._cache: + return self._cache[x] + + # Use new values only, as existing values would be cached. + for l in self._consumegen(): + if l == x: + return True + if l < x: + break + + self._cache[x] = False + return False def spanset(repo, start=0, end=None): """Create a spanset that represents a range of repository revisions