__init__.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. """
  2. Utility functions
  3. """
  4. import time
  5. from itertools import repeat
  6. from inspect import getargspec
  7. from uuid import UUID, uuid4, _uuid_generate_random
  8. from celery.utils.functional import curry
  9. import operator
  10. try:
  11. import ctypes
  12. except ImportError:
  13. ctypes = None
  14. noop = lambda *args, **kwargs: None
  15. def chunks(it, n):
  16. """Split an iterator into chunks with ``n`` elements each.
  17. Examples
  18. # n == 2
  19. >>> x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 2)
  20. >>> list(x)
  21. [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9], [10]]
  22. # n == 3
  23. >>> x = chunks(iter([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), 3)
  24. >>> list(x)
  25. [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
  26. """
  27. acc = []
  28. for i, item in enumerate(it):
  29. if i and not i % n:
  30. yield acc
  31. acc = []
  32. acc.append(item)
  33. yield acc
  34. def gen_unique_id():
  35. """Generate a unique id, having - hopefully - a very small chance of
  36. collission.
  37. For now this is provided by :func:`uuid.uuid4`.
  38. """
  39. # Workaround for http://bugs.python.org/issue4607
  40. if ctypes and _uuid_generate_random:
  41. buffer = ctypes.create_string_buffer(16)
  42. _uuid_generate_random(buffer)
  43. return str(UUID(bytes=buffer.raw))
  44. return str(uuid4())
  45. def mitemgetter(*keys):
  46. """Like :func:`operator.itemgetter` but returns `None` on missing keys
  47. instead of raising :exc:`KeyError`."""
  48. return lambda dict_: map(dict_.get, keys)
  49. def get_full_cls_name(cls):
  50. """With a class, get its full module and class name."""
  51. return ".".join([cls.__module__,
  52. cls.__name__])
  53. def repeatlast(it):
  54. """Iterate over all elements in the iterator, and when its exhausted
  55. yield the last value infinitely."""
  56. for item in it:
  57. yield item
  58. for item in repeat(item):
  59. yield item
  60. def retry_over_time(fun, catch, args=[], kwargs={}, errback=noop,
  61. max_retries=None, interval_start=2, interval_step=2, interval_max=30):
  62. """Retry the function over and over until max retries is exceeded.
  63. For each retry we sleep a for a while before we try again, this interval
  64. is increased for every retry until the max seconds is reached.
  65. :param fun: The function to try
  66. :param catch: Exceptions to catch, can be either tuple or a single
  67. exception class.
  68. :keyword args: Positional arguments passed on to the function.
  69. :keyword kwargs: Keyword arguments passed on to the function.
  70. :keyword errback: Callback for when an exception in ``catch`` is raised.
  71. The callback must take two arguments: ``exc`` and ``interval``, where
  72. ``exc`` is the exception instance, and ``interval`` is the time in
  73. seconds to sleep next..
  74. :keyword max_retries: Maximum number of retries before we give up.
  75. If this is not set, we will retry forever.
  76. :keyword interval_start: How long (in seconds) we start sleeping between
  77. retries.
  78. :keyword interval_step: By how much the interval is increased for each
  79. retry.
  80. :keyword interval_max: Maximum number of seconds to sleep between retries.
  81. """
  82. retries = 0
  83. interval_range = xrange(interval_start,
  84. interval_max + interval_start,
  85. interval_step)
  86. for interval in repeatlast(interval_range):
  87. try:
  88. retval = fun(*args, **kwargs)
  89. except catch, exc:
  90. if max_retries and retries > max_retries:
  91. raise
  92. errback(exc, interval)
  93. retries += 1
  94. time.sleep(interval)
  95. else:
  96. return retval
  97. def fun_takes_kwargs(fun, kwlist=[]):
  98. """With a function, and a list of keyword arguments, returns arguments
  99. in the list which the function takes.
  100. :param fun: The function to inspect arguments of.
  101. :param kwlist: The list of keyword arguments.
  102. Examples
  103. >>> def foo(self, x, y, logfile=None, loglevel=None):
  104. ... return x * y
  105. >>> fun_takes_kwargs(foo, ["logfile", "loglevel", "task_id"])
  106. ["logfile", "loglevel"]
  107. >>> def foo(self, x, y, **kwargs):
  108. >>> fun_takes_kwargs(foo, ["logfile", "loglevel", "task_id"])
  109. ["logfile", "loglevel", "task_id"]
  110. """
  111. args, _varargs, keywords, _defaults = getargspec(fun)
  112. if keywords != None:
  113. return kwlist
  114. return filter(curry(operator.contains, args), kwlist)