celerydocs.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. from __future__ import absolute_import, unicode_literals
  2. import sys
  3. import typing
  4. from docutils import nodes
  5. from sphinx.environment import NoUri
  6. APPATTRS = {
  7. 'amqp': 'celery.app.amqp.AMQP',
  8. 'backend': 'celery.backends.base.BaseBackend',
  9. 'conf': 'celery.app.utils.Settings',
  10. 'control': 'celery.app.control.Control',
  11. 'events': 'celery.events.Events',
  12. 'loader': 'celery.app.loaders.base.BaseLoader',
  13. 'log': 'celery.app.log.Logging',
  14. 'pool': 'kombu.connection.ConnectionPool',
  15. 'tasks': 'celery.app.registry.Registry',
  16. 'AsyncResult': 'celery.result.AsyncResult',
  17. 'ResultSet': 'celery.result.ResultSet',
  18. 'GroupResult': 'celery.result.GroupResult',
  19. 'Worker': 'celery.apps.worker.Worker',
  20. 'WorkController': 'celery.worker.WorkController',
  21. 'Beat': 'celery.apps.beat.Beat',
  22. 'Task': 'celery.app.task.Task',
  23. 'signature': 'celery.canvas.Signature',
  24. }
  25. APPDIRECT = {
  26. 'on_configure', 'on_after_configure', 'on_after_finalize',
  27. 'set_current', 'set_default', 'close', 'on_init', 'start',
  28. 'worker_main', 'task', 'gen_task_name', 'finalize',
  29. 'add_defaults', 'config_from_object', 'config_from_envvar',
  30. 'config_from_cmdline', 'setup_security', 'autodiscover_tasks',
  31. 'send_task', 'connection', 'connection_or_acquire',
  32. 'producer_or_acquire', 'prepare_config', 'now',
  33. 'select_queues', 'either', 'bugreport', 'create_task_cls',
  34. 'subclass_with_self', 'annotations', 'current_task', 'oid',
  35. 'timezone', '__reduce_keys__', 'fixups', 'finalized', 'configured',
  36. 'add_periodic_task',
  37. 'autofinalize', 'steps', 'user_options', 'main', 'clock',
  38. }
  39. APPATTRS.update({x: 'celery.Celery.{0}'.format(x) for x in APPDIRECT})
  40. ABBRS = {
  41. 'Celery': 'celery.Celery',
  42. }
  43. ABBR_EMPTY = {
  44. 'exc': 'celery.exceptions',
  45. }
  46. DEFAULT_EMPTY = 'celery.Celery'
  47. if sys.version_info[0] < 3:
  48. def bytes_if_py2(s):
  49. if isinstance(s, unicode):
  50. return s.encode()
  51. return s
  52. else:
  53. def bytes_if_py2(s): # noqa
  54. return s
  55. def typeify(S, type):
  56. if type in ('meth', 'func'):
  57. return S + '()'
  58. return S
  59. def shorten(S, newtarget, src_dict):
  60. if S.startswith('@-'):
  61. return S[2:]
  62. elif S.startswith('@'):
  63. if src_dict is APPATTRS:
  64. return '.'.join(['app', S[1:]])
  65. return S[1:]
  66. return S
  67. def get_abbr(pre, rest, type, orig=None):
  68. if pre:
  69. for d in APPATTRS, ABBRS:
  70. try:
  71. return d[pre], rest, d
  72. except KeyError:
  73. pass
  74. raise KeyError('Unknown abbreviation: {0} ({1})'.format(
  75. '.'.join([pre, rest]) if orig is None else orig, type,
  76. ))
  77. else:
  78. for d in APPATTRS, ABBRS:
  79. try:
  80. return d[rest], '', d
  81. except KeyError:
  82. pass
  83. return ABBR_EMPTY.get(type, DEFAULT_EMPTY), rest, ABBR_EMPTY
  84. def resolve(S, type):
  85. if '.' not in S:
  86. try:
  87. getattr(typing, S)
  88. except AttributeError:
  89. pass
  90. else:
  91. return 'typing.{0}'.format(S), None
  92. orig = S
  93. if S.startswith('@'):
  94. S = S.lstrip('@-')
  95. try:
  96. pre, rest = S.split('.', 1)
  97. except ValueError:
  98. pre, rest = '', S
  99. target, rest, src = get_abbr(pre, rest, type, orig)
  100. return '.'.join([target, rest]) if rest else target, src
  101. return S, None
  102. def pkg_of(module_fqdn):
  103. return module_fqdn.split('.', 1)[0]
  104. def basename(module_fqdn):
  105. return module_fqdn.lstrip('@').rsplit('.', -1)[-1]
  106. def modify_textnode(T, newtarget, node, src_dict, type):
  107. src = node.children[0].rawsource
  108. return nodes.Text(
  109. (typeify(basename(T), type) if '~' in src
  110. else typeify(shorten(T, newtarget, src_dict), type)),
  111. src,
  112. )
  113. def maybe_resolve_abbreviations(app, env, node, contnode):
  114. domainname = node.get('refdomain')
  115. target = node['reftarget']
  116. type = node['reftype']
  117. if target.startswith('@'):
  118. newtarget, src_dict = resolve(target, type)
  119. node['reftarget'] = newtarget
  120. # shorten text if '~' is not enabled.
  121. if len(contnode) and isinstance(contnode[0], nodes.Text):
  122. contnode[0] = modify_textnode(target, newtarget, node,
  123. src_dict, type)
  124. if domainname:
  125. try:
  126. domain = env.domains[node.get('refdomain')]
  127. except KeyError:
  128. raise NoUri
  129. return domain.resolve_xref(env, node['refdoc'], app.builder,
  130. type, newtarget,
  131. node, contnode)
  132. def setup(app):
  133. app.connect(
  134. bytes_if_py2('missing-reference'),
  135. maybe_resolve_abbreviations,
  136. )
  137. app.add_crossref_type(
  138. directivename=bytes_if_py2('sig'),
  139. rolename=bytes_if_py2('sig'),
  140. indextemplate=bytes_if_py2('pair: %s; sig'),
  141. )
  142. app.add_crossref_type(
  143. directivename=bytes_if_py2('state'),
  144. rolename=bytes_if_py2('state'),
  145. indextemplate=bytes_if_py2('pair: %s; state'),
  146. )
  147. app.add_crossref_type(
  148. directivename=bytes_if_py2('control'),
  149. rolename=bytes_if_py2('control'),
  150. indextemplate=bytes_if_py2('pair: %s; control'),
  151. )
  152. app.add_crossref_type(
  153. directivename=bytes_if_py2('event'),
  154. rolename=bytes_if_py2('event'),
  155. indextemplate=bytes_if_py2('pair: %s; event'),
  156. )