PageRenderTime 296ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/sphinxext/sphinx_cython.py

https://github.com/thurday/pyzmq
Python | 111 lines | 64 code | 18 blank | 29 comment | 21 complexity | d1f798826d447127b704d7a950641e21 MD5 | raw file
  1. '''
  2. sphinx_cython.py
  3. This module monkeypatches sphinx autodoc to support Cython generated
  4. function signatures in the first line of the docstring of functions
  5. implemented as C extensions.
  6. Copyright (C) Nikolaus Rath <Nikolaus@rath.org>
  7. This file is part of LLFUSE (http://python-llfuse.googlecode.com).
  8. LLFUSE can be distributed under the terms of the GNU LGPL.
  9. It has been slightly modified by MinRK.
  10. '''
  11. import sphinx.ext.autodoc as SphinxAutodoc
  12. from sphinx.util.docstrings import prepare_docstring
  13. import inspect
  14. import re
  15. from sphinx.util import force_decode
  16. TYPE_RE = re.compile(r'(?:int|char)(?:\s+\*?\s*|\s*\*?\s+)([a-zA-Z_].*)')
  17. ClassDocumenter = SphinxAutodoc.ClassDocumenter
  18. MethodDocumenter = SphinxAutodoc.MethodDocumenter
  19. FunctionDocumenter = SphinxAutodoc.FunctionDocumenter
  20. class MyDocumenter(SphinxAutodoc.Documenter):
  21. '''
  22. Overwrites `get_doc()` to remove function and
  23. method signatures and `format_args` to parse and give
  24. precedence to function signatures in the first line
  25. of the docstring.
  26. '''
  27. def get_doc(self, encoding=None):
  28. docstr = self.get_attr(self.object, '__doc__', None)
  29. myname = self.fullname[len(self.modname)+1:]
  30. if myname.endswith('()'):
  31. myname = myname[:-2]
  32. if (docstr
  33. and (myname + '(') in docstr
  34. and '\n' in docstr
  35. and docstr[docstr.index('\n')-1] == ')'):
  36. docstr = docstr[docstr.index('\n')+1:]
  37. if docstr:
  38. # make sure we have Unicode docstrings, then sanitize and split
  39. # into lines
  40. return [prepare_docstring(force_decode(docstr, encoding))]
  41. return []
  42. def format_args(self):
  43. myname = self.fullname[len(self.modname)+1:]
  44. if myname.endswith('()'):
  45. myname = myname[:-2]
  46. # Try to parse docstring
  47. docstr = self.get_attr(self.object, '__doc__', None)
  48. if (docstr
  49. and (myname + '(') in docstr
  50. and '\n' in docstr
  51. and docstr[docstr.index('\n')-1] == ')'):
  52. args = docstr[len(myname)+1:docstr.index('\n')-1]
  53. # Get rid of Cython style types declarations
  54. argl = []
  55. for arg in [ x.strip() for x in args.split(',') ]:
  56. if (arg in ('cls', 'self')
  57. and isinstance(self, SphinxAutodoc.MethodDocumenter)):
  58. continue
  59. hit = TYPE_RE.match(arg)
  60. if hit:
  61. argl.append(hit.group(1))
  62. else:
  63. argl.append(arg)
  64. args = '(%s)' % ', '.join(argl)
  65. else:
  66. # super seems to get this wrong:
  67. for cls in (MethodDocumenter,
  68. FunctionDocumenter,
  69. ClassDocumenter):
  70. if isinstance(self, cls):
  71. return cls.format_args(self)
  72. # return super(self.__class__, self).format_args()
  73. # escape backslashes for reST
  74. args = args.replace('\\', '\\\\')
  75. return args
  76. class MyFunctionDocumenter(MyDocumenter, SphinxAutodoc.FunctionDocumenter):
  77. pass
  78. class MyMethodDocumenter(MyDocumenter, SphinxAutodoc.MethodDocumenter):
  79. pass
  80. class MyClassDocumenter(MyDocumenter, SphinxAutodoc.ClassDocumenter):
  81. def format_signature(self):
  82. return self.format_args() or "()"
  83. SphinxAutodoc.ClassDocumenter = MyClassDocumenter
  84. SphinxAutodoc.MethodDocumenter = MyMethodDocumenter
  85. SphinxAutodoc.FunctionDocumenter = MyFunctionDocumenter
  86. # don't use AttributeDocumenter on 'method_descriptor' members:
  87. AD = SphinxAutodoc.AttributeDocumenter
  88. AD.method_types = tuple(list(AD.method_types) + [type(str.count)])