Ejemplo n.º 1
0
class _ProxyModule(Module):
    '''
    A proxy to create dependencies on configurable module
    '''
    service = True

    def __init__(self, server):
        '''
        Constructor
        '''
        Module.__init__(self, server)
        self.proxyhandler = EventHandler(self.scheduler)

    def load(self, container):
        self._targetname = self._proxytarget._instance.getServiceName()
        self.proxyhandler.registerHandler(
            ModuleAPICall.createMatcher(None, self.getServiceName()),
            self._proxyhandler)
        for m in Module.load(self, container):
            yield m

    def unload(self, container, force=False):
        self.proxyhandler.close()
        for m in Module.unload(self, container, force=force):
            yield m

    def _proxyhandler(self, event, scheduler):
        event.canignore = True
        scheduler.emergesend(
            ModuleAPICall(event.handle,
                          self._targetname,
                          event.name,
                          params=event.params))
Ejemplo n.º 2
0
class _ProxyModule(Module):
    '''
    A proxy to create dependencies on configurable module
    '''
    service = True
    def __init__(self, server):
        '''
        Constructor
        '''
        Module.__init__(self, server)        
        self.proxyhandler = EventHandler(self.scheduler)
    def load(self, container):
        self._targetname = self._proxytarget._instance.getServiceName()
        self.proxyhandler.registerHandler(ModuleAPICall.createMatcher(None, self.getServiceName()), self._proxyhandler)
        for m in Module.load(self, container):
            yield m
    def unload(self, container, force=False):
        self.proxyhandler.close()
        for m in Module.unload(self, container, force=force):
            yield m
    def _proxyhandler(self, event, scheduler):
        event.canignore = True
        scheduler.emergesend(ModuleAPICall(event.handle, self._targetname, event.name, params = event.params))        
Ejemplo n.º 3
0
class ModuleAPIHandler(RoutineContainer):
    """
    API Handler for modules
    """
    def __init__(self, moduleinst, apidefs = None, allowdiscover = True, rejectunknown = True):
        RoutineContainer.__init__(self, scheduler=moduleinst.scheduler, daemon=False)
        self.handler = EventHandler(self.scheduler)
        self.servicename = moduleinst.getServiceName()
        self.apidefs = apidefs
        self.registeredAPIs = {}
        self.discoverinfo = {}
        self.allowdiscover = allowdiscover
        self.rejectunknown = rejectunknown
    @staticmethod
    def createReply(handle, result):
        return ModuleAPIReply(handle, result=result)
    @staticmethod
    def createExceptionReply(handle, exception):
        return ModuleAPIReply(handle, exception = exception)
    def _createHandler(self, name, handler, container = None, discoverinfo = None, criteria = None):
        extra_params = {}
        if criteria:
            extra_params['_ismatch'] = lambda e: not e.canignore and criteria(**e.params)
        if name is None:
            matcher = ModuleAPICall.createMatcher(target = self.servicename, **extra_params)
        elif name.startswith('public/'):
            matcher = ModuleAPICall.createMatcher(target = 'public', name = name[len('public/'):], **extra_params)
        else:
            matcher = ModuleAPICall.createMatcher(target = self.servicename, name = name, **extra_params)
        if container is not None:
            async def wrapper(event):
                try:
                    r = await handler(event.name, event.params)
                    await container.wait_for_send(self.createReply(event.handle, r))
                except Exception as val:
                    await container.wait_for_send(self.createExceptionReply(event.handle, val))
            def event_handler(event, scheduler):
                event.canignore = True
                container.subroutine(wrapper(event), False)
        else:
            async def wrapper(event):
                try:
                    result = handler(event.name, event.params)
                    await self.wait_for_send(self.createReply(event.handle, result))
                except Exception as val:
                    await self.wait_for_send(self.createExceptionReply(event.handle, val))
            def event_handler(event, scheduler):
                event.canignore = True
                self.subroutine(wrapper(event), False)
        return (matcher, event_handler)
    def registerAPIs(self, apidefs):
        '''
        API definition is in format: `(name, handler, container, discoverinfo)`
        
        if the handler is a generator, container should be specified
        handler should accept two arguments::
        
            def handler(name, params):
                ...
        
        `name` is the method name, `params` is a dictionary contains the parameters.
        
        the handler can either return the result directly, or be a generator (async-api),
        and write the result to container.retvalue on exit.
        e.g::
        
            ('method1', self.method1),    # method1 directly returns the result
            ('method2', self.method2, self) # method2 is an async-api
        
        Use api() to automatically generate API definitions.
        '''
        handlers = [self._createHandler(*apidef) for apidef in apidefs]
        self.handler.registerAllHandlers(handlers)
        self.discoverinfo.update((apidef[0], apidef[3] if len(apidef) > 3 else {'description':cleandoc(apidef[1].__doc__)}) for apidef in apidefs)
    def registerAPI(self, name, handler, container = None, discoverinfo = None, criteria = None):
        """
        Append new API to this handler
        """
        self.handler.registerHandler(*self._createHandler(name, handler, container, criteria))
        if discoverinfo is None:
            self.discoverinfo[name] = {'description': cleandoc(handler.__doc__)}
        else:
            self.discoverinfo[name] = discoverinfo
    def unregisterAPI(self, name):
        """
        Remove an API from this handler
        """
        if name.startswith('public/'):
            target = 'public'
            name = name[len('public/'):]
        else:
            target = self.servicename
            name = name
        removes = [m for m in self.handler.handlers.keys() if m.target == target and m.name == name]
        for m in removes:
            self.handler.unregisterHandler(m)
    def discover(self, details = False):
        'Discover API definitions. Set details=true to show details'
        if details and not (isinstance(details, str) and details.lower() == 'false'):
            return copy.deepcopy(self.discoverinfo)
        else:
            return dict((k,v.get('description', '')) for k,v in self.discoverinfo.items())
    def reject(self, name, args):
        raise APIRejectedException('%r is not defined in module %r' % (name, self.servicename))
    def start(self, asyncStart=False):
        if self.apidefs:
            self.registerAPIs(self.apidefs)
        if self.allowdiscover:
            self.registerAPI(*api(self.discover))
        if self.rejectunknown:
            self.handler.registerHandler(*self._createHandler(None, self.reject, None))
    def close(self):
        self.handler.close()
