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, '&', '&'), |
155 return text.replace('&','&').replace('<','<').replace('>','>') |
158 '<', '<'), |
|
159 '>', '>') |
|
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) |