document.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2001, 2002 Zope Foundation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE.
  12. #
  13. ##############################################################################
  14. """ Pretty-Print an Interface object as structured text (Yum)
  15. This module provides a function, asStructuredText, for rendering an
  16. interface as structured text.
  17. """
  18. import zope.interface
  19. __all__ = [
  20. 'asReStructuredText',
  21. 'asStructuredText',
  22. ]
  23. def asStructuredText(iface, munge=0, rst=False):
  24. """ Output structured text format. Note, this will whack any existing
  25. 'structured' format of the text.
  26. If `rst=True`, then the output will quote all code as inline literals in
  27. accordance with 'reStructuredText' markup principles.
  28. """
  29. if rst:
  30. def inline_literal(s):
  31. return f"``{s}``"
  32. else:
  33. def inline_literal(s):
  34. return s
  35. r = [inline_literal(iface.getName())]
  36. outp = r.append
  37. level = 1
  38. if iface.getDoc():
  39. outp(_justify_and_indent(_trim_doc_string(iface.getDoc()), level))
  40. bases = [base
  41. for base in iface.__bases__
  42. if base is not zope.interface.Interface
  43. ]
  44. if bases:
  45. outp(_justify_and_indent("This interface extends:", level, munge))
  46. level += 1
  47. for b in bases:
  48. item = "o %s" % inline_literal(b.getName())
  49. outp(_justify_and_indent(_trim_doc_string(item), level, munge))
  50. level -= 1
  51. namesAndDescriptions = sorted(iface.namesAndDescriptions())
  52. outp(_justify_and_indent("Attributes:", level, munge))
  53. level += 1
  54. for name, desc in namesAndDescriptions:
  55. if not hasattr(desc, 'getSignatureString'): # ugh...
  56. item = "{} -- {}".format(
  57. inline_literal(desc.getName()),
  58. desc.getDoc() or 'no documentation'
  59. )
  60. outp(_justify_and_indent(_trim_doc_string(item), level, munge))
  61. level -= 1
  62. outp(_justify_and_indent("Methods:", level, munge))
  63. level += 1
  64. for name, desc in namesAndDescriptions:
  65. if hasattr(desc, 'getSignatureString'): # ugh...
  66. _call = f"{desc.getName()}{desc.getSignatureString()}"
  67. item = "{} -- {}".format(
  68. inline_literal(_call),
  69. desc.getDoc() or 'no documentation'
  70. )
  71. outp(_justify_and_indent(_trim_doc_string(item), level, munge))
  72. return "\n\n".join(r) + "\n\n"
  73. def asReStructuredText(iface, munge=0):
  74. """ Output reStructuredText format.
  75. Note, this will whack any existing 'structured' format of the text."""
  76. return asStructuredText(iface, munge=munge, rst=True)
  77. def _trim_doc_string(text):
  78. """ Trims a doc string to make it format
  79. correctly with structured text. """
  80. lines = text.replace('\r\n', '\n').split('\n')
  81. nlines = [lines.pop(0)]
  82. if lines:
  83. min_indent = min([len(line) - len(line.lstrip())
  84. for line in lines])
  85. for line in lines:
  86. nlines.append(line[min_indent:])
  87. return '\n'.join(nlines)
  88. def _justify_and_indent(text, level, munge=0, width=72):
  89. """ indent and justify text, rejustify (munge) if specified """
  90. indent = " " * level
  91. if munge:
  92. lines = []
  93. line = indent
  94. text = text.split()
  95. for word in text:
  96. line = ' '.join([line, word])
  97. if len(line) > width:
  98. lines.append(line)
  99. line = indent
  100. else:
  101. lines.append(line)
  102. return '\n'.join(lines)
  103. else:
  104. return indent + \
  105. text.strip().replace("\r\n", "\n") .replace("\n", "\n" + indent)