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
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}