def func(ret, *args, **kwargs):
     rval = ret["response"] and from_pickle(do_unpickle(ret["response"]))
     reca = ret["recached"] and from_pickle(do_unpickle(ret["recached"]))
     # recache all indicated objects
     [clean_object_caches(obj) for obj in reca]
     if f: return f(rval, *args, **kwargs)
     else: return rval
 def func(ret, *args, **kwargs):
     rval = ret["response"] and from_pickle(do_unpickle(ret["response"]))
     reca = ret["recached"] and from_pickle(do_unpickle(ret["recached"]))
     # recache all indicated objects
     [clean_object_caches(obj) for obj in reca]
     if f:
         return f(rval, *args, **kwargs)
     else:
         return rval
Example #3
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)
                val = lr and (lr == 1 and self.returns[0] or self.returns) or None
                if val not in (None, [], ()):
                    return do_pickle(to_pickle(val))
                else:
                    return ""

        _return = Ret()

        available_vars = {"_return": _return}
        if environment:
            # load environment
            try:
                environment = from_pickle(do_unpickle(environment))
                available_vars.update(environment)
            except Exception:
                logger.log_trace()
        # try to execute with eval first
        try:
            ret = eval(source, {}, available_vars)
            if ret not in (None, [], ()):
                ret = _return.get_returns() or do_pickle(to_pickle(ret))
            else:
                ret = ""
        except Exception:
            # use exec instead
            exec source in available_vars
            ret = _return.get_returns()
        # get the list of affected objects to recache
        objs = PROC_MODIFIED_OBJS.values()
        # 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)
        if objs not in (None, [], ()):
            to_recache = do_pickle(to_pickle(objs))
        else:
            to_recache = ""
        # empty the list without loosing memory reference
        # PROC_MODIFIED_OBJS[:] = []
        PROC_MODIFIED_OBJS.clear()  # TODO - is this not messing anything up?
        return {"response": ret, "recached": to_recache}
Example #4
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)
                val = lr and (lr == 1 and self.returns[0]
                              or self.returns) or None
                if val not in (None, [], ()):
                    return do_pickle(to_pickle(val))
                else:
                    return ""

        _return = Ret()

        available_vars = {'_return': _return}
        if environment:
            # load environment
            try:
                environment = from_pickle(do_unpickle(environment))
                available_vars.update(environment)
            except Exception:
                logger.log_trace()
        # try to execute with eval first
        try:
            ret = eval(source, {}, available_vars)
            if ret not in (None, [], ()):
                ret = _return.get_returns() or do_pickle(to_pickle(ret))
            else:
                ret = ""
        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)
        if objs not in (None, [], ()):
            to_recache = do_pickle(to_pickle(objs))
        else:
            to_recache = ""
        # empty the list without loosing memory reference
        PROC_MODIFIED_OBJS[:] = []
        return {'response': ret, 'recached': to_recache}