PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/celery/bin/base.py

https://github.com/jcsp/celery
Python | 216 lines | 192 code | 15 blank | 9 comment | 17 complexity | 1751f71051c132ceea70d59904b92ae1 MD5 | raw file
  1. from __future__ import absolute_import
  2. import os
  3. import sys
  4. import warnings
  5. from optparse import OptionParser, make_option as Option
  6. from .. import __version__, Celery
  7. from ..exceptions import CDeprecationWarning, CPendingDeprecationWarning
  8. # always enable DeprecationWarnings, so our users can see them.
  9. for warning in (CDeprecationWarning, CPendingDeprecationWarning):
  10. warnings.simplefilter("once", warning, 0)
  11. class Command(object):
  12. """Base class for command line applications.
  13. :keyword app: The current app.
  14. :keyword get_app: Callable returning the current app if no app provided.
  15. """
  16. _default_broker_url = r'amqp://guest:guest@localhost:5672//'
  17. #: Arg list used in help.
  18. args = ''
  19. #: Application version.
  20. version = __version__
  21. #: If false the parser will raise an exception if positional
  22. #: args are provided.
  23. supports_args = True
  24. #: List of options (without preload options).
  25. option_list = ()
  26. #: List of options to parse before parsing other options.
  27. preload_options = (
  28. Option("--app",
  29. default=None, action="store", dest="app",
  30. help="Name of the app instance to use. "),
  31. Option("-b", "--broker",
  32. default=None, action="store", dest="broker",
  33. help="Broker URL. Default is %s" % (
  34. _default_broker_url, )),
  35. Option("--loader",
  36. default=None, action="store", dest="loader",
  37. help="Name of the loader class to use. "
  38. "Taken from the environment variable CELERY_LOADER, "
  39. "or 'default' if that is not set."),
  40. Option("--config",
  41. default="celeryconfig", action="store",
  42. dest="config_module",
  43. help="Name of the module to read configuration from."),
  44. )
  45. #: Enable if the application should support config from the cmdline.
  46. enable_config_from_cmdline = False
  47. #: Default configuration namespace.
  48. namespace = "celery"
  49. Parser = OptionParser
  50. def __init__(self, app=None, get_app=None):
  51. self.app = app
  52. self.get_app = get_app or self._get_default_app
  53. def run(self, *args, **options):
  54. """This is the body of the command called by :meth:`handle_argv`."""
  55. raise NotImplementedError("subclass responsibility")
  56. def execute_from_commandline(self, argv=None):
  57. """Execute application from command line.
  58. :keyword argv: The list of command line arguments.
  59. Defaults to ``sys.argv``.
  60. """
  61. if argv is None:
  62. argv = list(sys.argv)
  63. argv = self.setup_app_from_commandline(argv)
  64. prog_name = os.path.basename(argv[0])
  65. return self.handle_argv(prog_name, argv[1:])
  66. def usage(self):
  67. """Returns the command-line usage string for this app."""
  68. return "%%prog [options] %s" % (self.args, )
  69. def get_options(self):
  70. """Get supported command line options."""
  71. return self.option_list
  72. def handle_argv(self, prog_name, argv):
  73. """Parses command line arguments from ``argv`` and dispatches
  74. to :meth:`run`.
  75. :param prog_name: The program name (``argv[0]``).
  76. :param argv: Command arguments.
  77. Exits with an error message if :attr:`supports_args` is disabled
  78. and ``argv`` contains positional arguments.
  79. """
  80. options, args = self.parse_options(prog_name, argv)
  81. if not self.supports_args and args:
  82. sys.stderr.write(
  83. "\nUnrecognized command line arguments: %r\n" % (
  84. ", ".join(args), ))
  85. sys.stderr.write("\nTry --help?\n")
  86. sys.exit(1)
  87. return self.run(*args, **vars(options))
  88. def parse_options(self, prog_name, arguments):
  89. """Parse the available options."""
  90. # Don't want to load configuration to just print the version,
  91. # so we handle --version manually here.
  92. if "--version" in arguments:
  93. print(self.version)
  94. sys.exit(0)
  95. parser = self.create_parser(prog_name)
  96. options, args = parser.parse_args(arguments)
  97. return options, args
  98. def create_parser(self, prog_name):
  99. return self.Parser(prog=prog_name,
  100. usage=self.usage(),
  101. version=self.version,
  102. option_list=(self.preload_options +
  103. self.get_options()))
  104. def setup_app_from_commandline(self, argv):
  105. preload_options = self.parse_preload_options(argv)
  106. app = (preload_options.pop("app", None) or
  107. os.environ.get("CELERY_APP") or
  108. self.app)
  109. loader = (preload_options.pop("loader", None) or
  110. os.environ.get("CELERY_LOADER") or
  111. "default")
  112. broker = preload_options.pop("broker", None)
  113. if broker:
  114. os.environ["CELERY_BROKER_URL"] = broker
  115. config_module = preload_options.pop("config_module", None)
  116. if config_module:
  117. os.environ["CELERY_CONFIG_MODULE"] = config_module
  118. if app:
  119. self.app = self.get_cls_by_name(app)
  120. else:
  121. self.app = self.get_app(loader=loader)
  122. if self.enable_config_from_cmdline:
  123. argv = self.process_cmdline_config(argv)
  124. return argv
  125. def get_cls_by_name(self, name):
  126. from ..utils import get_cls_by_name, import_from_cwd
  127. return get_cls_by_name(name, imp=import_from_cwd)
  128. def process_cmdline_config(self, argv):
  129. try:
  130. cargs_start = argv.index('--')
  131. except ValueError:
  132. return argv
  133. argv, cargs = argv[:cargs_start], argv[cargs_start + 1:]
  134. self.app.config_from_cmdline(cargs, namespace=self.namespace)
  135. return argv
  136. def parse_preload_options(self, args):
  137. acc = {}
  138. opts = {}
  139. for opt in self.preload_options:
  140. for t in (opt._long_opts, opt._short_opts):
  141. opts.update(dict(zip(t, [opt.dest] * len(t))))
  142. index = 0
  143. length = len(args)
  144. while index < length:
  145. arg = args[index]
  146. if arg.startswith('--') and '=' in arg:
  147. key, value = arg.split('=', 1)
  148. dest = opts.get(key)
  149. if dest:
  150. acc[dest] = value
  151. elif arg.startswith('-'):
  152. dest = opts.get(arg)
  153. if dest:
  154. acc[dest] = args[index + 1]
  155. index += 1
  156. index += 1
  157. return acc
  158. def _get_default_app(self, *args, **kwargs):
  159. return Celery(*args, **kwargs)
  160. def daemon_options(default_pidfile, default_logfile=None):
  161. return (
  162. Option('-f', '--logfile', default=default_logfile,
  163. action="store", dest="logfile",
  164. help="Path to the logfile"),
  165. Option('--pidfile', default=default_pidfile,
  166. action="store", dest="pidfile",
  167. help="Path to the pidfile."),
  168. Option('--uid', default=None,
  169. action="store", dest="uid",
  170. help="Effective user id to run as when detached."),
  171. Option('--gid', default=None,
  172. action="store", dest="gid",
  173. help="Effective group id to run as when detached."),
  174. Option('--umask', default=0,
  175. action="store", type="int", dest="umask",
  176. help="Umask of the process when detached."),
  177. Option('--workdir', default=None,
  178. action="store", dest="working_directory",
  179. help="Directory to change to when detached."),
  180. )