symbian-qemu-0.9.1-12/python-2.6.1/Lib/DocXMLRPCServer.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """Self documenting XML-RPC Server.
       
     2 
       
     3 This module can be used to create XML-RPC servers that
       
     4 serve pydoc-style documentation in response to HTTP
       
     5 GET requests. This documentation is dynamically generated
       
     6 based on the functions and methods registered with the
       
     7 server.
       
     8 
       
     9 This module is built upon the pydoc and SimpleXMLRPCServer
       
    10 modules.
       
    11 """
       
    12 
       
    13 import pydoc
       
    14 import inspect
       
    15 import re
       
    16 import sys
       
    17 
       
    18 from SimpleXMLRPCServer import (SimpleXMLRPCServer,
       
    19             SimpleXMLRPCRequestHandler,
       
    20             CGIXMLRPCRequestHandler,
       
    21             resolve_dotted_attribute)
       
    22 
       
    23 class ServerHTMLDoc(pydoc.HTMLDoc):
       
    24     """Class used to generate pydoc HTML document for a server"""
       
    25 
       
    26     def markup(self, text, escape=None, funcs={}, classes={}, methods={}):
       
    27         """Mark up some plain text, given a context of symbols to look for.
       
    28         Each context dictionary maps object names to anchor names."""
       
    29         escape = escape or self.escape
       
    30         results = []
       
    31         here = 0
       
    32 
       
    33         # XXX Note that this regular expression does not allow for the
       
    34         # hyperlinking of arbitrary strings being used as method
       
    35         # names. Only methods with names consisting of word characters
       
    36         # and '.'s are hyperlinked.
       
    37         pattern = re.compile(r'\b((http|ftp)://\S+[\w/]|'
       
    38                                 r'RFC[- ]?(\d+)|'
       
    39                                 r'PEP[- ]?(\d+)|'
       
    40                                 r'(self\.)?((?:\w|\.)+))\b')
       
    41         while 1:
       
    42             match = pattern.search(text, here)
       
    43             if not match: break
       
    44             start, end = match.span()
       
    45             results.append(escape(text[here:start]))
       
    46 
       
    47             all, scheme, rfc, pep, selfdot, name = match.groups()
       
    48             if scheme:
       
    49                 url = escape(all).replace('"', '"')
       
    50                 results.append('<a href="%s">%s</a>' % (url, url))
       
    51             elif rfc:
       
    52                 url = 'http://www.rfc-editor.org/rfc/rfc%d.txt' % int(rfc)
       
    53                 results.append('<a href="%s">%s</a>' % (url, escape(all)))
       
    54             elif pep:
       
    55                 url = 'http://www.python.org/dev/peps/pep-%04d/' % int(pep)
       
    56                 results.append('<a href="%s">%s</a>' % (url, escape(all)))
       
    57             elif text[end:end+1] == '(':
       
    58                 results.append(self.namelink(name, methods, funcs, classes))
       
    59             elif selfdot:
       
    60                 results.append('self.<strong>%s</strong>' % name)
       
    61             else:
       
    62                 results.append(self.namelink(name, classes))
       
    63             here = end
       
    64         results.append(escape(text[here:]))
       
    65         return ''.join(results)
       
    66 
       
    67     def docroutine(self, object, name, mod=None,
       
    68                    funcs={}, classes={}, methods={}, cl=None):
       
    69         """Produce HTML documentation for a function or method object."""
       
    70 
       
    71         anchor = (cl and cl.__name__ or '') + '-' + name
       
    72         note = ''
       
    73 
       
    74         title = '<a name="%s"><strong>%s</strong></a>' % (
       
    75             self.escape(anchor), self.escape(name))
       
    76 
       
    77         if inspect.ismethod(object):
       
    78             args, varargs, varkw, defaults = inspect.getargspec(object.im_func)
       
    79             # exclude the argument bound to the instance, it will be
       
    80             # confusing to the non-Python user
       
    81             argspec = inspect.formatargspec (
       
    82                     args[1:],
       
    83                     varargs,
       
    84                     varkw,
       
    85                     defaults,
       
    86                     formatvalue=self.formatvalue
       
    87                 )
       
    88         elif inspect.isfunction(object):
       
    89             args, varargs, varkw, defaults = inspect.getargspec(object)
       
    90             argspec = inspect.formatargspec(
       
    91                 args, varargs, varkw, defaults, formatvalue=self.formatvalue)
       
    92         else:
       
    93             argspec = '(...)'
       
    94 
       
    95         if isinstance(object, tuple):
       
    96             argspec = object[0] or argspec
       
    97             docstring = object[1] or ""
       
    98         else:
       
    99             docstring = pydoc.getdoc(object)
       
   100 
       
   101         decl = title + argspec + (note and self.grey(
       
   102                '<font face="helvetica, arial">%s</font>' % note))
       
   103 
       
   104         doc = self.markup(
       
   105             docstring, self.preformat, funcs, classes, methods)
       
   106         doc = doc and '<dd><tt>%s</tt></dd>' % doc
       
   107         return '<dl><dt>%s</dt>%s</dl>\n' % (decl, doc)
       
   108 
       
   109     def docserver(self, server_name, package_documentation, methods):
       
   110         """Produce HTML documentation for an XML-RPC server."""
       
   111 
       
   112         fdict = {}
       
   113         for key, value in methods.items():
       
   114             fdict[key] = '#-' + key
       
   115             fdict[value] = fdict[key]
       
   116 
       
   117         server_name = self.escape(server_name)
       
   118         head = '<big><big><strong>%s</strong></big></big>' % server_name
       
   119         result = self.heading(head, '#ffffff', '#7799ee')
       
   120 
       
   121         doc = self.markup(package_documentation, self.preformat, fdict)
       
   122         doc = doc and '<tt>%s</tt>' % doc
       
   123         result = result + '<p>%s</p>\n' % doc
       
   124 
       
   125         contents = []
       
   126         method_items = sorted(methods.items())
       
   127         for key, value in method_items:
       
   128             contents.append(self.docroutine(value, key, funcs=fdict))
       
   129         result = result + self.bigsection(
       
   130             'Methods', '#ffffff', '#eeaa77', pydoc.join(contents))
       
   131 
       
   132         return result
       
   133 
       
   134 class XMLRPCDocGenerator:
       
   135     """Generates documentation for an XML-RPC server.
       
   136 
       
   137     This class is designed as mix-in and should not
       
   138     be constructed directly.
       
   139     """
       
   140 
       
   141     def __init__(self):
       
   142         # setup variables used for HTML documentation
       
   143         self.server_name = 'XML-RPC Server Documentation'
       
   144         self.server_documentation = \
       
   145             "This server exports the following methods through the XML-RPC "\
       
   146             "protocol."
       
   147         self.server_title = 'XML-RPC Server Documentation'
       
   148 
       
   149     def set_server_title(self, server_title):
       
   150         """Set the HTML title of the generated server documentation"""
       
   151 
       
   152         self.server_title = server_title
       
   153 
       
   154     def set_server_name(self, server_name):
       
   155         """Set the name of the generated HTML server documentation"""
       
   156 
       
   157         self.server_name = server_name
       
   158 
       
   159     def set_server_documentation(self, server_documentation):
       
   160         """Set the documentation string for the entire server."""
       
   161 
       
   162         self.server_documentation = server_documentation
       
   163 
       
   164     def generate_html_documentation(self):
       
   165         """generate_html_documentation() => html documentation for the server
       
   166 
       
   167         Generates HTML documentation for the server using introspection for
       
   168         installed functions and instances that do not implement the
       
   169         _dispatch method. Alternatively, instances can choose to implement
       
   170         the _get_method_argstring(method_name) method to provide the
       
   171         argument string used in the documentation and the
       
   172         _methodHelp(method_name) method to provide the help text used
       
   173         in the documentation."""
       
   174 
       
   175         methods = {}
       
   176 
       
   177         for method_name in self.system_listMethods():
       
   178             if method_name in self.funcs:
       
   179                 method = self.funcs[method_name]
       
   180             elif self.instance is not None:
       
   181                 method_info = [None, None] # argspec, documentation
       
   182                 if hasattr(self.instance, '_get_method_argstring'):
       
   183                     method_info[0] = self.instance._get_method_argstring(method_name)
       
   184                 if hasattr(self.instance, '_methodHelp'):
       
   185                     method_info[1] = self.instance._methodHelp(method_name)
       
   186 
       
   187                 method_info = tuple(method_info)
       
   188                 if method_info != (None, None):
       
   189                     method = method_info
       
   190                 elif not hasattr(self.instance, '_dispatch'):
       
   191                     try:
       
   192                         method = resolve_dotted_attribute(
       
   193                                     self.instance,
       
   194                                     method_name
       
   195                                     )
       
   196                     except AttributeError:
       
   197                         method = method_info
       
   198                 else:
       
   199                     method = method_info
       
   200             else:
       
   201                 assert 0, "Could not find method in self.functions and no "\
       
   202                           "instance installed"
       
   203 
       
   204             methods[method_name] = method
       
   205 
       
   206         documenter = ServerHTMLDoc()
       
   207         documentation = documenter.docserver(
       
   208                                 self.server_name,
       
   209                                 self.server_documentation,
       
   210                                 methods
       
   211                             )
       
   212 
       
   213         return documenter.page(self.server_title, documentation)
       
   214 
       
   215 class DocXMLRPCRequestHandler(SimpleXMLRPCRequestHandler):
       
   216     """XML-RPC and documentation request handler class.
       
   217 
       
   218     Handles all HTTP POST requests and attempts to decode them as
       
   219     XML-RPC requests.
       
   220 
       
   221     Handles all HTTP GET requests and interprets them as requests
       
   222     for documentation.
       
   223     """
       
   224 
       
   225     def do_GET(self):
       
   226         """Handles the HTTP GET request.
       
   227 
       
   228         Interpret all HTTP GET requests as requests for server
       
   229         documentation.
       
   230         """
       
   231         # Check that the path is legal
       
   232         if not self.is_rpc_path_valid():
       
   233             self.report_404()
       
   234             return
       
   235 
       
   236         response = self.server.generate_html_documentation()
       
   237         self.send_response(200)
       
   238         self.send_header("Content-type", "text/html")
       
   239         self.send_header("Content-length", str(len(response)))
       
   240         self.end_headers()
       
   241         self.wfile.write(response)
       
   242 
       
   243         # shut down the connection
       
   244         self.wfile.flush()
       
   245         self.connection.shutdown(1)
       
   246 
       
   247 class DocXMLRPCServer(  SimpleXMLRPCServer,
       
   248                         XMLRPCDocGenerator):
       
   249     """XML-RPC and HTML documentation server.
       
   250 
       
   251     Adds the ability to serve server documentation to the capabilities
       
   252     of SimpleXMLRPCServer.
       
   253     """
       
   254 
       
   255     def __init__(self, addr, requestHandler=DocXMLRPCRequestHandler,
       
   256                  logRequests=1, allow_none=False, encoding=None,
       
   257                  bind_and_activate=True):
       
   258         SimpleXMLRPCServer.__init__(self, addr, requestHandler, logRequests,
       
   259                                     allow_none, encoding, bind_and_activate)
       
   260         XMLRPCDocGenerator.__init__(self)
       
   261 
       
   262 class DocCGIXMLRPCRequestHandler(   CGIXMLRPCRequestHandler,
       
   263                                     XMLRPCDocGenerator):
       
   264     """Handler for XML-RPC data and documentation requests passed through
       
   265     CGI"""
       
   266 
       
   267     def handle_get(self):
       
   268         """Handles the HTTP GET request.
       
   269 
       
   270         Interpret all HTTP GET requests as requests for server
       
   271         documentation.
       
   272         """
       
   273 
       
   274         response = self.generate_html_documentation()
       
   275 
       
   276         print 'Content-Type: text/html'
       
   277         print 'Content-Length: %d' % len(response)
       
   278         print
       
   279         sys.stdout.write(response)
       
   280 
       
   281     def __init__(self):
       
   282         CGIXMLRPCRequestHandler.__init__(self)
       
   283         XMLRPCDocGenerator.__init__(self)