Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/smartset.py @ 35941:f0827211eb1f
py3: build repr() of smartset as bytes then convert to str
This isn't pretty, but we have no way to teach Python 3 that our __repr__()
would like to return a byte string.
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Sat, 27 Jan 2018 17:12:35 +0900 |
parents | f484b9d95c23 |
children | fc44c2657dc5 |
comparison
equal
deleted
inserted
replaced
35940:72de5c504833 | 35941:f0827211eb1f |
---|---|
6 # GNU General Public License version 2 or any later version. | 6 # GNU General Public License version 2 or any later version. |
7 | 7 |
8 from __future__ import absolute_import | 8 from __future__ import absolute_import |
9 | 9 |
10 from . import ( | 10 from . import ( |
11 encoding, | |
11 error, | 12 error, |
13 pycompat, | |
12 util, | 14 util, |
13 ) | 15 ) |
14 | 16 |
15 def _formatsetrepr(r): | 17 def _formatsetrepr(r): |
16 """Format an optional printable representation of a set | 18 """Format an optional printable representation of a set |
17 | 19 |
18 ======== ================================= | 20 ======== ================================= |
19 type(r) example | 21 type(r) example |
20 ======== ================================= | 22 ======== ================================= |
21 tuple ('<not %r>', other) | 23 tuple ('<not %r>', other) |
22 str '<branch closed>' | 24 bytes '<branch closed>' |
23 callable lambda: '<branch %r>' % sorted(b) | 25 callable lambda: '<branch %r>' % sorted(b) |
24 object other | 26 object other |
25 ======== ================================= | 27 ======== ================================= |
26 """ | 28 """ |
27 if r is None: | 29 if r is None: |
28 return '' | 30 return '' |
29 elif isinstance(r, tuple): | 31 elif isinstance(r, tuple): |
30 return r[0] % r[1:] | 32 return r[0] % r[1:] |
31 elif isinstance(r, str): | 33 elif isinstance(r, bytes): |
32 return r | 34 return r |
33 elif callable(r): | 35 elif callable(r): |
34 return r() | 36 return r() |
35 else: | 37 else: |
36 return repr(r) | 38 return pycompat.sysbytes(repr(r)) |
39 | |
40 def _typename(o): | |
41 return pycompat.sysbytes(type(o).__name__).lstrip('_') | |
37 | 42 |
38 class abstractsmartset(object): | 43 class abstractsmartset(object): |
39 | 44 |
40 def __nonzero__(self): | 45 def __nonzero__(self): |
41 """True if the smartset is not empty""" | 46 """True if the smartset is not empty""" |
382 start, stop = max(len(data) - stop, 0), max(len(data) - start, 0) | 387 start, stop = max(len(data) - stop, 0), max(len(data) - start, 0) |
383 s = baseset(data[start:stop], istopo=self._istopo) | 388 s = baseset(data[start:stop], istopo=self._istopo) |
384 s._ascending = self._ascending | 389 s._ascending = self._ascending |
385 return s | 390 return s |
386 | 391 |
392 @encoding.strmethod | |
387 def __repr__(self): | 393 def __repr__(self): |
388 d = {None: '', False: '-', True: '+'}[self._ascending] | 394 d = {None: '', False: '-', True: '+'}[self._ascending] |
389 s = _formatsetrepr(self._datarepr) | 395 s = _formatsetrepr(self._datarepr) |
390 if not s: | 396 if not s: |
391 l = self._list | 397 l = self._list |
392 # if _list has been built from a set, it might have a different | 398 # if _list has been built from a set, it might have a different |
393 # order from one python implementation to another. | 399 # order from one python implementation to another. |
394 # We fallback to the sorted version for a stable output. | 400 # We fallback to the sorted version for a stable output. |
395 if self._ascending is not None: | 401 if self._ascending is not None: |
396 l = self._asclist | 402 l = self._asclist |
397 s = repr(l) | 403 s = pycompat.sysbytes(repr(l)) |
398 return '<%s%s %s>' % (type(self).__name__, d, s) | 404 return '<%s%s %s>' % (_typename(self), d, s) |
399 | 405 |
400 class filteredset(abstractsmartset): | 406 class filteredset(abstractsmartset): |
401 """Duck type for baseset class which iterates lazily over the revisions in | 407 """Duck type for baseset class which iterates lazily over the revisions in |
402 the subset and contains a function which tests for membership in the | 408 the subset and contains a function which tests for membership in the |
403 revset | 409 revset |
503 x = None | 509 x = None |
504 for x in self: | 510 for x in self: |
505 pass | 511 pass |
506 return x | 512 return x |
507 | 513 |
514 @encoding.strmethod | |
508 def __repr__(self): | 515 def __repr__(self): |
509 xs = [repr(self._subset)] | 516 xs = [pycompat.sysbytes(repr(self._subset))] |
510 s = _formatsetrepr(self._condrepr) | 517 s = _formatsetrepr(self._condrepr) |
511 if s: | 518 if s: |
512 xs.append(s) | 519 xs.append(s) |
513 return '<%s %s>' % (type(self).__name__, ', '.join(xs)) | 520 return '<%s %s>' % (_typename(self), ', '.join(xs)) |
514 | 521 |
515 def _iterordered(ascending, iter1, iter2): | 522 def _iterordered(ascending, iter1, iter2): |
516 """produce an ordered iteration from two iterators with the same order | 523 """produce an ordered iteration from two iterators with the same order |
517 | 524 |
518 The ascending is used to indicated the iteration direction. | 525 The ascending is used to indicated the iteration direction. |
753 self.reverse() | 760 self.reverse() |
754 val = self.first() | 761 val = self.first() |
755 self.reverse() | 762 self.reverse() |
756 return val | 763 return val |
757 | 764 |
765 @encoding.strmethod | |
758 def __repr__(self): | 766 def __repr__(self): |
759 d = {None: '', False: '-', True: '+'}[self._ascending] | 767 d = {None: '', False: '-', True: '+'}[self._ascending] |
760 return '<%s%s %r, %r>' % (type(self).__name__, d, self._r1, self._r2) | 768 return '<%s%s %r, %r>' % (_typename(self), d, self._r1, self._r2) |
761 | 769 |
762 class generatorset(abstractsmartset): | 770 class generatorset(abstractsmartset): |
763 """Wrap a generator for lazy iteration | 771 """Wrap a generator for lazy iteration |
764 | 772 |
765 Wrapper structure for generators that provides lazy membership and can | 773 Wrapper structure for generators that provides lazy membership and can |
916 for x in self._consumegen(): | 924 for x in self._consumegen(): |
917 pass | 925 pass |
918 return self.last() | 926 return self.last() |
919 return next(it(), None) | 927 return next(it(), None) |
920 | 928 |
929 @encoding.strmethod | |
921 def __repr__(self): | 930 def __repr__(self): |
922 d = {False: '-', True: '+'}[self._ascending] | 931 d = {False: '-', True: '+'}[self._ascending] |
923 return '<%s%s>' % (type(self).__name__.lstrip('_'), d) | 932 return '<%s%s>' % (_typename(self), d) |
924 | 933 |
925 class _generatorsetasc(generatorset): | 934 class _generatorsetasc(generatorset): |
926 """Special case of generatorset optimized for ascending generators.""" | 935 """Special case of generatorset optimized for ascending generators.""" |
927 | 936 |
928 fastasc = generatorset._iterator | 937 fastasc = generatorset._iterator |
1085 else: | 1094 else: |
1086 x = max(self._end - stop, self._start) | 1095 x = max(self._end - stop, self._start) |
1087 y = max(self._end - start, self._start) | 1096 y = max(self._end - start, self._start) |
1088 return _spanset(x, y, self._ascending, self._hiddenrevs) | 1097 return _spanset(x, y, self._ascending, self._hiddenrevs) |
1089 | 1098 |
1099 @encoding.strmethod | |
1090 def __repr__(self): | 1100 def __repr__(self): |
1091 d = {False: '-', True: '+'}[self._ascending] | 1101 d = {False: '-', True: '+'}[self._ascending] |
1092 return '<%s%s %d:%d>' % (type(self).__name__.lstrip('_'), d, | 1102 return '<%s%s %d:%d>' % (_typename(self), d, self._start, self._end) |
1093 self._start, self._end) | |
1094 | 1103 |
1095 class fullreposet(_spanset): | 1104 class fullreposet(_spanset): |
1096 """a set containing all revisions in the repo | 1105 """a set containing all revisions in the repo |
1097 | 1106 |
1098 This class exists to host special optimization and magic to handle virtual | 1107 This class exists to host special optimization and magic to handle virtual |
1121 other.sort(reverse=self.isdescending()) | 1130 other.sort(reverse=self.isdescending()) |
1122 return other | 1131 return other |
1123 | 1132 |
1124 def prettyformat(revs): | 1133 def prettyformat(revs): |
1125 lines = [] | 1134 lines = [] |
1126 rs = repr(revs) | 1135 rs = pycompat.sysbytes(repr(revs)) |
1127 p = 0 | 1136 p = 0 |
1128 while p < len(rs): | 1137 while p < len(rs): |
1129 q = rs.find('<', p + 1) | 1138 q = rs.find('<', p + 1) |
1130 if q < 0: | 1139 if q < 0: |
1131 q = len(rs) | 1140 q = len(rs) |