All pastes #34774 Raw Edit

Python

public python v1 · immutable
#34774 ·published 2005-12-24 03:09 UTC
rendered paste body
try:    from cStringIO import StringIOexcept ImportError:    from StringIO import StringIOimport xmlrpclibimport sysfrom trac.core import *from trac.perm import IPermissionRequestorfrom trac.web.main import IRequestHandlerfrom trac.wiki.api import WikiSystemfrom trac.wiki.model import WikiPageRPC_TYPES = {int: 'int', bool: 'boolean', str: 'string', float: 'double',             xmlrpclib.DateTime: 'dateTime.iso8601', xmlrpclib.base64: 'base64',             list: 'array', dict: 'struct'}class IXmlRpcHandler(Interface):    def xmlrpc_module():        pass    def xmlrpc_methods():        passclass AbstractRpcHandler(Component):    implements(IXmlRpcHandler)    abstract = True    def _init_methods(self):        import inspect        self._rpc_methods = {}        for name, val in inspect.getmembers(self):            if hasattr(val, '_xml_rpc_signatures'):                self._rpc_methods[name] = val._xml_rpc_signatures        self.log.debug('init: %s %s' % (self.__class__, self._rpc_methods))    def xmlrpc_methods(self):        if not hasattr(self, '_rpc_methods'):            self._init_methods()        return self._rpc_methodsdef expose_rpc(return_type, *arg_types):    def decorator(func):        if not hasattr(func, '_xml_rpc_signatures'):            func._xml_rpc_signatures = []        func._xml_rpc_signatures.append((return_type,) + tuple(arg_types))        return func    return decoratorclass XmlRpcModule(AbstractRpcHandler):    implements(IPermissionRequestor, IRequestHandler)    rpc_handlers = ExtensionPoint(IXmlRpcHandler)    def get_permission_actions(self):        return ['XML_RPC']    def match_request(self, req):        return req.path_info == '/xmlrpc'    def process_request(self, req):        try:            req.perm.assert_permission('XML_RPC')            xml = req.read(int(req.get_header('Content-Length')))            params, method = xmlrpclib.loads(xml)            result = self._call(method, params, req)            if result is None:                raise xmlrpclib.Fault(4, 'Method call did not return a value')            result = xmlrpclib.dumps((result,), methodresponse=True)        except:            self.log.error(sys.exc_value)            result = xmlrpclib.dumps(self._wrap_except())        req.send_response(200)        req.send_header('Content-Type', 'text/xml')        req.end_headers()        req.write(result)    def _get_info(self, method):        parts = method.split('.', 1)        if len(parts) < 2:            return None        moduleName, methodName = parts        module = None        for rpc in self.rpc_handlers:            if rpc.xmlrpc_module() == moduleName:                module = rpc                break        if not module or methodName not in module.xmlrpc_methods():            return None        return module, methodName    def _get_method(self, method):        info = self._get_info(method)        if not info:            return None        module, methodName = info        return getattr(module, methodName)    def _get_sig(self, method):        info = self._get_info(method)        if not info:            return None        module, methodName = info        return module.xmlrpc_methods()[methodName]    def _call(self, methodName, params, req):        func = self._get_method(methodName)        if func:            return func(req, *params)        else:            raise xmlrpclib.Fault(2, 'Unknown method')    def _wrap_except(self):        e = sys.exc_value        if isinstance(e, xmlrpclib.Fault):            return e        return xmlrpclib.Fault(1, '%s:%s' % (sys.exc_type, e))    def xmlrpc_module(self):        return 'system'    @expose_rpc(list)    def listMethods(self, req):        methods = []        for rpc in self.rpc_handlers:            module = rpc.xmlrpc_module()            for method in rpc.xmlrpc_methods():                methods.append('.'.join((module, method)))        return methods    @expose_rpc(str, str)    def methodHelp(self, req, methodName):        func = self._get_method(methodName)        if func:            import pydoc            return pydoc.getdoc(func)        else:            raise xmlrpclib.Fault(3, "Can't get help for unknown method: %s"                                     % methodName)    @expose_rpc(list, str)    def methodSignature(self, req, methodName):        sig = self._get_sig(methodName)        return [', '.join([RPC_TYPES[t] for t in s]) for s in sig]    @expose_rpc(list, dict)    def multicall(self, req, callParams):        results = []        for meth_sig in callParams:            try:                r = [self._call(**meth_sig)]            except:                r = self._wrap_except()            results.append(r)        return resultsclass WikiRpc(AbstractRpcHandler):    def __init__(self):        self.wiki = WikiSystem(self.env)    def xmlrpc_module(self):        return 'wiki'    def _to_timestamp(self, datetime):        import time        return time.mktime(time.strptime(datetime.value, '%Y%m%dT%H:%M:%S'))    def _page_info(self, name, time, author, version):        return dict(name=name, lastModified=xmlrpclib.DateTime(int(time)),                    author=author, version=int(version))    @expose_rpc(dict, xmlrpclib.DateTime)    def getRecentChanges(self, req, since):        req.perm.assert_permission('WIKI_VIEW')        since = self._to_timestamp(since)        db = self.env.get_db_cnx()        cursor = db.cursor()        cursor.execute('SELECT name, max(time), author, version FROM wiki'                       ' WHERE time >= %s GROUP BY name ORDER BY max(time) DESC', since)        result = []        for name, time, author, version in cursor:            result.append(self._page_info(name, time, author, version))        return result    @expose_rpc(int)    def getRPCVersionSupported(self, req):        req.perm.assert_permission('WIKI_VIEW')        return 2    @expose_rpc(str, str)    @expose_rpc(str, str, int)    def getPage(self, req, pagename, version=None):        req.perm.assert_permission('WIKI_VIEW')        page = WikiPage(self.env, pagename, version)        if page.exists:            return page.text        else:            msg = 'Wiki page "%s" does not exist' % pagename            if version is not None:                msg += ' at version %s' % version            raise xmlrpclib.Fault(0, msg)    getPageVersion = getPage    @expose_rpc(str, str)    @expose_rpc(str, str, int)    def getPageHTML(self, req, pagename, version=None):        req.perm.assert_permission('WIKI_VIEW')        pass    getPageHTMLVersion = getPageHTML    @expose_rpc(list)    def getAllPages(self, req):        '''        Returns a list of all pages.        The result is an array of utf8 pagenames.        '''        req.perm.assert_permission('WIKI_VIEW')        return list(self.wiki.get_pages())    @expose_rpc(dict, str)    @expose_rpc(dict, str, int)    def getPageInfo(self, req, pagename, version=None):        req.perm.assert_permission('WIKI_VIEW')        page = WikiPage(self.env, pagename, version)        if page.exists:            return self._page_info(page.name, page.time, page.author,                                   page.version)    getPageInfoVersion = getPageInfo    def listLinks(self, req, pagename):        req.perm.assert_permission('WIKI_VIEW')        pass