__init__.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import os
  2. import string
  3. import warnings
  4. import importlib
  5. from carrot.utils import rpartition
  6. from celery.utils import get_full_cls_name
  7. from celery.loaders.default import Loader as DefaultLoader
  8. from celery.loaders.djangoapp import Loader as DjangoLoader
  9. _DEFAULT_LOADER_CLASS_NAME = "Loader"
  10. LOADER_ALIASES = {"django": "celery.loaders.djangoapp.Loader",
  11. "default": "celery.loaders.default.Loader"}
  12. _loader_cache = {}
  13. _loader = None
  14. _settings = None
  15. def first_letter(s):
  16. for char in s:
  17. if char in string.letters:
  18. return char
  19. def resolve_loader(loader):
  20. loader = LOADER_ALIASES.get(loader, loader)
  21. loader_module_name, _, loader_cls_name = rpartition(loader, ".")
  22. if first_letter(loader_cls_name) not in string.uppercase:
  23. warnings.warn(DeprecationWarning(
  24. "CELERY_LOADER now needs loader class name, e.g. %s.%s" % (
  25. loader, _DEFAULT_LOADER_CLASS_NAME)))
  26. return loader, _DEFAULT_LOADER_CLASS_NAME
  27. return loader_module_name, loader_cls_name
  28. def _get_loader_cls(loader):
  29. loader_module_name, loader_cls_name = resolve_loader(loader)
  30. loader_module = importlib.import_module(loader_module_name)
  31. return getattr(loader_module, loader_cls_name)
  32. def get_loader_cls(loader):
  33. """Get loader class by name/alias"""
  34. if loader not in _loader_cache:
  35. _loader_cache[loader] = _get_loader_cls(loader)
  36. return _loader_cache[loader]
  37. def detect_loader():
  38. loader = os.environ.get("CELERY_LOADER")
  39. if loader:
  40. return get_loader_cls(loader)
  41. loader = _detect_loader()
  42. os.environ["CELERY_LOADER"] = get_full_cls_name(loader)
  43. return loader
  44. def _detect_loader(): # pragma: no cover
  45. from django.conf import settings
  46. if settings.configured:
  47. return DjangoLoader
  48. try:
  49. # A settings module may be defined, but Django didn't attempt to
  50. # load it yet. As an alternative to calling the private _setup(),
  51. # we could also check whether DJANGO_SETTINGS_MODULE is set.
  52. settings._setup()
  53. except ImportError:
  54. if not callable(getattr(os, "fork", None)):
  55. # Platform doesn't support fork()
  56. # XXX On systems without fork, multiprocessing seems to be
  57. # launching the processes in some other way which does
  58. # not copy the memory of the parent process. This means
  59. # any configured env might be lost. This is a hack to make
  60. # it work on Windows.
  61. # A better way might be to use os.environ to set the currently
  62. # used configuration method so to propogate it to the "child"
  63. # processes. But this has to be experimented with.
  64. # [asksol/heyman]
  65. from django.core.management import setup_environ
  66. try:
  67. settings_mod = os.environ.get("DJANGO_SETTINGS_MODULE",
  68. "settings")
  69. project_settings = __import__(settings_mod, {}, {}, [''])
  70. setup_environ(project_settings)
  71. return DjangoLoader
  72. except ImportError:
  73. pass
  74. else:
  75. return DjangoLoader
  76. return DefaultLoader
  77. def current_loader():
  78. """Detect and return the current loader."""
  79. global _loader
  80. if _loader is None:
  81. _loader = detect_loader()()
  82. return _loader
  83. def load_settings():
  84. """Load the global settings object."""
  85. global _settings
  86. if _settings is None:
  87. _settings = current_loader().conf
  88. return _settings