guide.rst 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. .. _internals-guide:
  2. ================================
  3. Contributors Guide to the Code
  4. ================================
  5. .. contents::
  6. :local:
  7. Philosophy
  8. ==========
  9. The API>RCP Precedence Rule
  10. ---------------------------
  11. - The API is more important than Readability
  12. - Readability is more important than Convention
  13. - Convention is more important than Performance
  14. - ...unless the code is a proven hotspot.
  15. More important than anything else is the end-user API.
  16. Conventions must step aside, and any suffering is always alleviated
  17. if the end result is a better API.
  18. Conventions and Idioms Used
  19. ===========================
  20. Classes
  21. -------
  22. Naming
  23. ~~~~~~
  24. - Follows :pep:`8`.
  25. - Class names must be CamelCase.
  26. - but not if they are verbs, verbs shall be lower_case:
  27. .. code-block:: python
  28. class TestFrobulator(Case): # BAD
  29. ...
  30. class test_Frobulator(Case): # GOOD
  31. ...
  32. class CreateContext(object): # BAD
  33. ...
  34. class create_context(object): # GOOD
  35. ...
  36. .. note::
  37. Sometimes it makes sense to have a class mask as a function,
  38. and there is precedence for this in the stdlib (e.g.
  39. :class:`~contextlib.contextmanager`). Celery examples include
  40. :class:`~celery.task.sets.subtask`, :class:`~celery.task.chords.chord`,
  41. ``inspect``, :class:`~kombu.utils.functional.promise` and more..
  42. - Factory functions and methods must be CamelCase (excluding verbs):
  43. .. code-block:: python
  44. class Celery(object):
  45. def consumer_factory(self): # BAD
  46. ...
  47. def Consumer(self): # GOOD
  48. Default values
  49. ~~~~~~~~~~~~~~
  50. Class attributes serve as default values for the instance,
  51. as this means that they can be set by either instantiation or inheritance.
  52. **Example:**
  53. .. code-block:: python
  54. class Producer(object):
  55. active = True
  56. serializer = "json"
  57. def __init__(self, serializer=None):
  58. self.serializer = serializer or None
  59. # must check for None when value can be false-y
  60. self.active = active if active is not None else self.active
  61. A subclass can change the default value:
  62. .. code-block:: python
  63. TaskProducer(Producer):
  64. serializer = "pickle"
  65. and the value can be set at instantiation:
  66. .. code-block:: python
  67. >>> producer = TaskProducer(serializer="msgpack")
  68. Exceptions
  69. ~~~~~~~~~~
  70. Custom exceptions raised by an objects methods and properties
  71. should be available as an attribute and documented in the
  72. method/property that throw.
  73. This way a user doesn't have to find out where to import the
  74. exception from, but rather use ``help(obj)`` and access
  75. the exception class from the instance directly.
  76. **Example**:
  77. .. code-block:: python
  78. class Empty(Exception):
  79. pass
  80. class Queue(object):
  81. Empty = Empty
  82. def get(self):
  83. """Get the next item from the queue.
  84. :raises Queue.Empty: if there are no more items left.
  85. """
  86. try:
  87. return self.queue.popleft()
  88. except IndexError:
  89. raise self.Empty()
  90. Composites
  91. ~~~~~~~~~~
  92. Similarly to exceptions, composite classes used should be override-able by
  93. inheritance and/or instantiation. Common sense should be used when
  94. selecting what classes to include, but often it's better to add one
  95. too many as predicting what users need to override is hard (this has
  96. saved us from many a monkey patch).
  97. **Example**:
  98. .. code-block:: python
  99. class Worker(object):
  100. Consumer = Consumer
  101. def __init__(self, connection, consumer_cls=None):
  102. self.Consumer = consumer_cls or self.Consumer
  103. def do_work(self):
  104. with self.Consumer(self.connection) as consumer:
  105. self.connection.drain_events()
  106. Applications vs. "single mode"
  107. ==============================
  108. In the beginning Celery was developed for Django, simply because
  109. this enabled us get the project started quickly, while also having
  110. a large potential user base.
  111. In Django there is a global settings object, so multiple Django projects
  112. can't co-exist in the same process space, this later posed a problem
  113. for using Celery with frameworks that doesn't have this limitation.
  114. Therefore the app concept was introduced. When using apps you use 'celery'
  115. objects instead of importing things from celery submodules, this sadly
  116. also means that Celery essentially has two API's.
  117. Here's an example using Celery in single-mode:
  118. .. code-block:: python
  119. from celery.task import task
  120. from celery.task.control import inspect
  121. from .models import CeleryStats
  122. @task
  123. def write_stats_to_db():
  124. stats = inspect().stats(timeout=1)
  125. for node_name, reply in stats:
  126. CeleryStats.objects.update_stat(node_name, stats)
  127. and here's the same using Celery app objects:
  128. .. code-block:: python
  129. from .celery import celery
  130. from .models import CeleryStats
  131. @celery.task
  132. def write_stats_to_db():
  133. stats = celery.control.inspect().stats(timeout=1)
  134. for node_name, reply in stats:
  135. CeleryStats.objects.update_stat(node_name, stats)
  136. In the example above the actual application instance is imported
  137. from a module in the project, this module could look something like this:
  138. .. code-block:: python
  139. from celery import Celery
  140. celery = Celery()
  141. celery.config_from_object(BROKER_URL="amqp://")
  142. Module Overview
  143. ===============
  144. - celery.app
  145. This is the core of Celery: the entry-point for all functionality.
  146. - celery.loaders
  147. Every app must have a loader. The loader decides how configuration
  148. is read, what happens when the worker starts, when a task starts and ends,
  149. and so on.
  150. The loaders included are:
  151. - app
  152. Custom celery app instances uses this loader by default.
  153. - default
  154. "single-mode" uses this loader by default.
  155. Extension loaders also exist, like ``django-celery``, ``celery-pylons``
  156. and so on.
  157. - celery.worker
  158. This is the worker implementation.
  159. - celery.backends
  160. Task result backends live here.
  161. - celery.apps
  162. Major user applications: ``celeryd``, and ``celerybeat``
  163. - celery.bin
  164. Command line applications.
  165. setup.py creates setuptools entrypoints for these.
  166. - celery.concurrency
  167. Execution pool implementations (processes, eventlet, gevent, threads).
  168. - celery.db
  169. Database models for the SQLAlchemy database result backend.
  170. (should be moved into :mod:`celery.backends.database`)
  171. - celery.events
  172. Sending and consuming monitoring events, also includes curses monitor,
  173. event dumper and utilities to work with in-memory cluster state.
  174. - celery.execute.trace
  175. How tasks are executed and traced by the worker, and in eager mode.
  176. - celery.security
  177. Security related functionality, currently a serializer using
  178. cryptographic digests.
  179. - celery.task
  180. single-mode interface to creating tasks, and controlling workers.
  181. - celery.tests
  182. The celery unittest suite.
  183. - celery.utils
  184. Utility functions used by the celery code base.
  185. Much of it is there to be compatible across Python versions.
  186. - celery.contrib
  187. Additional public code that doesn't fit into any other namespace.