compat.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. from __future__ import generators
  2. ############## urlparse.parse_qsl ###########################################
  3. try:
  4. from urlparse import parse_qsl
  5. except ImportError:
  6. from cgi import parse_qsl
  7. ############## __builtin__.all ##############################################
  8. try:
  9. all([True])
  10. all = all
  11. except NameError:
  12. def all(iterable):
  13. for item in iterable:
  14. if not item:
  15. return False
  16. return True
  17. ############## __builtin__.any ##############################################
  18. try:
  19. any([True])
  20. any = any
  21. except NameError:
  22. def any(iterable):
  23. for item in iterable:
  24. if item:
  25. return True
  26. return False
  27. ############## collections.OrderedDict ######################################
  28. import weakref
  29. try:
  30. from collections import MutableMapping
  31. except ImportError:
  32. from UserDict import DictMixin as MutableMapping
  33. from itertools import imap as _imap
  34. from operator import eq as _eq
  35. class _Link(object):
  36. """Doubly linked list."""
  37. __slots__ = 'prev', 'next', 'key', '__weakref__'
  38. class OrderedDict(dict, MutableMapping):
  39. """Dictionary that remembers insertion order"""
  40. # An inherited dict maps keys to values.
  41. # The inherited dict provides __getitem__, __len__, __contains__, and get.
  42. # The remaining methods are order-aware.
  43. # Big-O running times for all methods are the same as for regular
  44. # dictionaries.
  45. # The internal self.__map dictionary maps keys to links in a doubly
  46. # linked list.
  47. # The circular doubly linked list starts and ends with a sentinel element.
  48. # The sentinel element never gets deleted (this simplifies the algorithm).
  49. # The prev/next links are weakref proxies (to prevent circular
  50. # references).
  51. # Individual links are kept alive by the hard reference in self.__map.
  52. # Those hard references disappear when a key is deleted from
  53. # an OrderedDict.
  54. __marker = object()
  55. def __init__(self, *args, **kwds):
  56. """Initialize an ordered dictionary.
  57. Signature is the same as for regular dictionaries, but keyword
  58. arguments are not recommended because their insertion order is
  59. arbitrary.
  60. """
  61. if len(args) > 1:
  62. raise TypeError("expected at most 1 arguments, got %d" % (
  63. len(args)))
  64. try:
  65. self.__root
  66. except AttributeError:
  67. # sentinel node for the doubly linked list
  68. self.__root = root = _Link()
  69. root.prev = root.next = root
  70. self.__map = {}
  71. self.update(*args, **kwds)
  72. def clear(self):
  73. "od.clear() -> None. Remove all items from od."
  74. root = self.__root
  75. root.prev = root.next = root
  76. self.__map.clear()
  77. dict.clear(self)
  78. def __setitem__(self, key, value):
  79. "od.__setitem__(i, y) <==> od[i]=y"
  80. # Setting a new item creates a new link which goes at the end of the
  81. # linked list, and the inherited dictionary is updated with the new
  82. # key/value pair.
  83. if key not in self:
  84. self.__map[key] = link = _Link()
  85. root = self.__root
  86. last = root.prev
  87. link.prev, link.next, link.key = last, root, key
  88. last.next = root.prev = weakref.proxy(link)
  89. dict.__setitem__(self, key, value)
  90. def __delitem__(self, key):
  91. """od.__delitem__(y) <==> del od[y]"""
  92. # Deleting an existing item uses self.__map to find the
  93. # link which is then removed by updating the links in the
  94. # predecessor and successor nodes.
  95. dict.__delitem__(self, key)
  96. link = self.__map.pop(key)
  97. link.prev.next = link.next
  98. link.next.prev = link.prev
  99. def __iter__(self):
  100. """od.__iter__() <==> iter(od)"""
  101. # Traverse the linked list in order.
  102. root = self.__root
  103. curr = root.next
  104. while curr is not root:
  105. yield curr.key
  106. curr = curr.next
  107. def __reversed__(self):
  108. """od.__reversed__() <==> reversed(od)"""
  109. # Traverse the linked list in reverse order.
  110. root = self.__root
  111. curr = root.prev
  112. while curr is not root:
  113. yield curr.key
  114. curr = curr.prev
  115. def __reduce__(self):
  116. """Return state information for pickling"""
  117. items = [[k, self[k]] for k in self]
  118. tmp = self.__map, self.__root
  119. del(self.__map, self.__root)
  120. inst_dict = vars(self).copy()
  121. self.__map, self.__root = tmp
  122. if inst_dict:
  123. return (self.__class__, (items,), inst_dict)
  124. return self.__class__, (items,)
  125. def setdefault(self, key, default=None):
  126. try:
  127. return self[key]
  128. except KeyError:
  129. self[key] = default
  130. return default
  131. def update(self, other=(), **kwds):
  132. if isinstance(other, dict):
  133. for key in other:
  134. self[key] = other[key]
  135. elif hasattr(other, "keys"):
  136. for key in other.keys():
  137. self[key] = other[key]
  138. else:
  139. for key, value in other:
  140. self[key] = value
  141. for key, value in kwds.items():
  142. self[key] = value
  143. def pop(self, key, default=__marker):
  144. try:
  145. value = self[key]
  146. except KeyError:
  147. if default is self.__marker:
  148. raise
  149. return default
  150. else:
  151. del self[key]
  152. return value
  153. def values(self):
  154. return [self[key] for key in self]
  155. def items(self):
  156. return [(key, self[key]) for key in self]
  157. def itervalues(self):
  158. for key in self:
  159. yield self[key]
  160. def iteritems(self):
  161. for key in self:
  162. yield (key, self[key])
  163. def iterkeys(self):
  164. return iter(self)
  165. def keys(self):
  166. return list(self)
  167. def popitem(self, last=True):
  168. """od.popitem() -> (k, v)
  169. Return and remove a (key, value) pair.
  170. Pairs are returned in LIFO order if last is true or FIFO
  171. order if false.
  172. """
  173. if not self:
  174. raise KeyError('dictionary is empty')
  175. key = (last and reversed(self) or iter(self)).next()
  176. value = self.pop(key)
  177. return key, value
  178. def __repr__(self):
  179. "od.__repr__() <==> repr(od)"
  180. if not self:
  181. return '%s()' % (self.__class__.__name__,)
  182. return '%s(%r)' % (self.__class__.__name__, self.items())
  183. def copy(self):
  184. "od.copy() -> a shallow copy of od"
  185. return self.__class__(self)
  186. @classmethod
  187. def fromkeys(cls, iterable, value=None):
  188. """OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
  189. and values equal to v (which defaults to None)."""
  190. d = cls()
  191. for key in iterable:
  192. d[key] = value
  193. return d
  194. def __eq__(self, other):
  195. """od.__eq__(y) <==> od==y. Comparison to another OD is
  196. order-sensitive while comparison to a regular mapping
  197. is order-insensitive."""
  198. if isinstance(other, OrderedDict):
  199. return len(self) == len(other) and \
  200. all(_imap(_eq, self.iteritems(), other.iteritems()))
  201. return dict.__eq__(self, other)
  202. def __ne__(self, other):
  203. return not (self == other)
  204. ############## collections.defaultdict ######################################
  205. try:
  206. from collections import defaultdict
  207. except ImportError:
  208. # Written by Jason Kirtland, taken from Python Cookbook:
  209. # <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/523034>
  210. class defaultdict(dict):
  211. def __init__(self, default_factory=None, *args, **kwargs):
  212. dict.__init__(self, *args, **kwargs)
  213. self.default_factory = default_factory
  214. def __getitem__(self, key):
  215. try:
  216. return dict.__getitem__(self, key)
  217. except KeyError:
  218. return self.__missing__(key)
  219. def __missing__(self, key):
  220. if self.default_factory is None:
  221. raise KeyError(key)
  222. self[key] = value = self.default_factory()
  223. return value
  224. def __reduce__(self):
  225. f = self.default_factory
  226. args = f is None and tuple() or f
  227. return type(self), args, None, None, self.iteritems()
  228. def copy(self):
  229. return self.__copy__()
  230. def __copy__(self):
  231. return type(self)(self.default_factory, self)
  232. def __deepcopy__(self):
  233. import copy
  234. return type(self)(self.default_factory,
  235. copy.deepcopy(self.items()))
  236. def __repr__(self):
  237. return "defaultdict(%s, %s)" % (self.default_factory,
  238. dict.__repr__(self))
  239. import collections
  240. collections.defaultdict = defaultdict # Pickle needs this.
  241. ############## logging.LoggerAdapter ########################################
  242. import logging
  243. import multiprocessing
  244. import sys
  245. class _CompatLoggerAdapter(object):
  246. def __init__(self, logger, extra):
  247. self.logger = logger
  248. self.extra = extra
  249. def setLevel(self, level):
  250. self.logger.level = logging._checkLevel(level)
  251. def process(self, msg, kwargs):
  252. kwargs["extra"] = self.extra
  253. return msg, kwargs
  254. def debug(self, msg, *args, **kwargs):
  255. self.log(logging.DEBUG, msg, args, **kwargs)
  256. def info(self, msg, *args, **kwargs):
  257. self.log(logging.INFO, msg, args, **kwargs)
  258. def warning(self, msg, *args, **kwargs):
  259. self.log(logging.WARNING, msg, args, **kwargs)
  260. warn = warning
  261. def error(self, msg, *args, **kwargs):
  262. self.log(logging.ERROR, msg, args, **kwargs)
  263. def exception(self, msg, *args, **kwargs):
  264. kwargs.setdefault("exc_info", 1)
  265. self.error(msg, *args, **kwargs)
  266. def critical(self, msg, *args, **kwargs):
  267. self.log(logging.CRITICAL, msg, args, **kwargs)
  268. fatal = critical
  269. def log(self, level, msg, args, **kwargs):
  270. if self.logger.isEnabledFor(level):
  271. msg, kwargs = self.process(msg, kwargs)
  272. self._log(level, msg, args, **kwargs)
  273. def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
  274. func=None, extra=None):
  275. rv = logging.LogRecord(name, level, fn, lno,
  276. msg, args, exc_info, func)
  277. if extra is not None:
  278. for key, value in extra.items():
  279. if key in ("message", "asctime") or key in rv.__dict__:
  280. raise KeyError(
  281. "Attempt to override %r in LogRecord" % key)
  282. rv.__dict__[key] = value
  283. rv.processName = multiprocessing.current_process()._name
  284. return rv
  285. def _log(self, level, msg, args, exc_info=None, extra=None):
  286. defcaller = "(unknown file)", 0, "(unknown function)"
  287. if logging._srcfile:
  288. # IronPython doesn't track Python frames, so findCaller
  289. # throws an exception on some versions of IronPython.
  290. # We trap it here so that IronPython can use logging.
  291. try:
  292. fn, lno, func = self.logger.findCaller()
  293. except ValueError:
  294. fn, lno, func = defcaller
  295. else:
  296. fn, lno, func = defcaller
  297. if exc_info:
  298. if not isinstance(exc_info, tuple):
  299. exc_info = sys.exc_info()
  300. record = self.makeRecord(self.logger.name, level, fn, lno, msg,
  301. args, exc_info, func, extra)
  302. self.logger.handle(record)
  303. def isEnabledFor(self, level):
  304. return self.logger.isEnabledFor(level)
  305. def addHandler(self, hdlr):
  306. self.logger.addHandler(hdlr)
  307. def removeHandler(self, hdlr):
  308. self.logger.removeHandler(hdlr)
  309. try:
  310. from logging import LoggerAdapter
  311. except ImportError:
  312. LoggerAdapter = _CompatLoggerAdapter
  313. ############## itertools.izip_longest #######################################
  314. try:
  315. from itertools import izip_longest
  316. except ImportError:
  317. import itertools
  318. def izip_longest(*args, **kwds):
  319. fillvalue = kwds.get("fillvalue")
  320. def sentinel(counter=([fillvalue] * (len(args) - 1)).pop):
  321. yield counter() # yields the fillvalue, or raises IndexError
  322. fillers = itertools.repeat(fillvalue)
  323. iters = [itertools.chain(it, sentinel(), fillers)
  324. for it in args]
  325. try:
  326. for tup in itertools.izip(*iters):
  327. yield tup
  328. except IndexError:
  329. pass
  330. ############## itertools.chain.from_iterable ################################
  331. from itertools import chain
  332. def _compat_chain_from_iterable(iterables):
  333. for it in iterables:
  334. for element in it:
  335. yield element
  336. try:
  337. chain_from_iterable = getattr(chain, "from_iterable")
  338. except AttributeError:
  339. chain_from_iterable = _compat_chain_from_iterable