__init__.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.utils
  4. ~~~~~~~~~~~~
  5. Utility functions.
  6. :copyright: (c) 2009 - 2012 by Ask Solem.
  7. :license: BSD, see LICENSE for more details.
  8. """
  9. from __future__ import absolute_import
  10. from __future__ import with_statement
  11. import operator
  12. import sys
  13. import threading
  14. import traceback
  15. import warnings
  16. from functools import partial, wraps
  17. from inspect import getargspec
  18. from pprint import pprint
  19. from celery.exceptions import CPendingDeprecationWarning, CDeprecationWarning
  20. from .compat import StringIO
  21. from .functional import noop
  22. PENDING_DEPRECATION_FMT = """
  23. %(description)s is scheduled for deprecation in \
  24. version %(deprecation)s and removal in version v%(removal)s. \
  25. %(alternative)s
  26. """
  27. DEPRECATION_FMT = """
  28. %(description)s is deprecated and scheduled for removal in
  29. version %(removal)s. %(alternative)s
  30. """
  31. def warn_deprecated(description=None, deprecation=None, removal=None,
  32. alternative=None):
  33. ctx = {"description": description,
  34. "deprecation": deprecation, "removal": removal,
  35. "alternative": alternative}
  36. if deprecation is not None:
  37. w = CPendingDeprecationWarning(PENDING_DEPRECATION_FMT % ctx)
  38. else:
  39. w = CDeprecationWarning(DEPRECATION_FMT % ctx)
  40. warnings.warn(w)
  41. def deprecated(description=None, deprecation=None, removal=None,
  42. alternative=None):
  43. def _inner(fun):
  44. @wraps(fun)
  45. def __inner(*args, **kwargs):
  46. from .imports import qualname
  47. warn_deprecated(description=description or qualname(fun),
  48. deprecation=deprecation,
  49. removal=removal,
  50. alternative=alternative)
  51. return fun(*args, **kwargs)
  52. return __inner
  53. return _inner
  54. def lpmerge(L, R):
  55. """In place left precedent dictionary merge.
  56. Keeps values from `L`, if the value in `R` is :const:`None`."""
  57. set = L.__setitem__
  58. [set(k, v) for k, v in R.iteritems() if v is not None]
  59. return L
  60. def is_iterable(obj):
  61. try:
  62. iter(obj)
  63. except TypeError:
  64. return False
  65. return True
  66. def fun_takes_kwargs(fun, kwlist=[]):
  67. """With a function, and a list of keyword arguments, returns arguments
  68. in the list which the function takes.
  69. If the object has an `argspec` attribute that is used instead
  70. of using the :meth:`inspect.getargspec` introspection.
  71. :param fun: The function to inspect arguments of.
  72. :param kwlist: The list of keyword arguments.
  73. Examples
  74. >>> def foo(self, x, y, logfile=None, loglevel=None):
  75. ... return x * y
  76. >>> fun_takes_kwargs(foo, ["logfile", "loglevel", "task_id"])
  77. ["logfile", "loglevel"]
  78. >>> def foo(self, x, y, **kwargs):
  79. >>> fun_takes_kwargs(foo, ["logfile", "loglevel", "task_id"])
  80. ["logfile", "loglevel", "task_id"]
  81. """
  82. argspec = getattr(fun, "argspec", getargspec(fun))
  83. args, _varargs, keywords, _defaults = argspec
  84. if keywords != None:
  85. return kwlist
  86. return filter(partial(operator.contains, args), kwlist)
  87. def isatty(fh):
  88. # Fixes bug with mod_wsgi:
  89. # mod_wsgi.Log object has no attribute isatty.
  90. return getattr(fh, "isatty", None) and fh.isatty()
  91. def cry(): # pragma: no cover
  92. """Return stacktrace of all active threads.
  93. From https://gist.github.com/737056
  94. """
  95. tmap = {}
  96. main_thread = None
  97. # get a map of threads by their ID so we can print their names
  98. # during the traceback dump
  99. for t in threading.enumerate():
  100. if getattr(t, "ident", None):
  101. tmap[t.ident] = t
  102. else:
  103. main_thread = t
  104. out = StringIO()
  105. sep = "=" * 49 + "\n"
  106. for tid, frame in sys._current_frames().iteritems():
  107. thread = tmap.get(tid, main_thread)
  108. if not thread:
  109. # skip old junk (left-overs from a fork)
  110. continue
  111. out.write("%s\n" % (thread.getName(), ))
  112. out.write(sep)
  113. traceback.print_stack(frame, file=out)
  114. out.write(sep)
  115. out.write("LOCAL VARIABLES\n")
  116. out.write(sep)
  117. pprint(frame.f_locals, stream=out)
  118. out.write("\n\n")
  119. return out.getvalue()
  120. def maybe_reraise():
  121. """Reraise if an exception is currently being handled, or return
  122. otherwise."""
  123. exc_info = sys.exc_info()
  124. try:
  125. if exc_info[2]:
  126. raise exc_info[0], exc_info[1], exc_info[2]
  127. finally:
  128. # see http://docs.python.org/library/sys.html#sys.exc_info
  129. del(exc_info)
  130. # - XXX Compat
  131. from .log import LOG_LEVELS # noqa
  132. from .imports import ( # noqa
  133. qualname as get_full_cls_name, symbol_by_name as get_cls_by_name,
  134. instantiate, import_from_cwd
  135. )
  136. from .functional import chunks, noop # noqa
  137. from kombu.utils import cached_property, kwdict, uuid # noqa
  138. gen_unique_id = uuid