2972 iterate ascending: |
2972 iterate ascending: |
2973 >>> rs = addset(xs, ys, ascending=True) |
2973 >>> rs = addset(xs, ys, ascending=True) |
2974 >>> [x for x in rs], [x for x in rs.fastasc()] # without _asclist |
2974 >>> [x for x in rs], [x for x in rs.fastasc()] # without _asclist |
2975 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5]) |
2975 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5]) |
2976 >>> assert not rs._asclist |
2976 >>> assert not rs._asclist |
2977 >>> len(rs) # BROKEN |
2977 >>> len(rs) |
2978 6 |
2978 5 |
2979 >>> [x for x in rs], [x for x in rs.fastasc()] # BROKEN with _asclist |
2979 >>> [x for x in rs], [x for x in rs.fastasc()] |
2980 ([0, 2, 2, 3, 4, 5], [0, 2, 2, 3, 4, 5]) |
2980 ([0, 2, 3, 4, 5], [0, 2, 3, 4, 5]) |
2981 >>> assert rs._asclist |
2981 >>> assert rs._asclist |
2982 |
2982 |
2983 iterate descending: |
2983 iterate descending: |
2984 >>> rs = addset(xs, ys, ascending=False) |
2984 >>> rs = addset(xs, ys, ascending=False) |
2985 >>> [x for x in rs], [x for x in rs.fastdesc()] # without _asclist |
2985 >>> [x for x in rs], [x for x in rs.fastdesc()] # without _asclist |
2986 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0]) |
2986 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0]) |
2987 >>> assert not rs._asclist |
2987 >>> assert not rs._asclist |
2988 >>> len(rs) # BROKEN |
2988 >>> len(rs) |
2989 6 |
2989 5 |
2990 >>> [x for x in rs], [x for x in rs.fastdesc()] # BROKEN with _asclist |
2990 >>> [x for x in rs], [x for x in rs.fastdesc()] |
2991 ([5, 4, 3, 2, 2, 0], [5, 4, 3, 2, 2, 0]) |
2991 ([5, 4, 3, 2, 0], [5, 4, 3, 2, 0]) |
2992 >>> assert rs._asclist |
2992 >>> assert rs._asclist |
2993 |
2993 |
2994 iterate ascending without fastasc: |
2994 iterate ascending without fastasc: |
2995 >>> rs = addset(xs, generatorset(ys), ascending=True) |
2995 >>> rs = addset(xs, generatorset(ys), ascending=True) |
2996 >>> assert rs.fastasc is None |
2996 >>> assert rs.fastasc is None |
2997 >>> [x for x in rs] # BROKEN |
2997 >>> [x for x in rs] |
2998 [0, 2, 2, 3, 4, 5] |
2998 [0, 2, 3, 4, 5] |
2999 |
2999 |
3000 iterate descending without fastdesc: |
3000 iterate descending without fastdesc: |
3001 >>> rs = addset(generatorset(xs), ys, ascending=False) |
3001 >>> rs = addset(generatorset(xs), ys, ascending=False) |
3002 >>> assert rs.fastdesc is None |
3002 >>> assert rs.fastdesc is None |
3003 >>> [x for x in rs] # BROKEN |
3003 >>> [x for x in rs] |
3004 [5, 4, 3, 2, 2, 0] |
3004 [5, 4, 3, 2, 0] |
3005 """ |
3005 """ |
3006 def __init__(self, revs1, revs2, ascending=None): |
3006 def __init__(self, revs1, revs2, ascending=None): |
3007 self._r1 = revs1 |
3007 self._r1 = revs1 |
3008 self._r2 = revs2 |
3008 self._r2 = revs2 |
3009 self._iter = None |
3009 self._iter = None |
3018 return bool(self._r1) or bool(self._r2) |
3018 return bool(self._r1) or bool(self._r2) |
3019 |
3019 |
3020 @util.propertycache |
3020 @util.propertycache |
3021 def _list(self): |
3021 def _list(self): |
3022 if not self._genlist: |
3022 if not self._genlist: |
3023 self._genlist = baseset(self._iterator()) |
3023 self._genlist = baseset(iter(self)) |
3024 return self._genlist |
3024 return self._genlist |
3025 |
3025 |
3026 def _iterator(self): |
3026 def __iter__(self): |
3027 """Iterate over both collections without repeating elements |
3027 """Iterate over both collections without repeating elements |
3028 |
3028 |
3029 If the ascending attribute is not set, iterate over the first one and |
3029 If the ascending attribute is not set, iterate over the first one and |
3030 then over the second one checking for membership on the first one so we |
3030 then over the second one checking for membership on the first one so we |
3031 dont yield any duplicates. |
3031 dont yield any duplicates. |
3032 |
3032 |
3033 If the ascending attribute is set, iterate over both collections at the |
3033 If the ascending attribute is set, iterate over both collections at the |
3034 same time, yielding only one value at a time in the given order. |
3034 same time, yielding only one value at a time in the given order. |
3035 """ |
3035 """ |
3036 if self._ascending is None: |
3036 if self._ascending is None: |
3037 def gen(): |
3037 if self._genlist: |
|
3038 return iter(self._genlist) |
|
3039 def arbitraryordergen(): |
3038 for r in self._r1: |
3040 for r in self._r1: |
3039 yield r |
3041 yield r |
3040 inr1 = self._r1.__contains__ |
3042 inr1 = self._r1.__contains__ |
3041 for r in self._r2: |
3043 for r in self._r2: |
3042 if not inr1(r): |
3044 if not inr1(r): |
3043 yield r |
3045 yield r |
3044 gen = gen() |
3046 return arbitraryordergen() |
3045 else: |
3047 # try to use our own fast iterator if it exists |
3046 iter1 = iter(self._r1) |
|
3047 iter2 = iter(self._r2) |
|
3048 gen = self._iterordered(self._ascending, iter1, iter2) |
|
3049 return gen |
|
3050 |
|
3051 def __iter__(self): |
|
3052 if self._ascending is None: |
|
3053 if self._genlist: |
|
3054 return iter(self._genlist) |
|
3055 return iter(self._iterator()) |
|
3056 self._trysetasclist() |
3048 self._trysetasclist() |
3057 if self._ascending: |
3049 if self._ascending: |
3058 it = self.fastasc |
3050 it = self.fastasc |
3059 else: |
3051 else: |
3060 it = self.fastdesc |
3052 it = self.fastdesc |
3061 if it is None: |
3053 if it is not None: |
3062 # consume the gen and try again |
3054 return it() |
3063 self._list |
3055 # maybe half of the component supports fast |
3064 return iter(self) |
3056 attr = 'fastdesc' |
3065 return it() |
3057 if self._ascending: |
|
3058 attr = 'fastasc' |
|
3059 # get iterator for _r1 |
|
3060 iter1 = getattr(self._r1, attr) |
|
3061 if iter1 is None: |
|
3062 # let's avoid side effect (not sure it matters) |
|
3063 iter1 = iter(sorted(self._r1, reverse=not self._ascending)) |
|
3064 else: |
|
3065 iter1 = iter1() |
|
3066 # get iterator for _r2 |
|
3067 iter2 = getattr(self._r2, attr) |
|
3068 if iter2 is None: |
|
3069 # let's avoid side effect (not sure it matters) |
|
3070 iter2 = iter(sorted(self._r2, reverse=not self._ascending)) |
|
3071 else: |
|
3072 iter2 = iter2() |
|
3073 return self._iterordered(self._ascending, iter1, iter2) |
3066 |
3074 |
3067 def _trysetasclist(self): |
3075 def _trysetasclist(self): |
3068 """populate the _asclist attribute if possible and necessary""" |
3076 """populate the _asclist attribute if possible and necessary""" |
3069 if self._genlist is not None and self._asclist is None: |
3077 if self._genlist is not None and self._asclist is None: |
3070 self._asclist = sorted(self._genlist) |
3078 self._asclist = sorted(self._genlist) |