text: # Copyright (c) Microsoft Corporation. All rights reserved.
  # Licensed under the MIT License. See LICENSE in the project root
  # for license information.
  
  from __future__ import absolute_import, print_function, unicode_literals
  
  """Python 2/3 compatibility helpers.
  """
  
  import inspect
  import itertools
  import sys
  
  from ptvsd.common import fmt
  
  
  try:
      import builtins
  except ImportError:
      import __builtin__ as builtins  # noqa
  
  try:
      unicode = builtins.unicode
      bytes = builtins.str
  except AttributeError:
      unicode = builtins.str
      bytes = builtins.bytes
  
  try:
      xrange = builtins.xrange
  except AttributeError:
      xrange = builtins.range
  
  try:
      izip = itertools.izip
  except AttributeError:
      izip = builtins.zip
  
  try:
      reload = builtins.reload
  except AttributeError:
      from importlib import reload  # noqa
  
  try:
      import queue
  except ImportError:
      import Queue as queue  # noqa
  
  
  def force_unicode(s, encoding, errors="strict"):
      """Converts s to Unicode, using the provided encoding. If s is already Unicode,
      it is returned as is.
      """
      return s.decode(encoding, errors) if isinstance(s, bytes) else unicode(s)
  
  
  def force_bytes(s, encoding, errors="strict"):
      """Converts s to bytes, using the provided encoding. If s is already bytes,
      it is returned as is.
  
      If errors="strict" and s is bytes, its encoding is verified by decoding it;
      UnicodeError is raised if it cannot be decoded.
      """
      if isinstance(s, unicode):
          return s.encode(encoding, errors)
      else:
          s = bytes(s)
          if errors == "strict":
              # Return value ignored - invoked solely for verification.
              s.decode(encoding, errors)
          return s
  
  
  def force_str(s, encoding="ascii", errors="strict"):
      """Converts s to str (which is bytes on Python 2, and unicode on Python 3), using
      the provided encoding if necessary. If s is already str, it is returned as is.
  
      If errors="strict", str is bytes, and s is str, its encoding is verified by decoding
      it; UnicodeError is raised if it cannot be decoded.
      """
      return (force_bytes if str is bytes else force_unicode)(s, encoding, errors)
  
  
  def force_ascii(s, errors="strict"):
      """Same as force_bytes(s, "ascii", errors)
      """
      return force_bytes(s, "ascii", errors)
  
  
  def force_utf8(s, errors="strict"):
      """Same as force_bytes(s, "utf8", errors)
      """
      return force_bytes(s, "utf8", errors)
  
  
  def filename(s, errors="strict"):
      """Same as force_unicode(s, sys.getfilesystemencoding(), errors)
      """
      return force_unicode(s, sys.getfilesystemencoding(), errors)
  
  
  def filename_bytes(s, errors="strict"):
      """Same as force_bytes(s, sys.getfilesystemencoding(), errors)
      """
      return force_bytes(s, sys.getfilesystemencoding(), errors)
  
  
  def filename_str(s, errors="strict"):
      """Same as force_str(s, sys.getfilesystemencoding(), errors)
      """
      return force_str(s, sys.getfilesystemencoding(), errors)
  
  
  def nameof(obj, quote=False):
      """Returns the most descriptive name of a Python module, class, or function,
      as a Unicode string
  
      If quote=True, name is quoted with repr().
  
      Best-effort, but guaranteed to not fail - always returns something.
      """
  
      try:
          name = obj.__qualname__
      except Exception:
          try:
              name = obj.__name__
          except Exception:
              # Fall back to raw repr(), and skip quoting.
              try:
                  name = repr(obj)
              except Exception:
                  return "<unknown>"
              else:
                  quote = False
  
      if quote:
          try:
              name = repr(name)
          except Exception:
              pass
  
      return force_unicode(name, "utf-8", "replace")
  
  
  def unicode_repr(obj):
      """Like repr(), but guarantees that the result is Unicode even on Python 2.
      """
      return force_unicode(repr(obj), "ascii")
  
  
  def srcnameof(obj):
      """Returns the most descriptive name of a Python module, class, or function,
      including source information (filename and linenumber), if available.
  
      Best-effort, but guaranteed to not fail - always returns something.
      """
  
      name = nameof(obj, quote=True)
  
      # Get the source information if possible.
      try:
          src_file = filename(inspect.getsourcefile(obj), "replace")
      except Exception:
          pass
      else:
          name += fmt(" (file {0!r}", src_file)
          try:
              _, src_lineno = inspect.getsourcelines(obj)
          except Exception:
              pass
          else:
              name += fmt(", line {0}", src_lineno)
          name += ")"
  
      return name
  