utils.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # -*- coding: utf-8 -*-
  2. """
  3. celery.app.utils
  4. ~~~~~~~~~~~~~~~~
  5. App utilities: Compat settings, bugreport tool, pickling apps.
  6. """
  7. from __future__ import absolute_import
  8. import os
  9. import platform as _platform
  10. from celery import datastructures
  11. from celery import platforms
  12. from celery.utils.text import pretty
  13. from celery.utils.imports import qualname
  14. from .defaults import find
  15. #: Format used to generate bugreport information.
  16. BUGREPORT_INFO = """
  17. software -> celery:%(celery_v)s kombu:%(kombu_v)s py:%(py_v)s
  18. billiard:%(billiard_v)s %(driver_v)s
  19. platform -> system:%(system)s arch:%(arch)s imp:%(py_i)s
  20. loader -> %(loader)s
  21. settings -> transport:%(transport)s results:%(results)s
  22. %(human_settings)s
  23. """
  24. class Settings(datastructures.ConfigurationView):
  25. """Celery settings object."""
  26. @property
  27. def CELERY_RESULT_BACKEND(self):
  28. return self.first('CELERY_RESULT_BACKEND', 'CELERY_BACKEND')
  29. @property
  30. def BROKER_TRANSPORT(self):
  31. return self.first('BROKER_TRANSPORT',
  32. 'BROKER_BACKEND', 'CARROT_BACKEND')
  33. @property
  34. def BROKER_BACKEND(self):
  35. """Deprecated compat alias to :attr:`BROKER_TRANSPORT`."""
  36. return self.BROKER_TRANSPORT
  37. @property
  38. def BROKER_HOST(self):
  39. return (os.environ.get('CELERY_BROKER_URL') or
  40. self.first('BROKER_URL', 'BROKER_HOST'))
  41. @property
  42. def CELERY_TIMEZONE(self):
  43. # this way we also support django's time zone.
  44. return self.first('CELERY_TIMEZONE', 'TIME_ZONE')
  45. def without_defaults(self):
  46. """Returns the current configuration, but without defaults."""
  47. # the last stash is the default settings, so just skip that
  48. return Settings({}, self._order[:-1])
  49. def find_option(self, name, namespace='celery'):
  50. """Search for option by name.
  51. Will return ``(namespace, option_name, Option)`` tuple, e.g.::
  52. >>> celery.conf.find_option('disable_rate_limits')
  53. ('CELERY', 'DISABLE_RATE_LIMITS',
  54. <Option: type->bool default->False>))
  55. :param name: Name of option, cannot be partial.
  56. :keyword namespace: Preferred namespace (``CELERY`` by default).
  57. """
  58. return find(name, namespace)
  59. def find_value_for_key(self, name, namespace='celery'):
  60. """Shortcut to ``get_by_parts(*find_option(name)[:-1])``"""
  61. return self.get_by_parts(*self.find_option(name, namespace)[:-1])
  62. def get_by_parts(self, *parts):
  63. """Returns the current value for setting specified as a path.
  64. Example::
  65. >>> celery.conf.get_by_parts('CELERY', 'DISABLE_RATE_LIMITS')
  66. False
  67. """
  68. return self['_'.join(filter(None, parts))]
  69. def humanize(self):
  70. """Returns a human readable string showing changes to the
  71. configuration."""
  72. return '\n'.join(
  73. '%s %s' % (key + ':', pretty(value, width=50))
  74. for key, value in self.without_defaults().iteritems())
  75. class AppPickler(object):
  76. """Default application pickler/unpickler."""
  77. def __call__(self, cls, *args):
  78. kwargs = self.build_kwargs(*args)
  79. app = self.construct(cls, **kwargs)
  80. self.prepare(app, **kwargs)
  81. return app
  82. def prepare(self, app, **kwargs):
  83. app.conf.update(kwargs['changes'])
  84. def build_kwargs(self, *args):
  85. return self.build_standard_kwargs(*args)
  86. def build_standard_kwargs(self, main, changes, loader, backend, amqp,
  87. events, log, control, accept_magic_kwargs):
  88. return dict(main=main, loader=loader, backend=backend, amqp=amqp,
  89. changes=changes, events=events, log=log, control=control,
  90. set_as_current=False,
  91. accept_magic_kwargs=accept_magic_kwargs)
  92. def construct(self, cls, **kwargs):
  93. return cls(**kwargs)
  94. def _unpickle_app(cls, pickler, *args):
  95. return pickler()(cls, *args)
  96. def bugreport(app):
  97. """Returns a string containing information useful in bug reports."""
  98. import billiard
  99. import celery
  100. import kombu
  101. try:
  102. conn = app.connection()
  103. driver_v = '%s:%s' % (conn.transport.driver_name,
  104. conn.transport.driver_version())
  105. transport = conn.transport_cls
  106. except Exception:
  107. transport = driver_v = ''
  108. return BUGREPORT_INFO % {
  109. 'system': _platform.system(),
  110. 'arch': ', '.join(filter(None, _platform.architecture())),
  111. 'py_i': platforms.pyimplementation(),
  112. 'celery_v': celery.VERSION_BANNER,
  113. 'kombu_v': kombu.__version__,
  114. 'billiard_v': billiard.__version__,
  115. 'py_v': _platform.python_version(),
  116. 'driver_v': driver_v,
  117. 'transport': transport,
  118. 'results': app.conf.CELERY_RESULT_BACKEND or 'disabled',
  119. 'human_settings': app.conf.humanize(),
  120. 'loader': qualname(app.loader.__class__),
  121. }