compat.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. import array, sys
  2. # Run time aliasing of Python2/3 differences
  3. def htmlescape(s, quote=True):
  4. # this is html.escape reimplemented with cgi.escape,
  5. # so it works for python 2.x, 3.0 and 3.1
  6. import cgi
  7. s = cgi.escape(s, quote)
  8. if quote:
  9. # python 3.2 also replaces the single quotes:
  10. s = s.replace("'", "'")
  11. return s
  12. if sys.version_info[0] < 3:
  13. PY3 = False
  14. def b(s):
  15. return s
  16. import cStringIO as StringIO
  17. StringIO = BytesIO = StringIO.StringIO
  18. callable = callable
  19. integer_types = (int, long)
  20. iteritems = lambda o: o.iteritems()
  21. itervalues = lambda o: o.itervalues()
  22. iterkeys = lambda o: o.iterkeys()
  23. from itertools import izip
  24. long_type = long
  25. next = lambda o: o.next()
  26. import cPickle as pickle
  27. from cPickle import dumps, loads, dump, load
  28. string_type = basestring
  29. text_type = unicode
  30. bytes_type = str
  31. unichr = unichr
  32. from urllib import urlretrieve
  33. import Queue as queue
  34. def byte(num):
  35. return chr(num)
  36. def u(s):
  37. return unicode(s, "unicode_escape")
  38. def with_metaclass(meta, base=object):
  39. class _WhooshBase(base):
  40. __metaclass__ = meta
  41. return _WhooshBase
  42. xrange = xrange
  43. zip_ = zip
  44. def memoryview_(source, offset=None, length=None):
  45. if offset or length:
  46. return buffer(source, offset, length)
  47. else:
  48. return buffer(source)
  49. else:
  50. PY3 = True
  51. import collections
  52. def b(s):
  53. return s.encode("latin-1")
  54. import io
  55. BytesIO = io.BytesIO
  56. callable = lambda o: isinstance(o, collections.Callable)
  57. exec_ = eval("exec")
  58. integer_types = (int,)
  59. iteritems = lambda o: o.items()
  60. itervalues = lambda o: o.values()
  61. iterkeys = lambda o: iter(o.keys())
  62. izip = zip
  63. long_type = int
  64. next = next
  65. import pickle
  66. from pickle import dumps, loads, dump, load
  67. StringIO = io.StringIO
  68. string_type = str
  69. text_type = str
  70. bytes_type = bytes
  71. unichr = chr
  72. from urllib.request import urlretrieve
  73. import queue
  74. def byte(num):
  75. return bytes((num,))
  76. def u(s):
  77. if isinstance(s, bytes):
  78. return s.decode("ascii")
  79. return s
  80. def with_metaclass(meta, base=object):
  81. ns = dict(base=base, meta=meta)
  82. exec_("""class _WhooshBase(base, metaclass=meta):
  83. pass""", ns)
  84. return ns["_WhooshBase"]
  85. xrange = range
  86. zip_ = lambda * args: list(zip(*args))
  87. def memoryview_(source, offset=None, length=None):
  88. mv = memoryview(source)
  89. if offset or length:
  90. return mv[offset:offset + length]
  91. else:
  92. return mv
  93. try:
  94. # for python >= 3.2, avoid DeprecationWarning for cgi.escape
  95. from html import escape as htmlescape
  96. except ImportError:
  97. pass
  98. if hasattr(array.array, "tobytes"):
  99. def array_tobytes(arry):
  100. return arry.tobytes()
  101. def array_frombytes(arry, bs):
  102. return arry.frombytes(bs)
  103. else:
  104. def array_tobytes(arry):
  105. return arry.tostring()
  106. def array_frombytes(arry, bs):
  107. return arry.fromstring(bs)
  108. # Implementations missing from older versions of Python
  109. try:
  110. from itertools import permutations # @UnusedImport
  111. except ImportError:
  112. # Python 2.5
  113. def permutations(iterable, r=None):
  114. pool = tuple(iterable)
  115. n = len(pool)
  116. r = n if r is None else r
  117. if r > n:
  118. return
  119. indices = range(n)
  120. cycles = range(n, n - r, -1)
  121. yield tuple(pool[i] for i in indices[:r])
  122. while n:
  123. for i in reversed(range(r)):
  124. cycles[i] -= 1
  125. if cycles[i] == 0:
  126. indices[i:] = indices[i + 1:] + indices[i:i + 1]
  127. cycles[i] = n - i
  128. else:
  129. j = cycles[i]
  130. indices[i], indices[-j] = indices[-j], indices[i]
  131. yield tuple(pool[i] for i in indices[:r])
  132. break
  133. else:
  134. return
  135. try:
  136. # Python 2.6-2.7
  137. from itertools import izip_longest # @UnusedImport
  138. except ImportError:
  139. try:
  140. # Python 3.0
  141. from itertools import zip_longest as izip_longest # @UnusedImport
  142. except ImportError:
  143. # Python 2.5
  144. from itertools import chain, izip, repeat
  145. def izip_longest(*args, **kwds):
  146. fillvalue = kwds.get('fillvalue')
  147. def sentinel(counter=([fillvalue] * (len(args) - 1)).pop):
  148. yield counter()
  149. fillers = repeat(fillvalue)
  150. iters = [chain(it, sentinel(), fillers) for it in args]
  151. try:
  152. for tup in izip(*iters):
  153. yield tup
  154. except IndexError:
  155. pass
  156. try:
  157. from operator import methodcaller # @UnusedImport
  158. except ImportError:
  159. # Python 2.5
  160. def methodcaller(name, *args, **kwargs):
  161. def caller(obj):
  162. return getattr(obj, name)(*args, **kwargs)
  163. return caller
  164. try:
  165. from abc import abstractmethod # @UnusedImport
  166. except ImportError:
  167. # Python 2.5
  168. def abstractmethod(funcobj):
  169. """A decorator indicating abstract methods.
  170. """
  171. funcobj.__isabstractmethod__ = True
  172. return funcobj