mercurial/py3kcompat.py
changeset 30607 07025bd744a0
parent 30606 65835b850a72
child 30608 b52e8a4f4c0f
equal deleted inserted replaced
30606:65835b850a72 30607:07025bd744a0
     1 # py3kcompat.py - compatibility definitions for running hg in py3k
       
     2 #
       
     3 # Copyright 2010 Renato Cunha <renatoc@gmail.com>
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 from __future__ import absolute_import
       
     9 
       
    10 import builtins
       
    11 import numbers
       
    12 
       
    13 Number = numbers.Number
       
    14 
       
    15 def bytesformatter(format, args):
       
    16     '''Custom implementation of a formatter for bytestrings.
       
    17 
       
    18     This function currently relies on the string formatter to do the
       
    19     formatting and always returns bytes objects.
       
    20 
       
    21     >>> bytesformatter(20, 10)
       
    22     0
       
    23     >>> bytesformatter('unicode %s, %s!', ('string', 'foo'))
       
    24     b'unicode string, foo!'
       
    25     >>> bytesformatter(b'test %s', 'me')
       
    26     b'test me'
       
    27     >>> bytesformatter('test %s', 'me')
       
    28     b'test me'
       
    29     >>> bytesformatter(b'test %s', b'me')
       
    30     b'test me'
       
    31     >>> bytesformatter('test %s', b'me')
       
    32     b'test me'
       
    33     >>> bytesformatter('test %d: %s', (1, b'result'))
       
    34     b'test 1: result'
       
    35     '''
       
    36     # The current implementation just converts from bytes to unicode, do
       
    37     # what's needed and then convert the results back to bytes.
       
    38     # Another alternative is to use the Python C API implementation.
       
    39     if isinstance(format, Number):
       
    40         # If the fixer erroneously passes a number remainder operation to
       
    41         # bytesformatter, we just return the correct operation
       
    42         return format % args
       
    43     if isinstance(format, bytes):
       
    44         format = format.decode('utf-8', 'surrogateescape')
       
    45     if isinstance(args, bytes):
       
    46         args = args.decode('utf-8', 'surrogateescape')
       
    47     if isinstance(args, tuple):
       
    48         newargs = []
       
    49         for arg in args:
       
    50             if isinstance(arg, bytes):
       
    51                 arg = arg.decode('utf-8', 'surrogateescape')
       
    52             newargs.append(arg)
       
    53         args = tuple(newargs)
       
    54     ret = format % args
       
    55     return ret.encode('utf-8', 'surrogateescape')
       
    56 builtins.bytesformatter = bytesformatter
       
    57 
       
    58 origord = builtins.ord
       
    59 def fakeord(char):
       
    60     if isinstance(char, int):
       
    61         return char
       
    62     return origord(char)
       
    63 builtins.ord = fakeord
       
    64 
       
    65 if __name__ == '__main__':
       
    66     import doctest
       
    67     doctest.testmod()
       
    68