def generic(func): typemap = {(object,) * len(dispatch_args): func} def when_type(*types): "Decorator to add a method that will be called for the given types" if len(types) != len(dispatch_args): raise TypeError('Length mismatch: expected %d types, got %d' % (len(dispatch_args), len(types))) def dec(f): typemap[types] = f return f return dec def dispatch(dispatch_args, *args, **kw): types = tuple(type(arg) for arg in dispatch_args) try: # fast path return typemap[types](*args, **kw) except KeyError: pass _gettypemap = typemap.get for types in itertools.product(*(t.__mro__ for t in types)): f = _gettypemap(types) if f is not None: return f(*args, **kw) # else call the default implementation return func(*args, **kw) return FunctionMaker.create( func, 'return _f_({}, %(shortsignature)s)'.format(dispatch_str), dict(_f_=dispatch), when_type=when_type, default=func, typemap=typemap)
def generate_ui_command(self, display_name, name=None, argspec=None, method=None, function=None): if name is None: name = display_name if argspec.args[0] == "self": argspec.args.pop(0) signature = "%s(self, %s)" % (name, inspect.formatargspec(formatvalue=lambda val: "", *argspec)[1:-1]) # logger.error('sig=%s', signature) def func(self, *args, **kwargs): command = func.__command__ return self(_meth=command, *args, **kwargs) func = FunctionMaker.create( signature, # "return _func_(self, command, %(shortsignature)s)", "return _func_(%(shortsignature)s)", dict(_func_=func), __command__=name, ) func = types.MethodType(func, self) setattr(self, name, func) self._generated_ui_commands[name] = func
def decorator_apply(dec, func): """ Decorate a function by preserving the signature even if dec is not a signature-preserving decorator. """ return FunctionMaker.create( func, 'return decfunc(%(signature)s)', dict(decfunc=dec(func)), __wrapped__=func)
def replace_funct(fnc, body): """Returns a function with a new body that replaces the given function. The signature of the original function is preserved in the new function. """ fname = fnc.__name__ spec = getargspec(fnc) sig = formatargspec(*spec) return FunctionMaker.create('%s%s' % (fname,sig), body, {}, defaults=spec[3], doc=fnc.__doc__)
def decorator_apply(dec, func): """Decorate a function by preserving the signature even if dec is not a signature-preserving decorator. This recipe is derived from http://micheles.googlecode.com/hg/decorator/documentation.html#id14 """ return FunctionMaker.create( func, 'return decorated(%(signature)s)', dict(decorated=dec(func)), __wrapped__=func)
def decorator_apply(dec, func): """Decorate a function by preserving the signature even if dec is not a signature-preserving decorator. This recipe is derived from http://micheles.googlecode.com/hg/decorator/documentation.html#id14 """ return FunctionMaker.create(func, 'return decorated(%(signature)s)', dict(decorated=dec(func)), __wrapped__=func)
def _rpc(func): global _rpc_next_id, _rpc_map # Store function in the call map func_id = _rpc_next_id _rpc_next_id += 1 _rpc_map[func_id] = func # For local usage of the function, append a _ in the name #globals()['_' + func.__name__] = func # Handle special parameter 'websocket' func_meta = inspect.getargspec(func) try: ws_idx = func_meta.args.index('ws') except ValueError: ws_idx = -1 defaults = func_meta.defaults def ws_proxy_call(*args, **kwar): if len(args) > ws_idx: (ws_fd, ws_uid) = _ws_serialize(args[ws_idx]) args = list(args) args[ws_idx] = ws_uid ws_locator = ws_idx else: try: ws = kwar['ws'] except KeyError: ws = defaults[ws_idx] (ws_fd, ws_uid) = _ws_serialize(ws) kwar['ws'] = ws_uid ws_locator = None msg = pickle.dumps((func_id, args, kwar, ws_locator), pickle.HIGHEST_PROTOCOL) ret = fd_trick.send_with_fd(_call_endpoint, msg, ws_fd) if ret != len(msg): # TODO: Weird! Can this ever happen? Maybe if message is too big. # Do something about it... pass def proxy_call(*args, **kwar): msg = pickle.dumps((func_id, args, kwar), pickle.HIGHEST_PROTOCOL) ret = _call_endpoint.send(msg) if ret != len(msg): # TODO: Weird! Can this ever happen? Maybe if message is too big. # Do something about it... pass # Have no ideia of how this works, just copied from decorator.py: evaldict = func.func_globals.copy() evaldict['_call_'] = ws_proxy_call if ws_idx >= 0 else proxy_call return FunctionMaker.create(func, "return _call_(%(shortsignature)s)", evaldict)
def forwarder(cls, fnc, delegatename): """Returns a method that forwards calls on the scoping object to calls on the delegate object. The signature of the delegate method is preserved in the forwarding method. """ fname = fnc.__name__ spec = getargspec(fnc) sig = formatargspec(*spec) body = "return self.%s.%s(%s)" % (delegatename, fname, ",".join(spec[0][1:])) f = FunctionMaker.create("%s%s" % (fname, sig), body, {}, defaults=spec[3], doc=fnc.__doc__) return types.MethodType(f, None, cls)
def decorator_apply(dec, func): """ Decorate a function by preserving the signature even if dec is not a signature-preserving decorator. """ if (type(func) == types.BuiltinFunctionType) or (type(func) == types.BuiltinMethodType): return builtin_decorator_apply(dec, func) # FunctionMaker doesn't seem to work for built-ins (i.e. compiled code, it should though). return FunctionMaker.create( func, 'return decorated(%(signature)s)', dict(decorated=dec(func)), undecorated=func)
def forwarder(cls, fnc, delegatename): """Returns a method that forwards calls on the scoping object to calls on the delegate object. The signature of the delegate method is preserved in the forwarding method. """ fname = fnc.__name__ spec = getargspec(fnc) sig = formatargspec(*spec) body = 'return self.%s.%s(%s)' % (delegatename, fname, ','.join(spec[0][1:])) f = FunctionMaker.create('%s%s' % (fname,sig), body, {}, defaults=spec[3], doc=fnc.__doc__) return types.MethodType(f, None, cls)
def deco(func): return FunctionMaker.create( "w_wrapped_func(processes{})".format(pt_args), """ return exec_with_process( processes, func, args_list, kwargs_list, expected_results, timeout{}) """.format(pt_args), dict(args_list=args_list, kwargs_list=kwargs_list, expected_results=expected_results, timeout=timeout, func=func, exec_with_process=exec_with_process))
def factory(name, params, templ, rx=re.compile(r'{([^}]+)\}')): "Return a factory of Query objects" def _makesql(namespace, kind, as_, globs): def evaluator(match): return str(eval(match.group(1), globs or {}, namespace)) evaluated_templ = rx.sub(evaluator, templ) return Query(evaluated_templ, kind, as_) signature = "{}({}, kind, as_, globs)".format(name, ', '.join(params)) body = 'return _makesql(dict({}), kind, as_, globs)'.format( ', '.join('%s=%s' % (p, p) for p in params)) makesql = FunctionMaker.create( signature, body, dict(_makesql=_makesql), defaults=('all', None, None)) makesql.__doc__ = 'Build query objects from the template\n' + templ makesql.templ = templ return makesql
def litetask(func): """ Add monitoring support to the decorated function. The last argument must be a monitor object. """ def wrapper(*args): monitor = args[-1] monitor.flush = noflush with monitor('total ' + func.__name__, measuremem=True): result = func(*args) delattr(monitor, 'flush') return result # NB: we need pickle=True because celery is using the worst possible # protocol; once we remove celery we can try to remove pickle=True return FunctionMaker.create( func, 'return _s_(_w_, (%(shortsignature)s,), pickle=True)', dict(_s_=safely_call, _w_=wrapper), task_func=func)
def _decorate_polyfill(func, caller): """ decorate(func, caller) decorates a function using a caller. """ try: from decorator import decorate return decorate(func, caller) except ImportError: from decorator import FunctionMaker evaldict = dict(_call_=caller, _func_=func) fun = FunctionMaker.create(func, "return _call_(_func_, %(shortsignature)s)", evaldict, __wrapped__=func) if hasattr(func, '__qualname__'): fun.__qualname__ = func.__qualname__ return fun
def wrapped(func): return FunctionMaker.create( f"w_wrapped_func(processes{pt_args})", f""" return exec_with_process( processes, func, args_list, kwargs_list, expected_results, timeout{pt_args}) """, dict( args_list=args_list, kwargs_list=kwargs_list, expected_results=expected_results, timeout=timeout, func=func, exec_with_process=exec_with_process, ), )
def init_wrapper(cls, delegate_class_list): """Returns a function that calls the wrapped class' __init__ function and then creates an instance of each delegate class in delegate_class_list. """ fnc = cls.__init__ spec = getargspec(fnc) sig = formatargspec(*spec) template = ["if not hasattr(self, '_delegates_'): self._delegates_ = {}"] for name, delegate in delegate_class_list: template.append('self.%s = %s(self)' % (name, delegate.__name__)) template.append("self._delegates_['%s'] = self.%s" % (name,name)) template.append('old_init__(%s)' % ','.join(spec[0])) f = FunctionMaker.create('__init__%s' % sig, '\n'.join(template), dict([(c.__name__,c) for n,c in delegate_class_list]+ [('old_init__',fnc)]), doc=fnc.__doc__, defaults=spec[3]) return types.MethodType(f, None, cls)
def init_wrapper(cls, delegate_class_list): """Returns a function that calls the wrapped class' __init__ function and then creates an instance of each delegate class in delegate_class_list. """ fnc = cls.__init__ spec = getargspec(fnc) sig = formatargspec(*spec) template = [ 'old_init__(%s)' % ','.join(spec[0]), ] for name, delegate in delegate_class_list: template.append('self.%s = %s(self)' % (name, delegate.__name__)) template.append("if not hasattr(self, '_delegates_'): self._delegates_ = {}") template.append("self._delegates_['%s'] = self.%s" % (name,name)) f = FunctionMaker.create('__init__%s' % sig, '\n'.join(template), dict([(c.__name__,c) for n,c in delegate_class_list]+ [('old_init__',fnc)]), doc=fnc.__doc__, defaults=spec[3]) return types.MethodType(f, None, cls)
def litetask(func): """ Add monitoring support to the decorated function. The last argument must be a monitor object. """ def wrapper(*args): check_mem_usage() # check if too much memory is used monitor = args[-1] monitor.flush = NoFlush(monitor, func.__name__) with monitor('total ' + func.__name__, measuremem=True), \ GroundShakingIntensityModel.forbid_instantiation(): result = func(*args) rec_delattr(monitor, 'flush') return result # NB: we need pickle=True because celery is using the worst possible # protocol; once we remove celery we can try to remove pickle=True return FunctionMaker.create( func, 'return _s_(_w_, (%(shortsignature)s,), pickle=True)', dict(_s_=safely_call, _w_=wrapper), task_func=func)
def litetask_futures(func): """ Add monitoring support to the decorated function. The last argument must be a monitor object. """ def wrapper(*args): monitor = args[-1] check_mem_usage(monitor) # check if too much memory is used monitor.flush = NoFlush(monitor, func.__name__) with monitor('total ' + func.__name__, measuremem=True), \ GroundShakingIntensityModel.forbid_instantiation(): result = func(*args) rec_delattr(monitor, 'flush') return result # NB: we need pickle=True because celery is using the worst possible # protocol; once we remove celery we can try to remove pickle=True return FunctionMaker.create( func, 'return _s_(_w_, (%(shortsignature)s,), pickle=True)', dict(_s_=safely_call, _w_=wrapper), task_func=func)
def decorator(f): # collect our argspec sig = signature(f) @wraps(f) def _(*args, **kwargs): bvals = sig.bind(*args, **kwargs) # replace with instance if desired for varname, val in bvals.arguments.items(): anno = sig.parameters[varname].annotation if anno in classes or (len(classes) == 0 and anno != _empty): bvals.arguments[varname] = anno(val) return f(*bvals.args, **bvals.kwargs) # create another layer by wrapping in a FunctionMaker. this is done # to preserve the original signature return FunctionMaker.create( f, 'return _(%(signature)s)', dict(_=_, __wrapped__=f) )
def decorator_apply(dec, func): return FunctionMaker.create(func, 'return decorated(%(signature)s)', dict(decorated=dec(func)), __wrapped__=func)
def dec(f): check_is_argument(conn_arg, f) return FunctionMaker.create(f, '''\ with {}.opencopy() as {}, {}.begin(): return _f_(%(shortsignature)s) '''.format(conn_arg, conn_arg, conn_arg), dict(_f_=f))
def dec(f): check_is_argument(arg, f) return FunctionMaker.create(f, '''\ with {}: return _f_(%(shortsignature)s) '''.format(arg), dict(_f_=f))
def decorator_apply(dec, func): return FunctionMaker.create( func, 'return decorated(%(signature)s)', dict(decorated=dec(func)), __wrapped__=func)
def __call__(self, func): return FunctionMaker.create( func, 'with _self_: return _f_(%(shortsignature)s)', dict(_f_=func, _self_=self))