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)