[Python-checkins] CVS: python/nondist/sandbox/doctools textdoc.py,NONE,1.1 README,1.1,1.2 htmldoc.py,1.1,1.2 onlinehelp.py,1.1,1.2

Paul Prescod python-dev@python.org
2000年7月22日 11:51:38 -0700


Update of /cvsroot/python/python/nondist/sandbox/doctools
In directory slayer.i.sourceforge.net:/tmp/cvs-serv15410
Modified Files:
	README htmldoc.py onlinehelp.py 
Added Files:
	textdoc.py 
Log Message:
Better support for module documentation. Extracts classes, funcs, etc.
automatically.
--- NEW FILE ---
#!/usr/bin/env python
"""Generate text documentation from Python objects.
This module uses Ka-Ping Yee's inspect module to generate text documentation
given a python object. It borrows heavily from Ka-Ping Yee's htmldoc. Further
details of those modules can be found at http://www.lfw.org/python/.
Use:
import textdoc,cgi
print textdoc.document(cgi) # document an entire module
print textdoc.document(cgi.FieldStorage) # document a class
print textdoc.document(cgi.initlog) # document a function
print textdoc.document(len) # document a builtin
contact: richard_chamberlain@ntlworld.com
"""
# I, Richard Chamberlain, the author of this contribution, hereby grant to anyone
# and everyone a nonexclusive, irrevocable, royalty-free, worldwide license to
# reproduce, distribute, perform and/or display publicly, prepare derivative
# versions, and otherwise use this contribution in any fashion, or any
# derivative versions thereof, at no cost to anyone, and to authorize others
# to do so. This software is provided "as is", with NO WARRANTY WHATSOEVER,
# not even a warranty of merchantability or fitness for any particular purpose.
__version__ = "22 July 2000"
import inspect,string
def _getdoc(object):
 """Returns doc string for a given object."""
 result=''
 doc = inspect.getdoc(object)
 if not doc:
 try: doc = inspect.getcomments(object)
 except: pass
 if doc:
 for line in string.split(doc,'\n'): 
 result=result+'\t'+line+'\n'
 if result=='': result='\tno doc string'
 return result and string.rstrip(result) + "\n" or ""
def _tab(str,_tab=2):
 """Increase the indent on all but the first line"""
 result=[]
 lines=string.split(str,'\t')
 result.append(lines[0])
 for line in lines[1:]:
 result.append(('\t')*_tab+line)
 result=string.join(result)
 return result
 
def _document_module(object):
 """Produce text documentation for a given module."""
 results=[]
 name=object.__name__
 if hasattr(object,"__version__"):
 name=name+" (version: %s)\n" % object.__version__
 else: name=name+" \n"
 results.append(name)
 doc=_getdoc(object)
 results.append(doc)
 cadr = lambda list: list[0]
 # Get the modules
 modules = map(cadr,inspect.getmembers(object, inspect.ismodule))
 if modules:
 results.append('\nModules:\n\n')
 results.append(string.join(modules,', '))
 # Get the classes
 classes=inspect.getmembers(object,inspect.isclass)
 if classes:
 results.append('\n\nClasses:\n\n')
 for aclass in classes:
 results.append(_document_class(aclass[1]))
 results.append('\n')
 
 functions=inspect.getmembers(object,inspect.isroutine)
 if functions:
 results.append('Module Functions:\n\n')
 for function in functions:
 results.append(_document_function(function[1]))
 return results
def _document_class(object):
 """Produce text documentation for a given class object."""
 name = object.__name__
 bases = object.__bases__
 results = []
 title = "class %s" % name
 if bases:
 parents = []
 for base in bases:
 parents.append(base.__name__)
 title = title + "(%s)" % string.join(parents, ", ")
 results.append(title+":\n\n")
 doc=_getdoc(object)
 results.append(doc)
 
 functions=inspect.getmembers(object,inspect.isroutine)
 if functions:
 results.append('\n\tMethods:\n\n')
 for function in functions:
 results.append("\t"+_tab(document(function[1])))
 
 return results
def _document_method(object):
 """Produce text documentation for a given method."""
 return _document_function(object.im_func)
def defaultFormat(object):
 rep=repr( obj )
 match=re.match( r"<(.+?) at ......>", rep )
 if match:
 return "<"+match.group(1)+">"
 else:
 return rep