Ejemplo n.º 4
0
class ModuleAPIHandler(RoutineContainer):
    """
    API Handler for modules
    """
    def __init__(self, moduleinst, apidefs = None, allowdiscover = True, rejectunknown = True):
        RoutineContainer.__init__(self, scheduler=moduleinst.scheduler, daemon=False)
        self.handler = EventHandler(self.scheduler)
        self.servicename = moduleinst.getServiceName()
        self.apidefs = apidefs
        self.registeredAPIs = {}
        self.discoverinfo = {}
        self.allowdiscover = allowdiscover
        self.rejectunknown = True
    @staticmethod
    def createReply(handle, result):
        return ModuleAPIReply(handle, result=result)
    @staticmethod
    def createExceptionReply(handle, exception):
        return ModuleAPIReply(handle, exception = exception)
    def _createHandler(self, name, handler, container = None, discoverinfo = None, criteria = None):
        extra_params = {}
        if criteria:
            extra_params['_ismatch'] = lambda e: not e.canignore and criteria(**e.params)
        if name is None:
            matcher = ModuleAPICall.createMatcher(target = self.servicename, **extra_params)
            matcher = ModuleAPICall.createMatcher(target = self.servicename, **extra_params)
        elif name.startswith('public/'):
            matcher = ModuleAPICall.createMatcher(target = 'public', name = name[len('public/'):], **extra_params)
        else:
            matcher = ModuleAPICall.createMatcher(target = self.servicename, name = name, **extra_params)
        if container is not None:
            def wrapper(event):
                try:
                    for m in handler(event.name, event.params):
                        yield m
                    for m in container.waitForSend(self.createReply(event.handle, container.retvalue)):
                        yield m
                except Exception as val:
                    for m in container.waitForSend(self.createExceptionReply(event.handle, val)):
                        yield m
            def event_handler(event, scheduler):
                event.canignore = True
                container.subroutine(wrapper(event), False)
        else:
            def wrapper(event):
                try:
                    result = handler(event.name, event.params)
                    for m in self.waitForSend(self.createReply(event.handle, result)):
                        yield m
                except Exception as val:
                    for m in self.waitForSend(self.createExceptionReply(event.handle, val)):
                        yield m
            def event_handler(event, scheduler):
                event.canignore = True
                self.subroutine(wrapper(event), False)
        return (matcher, event_handler)
    def registerAPIs(self, apidefs):
        '''
        API definition is in format: `(name, handler, container, discoverinfo)`
        
        if the handler is a generator, container should be specified
        handler should accept two arguments::
        
            def handler(name, params):
                ...
        
        `name` is the method name, `params` is a dictionary contains the parameters.
        
        the handler can either return the result directly, or be a generator (async-api),
        and write the result to container.retvalue on exit.
        e.g::
        
            ('method1', self.method1),    # method1 directly returns the result
            ('method2', self.method2, self) # method2 is an async-api
        
        Use api() to automatically generate API definitions.
        '''
        handlers = [self._createHandler(*apidef) for apidef in apidefs]
        self.handler.registerAllHandlers(handlers)
        self.discoverinfo.update((apidef[0], apidef[3] if len(apidef) > 3 else {'description':cleandoc(apidef[1].__doc__)}) for apidef in apidefs)
    def registerAPI(self, name, handler, container = None, discoverinfo = None, criteria = None):
        """
        Append new API to this handler
        """
        self.handler.registerHandler(*self._createHandler(name, handler, container, criteria))
        if discoverinfo is None:
            self.discoverinfo[name] = {'description': cleandoc(handler.__doc__)}
        else:
            self.discoverinfo[name] = discoverinfo
    def unregisterAPI(self, name):
        """
        Remove an API from this handler
        """
        if name.startswith('public/'):
            target = 'public'
            name = name[len('public/'):]
        else:
            target = self.servicename
            name = name
        removes = [m for m in self.handler.handlers.keys() if m.target == target and m.name == name]
        for m in removes:
            self.handler.unregisterHandler(m)
    def discover(self, details = False):
        'Discover API definitions. Set details=true to show details'
        if details and not (isinstance(details, str) and details.lower() == 'false'):
            return copy.deepcopy(self.discoverinfo)
        else:
            return dict((k,v.get('description', '')) for k,v in self.discoverinfo.items())
    def reject(self, name, args):
        raise ValueError('%r is not defined in module %r' % (name, self.servicename))
    def start(self, asyncStart=False):
        if self.apidefs:
            self.registerAPIs(self.apidefs)
        if self.allowdiscover:
            self.registerAPI(*api(self.discover))
        if self.rejectunknown:
            self.handler.registerHandler(*self._createHandler(None, self.reject, None))
    def close(self):
        self.handler.close()