def commit_after(func): def _commit_after(func, *args, **kwargs): rval = func(*args, **kwargs) db.session.commit() return rval return decorator.decorate(func, _commit_after)
def _register(f): """Registration function""" allow_types = (string_types, int, float) fkey = key + "." + f.__name__ + ".pkl" if fkey not in Cache.cache_by_key: Cache.cache_by_key[fkey] = Cache(fkey) cache = Cache.cache_by_key[fkey] cargs = tuple(x.cell_contents for x in f.__closure__) cargs = (len(cargs),) + cargs def _memoized_f(func, *args, **kwargs): assert not kwargs, "Only allow positional call" key = cargs + args for arg in key: if isinstance(arg, tuple): for x in arg: assert isinstance(x, allow_types) else: assert isinstance(arg, allow_types) if key in cache.cache: print("Use memoize {0}{1}".format(fkey, key)) return cache.cache[key] res = func(*args) cache.cache[key] = res cache.dirty = True return res return decorate(f, _memoized_f)
def memoize(f): """ A simple memoize implementation. It works by adding a .cache dictionary to the decorated function. The cache will grow indefinitely, so it is your responsability to clear it, if needed. """ f.cache = {} return decorate(f, _memoize)
def model_create_single(method): """ Decorate a method that takes a dictionary and creates a single record. The method may be called with either a single dict or a list of dicts:: record = model.create(vals) records = model.create([vals, ...]) """ wrapper = decorate(method, _model_create_single) wrapper._api = 'model_create' return wrapper
def fdecorate(fdefault): """Wrap a target generic function, overriding the previous default that was set for the generic function. Parameters ---------- fdefault : function The default function. Returns ------- fgeneric : function A wrapped generic function. """ generic_func_node.set_default(fdefault, allow_override=True) def register(key, func=None, override=True): """Register function to be the dispatch function. Parameters ---------- key : str or list of str The key to be registered. func : function The function to be registered. override : bool, optional Whether override existing registration. Returns ------- The register function is necessary. """ def _do_reg(myf): generic_func_node.register(myf, key, override) return myf if func: return _do_reg(func) return _do_reg def dispatch_func(func, *args, **kwargs): #pylint: disable=unused-argument """The wrapped dispath function""" if kwargs: raise RuntimeError( "Keyword arguments cannot be used when invoking generic_func %s" % func_name) return generic_func_node(*args) fresult = decorate(fdefault, dispatch_func) fresult.register = register return fresult
def model_create_single(method): """ Decorate a method that takes a dictionary and creates a single record. The method may be called with either a single dict or a list of dicts:: record = model.create(vals) records = model.create([vals, ...]) """ _create_logger.warning("The model %s is not overriding the create method in batch", method.__module__) wrapper = decorate(method, _model_create_single) wrapper._api = 'model_create' return wrapper
def inner(fun): """ This one is not returned """ # set the base basepath, really need to refactor to Class _basepath = basepath if _basepath is None: _basepath = 'things' _basepath = os.path.join(_basepath, '{}:{}'.format(reg.sub('', os.path.basename(inspect.getmodule(fun).__file__)), fun.__name__)) # basically use pwd if not os.path.exists(os.path.dirname(_basepath)): _mkdir(os.path.dirname(_basepath)) def _inner(fun, *args, **kwargs): """ this one is returned """ _path = _basepath if type(_path) is str: tmp = '_'.join(default_namer(fun, args, kwargs)) if tmp == '': tmp = '__noargs__' # TODO is this the only place ... yikes tmp = '{}.things'.format(tmp) if tmp else '.things' # what about '/' in tmp ? _path = os.path.join(_path, tmp) # save locally, could get weird with this default if hasattr(_path, '__call__'): _path = _path(**kwargs) # in case you want to do something else? assert type(_path) is str print("checking cache {}".format(_path)) if os.path.exists(_path) and not _inner._dirty: d = from_dict_of_things(_path) else: d = fun(*args, **kwargs) to_dict_of_things(d, _path) _inner._dirty = False return d _inner = decorator.decorate(fun, _inner) _inner._dirty = False def list_caches(): """ list .things that have been computed """ # if you need to parse the filenames, you need to rewrite this using a better args, kwargs storing mechanisi and a hash files = glob.glob('{}*.things'.format(_basepath)) return files def load_all_caches(): """ load .things that have been computed """ files = glob.glob('{}*.things'.format(_basepath)) return {k: from_dict_of_things(k) for k in files} def poison_cache(): _inner._dirty = True def force_clean(): _inner._dirty = False def is_dirty(): return _inner._dirty _inner.poison_cache = poison_cache _inner.is_dirty = is_dirty _inner.force_clean = force_clean _inner.load_all_caches = load_all_caches _inner.list_caches = list_caches _inner.basepath = _basepath return _inner
def docannotate(func): """Annotate a function using information from its docstring or from type annotations. If function has a type annotations then docstring types would be ignored. The annotation actually happens at the time the function is first called to improve startup time. For this function to work, the docstring must be formatted correctly. You should use the typedargs pylint plugin to make sure there are no errors in the docstring. This decorator is also could be used on classes to annotate their __init__() method. If decorator applied on a class then the priority for source of type info would be: __init__() type annotations -> class docstring -> __init__() docstring Class docstring would be taken if it contains any argument type information. __init__() docstring would be ignored in this case. """ cls = None if inspect.isclass(func): cls = func func = cls.__init__ func.class_docstring = cls.__doc__ if cls.__doc__ else '' func.class_name = cls.__name__ func = annotated(func) func.metadata.load_from_doc = True if func.decorated: if cls: setattr(cls, '__init__', func) return cls return func func.decorated = True if cls: setattr(cls, '__init__', decorate(func, _check_and_execute)) return cls return decorate(func, _check_and_execute)
def leakcheck(fn): # Compare the memory (after GC) before and after the test to determine # if we leaked memory def wrapper(fn, *args, **kwargs): gc.collect() mem_before = MemoryUsage() rv = fn(*args, **kwargs) gc.collect() mem_after = MemoryUsage() assert mem_before >= mem_after return rv return decorator.decorate(fn, wrapper)
def _param(func): func = annotated(func) valids = _parse_validators(validators) func.metadata.add_param(name, None, type_name, valids, **kwargs) # Only decorate the function once even if we have multiple param decorators if func.decorated: return func func.decorated = True return decorate(func, _check_and_execute)
def log(func, *args, **kwargs): """Add debug messages to logger.""" logger = logging.getLogger(func.__module__) def decorator(self, *args, **kwargs): logger.debug(f'Entering {func.__name__}') result = func(*args, **kwargs) logger.debug(result) logger.debug(f'Exiting {func.__name__}') return result return decorate(func, decorator)
def fdecorate(fdefault): """Wrap a target generic function, overriding the previous default that was set for the generic function. Parameters ---------- fdefault : function The default function. Returns ------- fgeneric : function A wrapped generic function. """ generic_func_node.set_default(fdefault, allow_override=True) def register(key, func=None, override=True): """Register function to be the dispatch function. Parameters ---------- key : str or list of str The key to be registered. func : function The function to be registered. override : bool, optional Whether override existing registration. Returns ------- The register function is necessary. """ def _do_reg(myf): generic_func_node.register(myf, key, override) return myf if func: return _do_reg(func) return _do_reg def dispatch_func(func, *args, **kwargs): #pylint: disable=unused-argument """The wrapped dispath function""" if kwargs: raise RuntimeError( "Keyword arguments cannot be used when invoking generic_func %s" % func_name) return generic_func_node(*args) fresult = decorate(fdefault, dispatch_func) fresult.fdefault = fdefault fresult.register = register return fresult
def with_mitmproxy(*args, **kwargs): '''Decorator to abstract fixture recording and scenario setup for the E2E tests with mitmproxy. Args: scenario_name (Optional[str]): scenario name, by default test name without 'test_' prefix should_record (Optional[bool]): is recording new interactions allowed during test run, by default `False` *args (List[Callable]): list of length of either zero or one: decorated function. This is to allow the decorator to function both with and without calling it with parameters: if args is present, we can deduce that the decorator was used without parameters. Returns: Callable: a decorator the can be used both with and without calling brackets (if all params should be default) ''' scenario_name = kwargs.pop('scenario_name', None) should_record = kwargs.pop('should_record', False) if not args: assert not kwargs, 'Parameters %s not expected' % kwargs def _with_mitmproxy(func, *args, **kwargs): def ommit_test_in_name(name): if name.startswith('test_'): return name[5:] mitmproxy_url = environ.get('MITMPROXY_HOST', 'http://mitm-manager.local') mitm_client = MITMClient(mitmproxy_url) final_scenario_name = scenario_name or ommit_test_in_name( func.__name__) try: mitm_client.set_scenario(final_scenario_name) if should_record: mitm_client.start_recording() func(*args, **kwargs) except Exception: raise finally: mitm_client.stop_recording() mitm_client.set_scenario('default') def _decorator(func): return decorate(func, _with_mitmproxy) if args: return decorate(args[0], _with_mitmproxy) return _decorator
def decorate(func, fwrapped): """A wrapper call of decorator package, differs to call time Parameters ---------- func : function The original function fwrapped : function The wrapped function """ import decorator return decorator.decorate(func, fwrapped)
def outer(wrapped): @functools.wraps(wrapped) def wrapper(self, *args, **kwargs): params = inspect.getcallargs(wrapped, *args, **kwargs) for arg_name, validators in to_validate.items(): for validator in validators: params[arg_name], errs = validator( arg_name, params.get(arg_name, None)) if errs: raise ValidationError(errs) return wrapped(**params) return decorator.decorate(wrapped, wrapper)
def with_mitmproxy(*args, **kwargs): '''Decorator to abstract fixture recording and scenario setup for the E2E tests with mitmproxy. Args: scenario_name (Optional[str]): scenario name, by default test name without 'test_' prefix should_record (Optional[bool]): is recording new interactions allowed during test run, by default `False` *args (List[Callable]): list of length of either zero or one: decorated function. This is to allow the decorator to function both with and without calling it with parameters: if args is present, we can deduce that the decorator was used without parameters. Returns: Callable: a decorator the can be used both with and without calling brackets (if all params should be default) ''' scenario_name = kwargs.pop('scenario_name', None) should_record = kwargs.pop('should_record', False) if not args: assert not kwargs, 'Parameters %s not expected' % kwargs def _with_mitmproxy(func, *args, **kwargs): def ommit_test_in_name(name): if name.startswith('test_'): return name[5:] mitmproxy_url = environ.get('MITMPROXY_HOST', 'http://mitm-manager.local') mitm_client = MITMClient(mitmproxy_url) final_scenario_name = scenario_name or ommit_test_in_name(func.__name__) try: mitm_client.set_scenario(final_scenario_name) if should_record: mitm_client.start_recording() func(*args, **kwargs) except Exception: raise finally: mitm_client.stop_recording() mitm_client.set_scenario('default') def _decorator(func): return decorate(func, _with_mitmproxy) if args: return decorate(args[0], _with_mitmproxy) return _decorator
def module_lock(self, f): def do_function(func, module, *args, **kwargs): with self.local_lock: module_name = module.__class__.__name__ if module_name not in self.m_lock: m_lock = self.m_lock[module_name] = Lock() else: m_lock = self.m_lock[module_name] with m_lock: result = func(module, *args, **kwargs) return result return decorate(f, do_function)
def function_lock(self, f): def do_function(func, module, *args, **kwargs): with self.local_lock: lock_name = module.__class__.__name__ + "-" + func.__name__ if lock_name not in self.f_lock: f_lock = self.f_lock[lock_name] = Lock() else: f_lock = self.f_lock[lock_name] with f_lock: result = func(module, *args, **kwargs) return result return decorate(f, do_function)
def fun_wrap(func): def do_function(*args, **kwargs): with self.local_lock: if name not in self.n_lock: n_lock = self.n_lock[name] = Lock() else: n_lock = self.n_lock[name] with n_lock: result = func( *args[1:], **kwargs) # XXX, too hard to write this line. return result return decorate(func, do_function)
def deprecated(*optional_message): """This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used. Parameters ---------- *optional_message : str an optional user level hint which should indicate which feature to use otherwise. """ def _deprecated(func, *args, **kw): try: caller_stack = stack()[1:] while len(caller_stack) > 0: frame = caller_stack.pop(0) filename = frame[1] # skip callee frames if they are other decorators or this file(func) if 'decorator' in filename or __file__ in filename: continue else: break lineno = frame[2] # avoid cyclic references! del caller_stack, frame except OSError: # eg. os.getcwd() fails in conda-test, since cwd gets deleted. filename = 'unknown' lineno = -1 user_msg = 'Call to deprecated function "%s". Called from %s line %i. %s' \ % (func.__name__, filename, lineno, msg) warnings.warn_explicit( user_msg, category=PyEMMA_DeprecationWarning, filename=filename, lineno=lineno ) return func(*args, **kw) # add deprecation notice to func docstring: if len(optional_message) == 1 and callable(optional_message[0]): # this is the function itself, decorate! msg = "" return decorate(optional_message[0], _deprecated) else: # actually got a message (or empty parenthesis) msg = optional_message[0] if len(optional_message) > 0 else "" return decorator(_deprecated)
def __call__(self, f): def g(obj, *args, **kw): obj = args[0] if not hasattr(obj, 'cachers'): obj.cachers = {} caches = obj.cachers if f in caches: cacher = caches[f] else: cacher = caches[f] = Cacher(f, self.limit, self.ignore_args, self.force_kwargs) return cacher(*args, **kw) g.__name__ = f.__name__ g.__doc__ = f.__doc__ return decorator.decorate(f, g)
def rlock(func): """ Place a threading recursive lock (Rlock) on the wrapped function """ # This lock will be instantiated at function creation time, i.e. at the # time the Python interpreter sees the decorated function the very # first time - this lock thus exists once for each decorated function. _rlock = threading.RLock() def _locked_f(f, *args, **kwargs): with _rlock: return func(*args, **kwargs) return decorate(func, _locked_f)
def outer(wrapped): @functools.wraps(wrapped) def wrapper(self, *args, **kwargs): params = inspect.getcallargs(wrapped, *args, **kwargs) for arg_name, validators in to_validate.items(): for validator in validators: params[arg_name], errs = validator(arg_name, params.get( arg_name, None)) if errs: raise ValidationError(errs) return wrapped(**params) return decorator.decorate(wrapped, wrapper)
def exception_improved_logging(f): """ decorator to increment the error message with the name of the class in which it appears """ # useful when using inherited class def _exception_handling(f, self, *args, **kwargs): try: return f(self, *args, **kwargs) except Exception as e: raise type(e)(str(e) + " (within %s)" % self.__class__).with_traceback( sys.exc_info()[2]) return decorate(f, _exception_handling)
def decorator(func): assert_typed(func) def _ensure_series_options(func, *a, **kw): res = func(*a, **kw) if isinstance(res, pd.Series): if not getattr(res, 'options', None): res.options = {} return res dec = decorate(func, _ensure_series_options) FUNCS[name] = dec return dec
def __call__(self, f): self.f = f def g(obj, *args, **kw): obj = args[0] if not hasattr(obj, 'cache'): obj.cache = FunctionCache() cache = obj.cache if self.f in cache: cacher = cache[self.f] else: cacher = cache[self.f] = Cacher(self.f, self.limit, self.ignore_args, self.force_kwargs, cacher_enabled=cache.caching_enabled) return cacher(*args, **kw) g.__name__ = f.__name__ g.__doc__ = f.__doc__ return decorator.decorate(self.f, g)
def decorator(func): def _ensure_finder_keys(func, *a, **kw): res = func(*a, **kw) for name, meta in res.items(): if meta is None: # underlying series is void, must be # register_formula(..., reject_unknown=False) continue missing = _KEYS - set(meta.keys()) if len(missing): warn(f'{name} has missing metadata keys ({missing})') return res dec = decorate(func, _ensure_finder_keys) FINDERS[name] = dec return dec
def inner(f): f_ = decorator.decorate(f, _memoize) keys = dict(active=active, copy_numpy=copy_numpy) f.keys = keys f_.keys = keys def reset(): cache = {} f.cache = cache f_.cache = cache reset() f_.reset = reset return f_
def memoized(f): """Decorate a function to cache its return value the first time it is called. If called later with the same arguments, the cached value is returned (not reevaluated). """ f.cache = {} def drop_cache(): logger.debug('Dropping cache for %s', f) f.cache = {} f.drop_cache = drop_cache return decorate(f, _memoize)
def docannotate(func): """Annotate a function using information from its docstring. The annotation actually happens at the time the function is first called to improve startup time. For this function to work, the docstring must be formatted correctly. You should use the typedargs pylint plugin to make sure there are no errors in the docstring. """ func = annotated(func) func.metadata.load_from_doc = True if func.decorated: return func func.decorated = True return decorate(func, _check_and_execute)
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 logging_scope(name, *wargs, **wkwargs): """ A decorator to add the decorated function as a new logging scope, with name `name`. All additional arguments are passed to `StatusLogger._scope_enter`. Current supported keyword arguments are "timed", in which case when the scope closes, the duration of the call is shown. """ def logging_scope(func, *args, **kwargs): logger._scope_enter(name, *wargs, **wkwargs) success = True try: f = func(*args, **kwargs) return f except Exception as e: success = False raise_with_traceback(e) finally: logger._scope_exit(success) return lambda func: decorate(func, logging_scope)
def functioncache_decorator(function): # make sure cache is loaded if not hasattr(function, '_db'): cache_name = (_get_cache_name(function), type(backend)) if cache_name in OPEN_DBS: function._db = OPEN_DBS[cache_name] else: backend.setup(function) function._db = backend OPEN_DBS[cache_name] = function._db function_with_cache._db = function._db function._seconds_of_validity = seconds_of_validity function._fail_silently = fail_silently function._ignore_instance = ignore_instance function._function_key = function_key return decorate(function, function_with_cache)
def check_process(func): """Decorator for ``TestRemoteRobot.test_...`` methods to check if the external ``RemoteRobot`` process is still running, which is passed to every test method as ``process`` fixture. """ def caller(func, self, process, *args, **kwargs): cls = type(self) # ensure that process was not recreated for some reason if hasattr(cls, 'process'): assert process is cls.process, \ "RemoteRobot process was recreated. " \ "Check `process` fixture." cls.process = process # polling returns None as long as process is running assert process.poll() is None, \ "RemoteRobot process is not running (anymore)." return func(self, process, *args, **kwargs) return decorate(func, caller)
def cache_decorator(user_func): if to_str is compat.string_type: # backwards compatible key_generator = function_key_generator(namespace, user_func) else: key_generator = function_key_generator(namespace, user_func, to_str=to_str) def refresh(*arg, **kw): """ Like invalidate, but regenerates the value instead """ key = key_generator(*arg, **kw) value = user_func(*arg, **kw) self.set(key, value) return value def invalidate(*arg, **kw): key = key_generator(*arg, **kw) self.delete(key) def set_(value, *arg, **kw): key = key_generator(*arg, **kw) self.set(key, value) def get(*arg, **kw): key = key_generator(*arg, **kw) return self.get(key) user_func.set = set_ user_func.invalidate = invalidate user_func.get = get user_func.refresh = refresh user_func.key_generator = key_generator user_func.original = user_func # Use `decorate` to preserve the signature of :param:`user_func`. return decorate( user_func, functools.partial(get_or_create_for_user_func, key_generator))
def __call__(self, f): self.f = f def g(obj, *args, **kw): obj = args[0] if not hasattr(obj, 'cache'): obj.cache = FunctionCache() cache = obj.cache if self.f in cache: cacher = cache[self.f] else: cacher = cache[self.f] = Cacher(self.f, self.limit, self.ignore_args, self.force_kwargs, cacher_enabled=cache.caching_enabled) return cacher(*args, **kw) g.__name__ = f.__name__ g.__doc__ = f.__doc__ try: # readthedocs weirdness......... from decorator import decorate # @UnresolvedImport g = decorate(self.f, g) except (AttributeError, ImportError): pass return g
def distributionMethod(method): """Decorator for wrapping a method so that it can take distributions as arguments.""" def helper(wrapped, self, *args, **kwargs): args = tuple(toDistribution(arg) for arg in args) kwargs = {name: toDistribution(arg) for name, arg in kwargs.items()} if any( needsSampling(arg) for arg in itertools.chain(args, kwargs.values())): return MethodDistribution(method, self, args, kwargs) elif any( needsLazyEvaluation(arg) for arg in itertools.chain(args, kwargs.values())): # see analogous comment in distributionFunction return makeDelayedFunctionCall(helper, (method, self) + args, kwargs) else: return method(self, *args, **kwargs) return unpacksDistributions( decorator.decorate(method, helper, kwsyntax=True))
def _decorate_function_with_mapping(self, f, m, force_update: bool = False): try: # try to update the mapping of an already decorated function mapping = f.schalter_mapping if force_update: mapping.update(m) else: updates = { k for k in mapping.keys() & m.keys() if mapping[k][0] != m[k][0] } for k in updates: # introduce a strict mode where this raises an error? msg = ( "Replacing original mapping of argument '{}' " "to config entry '{}' with new mapping to '{}'.".format( k, m[k][0], mapping[k][0] ) ) logger.warning("Function '{}': {}".format(f.__name__, msg)) mapping.update({k: v for k, v in m.items() if k not in updates}) f.schalter_f.__kwdefaults__ = f.__kwdefaults__ except AttributeError: # first decoration of function. Save mapping and original function setattr(f, "schalter_mapping", m) decorated = decorate(f, self.make_call_decorated_function(m)) setattr(decorated, "schalter_f", f) f = decorated try: if id(f.schalter_config) != id(self): raise NotImplementedError() except AttributeError: setattr(f, "schalter_config", self) return f
def memoize(func): """ Rather simple memoize implementation supporting arbitrary signature function calls. Since it simply appends a caching dict to the function, it is neither optimal in performance, nor does it cover all edge cases. Implementation is shamelessly stolen from: https://decorator.readthedocs.io/en/latest/tests.documentation.html#the-solution """ def _memoize(func, *args, **kwargs): if kwargs: key = args, frozenset(kwargs.items()) else: key = args cache = func.cache if key not in cache: cache[key] = func(*args, **kwargs) return cache[key] func.cache = {} return decorate(func, _memoize)
def api_error_handle(func): def func_wrapper(f, *args, **kwargs): try: return f(*args, **kwargs) except RateLimitError as e: raise APIQuotaError(str(e)) except TweepError as e: if e.api_code == TWITTER_AUTOMATED_REQUEST_ERROR: raise AutomatedRequestError elif e.api_code == TWITTER_OVER_CAPACITY_ERROR: raise OverCapacityError elif e.api_code in [TWITTER_CHARACTER_LIMIT_ERROR_1, TWITTER_CHARACTER_LIMIT_ERROR_2]: raise CharacterLimitError elif e.api_code == TWITTER_DAILY_STATUS_UPDATE_LIMIT_ERROR: raise DailyStatusUpdateError elif e.api_code == TWITTER_STATUS_DUPLICATE_ERROR: raise StatusDuplicateError else: raise return decorate(func, func_wrapper)
def decorator_gridify(f): arg_str = ', '.join([k for k in defaults]) signature = '' for k, v in defaults.items(): signature = signature + "{} = {},".format(k, k) scope = {**defaults} scope['np'] = np scope[f.__name__] = f exec( grid_wrapper_def.format(signature=signature, arg_str=arg_str, fname=f.__name__), scope) wrapped = scope['wrapped'] wrapped.__name__ = f.__name__ wrapped.__doc__ = f.__doc__ return decorate(wrapped, decorator_wrapper)
def __call__(self, fdecl): def tagged_fdecl(func, *args, **kwargs): with self: return func(*args, **kwargs) return decorate(fdecl, tagged_fdecl)
def dispatcher(fworkload): """Wrap a workload dispatcher function. Parameters ---------- fworkload : function The workload extraction function from arguments. Returns ------- fdispatcher : function A wrapped dispatcher function, which will dispatch based on DispatchContext and the current workload. """ dispatch_dict = {} func_name = fworkload.__name__ def register(key, func=None, override=False): """Register template function. Parameters ---------- key : str or List of str The template key to identify the template under this dispatcher. func : function The function to be registered. The first argument of the function is always cfg returned by DispatchContext, the rest arguments are the same as the fworkload. override : bool Whether override existing registration. Returns ------- The register function if necessary. """ if isinstance(key, str): key = [key] def _do_reg(myf): for x in key: if x in dispatch_dict and not override: raise ValueError( "Key %s is already registered for %s" % (x, func_name)) dispatch_dict[x] = myf return myf if func: return _do_reg(func) return _do_reg def dispatch_func(func, *args, **kwargs): """The wrapped dispatch function""" tgt = _target.current_target() workload = func(*args, **kwargs) cfg = DispatchContext.current.query(tgt, workload) if cfg.is_fallback and not cfg.template_key: # first try 'direct' template if 'direct' in dispatch_dict: return dispatch_dict['direct'](cfg, *args, **kwargs) # otherwise pick a random template for v in dispatch_dict.values(): return v(cfg, *args, **kwargs) else: return dispatch_dict[cfg.template_key](cfg, *args, **kwargs) fdecorate = decorate(fworkload, dispatch_func) fdecorate.register = register return fdecorate
def decorate(func): def wrapper(func, *args, **kwargs): with block_timer(name, **tags): result = func(*args, **kwargs) return result return decorator.decorate(func, wrapper)
def decorater(f): for key, value in kwargs.items(): setattr(f, key, value) return decorate(f, deco)
def memoize(f): f.cache = {} return decorate(f, _memoize)
def trace(f): return decorate(f, _trace)
def memoize(f): f.cache = weakref.WeakKeyDictionary() return decorate(f, _memoize)
def _decorator(func): return decorate(func, _with_mitmproxy)
def generic_func(fdefault): """Wrap a target generic function. Generic function allows registeration of further functions that can be dispatched on current target context. If no registered dispatch is matched, the fdefault will be called. Parameters ---------- fdefault : function The default function. Returns ------- fgeneric : function A wrapped generic function. Example ------- .. code-block:: python import tvm # wrap function as target generic @tvm.target.generic_func def my_func(a): return a + 1 # register specialization of my_func under target cuda @my_func.register("cuda") def my_func_cuda(a): return a + 2 # displays 3, because my_func is called print(my_func(2)) # displays 4, because my_func_cuda is called with tvm.target.cuda(): print(my_func(2)) """ dispatch_dict = {} func_name = fdefault.__name__ def register(key, func=None, override=False): """Register function to be the dispatch function. Parameters ---------- key : str or list of str The key to be registered. func : function The function to be registered. override : bool Whether override existing registeration. Returns ------- The register function is necessary. """ def _do_reg(myf): key_list = [key] if isinstance(key, str) else key for k in key_list: if k in dispatch_dict and not override: raise ValueError( "Key is already registered for %s" % func_name) dispatch_dict[k] = myf return myf if func: return _do_reg(func) return _do_reg def dispatch_func(func, *args, **kwargs): """The wrapped dispath function""" target = current_target() if target is None: return func(*args, **kwargs) for k in target.keys: if k in dispatch_dict: return dispatch_dict[k](*args, **kwargs) return func(*args, **kwargs) fdecorate = decorate(fdefault, dispatch_func) fdecorate.register = register fdecorate.fdefault = fdefault return fdecorate
def _versioned(f): f.version = version return decorator.decorate(f, __versioned)
def wrapper(func): def new_init(func, self, *args, **kwargs): func(self, *args, **kwargs) self.name = module_name return decorate(func, new_init, make_weak_signature(func))