Source code for domonic.decorators

"""
    domonic.decorators
    ====================================

"""

import functools
import warnings
from functools import wraps
from typing import Callable


[docs]def el(element="div", string: bool = False): """[wraps the results of a function in an element]""" if isinstance(element, str): from domonic.dom import Document element = Document.createElement(element).__class__ def decorator(function): def wrapper(*args, **kwargs): result = function(*args, **kwargs) if string == False: return element(result) else: return str(element(result)) return wrapper return decorator
# @el(div) # @el(span) # def doctype(doctype): # """ # @doctype('html') # @doctype('xhtml') # @doctype('xml') # """ # def decorator(f): # @wraps(f) # def wrapper(*args, **kwargs): # return f(*args, **kwargs) # return wrapper # return decorator
[docs]def called(before=None, error: Callable[[Exception], None] = None): """ Decorator to call a function before and after a function call. """ def decorator(f): @functools.wraps(f) def wrapper(*args, **kwargs): if before: before() try: return f(*args, **kwargs) except Exception as e: if error: error(e) else: raise finally: if before: before() return wrapper return decorator """[calls before() passing the response as args to the decorated function. optional error handler. run the decorated function immediately. WARNING: this is not for the regular decorating of a function its syntactical sugar for a callback i.e. @called( lambda: º.ajax('https://www.google.com'), lambda err: print('error:', err)) def success(data=None): print("sweet!") print(data) """ def decorator(function): nonlocal before nonlocal error try: if before is None: return function() r = before() return function(r) except Exception as e: if error is not None: error(e) else: raise e return decorator
iife = called # pass None for an iife # def static(endpoint, update="11101"): # ''' # render the endpoint to a cron timestamp. when user vists that function. # it will load the rendered version instead of executing the function. # ''' # def dont_do_it(f): # return None # return dont_do_it # https://www.python.org/dev/peps/pep-0318/ # https://stackoverflow.com/questions/15299878/how-to-use-python-decorators-to-check-function-arguments def accepts(*types): def check_accepts(f): assert len(types) == f.__code__.co_argcount def new_f(*args, **kwds): for (a, t) in zip(args, types): assert isinstance(a, t), "arg %r does not match %s" % (a, t) return f(*args, **kwds) new_f.__name__ = f.__name__ return new_f return check_accepts # @accepts(int) # CACHED = {} # def memoize(f): # """ # @memoize # def fib(n): # if n in (0, 1): # return n # return fib(n - 1) + fib(n - 2) # """ # @functools.wraps(f) # def new_f(*args): # if args in CACHED: # return CACHED[args] # else: # result = f(*args) # CACHED[args] = result # return result # return new_f # def requires_websocket(f): # decorate all functions that require websockets to warn user
[docs]def silence(*args, **kwargs): """stop a function from doing anything""" def dont_do_it(f): return None return dont_do_it
# @silence
[docs]def check(f): """Prints entry and exit of a function to the console""" def new_f(*args, **kwargs): print("Entering", f.__name__) f(*args, **kwargs) print("Exited", f.__name__) return new_f
# @check()
[docs]def log(logger, level="info"): """@log(logging.getLogger('main'), level='warning')""" def log_decorator(fn): @functools.wraps(fn) def wrapper(*a, **kwa): getattr(logger, level)(fn.__name__) return fn(*a, **kwa) return wrapper return log_decorator
[docs]def instead(f, somethingelse): """what to return if it fails""" def new_f(): try: return f() except Exception as e: print("failed", e) return somethingelse return new_f
# @instead("something else instead of what was supposed to happen")
[docs]def deprecated(func): """ marks a function as deprecated. """ @functools.wraps(func) def new_func(*args, **kwargs): warnings.simplefilter("always", DeprecationWarning) warnings.warn( "Call to deprecated function {}.".format(func.__name__), category=DeprecationWarning, stacklevel=2 ) warnings.simplefilter("default", DeprecationWarning) return func(*args, **kwargs) return new_func
[docs]def as_json(func): """decorate any function to return json instead of a python obj note - used by JSON.py """ def JSON_decorator(*args, **kwargs): import json return json.dumps(func(*args, **kwargs)) return JSON_decorator
# def evt(event, *args, **kwargs): #TODO # """ # a decorator that will call a function when an event is triggered. # """ # def decorator(f): # def wrapper(*args, **kwargs): # return f(*args, **kwargs) # return wrapper # return decorator # @evt('event', 'args', 'kwargs') # def catch(f): # """ catch exceptions and return None """ # def new_f(): # try: # return f() # except Exception as e: # print('failed', e) # return None # return new_f # def lenient(*args, **kwargs): # """ can try to remap args if passed incorrectly. # i.e. if expecting array but gets string, puts string in arr # should never switch order probably. just re-type # prints warning and runs # """ ''' def aka(names): """ @aka(*mylist) """ def aka_decorator(fn): @functools.wraps(fn) def wrapper(*a, **kwa): return fn(*a, **kwa) return wrapper return log_decorator '''