Differences between revisions 1 and 3 (spanning 2 versions)
Revision 1 as of 2005-07-03 22:24:10
Size: 4160
Editor: aaron
Comment: (your python module + xrcgi.py) / (CGI directory) = instant XML-RPC
Revision 3 as of 2008-11-15 14:00:03
Size: 4233
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
[[TableOfContents()]] <<TableOfContents>>
Line 46: Line 46:
 * If you define a function "uli" ({{{def uli(msg):}}}), you can call it in IRC with [http://onebigsoup.wiki.taoriver.net/moin.cgi/UliBot UliBot!]  * If you define a function "uli" ({{{def uli(msg):}}}), you can call it in IRC with [[http://onebigsoup.wiki.taoriver.net/moin.cgi/UliBot|UliBot!]]
Line 127: Line 127:
            if func.__name__.startswith("_"):
                continue
Line 148: Line 150:
-- LionKimbro [[DateTime(2005-04-17T05:51:41Z)]] -- LionKimbro <<DateTime(2005-04-17T05:51:41Z)>>

This is a CGI version of the "automatic DocXmlRpcServer."

Tutorial

Suppose you have a Python module:

   1 def spam():
   2     return "spam"

How can we quickly share this functionality?

Mark it like this:

   1 XMLRPC_namespace = "eggs"
   2 
   3 def spam():
   4     return "spam"

Now, put that script, and the AutoXmlRpcCgi script, into a CGI directory. You're done!

You can use that function via XML-RPC on the CGI.

Your friends can now call your function!

   1 import xmlrpclib
   2 
   3 server = xmlrpclib.ServerProxy("http://example.net/xrcgi.py")
   4 print server.eggs.spam()

There it is!

Notes

Code: xrcgi.py

   1 #!/usr/bin/env python2.4
   2 """CGI between XML-RPC web requests, and specially marked modules.
   3 
   4 This script is a gateway (CGI) between web XML-RPC requests, and
   5 Python modules that define "XMLRPC_namespace".
   6 
   7 Functions within Modules that define the name "XMLRPC_namespace" are
   8 accessible by XML-RPC. Function names that begin with an underscore (ex:
   9 _eggs) are not published. Functions are published within the XML-RPC
  10 namespace designated by the XMLRPC_namespace value, or the base
  11 namespace if the value is None.
  12 """
  13 
  14 import time
  15 import os
  16 import sets
  17 import imp
  18 import types
  19 
  20 import DocXMLRPCServer
  21 
  22 
  23 def find_modules(path="."):
  24     """Return names of modules in a directory.
  25 
  26     Returns module names in a list. Filenames that end in ".py" or
  27     ".pyc" are considered to be modules. The extension is not included
  28     in the returned list.
  29     """
  30     modules = sets.Set()
  31     for filename in os.listdir(path):
  32         module = None
  33         if filename.endswith(".py"):
  34             module = filename[:-3]
  35         elif filename.endswith(".pyc"):
  36             module = filename[:-4]
  37         if module is not None:
  38             modules.add(module)
  39     return list(modules)
  40 
  41 
  42 def load_module(name, path=["."]):
  43     """Return a named module found in a given path."""
  44     (file, pathname, description) = imp.find_module(name, path)
  45     return imp.load_module(name, file, pathname, description)
  46 
  47 
  48 def find_xmlrpc_modules():
  49     """Find modules that define XMLRPC_namespace.
  50 
  51     Loads all modules in the current working directory. Returns a list
  52     of modules, the modules that define XMLRPC_namespace.
  53     """
  54     modules = [load_module(m) for m in find_modules()]
  55     xmlrpc_modules = []
  56     for m in modules:
  57         if m.__dict__.has_key("XMLRPC_namespace"):
  58             xmlrpc_modules.append(m)
  59     return xmlrpc_modules
  60 
  61 
  62 def functions_in_module(module):
  63     """Find all functions in a module."""
  64     functions = []
  65     for obj in module.__dict__.values():
  66         if isinstance(obj, types.FunctionType):
  67             functions.append(obj)
  68     return functions
  69 
  70 
  71 if __name__ == "__main__":
  72     handler = DocXMLRPCServer.DocCGIXMLRPCRequestHandler()
  73 
  74     for module in find_xmlrpc_modules():
  75         for func in functions_in_module(module):
  76             if func.__name__.startswith("_"):
  77                 continue
  78             full_name = func.__name__
  79             if module.XMLRPC_namespace is not None:
  80                 full_name = "%s.%s" % (module.XMLRPC_namespace,
  81                                        full_name)
  82             handler.register_function(func, full_name)
  83 
  84     handler.set_server_title("xrserver")
  85     handler.register_introspection_functions()
  86     handler.register_multicall_functions()
  87     handler.handle_request()

Discussion

This could be improved. Some ideas:

  • What if there's an exception while loading a module? What then?
  • Log modules successfully loaded.
    • If you're either brave or insane, make use of the LoggingModule.

  • Perhaps perform some sort of caching, to speed up invocation.

-- LionKimbro 2005-04-17 05:51:41

AutoXmlRpcCgi (last edited 2009-12-03 23:19:57 by vpn-8061f549)

Unable to edit the page? See the FrontPage for instructions.