# # # import sys def usage(): print "python pytowiki.py module_name output_file" class CodeplexFormatter: def endl( self ): return "\n" def header1( self, s ): return "! " + s + self.endl() def header2( self, s ): return "!! " + s + self.endl() def header3( self, s ): return "!!! " + s + self.endl() def header4( self, s ): return "!!!! " + s + self.endl() def bulletItem( self, s ): return "* " + s + self.endl() def escapeMarkup( self, s ): return "{\"" + s + "\"}" def link( self, text, link ): return "[" + text + "|#" + link + "]" def anchor( self, link ): return "{anchor:" + link + "}" + self.endl() class MarkdownFormatter: def endl( self ): return "\n" def header1( self, s ): return "# " + s + self.endl() def header2( self, s ): return "## " + s + self.endl() def header3( self, s ): return "### " + s + self.endl() def header4( self, s ): return "#### " + s + self.endl() def bulletItem( self, s ): return "* " + s + self.endl() def escapeMarkup( self, s ): return self.endl() + "```" + self.endl() + s + self.endl() + "```" + self.endl() def link( self, text, link ): return "[" + text + "](#" + link + ")" def anchor( self, link ): return "" + self.endl() def escapeSymbols(self, text): output = "" escapeSyms = ['_'] for s in text: if s in escapeSyms: output += "\\" + s else: output += s return output class ModuleInfo: def __init__ (self, module): self.funcs = sorted( [ item for item in module.__dict__.values() if type(item).__name__ == "function" ], key=lambda x: x.__name__ ) self.classes = sorted( [ item for item in module.__dict__.values() if type(item).__name__ == "class" or type(item).__name__ == "type" ], key=lambda x: x.__name__ ) for cls in self.classes: cls.methods = sorted( [ item for item in cls.__dict__.values() if type(item).__name__ == "function" ], key=lambda x: x.__name__ ) cls.properties = sorted( [ item for item in cls.__dict__.items() if type(item[1]).__name__ == "property" ], key=lambda x: x[0] ) cls.enum = cls.__dict__.get("names", [] ) def buildDoc( ioStream, formatter, apiInfo ): ioStream.write( formatter.header2( "Functions" ) ) for func in apiInfo.funcs: ioStream.write( formatter.bulletItem( formatter.link( func.__name__, func.__name__ ) ) ) ioStream.write( formatter.endl() ) ioStream.write( formatter.header2( "Classes" ) ) for cls in apiInfo.classes: ioStream.write( formatter.bulletItem( formatter.link( cls.__name__, cls.__name__ ) ) ) ioStream.write( formatter.endl() ) for func in apiInfo.funcs: ioStream.write( formatter.anchor( func.__name__ ) ) ioStream.write( formatter.header3( "Function " + func.__name__ ) ) if func.__doc__ != None: ioStream.write( formatter.escapeMarkup( func.__doc__) + formatter.endl() ) for cls in apiInfo.classes: ioStream.write( formatter.anchor( cls.__name__ ) ) ioStream.write( formatter.header3( "Class " + cls.__name__ ) ) if cls.__doc__ != None: ioStream.write( formatter.escapeMarkup( cls.__doc__) + formatter.endl() ) ioStream.write( formatter.header4( "Base classes:") ) for b in cls.__bases__: if b in apiInfo.classes: ioStream.write( formatter.link( b.__name__, b.__name__ ) + formatter.endl() ) else: ioStream.write( b.__name__ + formatter.endl() ) if cls.properties: ioStream.write( formatter.header4( "Properties:") ) for p in cls.properties: ioStream.write( formatter.bulletItem( formatter.link( p[0], cls.__name__ + "." + p[0]) ) ) ioStream.write( formatter.endl() ) methods = filter( lambda m: m.__doc__ != None, cls.methods ) if methods: ioStream.write( formatter.header4( "Methods:") ) for m in methods: ioStream.write( formatter.bulletItem( formatter.link( formatter.escapeSymbols(m.__name__), cls.__name__ + "." + m.__name__)) ) ioStream.write( formatter.endl() ) if cls.enum: ioStream.write( formatter.header4( "Values:") ) for v in cls.enum.items(): ioStream.write( formatter.bulletItem( "%s: %d" % v ) ) ioStream.write( formatter.endl() ) if cls.properties: for p in cls.properties: if p[1].__doc__ != None: ioStream.write( formatter.anchor( cls.__name__ + "." + p[0] ) ) ioStream.write( formatter.header4( "Property " + cls.__name__ + "." + p[0] ) ) ioStream.write( formatter.escapeMarkup( p[1].__doc__ ) + formatter.endl() ) if methods: for m in methods: ioStream.write( formatter.anchor( cls.__name__ + "." + m.__name__ ) ) ioStream.write( formatter.header4( formatter.escapeSymbols("Method " + cls.__name__ + "." + m.__name__ )) ) ioStream.write( formatter.escapeMarkup( m.__doc__ ) + formatter.endl() ) def main(): if len(sys.argv) < 3: usage() return moduleName = sys.argv[1] fileName = sys.argv[2] try: module = __import__( moduleName ) with file( fileName, "w" ) as wikiIo: apiInfo = ModuleInfo( module ) #formatter = CodeplexFormatter() formatter = MarkdownFormatter() buildDoc( wikiIo, formatter, apiInfo ) except ImportWarning: print "failed to import module " + moduleName if __name__ == "__main__": main()