test_loaders.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. from __future__ import absolute_import, unicode_literals
  2. import os
  3. import sys
  4. import warnings
  5. import pytest
  6. from case import Mock, mock, patch
  7. from celery import loaders
  8. from celery.exceptions import NotConfigured
  9. from celery.five import bytes_if_py2
  10. from celery.loaders import base, default
  11. from celery.loaders.app import AppLoader
  12. from celery.utils.imports import NotAPackage
  13. class DummyLoader(base.BaseLoader):
  14. def read_configuration(self):
  15. return {'foo': 'bar', 'imports': ('os', 'sys')}
  16. class test_loaders:
  17. def test_get_loader_cls(self):
  18. assert loaders.get_loader_cls('default') is default.Loader
  19. class test_LoaderBase:
  20. message_options = {'subject': 'Subject',
  21. 'body': 'Body',
  22. 'sender': 'x@x.com',
  23. 'to': 'y@x.com'}
  24. server_options = {'host': 'smtp.x.com',
  25. 'port': 1234,
  26. 'user': 'x',
  27. 'password': 'qwerty',
  28. 'timeout': 3}
  29. def setup(self):
  30. self.loader = DummyLoader(app=self.app)
  31. def test_handlers_pass(self):
  32. self.loader.on_task_init('foo.task', 'feedface-cafebabe')
  33. self.loader.on_worker_init()
  34. def test_now(self):
  35. assert self.loader.now(utc=True)
  36. assert self.loader.now(utc=False)
  37. def test_read_configuration_no_env(self):
  38. assert base.BaseLoader(app=self.app).read_configuration(
  39. 'FOO_X_S_WE_WQ_Q_WE') is None
  40. def test_autodiscovery(self):
  41. with patch('celery.loaders.base.autodiscover_tasks') as auto:
  42. auto.return_value = [Mock()]
  43. auto.return_value[0].__name__ = 'moo'
  44. self.loader.autodiscover_tasks(['A', 'B'])
  45. assert 'moo' in self.loader.task_modules
  46. self.loader.task_modules.discard('moo')
  47. def test_import_task_module(self):
  48. assert sys == self.loader.import_task_module('sys')
  49. def test_init_worker_process(self):
  50. self.loader.on_worker_process_init()
  51. m = self.loader.on_worker_process_init = Mock()
  52. self.loader.init_worker_process()
  53. m.assert_called_with()
  54. def test_config_from_object_module(self):
  55. self.loader.import_from_cwd = Mock()
  56. self.loader.config_from_object('module_name')
  57. self.loader.import_from_cwd.assert_called_with('module_name')
  58. def test_conf_property(self):
  59. assert self.loader.conf['foo'] == 'bar'
  60. assert self.loader._conf['foo'] == 'bar'
  61. assert self.loader.conf['foo'] == 'bar'
  62. def test_import_default_modules(self):
  63. def modnames(l):
  64. return [m.__name__ for m in l]
  65. self.app.conf.imports = ('os', 'sys')
  66. assert (sorted(modnames(self.loader.import_default_modules())) ==
  67. sorted(modnames([os, sys])))
  68. def test_import_default_modules_with_exception(self):
  69. """ Make sure exceptions are not silenced since this step is prior to
  70. setup logging. """
  71. def trigger_exception(**kwargs):
  72. raise ImportError('Dummy ImportError')
  73. from celery.signals import import_modules
  74. x = import_modules.connect(trigger_exception)
  75. self.app.conf.imports = ('os', 'sys')
  76. with pytest.raises(ImportError):
  77. self.loader.import_default_modules()
  78. import_modules.disconnect(x)
  79. def test_import_from_cwd_custom_imp(self):
  80. imp = Mock(name='imp')
  81. self.loader.import_from_cwd('foo', imp=imp)
  82. imp.assert_called()
  83. def test_cmdline_config_ValueError(self):
  84. with pytest.raises(ValueError):
  85. self.loader.cmdline_config_parser(['broker.port=foobar'])
  86. class test_DefaultLoader:
  87. @patch('celery.loaders.base.find_module')
  88. def test_read_configuration_not_a_package(self, find_module):
  89. find_module.side_effect = NotAPackage()
  90. l = default.Loader(app=self.app)
  91. with pytest.raises(NotAPackage):
  92. l.read_configuration(fail_silently=False)
  93. @patch('celery.loaders.base.find_module')
  94. @mock.environ('CELERY_CONFIG_MODULE', 'celeryconfig.py')
  95. def test_read_configuration_py_in_name(self, find_module):
  96. find_module.side_effect = NotAPackage()
  97. l = default.Loader(app=self.app)
  98. with pytest.raises(NotAPackage):
  99. l.read_configuration(fail_silently=False)
  100. @patch('celery.loaders.base.find_module')
  101. def test_read_configuration_importerror(self, find_module):
  102. default.C_WNOCONF = True
  103. find_module.side_effect = ImportError()
  104. l = default.Loader(app=self.app)
  105. with pytest.warns(NotConfigured):
  106. l.read_configuration(fail_silently=True)
  107. default.C_WNOCONF = False
  108. l.read_configuration(fail_silently=True)
  109. def test_read_configuration(self):
  110. from types import ModuleType
  111. class ConfigModule(ModuleType):
  112. pass
  113. configname = os.environ.get('CELERY_CONFIG_MODULE') or 'celeryconfig'
  114. celeryconfig = ConfigModule(bytes_if_py2(configname))
  115. celeryconfig.imports = ('os', 'sys')
  116. prevconfig = sys.modules.get(configname)
  117. sys.modules[configname] = celeryconfig
  118. try:
  119. l = default.Loader(app=self.app)
  120. l.find_module = Mock(name='find_module')
  121. settings = l.read_configuration(fail_silently=False)
  122. assert settings.imports == ('os', 'sys')
  123. settings = l.read_configuration(fail_silently=False)
  124. assert settings.imports == ('os', 'sys')
  125. l.on_worker_init()
  126. finally:
  127. if prevconfig:
  128. sys.modules[configname] = prevconfig
  129. def test_read_configuration_ImportError(self):
  130. sentinel = object()
  131. prev, os.environ['CELERY_CONFIG_MODULE'] = (
  132. os.environ.get('CELERY_CONFIG_MODULE', sentinel), 'daweqew.dweqw',
  133. )
  134. try:
  135. l = default.Loader(app=self.app)
  136. with pytest.raises(ImportError):
  137. l.read_configuration(fail_silently=False)
  138. l.read_configuration(fail_silently=True)
  139. finally:
  140. if prev is not sentinel:
  141. os.environ['CELERY_CONFIG_MODULE'] = prev
  142. else:
  143. os.environ.pop('CELERY_CONFIG_MODULE', None)
  144. def test_import_from_cwd(self):
  145. l = default.Loader(app=self.app)
  146. old_path = list(sys.path)
  147. try:
  148. sys.path.remove(os.getcwd())
  149. except ValueError:
  150. pass
  151. celery = sys.modules.pop('celery', None)
  152. sys.modules.pop('celery.local', None)
  153. try:
  154. assert l.import_from_cwd('celery')
  155. sys.modules.pop('celery', None)
  156. sys.modules.pop('celery.local', None)
  157. sys.path.insert(0, os.getcwd())
  158. assert l.import_from_cwd('celery')
  159. finally:
  160. sys.path = old_path
  161. sys.modules['celery'] = celery
  162. def test_unconfigured_settings(self):
  163. context_executed = [False]
  164. class _Loader(default.Loader):
  165. def find_module(self, name):
  166. raise ImportError(name)
  167. with warnings.catch_warnings(record=True):
  168. l = _Loader(app=self.app)
  169. assert not l.configured
  170. context_executed[0] = True
  171. assert context_executed[0]
  172. class test_AppLoader:
  173. def setup(self):
  174. self.loader = AppLoader(app=self.app)
  175. def test_on_worker_init(self):
  176. self.app.conf.imports = ('subprocess',)
  177. sys.modules.pop('subprocess', None)
  178. self.loader.init_worker()
  179. assert 'subprocess' in sys.modules
  180. class test_autodiscovery:
  181. def test_autodiscover_tasks(self):
  182. base._RACE_PROTECTION = True
  183. try:
  184. base.autodiscover_tasks(['foo'])
  185. finally:
  186. base._RACE_PROTECTION = False
  187. with patch('celery.loaders.base.find_related_module') as frm:
  188. base.autodiscover_tasks(['foo'])
  189. frm.assert_called()
  190. def test_find_related_module(self):
  191. with patch('importlib.import_module') as imp:
  192. imp.return_value = Mock()
  193. imp.return_value.__path__ = 'foo'
  194. assert base.find_related_module('bar', 'tasks').__path__ == 'foo'
  195. imp.assert_any_call('bar')
  196. imp.assert_any_call('bar.tasks')
  197. imp.reset_mock()
  198. assert base.find_related_module('bar', None).__path__ == 'foo'
  199. imp.assert_called_once_with('bar')
  200. imp.side_effect = ImportError()
  201. with pytest.raises(ImportError):
  202. base.find_related_module('bar', 'tasks')
  203. assert base.find_related_module('bar.foo', 'tasks') is None