tools/docco/docpy.py
branchpy33
changeset 3794 398ea04239b5
parent 3721 0c93dd8ff567
child 3881 b3e5f1288b86
equal deleted inserted replaced
3793:cc3f9cc828f7 3794:398ea04239b5
    31 
    31 
    32 
    32 
    33 __version__ = '0.8'
    33 __version__ = '0.8'
    34 
    34 
    35 
    35 
    36 import sys, os, re, types, string, getopt, copy, time
    36 import sys, os, re, types, getopt, copy, time
    37 from string import find, join, split, replace, expandtabs, rstrip
       
    38 
       
    39 from reportlab.pdfgen import canvas
    37 from reportlab.pdfgen import canvas
    40 from reportlab.lib import colors
    38 from reportlab.lib import colors
    41 from reportlab.lib.units import inch, cm
    39 from reportlab.lib.units import inch, cm
    42 from reportlab.lib.pagesizes import A4
    40 from reportlab.lib.pagesizes import A4
    43 from reportlab.lib import enums
    41 from reportlab.lib import enums
    72     canvas.line(2*cm, 2*cm, A4[0]-2*cm, 2*cm)
    70     canvas.line(2*cm, 2*cm, A4[0]-2*cm, 2*cm)
    73     if pageNumber > 1:
    71     if pageNumber > 1:
    74         canvas.setFont('Times-Roman', 12)
    72         canvas.setFont('Times-Roman', 12)
    75         canvas.drawString(4 * inch, cm, "%d" % pageNumber)
    73         canvas.drawString(4 * inch, cm, "%d" % pageNumber)
    76         if hasattr(canvas, 'headerLine'): # hackish
    74         if hasattr(canvas, 'headerLine'): # hackish
    77             headerline = string.join(canvas.headerLine, ' \215 ') # bullet
    75             headerline = , ' \215 '.join(canvas.headerLine) # bullet
    78             canvas.drawString(2*cm, A4[1]-1.75*cm, headerline)
    76             canvas.drawString(2*cm, A4[1]-1.75*cm, headerline)
    79 
    77 
    80     canvas.setFont('Times-Roman', 8)
    78     canvas.setFont('Times-Roman', 8)
    81     msg = "Generated with reportlab.lib.docpy. See http://www.reportlab.com!"
    79     msg = "Generated with reportlab.lib.docpy. See http://www.reportlab.com!"
    82     canvas.drawString(2*cm, 1.65*cm, msg)
    80     canvas.drawString(2*cm, 1.65*cm, msg)
   152 #
   150 #
   153 ####################################################################
   151 ####################################################################
   154 
   152 
   155 def htmlescape(text):
   153 def htmlescape(text):
   156     "Escape special HTML characters, namely &, <, >."
   154     "Escape special HTML characters, namely &, <, >."
   157     return replace(replace(replace(text, '&', '&amp;'),
   155     return text.replace('&','&amp;').replace('<','&lt;').replace('>','&gt;')
   158                                          '<', '&lt;'),
       
   159                                          '>', '&gt;')
       
   160 
   156 
   161 def htmlrepr(object):
   157 def htmlrepr(object):
   162     return htmlescape(repr(object))
   158     return htmlescape(repr(object))
   163 
   159 
   164 
   160 
   171     if not result:
   167     if not result:
   172         try:
   168         try:
   173             result = inspect.getcomments(object)
   169             result = inspect.getcomments(object)
   174         except:
   170         except:
   175             pass
   171             pass
   176     return result and rstrip(result) + '\n' or ''
   172     return result and result.rstrip() + '\n' or ''
   177 
   173 
   178 
   174 
   179 def reduceDocStringLength(docStr):
   175 def reduceDocStringLength(docStr):
   180     "Return first line of a multiline string."
   176     "Return first line of a multiline string."
   181 
   177 
   182     return split(docStr, '\n')[0]
   178     return docStr.split('\n')[0]
   183 
   179 
   184 
   180 
   185 ####################################################################
   181 ####################################################################
   186 #
   182 #
   187 # More utility functions
   183 # More utility functions
   191 def makeHtmlSection(text, bgcolor='#FFA0FF'):
   187 def makeHtmlSection(text, bgcolor='#FFA0FF'):
   192     """Create HTML code for a section.
   188     """Create HTML code for a section.
   193 
   189 
   194     This is usually a header for all classes or functions.
   190     This is usually a header for all classes or functions.
   195 u    """
   191 u    """
   196     text = htmlescape(expandtabs(text))
   192     text = htmlescape(text.expandtabs())
   197     result = []
   193     result = []
   198     result.append("""<TABLE WIDTH="100\%" BORDER="0">""")
   194     result.append("""<TABLE WIDTH="100\%" BORDER="0">""")
   199     result.append("""<TR><TD BGCOLOR="%s" VALIGN="CENTER">""" % bgcolor)
   195     result.append("""<TR><TD BGCOLOR="%s" VALIGN="CENTER">""" % bgcolor)
   200     result.append("""<H2>%s</H2>""" % text)
   196     result.append("""<H2>%s</H2>""" % text)
   201     result.append("""</TD></TR></TABLE>""")
   197     result.append("""</TD></TR></TABLE>""")
   202     result.append('')
   198     result.append('')
   203 
   199 
   204     return join(result, '\n')
   200     return '\n'.join(result)
   205 
   201 
   206 
   202 
   207 def makeHtmlSubSection(text, bgcolor='#AAA0FF'):
   203 def makeHtmlSubSection(text, bgcolor='#AAA0FF'):
   208     """Create HTML code for a subsection.
   204     """Create HTML code for a subsection.
   209 
   205 
   210     This is usually a class or function name.
   206     This is usually a class or function name.
   211     """
   207     """
   212     text = htmlescape(expandtabs(text))
   208     text = htmlescape(text.expandtabs())
   213     result = []
   209     result = []
   214     result.append("""<TABLE WIDTH="100\%" BORDER="0">""")
   210     result.append("""<TABLE WIDTH="100\%" BORDER="0">""")
   215     result.append("""<TR><TD BGCOLOR="%s" VALIGN="CENTER">""" % bgcolor)
   211     result.append("""<TR><TD BGCOLOR="%s" VALIGN="CENTER">""" % bgcolor)
   216     result.append("""<H3><TT><FONT SIZE="+2">%s</FONT></TT></H3>""" % text)
   212     result.append("""<H3><TT><FONT SIZE="+2">%s</FONT></TT></H3>""" % text)
   217     result.append("""</TD></TR></TABLE>""")
   213     result.append("""</TD></TR></TABLE>""")
   218     result.append('')
   214     result.append('')
   219 
   215 
   220     return join(result, '\n')
   216     return '\n'.join(result)
   221 
   217 
   222 
   218 
   223 def makeHtmlInlineImage(text):
   219 def makeHtmlInlineImage(text):
   224     """Create HTML code for an inline image.
   220     """Create HTML code for an inline image.
   225     """
   221     """
   611         append = self.outLines.append
   607         append = self.outLines.append
   612         lev, label = self.indentLevel, self.indentLabel
   608         lev, label = self.indentLevel, self.indentLabel
   613 
   609 
   614         if bases:
   610         if bases:
   615             bases = [b.__name__ for b in bases] # hack
   611             bases = [b.__name__ for b in bases] # hack
   616             append('%s%s(%s)' % (lev*label, name, join(bases, ', ')))
   612             append('%s%s(%s)' % (lev*label, name, ', '.join(bases)))
   617         else:
   613         else:
   618             append('%s%s' % (lev*label, name))
   614             append('%s%s' % (lev*label, name))
   619         return
   615         return
   620 
   616 
   621 ##        append('%s%s' % ((lev+1)*label, reduceDocStringLength(doc)))
   617 ##        append('%s%s' % ((lev+1)*label, reduceDocStringLength(doc)))
   694             self.outLines.append("""<title>%s</title>""" % name)
   690             self.outLines.append("""<title>%s</title>""" % name)
   695             self.outLines.append("""<body bgcolor="#ffffff">""")
   691             self.outLines.append("""<body bgcolor="#ffffff">""")
   696 
   692 
   697         self.outLines.append("""<H1>%s</H1>""" % name)
   693         self.outLines.append("""<H1>%s</H1>""" % name)
   698         self.outLines.append('')
   694         self.outLines.append('')
   699         for line in split(doc, '\n'):
   695         for line in doc.split('\n'):
   700             self.outLines.append("""<FONT SIZE="-1">%s</FONT>""" % htmlescape(line))
   696             self.outLines.append("""<FONT SIZE="-1">%s</FONT>""" % htmlescape(line))
   701             self.outLines.append('<BR>')
   697             self.outLines.append('<BR>')
   702         self.outLines.append('')
   698         self.outLines.append('')
   703 
   699 
   704         if imported:
   700         if imported:
   719 ##        # Keep an eye on the base classes.
   715 ##        # Keep an eye on the base classes.
   720 ##        self.currentBaseClasses = bases
   716 ##        self.currentBaseClasses = bases
   721 
   717 
   722         if bases:
   718         if bases:
   723             bases = [b.__name__ for b in bases] # hack
   719             bases = [b.__name__ for b in bases] # hack
   724             self.outLines.append(makeHtmlSubSection('%s(%s)' % (name, join(bases, ', '))))
   720             self.outLines.append(makeHtmlSubSection('%s(%s)' % (name, ', '.join(bases))))
   725         else:
   721         else:
   726             self.outLines.append(makeHtmlSubSection('%s' % name))
   722             self.outLines.append(makeHtmlSubSection('%s' % name))
   727         for line in split(doc, '\n'):
   723         for line in doc.split('\n'):
   728             self.outLines.append("""<FONT SIZE="-1">%s</FONT>""" % htmlescape(line))
   724             self.outLines.append("""<FONT SIZE="-1">%s</FONT>""" % htmlescape(line))
   729             self.outLines.append('<BR>')
   725             self.outLines.append('<BR>')
   730 
   726 
   731         self.outLines.append('')
   727         self.outLines.append('')
   732 
   728 
   748 
   744 
   749     def beginFunction(self, name, doc, sig):
   745     def beginFunction(self, name, doc, sig):
   750         append = self.outLines.append
   746         append = self.outLines.append
   751         append("""<DL><DL><DT><TT><STRONG>%s</STRONG>%s</TT></DT>""" % (name, sig))
   747         append("""<DL><DL><DT><TT><STRONG>%s</STRONG>%s</TT></DT>""" % (name, sig))
   752         append('')
   748         append('')
   753         for line in split(doc, '\n'):
   749         for line in doc.split('\n'):
   754             append("""<DD><FONT SIZE="-1">%s</FONT></DD>""" % htmlescape(line))
   750             append("""<DD><FONT SIZE="-1">%s</FONT></DD>""" % htmlescape(line))
   755             append('<BR>')
   751             append('<BR>')
   756         append('</DL></DL>')
   752         append('</DL></DL>')
   757         append('')
   753         append('')
   758 
   754 
   874     def beginClass(self, name, doc, bases):
   870     def beginClass(self, name, doc, bases):
   875         bt = self.bt
   871         bt = self.bt
   876         story = self.story
   872         story = self.story
   877         if bases:
   873         if bases:
   878             bases = [b.__name__ for b in bases] # hack
   874             bases = [b.__name__ for b in bases] # hack
   879             story.append(Paragraph('%s(%s)' % (name, join(bases, ', ')), self.makeHeadingStyle(self.indentLevel, 'class')))
   875             story.append(Paragraph('%s(%s)' % (name,', '.join(bases)), self.makeHeadingStyle(self.indentLevel, 'class')))
   880         else:
   876         else:
   881             story.append(Paragraph(name, self.makeHeadingStyle(self.indentLevel, 'class')))
   877             story.append(Paragraph(name, self.makeHeadingStyle(self.indentLevel, 'class')))
   882 
   878 
   883         if doc:
   879         if doc:
   884             story.append(XPreformatted(htmlescape(doc), bt))
   880             story.append(XPreformatted(htmlescape(doc), bt))
   958         self.classCompartment = ''
   954         self.classCompartment = ''
   959         self.methodCompartment = []
   955         self.methodCompartment = []
   960 
   956 
   961         if bases:
   957         if bases:
   962             bases = [b.__name__ for b in bases] # hack
   958             bases = [b.__name__ for b in bases] # hack
   963             self.classCompartment = '%s(%s)' % (name, join(bases, ', '))
   959             self.classCompartment = '%s(%s)' % (name, ', '.join(bases))
   964         else:
   960         else:
   965             self.classCompartment = name
   961             self.classCompartment = name
   966 
   962 
   967 
   963 
   968     def endClass(self, name, doc, bases):
   964     def endClass(self, name, doc, bases):
  1180     else:
  1176     else:
  1181         name = pathOrName
  1177         name = pathOrName
  1182         package = __import__(name)
  1178         package = __import__(name)
  1183         # Some special care needed for dotted names.
  1179         # Some special care needed for dotted names.
  1184         if '.' in name:
  1180         if '.' in name:
  1185             subname = 'package' + name[find(name, '.'):]
  1181             subname = 'package' + name[name.find('.'):]
  1186             package = eval(subname)
  1182             package = eval(subname)
  1187         path = os.path.dirname(package.__file__)
  1183         path = os.path.dirname(package.__file__)
  1188 
  1184 
  1189     cwd = os.getcwd()
  1185     cwd = os.getcwd()
  1190     builder.beginPackage(name)
  1186     builder.beginPackage(name)