I'm using pyAMF in my app, but I want to set smart service like explained here:

341 views Asked by At

In a normal application i set services

services = {
    'users.login': login,
    'test': router
}

but I would like to do like this:

services = [
    'users.login',
    'test'
]

and every request goes to router function. this takes 2 params: service name (can be "users.login" or "test" in this case) and input (that is the object sent by flex to python) then if the command(service) from flex is named "users.login". I would like to run the router with the params and then this will open the function login in the commands.users.login package. How would I do that? Thanks.

2

There are 2 answers

0
Totty.js On BEST ANSWER

Solved last night!

from pyamf.remoting.gateway.google import WebAppGateway
import logging

class TottysGateway(WebAppGateway):
def __init__(self, services_available, root_path, not_found_service, logger, debug):
    # override the contructor and then call the super
    self.services_available = services_available
    self.root_path = root_path
    self.not_found_service = not_found_service
    WebAppGateway.__init__(self, {}, logger=logging, debug=True)

def getServiceRequest(self, request, target):
    # override the original getServiceRequest method
    try:
        # try looking for the service in the services list
        return WebAppGateway.getServiceRequest(self, request, target)
    except:
        pass

    try:
        # don't know what it does but is an error for now
        service_func = self.router(target)
    except:
        if(target in self.services_available):
            # only if is an available service import it's module
            # so it doesn't access services that should be hidden
            try:
                module_path = self.root_path + '.' + target
                paths = target.rsplit('.')
                func_name = paths[len(paths) - 1]
                import_as = '_'.join(paths) + '_' + func_name
                import_string = "from "+module_path+" import "+func_name+' as service_func'
                exec import_string
            except:
                service_func = False

    if(not service_func):
        # if is not found load the default not found service
        module_path = self.rootPath + '.' + self.not_found_service
        import_string = "from "+module_path+" import "+func_name+' as service_func'

    # add the service loaded above
    assign_string = "self.addService(service_func, target)"
    exec assign_string

    return WebAppGateway.getServiceRequest(self, request, target)
1
njoyce On

If I understand your question correctly, in order to achieve this, you are going to need to to override getServiceRequest on the Gateway class that you are using:

from pyamf.remoting.gateway.django import DjangoGateway
from pyamf.remoting.gateway import UnknownServiceError


class MyGateway(DjangoGateway):
    def __init__(self, router_func, **kwargs):
        self.router = router_func

        DjangoGateway.__init__(self, **kwargs)

    def getServiceRequest(self, request, target):
        try:
            return DjangoGateway.getServiceRequest(self, request, target)
        except UnknownServiceError, e:
            pass

        # cached service was not found, try to discover it
        try:
            service_func = self.router(target)
        except:
            # perhaps some logging here
            service_func = None

        if not service_func:
            # couldn't find a service matching `target`, crap out appropriately
            raise e

        self.addService(service_func, target)

        return DjangoGateway.getServiceRequest(self, request, target)

self.router is a function that you supply to the constructor of the gateway. It takes the string target of the AMF remoting request and returns a matching function. If it returns None or raises an exception, an unknown service response will be returned to the requestor.

Hopefully this goes some way to laying the groundwork for what you require.