예제 #1
0
 def func(ret, *args, **kwargs):
     rval = ret["response"] and from_pickle(ret["response"])
     reca = ret["recached"] and from_pickle(ret["recached"])
     # recache all indicated objects
     [clean_object_caches(obj) for obj in reca]
     if f: return f(rval, *args, **kwargs)
     else: return rval
예제 #2
0
    def executecode(self, source, environment):
        """
        Remote code execution

        source - Python code snippet
        environment - pickled dictionary of environment
                      variables. They are stored in
                      two keys "normal" and "objs" where
                      normal holds a dictionary of
                      normally pickled python objects
                      wheras objs points to a dictionary
                      of database represenations ((app,key),id).

        The environment's entries will be made available as
        local variables during the execution. Normal eval
        results will be returned as-is. For more complex
        code snippets (run by exec), the _return function
        is available: All data sent to _return(retval) will
        be returned from this system whenever the system
        finishes. Multiple calls to _return will result in
        a list being return. The return value is pickled
        and thus allows for returning any pickleable data.

        """

        class Ret(object):
            "Helper class for holding returns from exec"
            def __init__(self):
                self.returns = []
            def __call__(self, *args, **kwargs):
                self.returns.extend(list(args))
            def get_returns(self):
                lr = len(self.returns)
                if lr == 0:
                    return ""
                elif lr == 1:
                    return to_pickle(self.returns[0], emptypickle=False) or ""
                else:
                    return to_pickle(self.returns, emptypickle=False) or ""
        _return = Ret()


        available_vars = {'_return':_return}
        if environment:
            # load environment
            try:
                environment = from_pickle(environment)
                available_vars.update(environment)
            except Exception:
                logger.log_trace()
        # try to execute with eval first
        try:
            ret = eval(source, {}, available_vars)
            ret = _return.get_returns() or to_pickle(ret, emptypickle=False) or ""
        except Exception:
            # use exec instead
            exec source in available_vars
            ret = _return.get_returns()
        # get the list of affected objects to recache
        objs = list(set(PROC_MODIFIED_OBJS))
        # we need to include the locations too, to update their content caches
        objs = objs + list(set([o.location for o in objs if hasattr(o, "location") and o.location]))
        #print "objs:", objs
        #print "to_pickle", to_pickle(objs, emptypickle=False, do_pickle=False)
        to_recache = to_pickle(objs, emptypickle=False) or ""
        # empty the list without loosing memory reference
        PROC_MODIFIED_OBJS[:] = []
        return {'response': ret,
                'recached': to_recache}