def _document_function(object):
 """Produce text documentation for a given function."""
 try:
 args, varargs, varkw, defaults = inspect.getargspec(object)
 argspec = inspect.formatargspec(
 args, varargs, varkw, defaults)
 except TypeError:
 argspec = "(no arg info)"
 if object.__name__ == "<lambda>":
 decl = ["lambda ", argspec[1:-1]]
 else:
 decl = [object.__name__, argspec, "\n"]
 doc = _getdoc(object)
 return [decl, doc+"\n"]
def _document_builtin(object):
 """Produce text documentation for a given builtin."""
 results=[]
 results.append(object.__name__+'\n')
 doc=_getdoc(object)
 results.append('\n'+doc)
 return results
def document(object):
 """Generate documentation for a given object."""
 if inspect.ismodule(object): results = _document_module(object)
 elif inspect.isclass(object): results = _document_class(object)
 elif inspect.ismethod(object): results = _document_method(object)
 elif inspect.isfunction(object): results = _document_function(object)
 elif inspect.isbuiltin(object): results = _document_builtin(object)
 else: raise TypeError, "don't know how to document this kind of object"
 return _serialise(results)
def _serialise(list):
 """Combine a list containing strings and nested lists into a single
 string. This lets us manipulate lists until the last moment, since
 rearranging lists is faster than rearranging strings."""
 results = []
 if list==None: return ""
 for item in list:
 if type(item) is type(""): results.append(item)
 else: results.append(_serialise(item))
 return string.join(results, "")
if __name__=='__main__':
 # Test Code
 import Tkinter,cgi,calendar
 print document(Tkinter) # Try a module with classes
 print document(calendar) # Module without classes
 print document(cgi.FieldStorage) # Just a class
 print document(inspect.getdoc) # a method
 print document(len) # a builtin
 
 
Index: README
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/doctools/README,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** README	2000年07月21日 21:31:27	1.1
--- README	2000年07月22日 18:51:36	1.2
***************
*** 4,7 ****
 
 onlinehelp.py -- onlinehelp for Python. Read the docstring.
- htmldoc.py -- Builds HTML documentation from docstrings
 inspect.py -- introspection API used by both of the above
--- 4,8 ----
 
 onlinehelp.py -- onlinehelp for Python. Read the docstring.
 inspect.py -- introspection API used by both of the above
+ htmldoc.py -- Builds HTML documentation from docstrings
+ textdoc.py -- Builds raw text documentation from docstrings
Index: htmldoc.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/doctools/htmldoc.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** htmldoc.py	2000年07月21日 21:31:27	1.1
--- htmldoc.py	2000年07月22日 18:51:36	1.2
***************
*** 10,15 ****
 return string.replace(string.replace(str, "&", "&amp;"), "<", "&lt;")
 
 def htmlrepr(object):
! return htmlescape(repr(object))
 
 def preformat(str):
--- 10,27 ----
 return string.replace(string.replace(str, "&", "&amp;"), "<", "&lt;")
 
+ 
+ # added by prescod
+ # physical addresses produced by repr were defeating diff and they are 
+ # ugly anyhow
+ def smartRepr( obj ):
+ rep=repr( obj )
+ match=re.match( r"<(.+?) at ......>", rep )
+ if match:
+ return "<"+match.group(1)+">"
+ else:
+ return rep
+ 
 def htmlrepr(object):
! return htmlescape(smartRepr(object))
 
 def preformat(str):
Index: onlinehelp.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/doctools/onlinehelp.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -r1.1 -r1.2
*** onlinehelp.py	2000年07月21日 21:31:27	1.1
--- onlinehelp.py	2000年07月22日 18:51:36	1.2
***************
*** 41,44 ****
--- 41,49 ----
 
 python onlinehelp.py if
