compat.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  2. #
  3. # Modifications made by Cloudera are:
  4. # Copyright (c) 2016 Cloudera, Inc. All rights reserved.
  5. #
  6. # Licensed under the Apache License, Version 2.0 (the "License"). You
  7. # may not use this file except in compliance with the License. A copy of
  8. # the License is located at
  9. #
  10. # http://aws.amazon.com/apache2.0/
  11. #
  12. # or in the "license" file accompanying this file. This file is
  13. # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
  14. # ANY KIND, either express or implied. See the License for the specific
  15. # language governing permissions and limitations under the License.
  16. import copy
  17. import sys
  18. from ccscli.thirdparty import six # noqa
  19. if six.PY3:
  20. from base64 import encodebytes # noqa
  21. from email.utils import formatdate # noqa
  22. from http.client import HTTPResponse # noqa
  23. import locale
  24. from six.moves import http_client
  25. from urllib.parse import urlsplit # noqa
  26. from urllib.parse import urlunsplit # noqa
  27. raw_input = input
  28. class HTTPHeaders(http_client.HTTPMessage):
  29. pass
  30. def get_stdout_text_writer():
  31. return sys.stdout
  32. def ensure_unicode(s, encoding=None, errors=None):
  33. # NOOP in Python 3, because every string is already unicode
  34. return s
  35. def compat_open(filename, mode='r', encoding=None):
  36. """Back-port open() that accepts an encoding argument.
  37. In python3 this uses the built in open() and in python2 this
  38. uses the io.open() function.
  39. If the file is not being opened in binary mode, then we'll
  40. use locale.getpreferredencoding() to find the preferred
  41. encoding.
  42. """
  43. if 'b' not in mode:
  44. encoding = locale.getpreferredencoding()
  45. return open(filename, mode, encoding=encoding)
  46. else:
  47. from base64 import encodestring as encodebytes # noqa
  48. import codecs
  49. from email.message import Message
  50. from email.Utils import formatdate # noqa
  51. from httplib import HTTPResponse # noqa
  52. import io
  53. import locale
  54. from urlparse import urlsplit # noqa
  55. from urlparse import urlunsplit # noqa
  56. raw_input = raw_input
  57. class HTTPHeaders(Message):
  58. # The __iter__ method is not available in python2.x, so we have
  59. # to port the py3 version.
  60. def __iter__(self):
  61. for field, value in self._headers:
  62. yield field
  63. def get_stdout_text_writer():
  64. # In python3, all the sys.stdout/sys.stderr streams are in text
  65. # mode. This means they expect unicode, and will encode the
  66. # unicode automatically before actually writing to stdout/stderr.
  67. # In python2, that's not the case. In order to provide a consistent
  68. # interface, we can create a wrapper around sys.stdout that will take
  69. # unicode, and automatically encode it to the preferred encoding.
  70. # That way consumers can just call get_stdout_text_writer() and write
  71. # unicode to the returned stream. Note that get_stdout_text_writer
  72. # just returns sys.stdout in the PY3 section above because python3
  73. # handles this.
  74. return codecs.getwriter(locale.getpreferredencoding())(sys.stdout)
  75. def ensure_unicode(s, encoding='utf-8', errors='strict'):
  76. if isinstance(s, six.text_type):
  77. return s
  78. return unicode(s, encoding, errors)
  79. def compat_open(filename, mode='r', encoding=None):
  80. # See docstring for compat_open in the PY3 section above.
  81. if 'b' not in mode:
  82. encoding = locale.getpreferredencoding()
  83. return io.open(filename, mode, encoding=encoding)
  84. try:
  85. from collections import OrderedDict
  86. except ImportError:
  87. from ordereddict import OrderedDict # noqa
  88. if sys.version_info[:2] == (2, 6):
  89. import simplejson as json
  90. else:
  91. import json # noqa
  92. @classmethod
  93. def from_dict(cls, d):
  94. new_instance = cls()
  95. for key, value in d.items():
  96. new_instance[key] = value
  97. return new_instance
  98. @classmethod
  99. def from_pairs(cls, pairs):
  100. new_instance = cls()
  101. for key, value in pairs:
  102. new_instance[key] = value
  103. return new_instance
  104. HTTPHeaders.from_dict = from_dict
  105. HTTPHeaders.from_pairs = from_pairs
  106. def copy_kwargs(kwargs):
  107. """
  108. There is a bug in Python versions < 2.6.5 that prevents you from passing
  109. unicode keyword args (#4978). This function takes a dictionary of kwargs and
  110. returns a copy. If you are using Python < 2.6.5, it also encodes the keys to
  111. avoid this bug. Oh, and version_info wasn't a namedtuple back then, either!
  112. """
  113. vi = sys.version_info
  114. if vi[0] == 2 and vi[1] <= 6 and vi[3] < 5:
  115. copy_kwargs = {}
  116. for key in kwargs:
  117. copy_kwargs[key.encode('utf-8')] = kwargs[key]
  118. else:
  119. copy_kwargs = copy.copy(kwargs)
  120. return copy_kwargs
  121. def compat_input(prompt):
  122. """
  123. Cygwin's pty's are based on pipes. Therefore, when it interacts with a Win32
  124. program (such as Win32 python), what that program sees is a pipe instead of
  125. a console. This is important because python buffers pipes, and so on a
  126. pty-based terminal, text will not necessarily appear immediately. In most
  127. cases, this isn't a big deal. But when we're doing an interactive prompt,
  128. the result is that the prompts won't display until we fill the buffer. Since
  129. raw_input does not flush the prompt, we need to manually write and flush it.
  130. See https://github.com/mintty/mintty/issues/56 for more details.
  131. """
  132. sys.stdout.write(prompt)
  133. sys.stdout.flush()
  134. return raw_input()