Home | History | Annotate | Download | only in util
      1 # Copyright 2015 The TensorFlow Authors. All Rights Reserved.
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #     http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 # ==============================================================================
     15 """Functions for Python 2 vs. 3 compatibility.
     16 
     17 ## Conversion routines
     18 In addition to the functions below, `as_str` converts an object to a `str`.
     19 
     20 @@as_bytes
     21 @@as_text
     22 @@as_str_any
     23 @@path_to_str
     24 
     25 ## Types
     26 The compatibility module also provides the following types:
     27 
     28 * `bytes_or_text_types`
     29 * `complex_types`
     30 * `integral_types`
     31 * `real_types`
     32 """
     33 
     34 from __future__ import absolute_import
     35 from __future__ import division
     36 from __future__ import print_function
     37 
     38 import numbers as _numbers
     39 
     40 import numpy as _np
     41 import six as _six
     42 
     43 from tensorflow.python.util.all_util import remove_undocumented
     44 from tensorflow.python.util.tf_export import tf_export
     45 from tensorflow.python.util.tf_export import tf_export
     46 
     47 
     48 @tf_export('compat.as_bytes', 'compat.as_str')
     49 def as_bytes(bytes_or_text, encoding='utf-8'):
     50   """Converts either bytes or unicode to `bytes`, using utf-8 encoding for text.
     51 
     52   Args:
     53     bytes_or_text: A `bytes`, `str`, or `unicode` object.
     54     encoding: A string indicating the charset for encoding unicode.
     55 
     56   Returns:
     57     A `bytes` object.
     58 
     59   Raises:
     60     TypeError: If `bytes_or_text` is not a binary or unicode string.
     61   """
     62   if isinstance(bytes_or_text, _six.text_type):
     63     return bytes_or_text.encode(encoding)
     64   elif isinstance(bytes_or_text, bytes):
     65     return bytes_or_text
     66   else:
     67     raise TypeError('Expected binary or unicode string, got %r' %
     68                     (bytes_or_text,))
     69 
     70 
     71 @tf_export('compat.as_text')
     72 def as_text(bytes_or_text, encoding='utf-8'):
     73   """Returns the given argument as a unicode string.
     74 
     75   Args:
     76     bytes_or_text: A `bytes`, `str`, or `unicode` object.
     77     encoding: A string indicating the charset for decoding unicode.
     78 
     79   Returns:
     80     A `unicode` (Python 2) or `str` (Python 3) object.
     81 
     82   Raises:
     83     TypeError: If `bytes_or_text` is not a binary or unicode string.
     84   """
     85   if isinstance(bytes_or_text, _six.text_type):
     86     return bytes_or_text
     87   elif isinstance(bytes_or_text, bytes):
     88     return bytes_or_text.decode(encoding)
     89   else:
     90     raise TypeError('Expected binary or unicode string, got %r' % bytes_or_text)
     91 
     92 
     93 # Convert an object to a `str` in both Python 2 and 3.
     94 if _six.PY2:
     95   as_str = as_bytes
     96 else:
     97   as_str = as_text
     98 
     99 
    100 @tf_export('compat.as_str_any')
    101 def as_str_any(value):
    102   """Converts to `str` as `str(value)`, but use `as_str` for `bytes`.
    103 
    104   Args:
    105     value: A object that can be converted to `str`.
    106 
    107   Returns:
    108     A `str` object.
    109   """
    110   if isinstance(value, bytes):
    111     return as_str(value)
    112   else:
    113     return str(value)
    114 
    115 
    116 @tf_export('compat.path_to_str')
    117 def path_to_str(path):
    118   """Returns the file system path representation of a `PathLike` object, else as it is.
    119 
    120   Args:
    121     path: An object that can be converted to path representation.
    122 
    123   Returns:
    124     A `str` object.
    125   """
    126   if hasattr(path, '__fspath__'):
    127     path = as_str_any(path.__fspath__())
    128   return path
    129 
    130 
    131 # Numpy 1.8 scalars don't inherit from numbers.Integral in Python 3, so we
    132 # need to check them specifically.  The same goes from Real and Complex.
    133 integral_types = (_numbers.Integral, _np.integer)
    134 tf_export('compat.integral_types').export_constant(__name__, 'integral_types')
    135 real_types = (_numbers.Real, _np.integer, _np.floating)
    136 tf_export('compat.real_types').export_constant(__name__, 'real_types')
    137 complex_types = (_numbers.Complex, _np.number)
    138 tf_export('compat.complex_types').export_constant(__name__, 'complex_types')
    139 
    140 # Either bytes or text.
    141 bytes_or_text_types = (bytes, _six.text_type)
    142 tf_export('compat.bytes_or_text_types').export_constant(__name__,
    143                                                         'bytes_or_text_types')
    144 
    145 _allowed_symbols = [
    146     'as_str',
    147     'bytes_or_text_types',
    148     'complex_types',
    149     'integral_types',
    150     'real_types',
    151 ]
    152 
    153 remove_undocumented(__name__, _allowed_symbols)
    154