comparison mercurial/util.py @ 34131:0fa781320203

doctest: bulk-replace string literals with b'' for Python 3 Our code transformer can't rewrite string literals in docstrings, and I don't want to make the transformer more complex.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 03 Sep 2017 14:32:11 +0900
parents 6c5cdb02f2f9
children d4d4d11bac77
comparison
equal deleted inserted replaced
34130:ada8a19672ab 34131:0fa781320203
225 class digester(object): 225 class digester(object):
226 """helper to compute digests. 226 """helper to compute digests.
227 227
228 This helper can be used to compute one or more digests given their name. 228 This helper can be used to compute one or more digests given their name.
229 229
230 >>> d = digester(['md5', 'sha1']) 230 >>> d = digester([b'md5', b'sha1'])
231 >>> d.update('foo') 231 >>> d.update(b'foo')
232 >>> [k for k in sorted(d)] 232 >>> [k for k in sorted(d)]
233 ['md5', 'sha1'] 233 ['md5', 'sha1']
234 >>> d['md5'] 234 >>> d[b'md5']
235 'acbd18db4cc2f85cedef654fccc4a4d8' 235 'acbd18db4cc2f85cedef654fccc4a4d8'
236 >>> d['sha1'] 236 >>> d[b'sha1']
237 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' 237 '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
238 >>> digester.preferred(['md5', 'sha1']) 238 >>> digester.preferred([b'md5', b'sha1'])
239 'sha1' 239 'sha1'
240 """ 240 """
241 241
242 def __init__(self, digests, s=''): 242 def __init__(self, digests, s=''):
243 self._hashes = {} 243 self._hashes = {}
446 If it isn't defined, the current Mercurial version string will be parsed. 446 If it isn't defined, the current Mercurial version string will be parsed.
447 447
448 ``n`` can be 2, 3, or 4. Here is how some version strings map to 448 ``n`` can be 2, 3, or 4. Here is how some version strings map to
449 returned values: 449 returned values:
450 450
451 >>> v = '3.6.1+190-df9b73d2d444' 451 >>> v = b'3.6.1+190-df9b73d2d444'
452 >>> versiontuple(v, 2) 452 >>> versiontuple(v, 2)
453 (3, 6) 453 (3, 6)
454 >>> versiontuple(v, 3) 454 >>> versiontuple(v, 3)
455 (3, 6, 1) 455 (3, 6, 1)
456 >>> versiontuple(v, 4) 456 >>> versiontuple(v, 4)
457 (3, 6, 1, '190-df9b73d2d444') 457 (3, 6, 1, '190-df9b73d2d444')
458 458
459 >>> versiontuple('3.6.1+190-df9b73d2d444+20151118') 459 >>> versiontuple(b'3.6.1+190-df9b73d2d444+20151118')
460 (3, 6, 1, '190-df9b73d2d444+20151118') 460 (3, 6, 1, '190-df9b73d2d444+20151118')
461 461
462 >>> v = '3.6' 462 >>> v = b'3.6'
463 >>> versiontuple(v, 2) 463 >>> versiontuple(v, 2)
464 (3, 6) 464 (3, 6)
465 >>> versiontuple(v, 3) 465 >>> versiontuple(v, 3)
466 (3, 6, None) 466 (3, 6, None)
467 >>> versiontuple(v, 4) 467 >>> versiontuple(v, 4)
468 (3, 6, None, None) 468 (3, 6, None, None)
469 469
470 >>> v = '3.9-rc' 470 >>> v = b'3.9-rc'
471 >>> versiontuple(v, 2) 471 >>> versiontuple(v, 2)
472 (3, 9) 472 (3, 9)
473 >>> versiontuple(v, 3) 473 >>> versiontuple(v, 3)
474 (3, 9, None) 474 (3, 9, None)
475 >>> versiontuple(v, 4) 475 >>> versiontuple(v, 4)
476 (3, 9, None, 'rc') 476 (3, 9, None, 'rc')
477 477
478 >>> v = '3.9-rc+2-02a8fea4289b' 478 >>> v = b'3.9-rc+2-02a8fea4289b'
479 >>> versiontuple(v, 2) 479 >>> versiontuple(v, 2)
480 (3, 9) 480 (3, 9)
481 >>> versiontuple(v, 3) 481 >>> versiontuple(v, 3)
482 (3, 9, None) 482 (3, 9, None)
483 >>> versiontuple(v, 4) 483 >>> versiontuple(v, 4)
577 return f 577 return f
578 578
579 class sortdict(collections.OrderedDict): 579 class sortdict(collections.OrderedDict):
580 '''a simple sorted dictionary 580 '''a simple sorted dictionary
581 581
582 >>> d1 = sortdict([('a', 0), ('b', 1)]) 582 >>> d1 = sortdict([(b'a', 0), (b'b', 1)])
583 >>> d2 = d1.copy() 583 >>> d2 = d1.copy()
584 >>> d2 584 >>> d2
585 sortdict([('a', 0), ('b', 1)]) 585 sortdict([('a', 0), ('b', 1)])
586 >>> d2.update([('a', 2)]) 586 >>> d2.update([(b'a', 2)])
587 >>> d2.keys() # should still be in last-set order 587 >>> d2.keys() # should still be in last-set order
588 ['b', 'a'] 588 ['b', 'a']
589 ''' 589 '''
590 590
591 def __setitem__(self, key, value): 591 def __setitem__(self, key, value):
1238 _winreservedchars = ':*?"<>|' 1238 _winreservedchars = ':*?"<>|'
1239 def checkwinfilename(path): 1239 def checkwinfilename(path):
1240 r'''Check that the base-relative path is a valid filename on Windows. 1240 r'''Check that the base-relative path is a valid filename on Windows.
1241 Returns None if the path is ok, or a UI string describing the problem. 1241 Returns None if the path is ok, or a UI string describing the problem.
1242 1242
1243 >>> checkwinfilename("just/a/normal/path") 1243 >>> checkwinfilename(b"just/a/normal/path")
1244 >>> checkwinfilename("foo/bar/con.xml") 1244 >>> checkwinfilename(b"foo/bar/con.xml")
1245 "filename contains 'con', which is reserved on Windows" 1245 "filename contains 'con', which is reserved on Windows"
1246 >>> checkwinfilename("foo/con.xml/bar") 1246 >>> checkwinfilename(b"foo/con.xml/bar")
1247 "filename contains 'con', which is reserved on Windows" 1247 "filename contains 'con', which is reserved on Windows"
1248 >>> checkwinfilename("foo/bar/xml.con") 1248 >>> checkwinfilename(b"foo/bar/xml.con")
1249 >>> checkwinfilename("foo/bar/AUX/bla.txt") 1249 >>> checkwinfilename(b"foo/bar/AUX/bla.txt")
1250 "filename contains 'AUX', which is reserved on Windows" 1250 "filename contains 'AUX', which is reserved on Windows"
1251 >>> checkwinfilename("foo/bar/bla:.txt") 1251 >>> checkwinfilename(b"foo/bar/bla:.txt")
1252 "filename contains ':', which is reserved on Windows" 1252 "filename contains ':', which is reserved on Windows"
1253 >>> checkwinfilename("foo/bar/b\07la.txt") 1253 >>> checkwinfilename(b"foo/bar/b\07la.txt")
1254 "filename contains '\\x07', which is invalid on Windows" 1254 "filename contains '\\x07', which is invalid on Windows"
1255 >>> checkwinfilename("foo/bar/bla ") 1255 >>> checkwinfilename(b"foo/bar/bla ")
1256 "filename ends with ' ', which is not allowed on Windows" 1256 "filename ends with ' ', which is not allowed on Windows"
1257 >>> checkwinfilename("../bar") 1257 >>> checkwinfilename(b"../bar")
1258 >>> checkwinfilename("foo\\") 1258 >>> checkwinfilename(b"foo\\")
1259 "filename ends with '\\', which is invalid on Windows" 1259 "filename ends with '\\', which is invalid on Windows"
1260 >>> checkwinfilename("foo\\/bar") 1260 >>> checkwinfilename(b"foo\\/bar")
1261 "directory name ends with '\\', which is invalid on Windows" 1261 "directory name ends with '\\', which is invalid on Windows"
1262 ''' 1262 '''
1263 if path.endswith('\\'): 1263 if path.endswith('\\'):
1264 return _("filename ends with '\\', which is invalid on Windows") 1264 return _("filename ends with '\\', which is invalid on Windows")
1265 if '\\/' in path: 1265 if '\\/' in path:
1992 """parse a localized date/time and return a (unixtime, offset) tuple. 1992 """parse a localized date/time and return a (unixtime, offset) tuple.
1993 1993
1994 The date may be a "unixtime offset" string or in one of the specified 1994 The date may be a "unixtime offset" string or in one of the specified
1995 formats. If the date already is a (unixtime, offset) tuple, it is returned. 1995 formats. If the date already is a (unixtime, offset) tuple, it is returned.
1996 1996
1997 >>> parsedate(' today ') == parsedate(\ 1997 >>> parsedate(b' today ') == parsedate(\
1998 datetime.date.today().strftime('%b %d')) 1998 datetime.date.today().strftime('%b %d'))
1999 True 1999 True
2000 >>> parsedate( 'yesterday ') == parsedate((datetime.date.today() -\ 2000 >>> parsedate(b'yesterday ') == parsedate((datetime.date.today() -\
2001 datetime.timedelta(days=1)\ 2001 datetime.timedelta(days=1)\
2002 ).strftime('%b %d')) 2002 ).strftime('%b %d'))
2003 True 2003 True
2004 >>> now, tz = makedate() 2004 >>> now, tz = makedate()
2005 >>> strnow, strtz = parsedate('now') 2005 >>> strnow, strtz = parsedate(b'now')
2006 >>> (strnow - now) < 1 2006 >>> (strnow - now) < 1
2007 True 2007 True
2008 >>> tz == strtz 2008 >>> tz == strtz
2009 True 2009 True
2010 """ 2010 """
2074 2074
2075 '<{date}' on or before a given date 2075 '<{date}' on or before a given date
2076 2076
2077 '>{date}' on or after a given date 2077 '>{date}' on or after a given date
2078 2078
2079 >>> p1 = parsedate("10:29:59") 2079 >>> p1 = parsedate(b"10:29:59")
2080 >>> p2 = parsedate("10:30:00") 2080 >>> p2 = parsedate(b"10:30:00")
2081 >>> p3 = parsedate("10:30:59") 2081 >>> p3 = parsedate(b"10:30:59")
2082 >>> p4 = parsedate("10:31:00") 2082 >>> p4 = parsedate(b"10:31:00")
2083 >>> p5 = parsedate("Sep 15 10:30:00 1999") 2083 >>> p5 = parsedate(b"Sep 15 10:30:00 1999")
2084 >>> f = matchdate("10:30") 2084 >>> f = matchdate(b"10:30")
2085 >>> f(p1[0]) 2085 >>> f(p1[0])
2086 False 2086 False
2087 >>> f(p2[0]) 2087 >>> f(p2[0])
2088 True 2088 True
2089 >>> f(p3[0]) 2089 >>> f(p3[0])
2154 >>> def itest(pattern, *tests): 2154 >>> def itest(pattern, *tests):
2155 ... kind, pattern, matcher = stringmatcher(pattern, casesensitive=False) 2155 ... kind, pattern, matcher = stringmatcher(pattern, casesensitive=False)
2156 ... return (kind, pattern, [bool(matcher(t)) for t in tests]) 2156 ... return (kind, pattern, [bool(matcher(t)) for t in tests])
2157 2157
2158 exact matching (no prefix): 2158 exact matching (no prefix):
2159 >>> test('abcdefg', 'abc', 'def', 'abcdefg') 2159 >>> test(b'abcdefg', b'abc', b'def', b'abcdefg')
2160 ('literal', 'abcdefg', [False, False, True]) 2160 ('literal', 'abcdefg', [False, False, True])
2161 2161
2162 regex matching ('re:' prefix) 2162 regex matching ('re:' prefix)
2163 >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar') 2163 >>> test(b're:a.+b', b'nomatch', b'fooadef', b'fooadefbar')
2164 ('re', 'a.+b', [False, False, True]) 2164 ('re', 'a.+b', [False, False, True])
2165 2165
2166 force exact matches ('literal:' prefix) 2166 force exact matches ('literal:' prefix)
2167 >>> test('literal:re:foobar', 'foobar', 're:foobar') 2167 >>> test(b'literal:re:foobar', b'foobar', b're:foobar')
2168 ('literal', 're:foobar', [False, True]) 2168 ('literal', 're:foobar', [False, True])
2169 2169
2170 unknown prefixes are ignored and treated as literals 2170 unknown prefixes are ignored and treated as literals
2171 >>> test('foo:bar', 'foo', 'bar', 'foo:bar') 2171 >>> test(b'foo:bar', b'foo', b'bar', b'foo:bar')
2172 ('literal', 'foo:bar', [False, False, True]) 2172 ('literal', 'foo:bar', [False, False, True])
2173 2173
2174 case insensitive regex matches 2174 case insensitive regex matches
2175 >>> itest('re:A.+b', 'nomatch', 'fooadef', 'fooadefBar') 2175 >>> itest(b're:A.+b', b'nomatch', b'fooadef', b'fooadefBar')
2176 ('re', 'A.+b', [False, False, True]) 2176 ('re', 'A.+b', [False, False, True])
2177 2177
2178 case insensitive literal matches 2178 case insensitive literal matches
2179 >>> itest('ABCDEFG', 'abc', 'def', 'abcdefg') 2179 >>> itest(b'ABCDEFG', b'abc', b'def', b'abcdefg')
2180 ('literal', 'ABCDEFG', [False, False, True]) 2180 ('literal', 'ABCDEFG', [False, False, True])
2181 """ 2181 """
2182 if pattern.startswith('re:'): 2182 if pattern.startswith('re:'):
2183 pattern = pattern[3:] 2183 pattern = pattern[3:]
2184 try: 2184 try:
2647 Note that for backward compatibility reasons, bundle URLs do not 2647 Note that for backward compatibility reasons, bundle URLs do not
2648 take host names. That means 'bundle://../' has a path of '../'. 2648 take host names. That means 'bundle://../' has a path of '../'.
2649 2649
2650 Examples: 2650 Examples:
2651 2651
2652 >>> url('http://www.ietf.org/rfc/rfc2396.txt') 2652 >>> url(b'http://www.ietf.org/rfc/rfc2396.txt')
2653 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'> 2653 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
2654 >>> url('ssh://[::1]:2200//home/joe/repo') 2654 >>> url(b'ssh://[::1]:2200//home/joe/repo')
2655 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'> 2655 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
2656 >>> url('file:///home/joe/repo') 2656 >>> url(b'file:///home/joe/repo')
2657 <url scheme: 'file', path: '/home/joe/repo'> 2657 <url scheme: 'file', path: '/home/joe/repo'>
2658 >>> url('file:///c:/temp/foo/') 2658 >>> url(b'file:///c:/temp/foo/')
2659 <url scheme: 'file', path: 'c:/temp/foo/'> 2659 <url scheme: 'file', path: 'c:/temp/foo/'>
2660 >>> url('bundle:foo') 2660 >>> url(b'bundle:foo')
2661 <url scheme: 'bundle', path: 'foo'> 2661 <url scheme: 'bundle', path: 'foo'>
2662 >>> url('bundle://../foo') 2662 >>> url(b'bundle://../foo')
2663 <url scheme: 'bundle', path: '../foo'> 2663 <url scheme: 'bundle', path: '../foo'>
2664 >>> url(r'c:\foo\bar') 2664 >>> url(br'c:\foo\bar')
2665 <url path: 'c:\\foo\\bar'> 2665 <url path: 'c:\\foo\\bar'>
2666 >>> url(r'\\blah\blah\blah') 2666 >>> url(br'\\blah\blah\blah')
2667 <url path: '\\\\blah\\blah\\blah'> 2667 <url path: '\\\\blah\\blah\\blah'>
2668 >>> url(r'\\blah\blah\blah#baz') 2668 >>> url(br'\\blah\blah\blah#baz')
2669 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'> 2669 <url path: '\\\\blah\\blah\\blah', fragment: 'baz'>
2670 >>> url(r'file:///C:\users\me') 2670 >>> url(br'file:///C:\users\me')
2671 <url scheme: 'file', path: 'C:\\users\\me'> 2671 <url scheme: 'file', path: 'C:\\users\\me'>
2672 2672
2673 Authentication credentials: 2673 Authentication credentials:
2674 2674
2675 >>> url('ssh://joe:xyz@x/repo') 2675 >>> url(b'ssh://joe:xyz@x/repo')
2676 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'> 2676 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
2677 >>> url('ssh://joe@x/repo') 2677 >>> url(b'ssh://joe@x/repo')
2678 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'> 2678 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
2679 2679
2680 Query strings and fragments: 2680 Query strings and fragments:
2681 2681
2682 >>> url('http://host/a?b#c') 2682 >>> url(b'http://host/a?b#c')
2683 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'> 2683 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
2684 >>> url('http://host/a?b#c', parsequery=False, parsefragment=False) 2684 >>> url(b'http://host/a?b#c', parsequery=False, parsefragment=False)
2685 <url scheme: 'http', host: 'host', path: 'a?b#c'> 2685 <url scheme: 'http', host: 'host', path: 'a?b#c'>
2686 2686
2687 Empty path: 2687 Empty path:
2688 2688
2689 >>> url('') 2689 >>> url(b'')
2690 <url path: ''> 2690 <url path: ''>
2691 >>> url('#a') 2691 >>> url(b'#a')
2692 <url path: '', fragment: 'a'> 2692 <url path: '', fragment: 'a'>
2693 >>> url('http://host/') 2693 >>> url(b'http://host/')
2694 <url scheme: 'http', host: 'host', path: ''> 2694 <url scheme: 'http', host: 'host', path: ''>
2695 >>> url('http://host/#a') 2695 >>> url(b'http://host/#a')
2696 <url scheme: 'http', host: 'host', path: '', fragment: 'a'> 2696 <url scheme: 'http', host: 'host', path: '', fragment: 'a'>
2697 2697
2698 Only scheme: 2698 Only scheme:
2699 2699
2700 >>> url('http:') 2700 >>> url(b'http:')
2701 <url scheme: 'http'> 2701 <url scheme: 'http'>
2702 """ 2702 """
2703 2703
2704 _safechars = "!~*'()+" 2704 _safechars = "!~*'()+"
2705 _safepchars = "/!~*'()+:\\" 2705 _safepchars = "/!~*'()+:\\"
2810 def __bytes__(self): 2810 def __bytes__(self):
2811 r"""Join the URL's components back into a URL string. 2811 r"""Join the URL's components back into a URL string.
2812 2812
2813 Examples: 2813 Examples:
2814 2814
2815 >>> str(url('http://user:pw@host:80/c:/bob?fo:oo#ba:ar')) 2815 >>> str(url(b'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'))
2816 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar' 2816 'http://user:pw@host:80/c:/bob?fo:oo#ba:ar'
2817 >>> str(url('http://user:pw@host:80/?foo=bar&baz=42')) 2817 >>> str(url(b'http://user:pw@host:80/?foo=bar&baz=42'))
2818 'http://user:pw@host:80/?foo=bar&baz=42' 2818 'http://user:pw@host:80/?foo=bar&baz=42'
2819 >>> str(url('http://user:pw@host:80/?foo=bar%3dbaz')) 2819 >>> str(url(b'http://user:pw@host:80/?foo=bar%3dbaz'))
2820 'http://user:pw@host:80/?foo=bar%3dbaz' 2820 'http://user:pw@host:80/?foo=bar%3dbaz'
2821 >>> str(url('ssh://user:pw@[::1]:2200//home/joe#')) 2821 >>> str(url(b'ssh://user:pw@[::1]:2200//home/joe#'))
2822 'ssh://user:pw@[::1]:2200//home/joe#' 2822 'ssh://user:pw@[::1]:2200//home/joe#'
2823 >>> str(url('http://localhost:80//')) 2823 >>> str(url(b'http://localhost:80//'))
2824 'http://localhost:80//' 2824 'http://localhost:80//'
2825 >>> str(url('http://localhost:80/')) 2825 >>> str(url(b'http://localhost:80/'))
2826 'http://localhost:80/' 2826 'http://localhost:80/'
2827 >>> str(url('http://localhost:80')) 2827 >>> str(url(b'http://localhost:80'))
2828 'http://localhost:80/' 2828 'http://localhost:80/'
2829 >>> str(url('bundle:foo')) 2829 >>> str(url(b'bundle:foo'))
2830 'bundle:foo' 2830 'bundle:foo'
2831 >>> str(url('bundle://../foo')) 2831 >>> str(url(b'bundle://../foo'))
2832 'bundle:../foo' 2832 'bundle:../foo'
2833 >>> str(url('path')) 2833 >>> str(url(b'path'))
2834 'path' 2834 'path'
2835 >>> str(url('file:///tmp/foo/bar')) 2835 >>> str(url(b'file:///tmp/foo/bar'))
2836 'file:///tmp/foo/bar' 2836 'file:///tmp/foo/bar'
2837 >>> str(url('file:///c:/tmp/foo/bar')) 2837 >>> str(url(b'file:///c:/tmp/foo/bar'))
2838 'file:///c:/tmp/foo/bar' 2838 'file:///c:/tmp/foo/bar'
2839 >>> print url(r'bundle:foo\bar') 2839 >>> print url(br'bundle:foo\bar')
2840 bundle:foo\bar 2840 bundle:foo\bar
2841 >>> print url(r'file:///D:\data\hg') 2841 >>> print url(br'file:///D:\data\hg')
2842 file:///D:\data\hg 2842 file:///D:\data\hg
2843 """ 2843 """
2844 if self._localpath: 2844 if self._localpath:
2845 s = self.path 2845 s = self.path
2846 if self.scheme == 'bundle': 2846 if self.scheme == 'bundle':
3015 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1)) 3015 ('kb', 2**10), ('mb', 2**20), ('gb', 2**30), ('b', 1))
3016 3016
3017 def sizetoint(s): 3017 def sizetoint(s):
3018 '''Convert a space specifier to a byte count. 3018 '''Convert a space specifier to a byte count.
3019 3019
3020 >>> sizetoint('30') 3020 >>> sizetoint(b'30')
3021 30 3021 30
3022 >>> sizetoint('2.2kb') 3022 >>> sizetoint(b'2.2kb')
3023 2252 3023 2252
3024 >>> sizetoint('6M') 3024 >>> sizetoint(b'6M')
3025 6291456 3025 6291456
3026 ''' 3026 '''
3027 t = s.strip().lower() 3027 t = s.strip().lower()
3028 try: 3028 try:
3029 for k, u in _sizeunits: 3029 for k, u in _sizeunits: