1# -*- coding: utf-8 -*- 
    2# 
    3#  Util/py3compat.py : Compatibility code for handling Py3k / Python 2.x 
    4# 
    5# Written in 2010 by Thorsten Behrens 
    6# 
    7# =================================================================== 
    8# The contents of this file are dedicated to the public domain.  To 
    9# the extent that dedication to the public domain is not available, 
    10# everyone is granted a worldwide, perpetual, royalty-free, 
    11# non-exclusive license to exercise all rights associated with the 
    12# contents of this file for any purpose whatsoever. 
    13# No rights are reserved. 
    14# 
    15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
    16# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    17# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
    18# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
    19# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
    20# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
    21# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
    22# SOFTWARE. 
    23# =================================================================== 
    24 
    25"""Compatibility code for handling string/bytes changes from Python 2.x to Py3k 
    26 
    27In Python 2.x, strings (of type ''str'') contain binary data, including encoded 
    28Unicode text (e.g. UTF-8).  The separate type ''unicode'' holds Unicode text. 
    29Unicode literals are specified via the u'...' prefix.  Indexing or slicing 
    30either type always produces a string of the same type as the original. 
    31Data read from a file is always of '''str'' type. 
    32 
    33In Python 3.x, strings (type ''str'') may only contain Unicode text. The u'...' 
    34prefix and the ''unicode'' type are now redundant.  A new type (called 
    35''bytes'') has to be used for binary data (including any particular 
    36''encoding'' of a string).  The b'...' prefix allows one to specify a binary 
    37literal.  Indexing or slicing a string produces another string.  Slicing a byte 
    38string produces another byte string, but the indexing operation produces an 
    39integer.  Data read from a file is of '''str'' type if the file was opened in 
    40text mode, or of ''bytes'' type otherwise. 
    41 
    42Since PyCrypto aims at supporting both Python 2.x and 3.x, the following helper 
    43functions are used to keep the rest of the library as independent as possible 
    44from the actual Python version. 
    45 
    46In general, the code should always deal with binary strings, and use integers 
    47instead of 1-byte character strings. 
    48 
    49b(s) 
    50    Take a text string literal (with no prefix or with u'...' prefix) and 
    51    make a byte string. 
    52bchr(c) 
    53    Take an integer and make a 1-character byte string. 
    54bord(c) 
    55    Take the result of indexing on a byte string and make an integer. 
    56tobytes(s) 
    57    Take a text string, a byte string, or a sequence of character taken from 
    58    a byte string and make a byte string. 
    59""" 
    60 
    61import sys 
    62import abc 
    63 
    64 
    65if sys.version_info[0] == 2: 
    66    def b(s): 
    67        return s 
    68    def bchr(s): 
    69        return chr(s) 
    70    def bstr(s): 
    71        return str(s) 
    72    def bord(s): 
    73        return ord(s) 
    74    def tobytes(s, encoding="latin-1"): 
    75        if isinstance(s, unicode): 
    76            return s.encode(encoding) 
    77        elif isinstance(s, str): 
    78            return s 
    79        elif isinstance(s, bytearray): 
    80            return bytes(s) 
    81        elif isinstance(s, memoryview): 
    82            return s.tobytes() 
    83        else: 
    84            return ''.join(s) 
    85    def tostr(bs): 
    86        return bs 
    87    def byte_string(s): 
    88        return isinstance(s, str) 
    89 
    90    # In Python 2, a memoryview does not support concatenation 
    91    def concat_buffers(a, b): 
    92        if isinstance(a, memoryview): 
    93            a = a.tobytes() 
    94        if isinstance(b, memoryview): 
    95            b = b.tobytes() 
    96        return a + b 
    97 
    98    from StringIO import StringIO 
    99    BytesIO = StringIO 
    100 
    101    from sys import maxint 
    102 
    103    iter_range = xrange 
    104 
    105    def is_native_int(x): 
    106        return isinstance(x, (int, long)) 
    107 
    108    def is_string(x): 
    109        return isinstance(x, basestring) 
    110 
    111    def is_bytes(x): 
    112        return isinstance(x, str) or \ 
    113                isinstance(x, bytearray) or \ 
    114                isinstance(x, memoryview) 
    115 
    116    ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()}) 
    117 
    118    FileNotFoundError = IOError 
    119 
    120else: 
    121    def b(s): 
    122       return s.encode("latin-1") # utf-8 would cause some side-effects we don't want 
    123    def bchr(s): 
    124        return bytes([s]) 
    125    def bstr(s): 
    126        if isinstance(s,str): 
    127            return bytes(s,"latin-1") 
    128        else: 
    129            return bytes(s) 
    130    def bord(s): 
    131        return s 
    132    def tobytes(s, encoding="latin-1"): 
    133        if isinstance(s, bytes): 
    134            return s 
    135        elif isinstance(s, bytearray): 
    136            return bytes(s) 
    137        elif isinstance(s,str): 
    138            return s.encode(encoding) 
    139        elif isinstance(s, memoryview): 
    140            return s.tobytes() 
    141        else: 
    142            return bytes([s]) 
    143    def tostr(bs): 
    144        return bs.decode("latin-1") 
    145    def byte_string(s): 
    146        return isinstance(s, bytes) 
    147 
    148    def concat_buffers(a, b): 
    149        return a + b 
    150 
    151    from io import BytesIO 
    152    from io import StringIO 
    153    from sys import maxsize as maxint 
    154 
    155    iter_range = range 
    156 
    157    def is_native_int(x): 
    158        return isinstance(x, int) 
    159 
    160    def is_string(x): 
    161        return isinstance(x, str) 
    162 
    163    def is_bytes(x): 
    164        return isinstance(x, bytes) or \ 
    165                isinstance(x, bytearray) or \ 
    166                isinstance(x, memoryview) 
    167 
    168    from abc import ABC 
    169 
    170    FileNotFoundError = FileNotFoundError 
    171 
    172 
    173def _copy_bytes(start, end, seq): 
    174    """Return an immutable copy of a sequence (byte string, byte array, memoryview) 
    175    in a certain interval [start:seq]""" 
    176 
    177    if isinstance(seq, memoryview): 
    178        return seq[start:end].tobytes() 
    179    elif isinstance(seq, bytearray): 
    180        return bytes(seq[start:end]) 
    181    else: 
    182        return seq[start:end] 
    183 
    184del sys 
    185del abc