+ 
+ Security warning: this module will attempt to import modules with the same
+ names as requested topics. Don't use the modules if you
+ are not confident that everything in your pythonpath is
+ from a trusted source.
 """
 
***************
*** 64,67 ****
--- 69,73 ----
 import os, sys
 import re
+ import textdoc, types
 
 prompt="--more-- (enter for more, q to quit) "
***************
*** 213,216 ****
--- 219,233 ----
 envir_var="PYTHONDOCS"
 
+ def my_import(name):
+ try:
+ mod = __import__(name)
+ except ImportError:
+ return None
+ 
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+ 
 class Help:
 def __init__( self, out, line_length, docdir=None ):
***************
*** 257,301 ****
 def call( self, ob, out ):
 self.pager=out or self.Pager( self.out, self.line_length )
 
! if type( ob ) in (type(""),type(u"")):
! if ob.startswith( "<" ):
! ob=ob[1:]
! if ob.endswith( ">" ):
! ob=ob[:-1]
! 
! self.write( 'Topic: help( "%s" )\n' % ob )
! 
! if ob.startswith("doc:"):
! path=ob[4:]
! if not self.docdir:
! self.initDocDir()
! fullpath=os.path.join( self.docdir, path )
! data=open( fullpath ).read()
! index=ob.rfind( "/" )
! self.writeHTML( ob[:index], data )
 else:
! try:
! info=topics[ob]
! docrlmatch=re.search( "(<doc:[^>]+>)", info.split("\n")[0] )
! if docrlmatch: # a first-line redirect
! self( docrlmatch.group(1) )
! else:
! self.writeHTML( "", info )
! except KeyError:
! glo=__builtins__.__dict__.get( ob, 0 )
! if glo:
! self( glo )
! else:
! sys.stderr.write( "No such topic "+`ob` )
! return None
 else:
! self.write( 'Topic: help( %s )\n' % ob )
! self.writeText( self.getdoc( ob ) )
 
! def getdoc( self, ob ):
! if hasattr( ob, "__doc__" ):
! return ob.__doc__
 else:
! type( ob ).__doc__
 
 
--- 274,374 ----
 def call( self, ob, out ):
 self.pager=out or self.Pager( self.out, self.line_length )
+ 
+ if type( ob ) in (types.StringType,types.UnicodeType): #string
 
! # doc form of URL
! if ob.startswith("doc:") or ob.startswith( "<doc:" ):
! self.handleDocrl( ob )
 else:
! self.handleTopic( ob )
 else:
! self.handleObject( ob )
! 
! def handleDocrl( self, docrl ):
! # strip leading/trailing "<" and ">"
! if docrl.startswith( "<" ): 
! docrl=docrl[1:]
! if docrl.endswith( ">" ):
! docrl=ob[:-1]
! 
! path=docrl[4:]
! if not self.docdir:
! self.initDocDir()
! 
! fullpath=os.path.join( self.docdir, path )
! data=open( fullpath ).read()
! index=docrl.rfind( "/" )
! 
! self.write( 'Topic: help( "%s" )\n' % docrl )
! self.writeHTML( ob[:index], data )
! 
! def matchDocrlPattern( self, info ):
! firstline=info.split("\n")[0]
! docrlmatch=re.search( "<(doc:[^>]+)>", firstline )
! if docrlmatch:
! return docrlmatch.group( 1 )
! else:
! return None
 
! def handleTopic( self, topic ):
! # otherwise a topic
! info=topics.get(topic, 0 )
! if info:
! match=self.matchDocrlPattern( info )
! if match: # a first-line redirect
! self.handledocrl( match )
 else:
! self.write( 'Topic: help( "%s" )\n' % topic )
! self.writeHTML( "", info )
! return None
! 
! # try again -- this time in builtins
! glo=__builtins__.__dict__.get( topic, 0 )
! if glo:
! self.handleObject( glo )
! return None
! 
! # try again -- this time as a module
! mod=my_import( topic )
! if mod:
! print mod
! self.handleObject( mod )
! return None
! 
! # try again -- this time as an attribute OF a module
! ### FIXME/XXX/TODO: this code is not finished yet!
! parts=string.split( topic, "." )
! for i in range( len( parts ), -1, -1 ):
! if i:
! front=string.join( parts[:i], "." )
! mod=my_import( front )
! if mod:
! self.handleObject( mod )
! return None
! 
! sys.stderr.write( "No such topic "+`topic` )
! return None
! 
! def handleObject( self, ob ):
! docstr=self.getdocstring( ob )
! 
! if docstr:
! match=self.matchDocrlPattern( docstr )
! else:
! match=None
! 
! if match: # a first-line redirect
! self.handledocrl( match )
! else:
! text=textdoc.document( ob )
! self.write( 'Topic: help( %s )\n' % ob )
! self.writeText( text )
! 
! def getdocstring( self, ob ):
! # todo: use inspect.py instead
! if hasattr( ob, "__doc__" ):
! return ob.__doc__
! else:
! return type( ob ).__doc__
 
 
***************
*** 374,377 ****
 test()
 else:
! help( eval( sys.argv[1] ) )
 
--- 447,450 ----
 test()
 else:
! help( sys.argv[1] )
 

AltStyle によって変換されたページ (->オリジナル) /