770 >>> xs = generatorset([0, 1, 4], iterasc=True) |
770 >>> xs = generatorset([0, 1, 4], iterasc=True) |
771 >>> assert xs.last() == xs.last() |
771 >>> assert xs.last() == xs.last() |
772 >>> xs.last() # cached |
772 >>> xs.last() # cached |
773 4 |
773 4 |
774 """ |
774 """ |
|
775 def __new__(cls, gen, iterasc=None): |
|
776 if iterasc is None: |
|
777 typ = cls |
|
778 elif iterasc: |
|
779 typ = _generatorsetasc |
|
780 else: |
|
781 typ = _generatorsetdesc |
|
782 |
|
783 return super(generatorset, cls).__new__(typ) |
|
784 |
775 def __init__(self, gen, iterasc=None): |
785 def __init__(self, gen, iterasc=None): |
776 """ |
786 """ |
777 gen: a generator producing the values for the generatorset. |
787 gen: a generator producing the values for the generatorset. |
778 """ |
788 """ |
779 self._gen = gen |
789 self._gen = gen |
780 self._asclist = None |
790 self._asclist = None |
781 self._cache = {} |
791 self._cache = {} |
782 self._genlist = [] |
792 self._genlist = [] |
783 self._finished = False |
793 self._finished = False |
784 self._ascending = True |
794 self._ascending = True |
785 if iterasc is not None: |
|
786 if iterasc: |
|
787 self.fastasc = self._iterator |
|
788 self.__contains__ = self._asccontains |
|
789 else: |
|
790 self.fastdesc = self._iterator |
|
791 self.__contains__ = self._desccontains |
|
792 |
795 |
793 def __nonzero__(self): |
796 def __nonzero__(self): |
794 # Do not use 'for r in self' because it will enforce the iteration |
797 # Do not use 'for r in self' because it will enforce the iteration |
795 # order (default ascending), possibly unrolling a whole descending |
798 # order (default ascending), possibly unrolling a whole descending |
796 # iterator. |
799 # iterator. |
808 |
811 |
809 # Use new values only, as existing values would be cached. |
812 # Use new values only, as existing values would be cached. |
810 for l in self._consumegen(): |
813 for l in self._consumegen(): |
811 if l == x: |
814 if l == x: |
812 return True |
815 return True |
813 |
|
814 self._cache[x] = False |
|
815 return False |
|
816 |
|
817 def _asccontains(self, x): |
|
818 """version of contains optimised for ascending generator""" |
|
819 if x in self._cache: |
|
820 return self._cache[x] |
|
821 |
|
822 # Use new values only, as existing values would be cached. |
|
823 for l in self._consumegen(): |
|
824 if l == x: |
|
825 return True |
|
826 if l > x: |
|
827 break |
|
828 |
|
829 self._cache[x] = False |
|
830 return False |
|
831 |
|
832 def _desccontains(self, x): |
|
833 """version of contains optimised for descending generator""" |
|
834 if x in self._cache: |
|
835 return self._cache[x] |
|
836 |
|
837 # Use new values only, as existing values would be cached. |
|
838 for l in self._consumegen(): |
|
839 if l == x: |
|
840 return True |
|
841 if l < x: |
|
842 break |
|
843 |
816 |
844 self._cache[x] = False |
817 self._cache[x] = False |
845 return False |
818 return False |
846 |
819 |
847 def __iter__(self): |
820 def __iter__(self): |
945 return self.last() |
918 return self.last() |
946 return next(it(), None) |
919 return next(it(), None) |
947 |
920 |
948 def __repr__(self): |
921 def __repr__(self): |
949 d = {False: '-', True: '+'}[self._ascending] |
922 d = {False: '-', True: '+'}[self._ascending] |
950 return '<%s%s>' % (type(self).__name__, d) |
923 return '<%s%s>' % (type(self).__name__.lstrip('_'), d) |
|
924 |
|
925 class _generatorsetasc(generatorset): |
|
926 """Special case of generatorset optimized for ascending generators.""" |
|
927 |
|
928 fastasc = generatorset._iterator |
|
929 |
|
930 def __contains__(self, x): |
|
931 if x in self._cache: |
|
932 return self._cache[x] |
|
933 |
|
934 # Use new values only, as existing values would be cached. |
|
935 for l in self._consumegen(): |
|
936 if l == x: |
|
937 return True |
|
938 if l > x: |
|
939 break |
|
940 |
|
941 self._cache[x] = False |
|
942 return False |
|
943 |
|
944 class _generatorsetdesc(generatorset): |
|
945 """Special case of generatorset optimized for descending generators.""" |
|
946 |
|
947 fastdesc = generatorset._iterator |
|
948 |
|
949 def __contains__(self, x): |
|
950 if x in self._cache: |
|
951 return self._cache[x] |
|
952 |
|
953 # Use new values only, as existing values would be cached. |
|
954 for l in self._consumegen(): |
|
955 if l == x: |
|
956 return True |
|
957 if l < x: |
|
958 break |
|
959 |
|
960 self._cache[x] = False |
|
961 return False |
951 |
962 |
952 def spanset(repo, start=0, end=None): |
963 def spanset(repo, start=0, end=None): |
953 """Create a spanset that represents a range of repository revisions |
964 """Create a spanset that represents a range of repository revisions |
954 |
965 |
955 start: first revision included the set (default to 0) |
966 start: first revision included the set (default to 0) |