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