misc_ops.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import sys
  2. import hashlib
  3. def unicode(text):
  4. if sys.version_info < (3, 0):
  5. if isinstance(text, str):
  6. text = text.decode('utf-8')
  7. import __builtin__
  8. return __builtin__.unicode(text)
  9. elif not isinstance(text, str):
  10. return text.decode('utf-8')
  11. else:
  12. return text
  13. def bytes(text):
  14. """
  15. Convert Unicode text to UTF-8 encoded bytes.
  16. Since Python 2.6+ and Python 3+ have similar but incompatible
  17. signatures, this function unifies the two to keep code sane.
  18. :param text: Unicode text to convert to bytes
  19. :rtype: bytes (Python3), str (Python2.6+)
  20. """
  21. if text is None:
  22. return b''
  23. if sys.version_info < (3, 0):
  24. import __builtin__
  25. return __builtin__.bytes(text)
  26. else:
  27. import builtins
  28. if isinstance(text, builtins.bytes):
  29. # We already have bytes, so do nothing
  30. return text
  31. if isinstance(text, list):
  32. # Convert a list of integers to bytes
  33. return builtins.bytes(text)
  34. else:
  35. # Convert UTF-8 text to bytes
  36. return builtins.bytes(text, encoding='utf-8')
  37. def quote(text):
  38. """
  39. Enclose in quotes and escape internal slashes and double quotes.
  40. :param text: A Unicode or byte string.
  41. """
  42. text = bytes(text)
  43. return b'"' + text.replace(b'\\', b'\\\\').replace(b'"', b'\\"') + b'"'
  44. def num_to_bytes(num):
  45. """
  46. Convert an integer into a four byte sequence.
  47. :param integer num: An integer to convert to its byte representation.
  48. """
  49. bval = b''
  50. bval += bytes(chr(0xFF & (num >> 24)))
  51. bval += bytes(chr(0xFF & (num >> 16)))
  52. bval += bytes(chr(0xFF & (num >> 8)))
  53. bval += bytes(chr(0xFF & (num >> 0)))
  54. return bval
  55. def bytes_to_num(bval):
  56. """
  57. Convert a four byte sequence to an integer.
  58. :param bytes bval: A four byte sequence to turn into an integer.
  59. """
  60. num = 0
  61. num += ord(bval[0] << 24)
  62. num += ord(bval[1] << 16)
  63. num += ord(bval[2] << 8)
  64. num += ord(bval[3])
  65. return num
  66. def XOR(x, y):
  67. """
  68. Return the results of an XOR operation on two equal length byte strings.
  69. :param bytes x: A byte string
  70. :param bytes y: A byte string
  71. :rtype: bytes
  72. """
  73. result = b''
  74. for a, b in zip(x, y):
  75. if sys.version_info < (3, 0):
  76. result += chr((ord(a) ^ ord(b)))
  77. else:
  78. result += bytes([a ^ b])
  79. return result
  80. def hash(name):
  81. """
  82. Return a hash function implementing the given algorithm.
  83. :param name: The name of the hashing algorithm to use.
  84. :type name: string
  85. :rtype: function
  86. """
  87. name = name.lower()
  88. if name.startswith('sha-'):
  89. name = 'sha' + name[4:]
  90. if name in dir(hashlib):
  91. return getattr(hashlib, name)
  92. return None
  93. def hashes():
  94. """
  95. Return a list of available hashing algorithms.
  96. :rtype: list of strings
  97. """
  98. t = []
  99. if 'md5' in dir(hashlib):
  100. t = ['MD5']
  101. if 'md2' in dir(hashlib):
  102. t += ['MD2']
  103. hashes = ['SHA-' + h[3:] for h in dir(hashlib) if h.startswith('sha')]
  104. return t + hashes
  105. def setdefaultencoding(encoding):
  106. """
  107. Set the current default string encoding used by the Unicode implementation.
  108. Actually calls sys.setdefaultencoding under the hood - see the docs for that
  109. for more details. This method exists only as a way to call find/call it
  110. even after it has been 'deleted' when the site module is executed.
  111. :param string encoding: An encoding name, compatible with sys.setdefaultencoding
  112. """
  113. func = getattr(sys, 'setdefaultencoding', None)
  114. if func is None:
  115. import gc
  116. import types
  117. for obj in gc.get_objects():
  118. if (isinstance(obj, types.BuiltinFunctionType)
  119. and obj.__name__ == 'setdefaultencoding'):
  120. func = obj
  121. break
  122. if func is None:
  123. raise RuntimeError("Could not find setdefaultencoding")
  124. sys.setdefaultencoding = func
  125. return func(encoding)
  126. def safedict(data):
  127. if sys.version_info < (2, 7):
  128. safe = {}
  129. for key in data:
  130. safe[key.encode('utf8')] = data[key]
  131. return safe
  132. else:
  133. return data