Uses either uwsgi's atexit mechanism, or atexit from the stdlib.

    When running under uwsgi, using their atexit handler is more reliable,
    especially when using gevent
    :param func: the function to call at exit
163720
def atexit_register(func):
    
    try:
        import uwsgi

        orig = getattr(uwsgi, "atexit", None)

        def uwsgi_atexit():
            if callable(orig):
                orig()
            func()

        uwsgi.atexit = uwsgi_atexit
    except ImportError:
        atexit.register(func)
410108
def elog(exc, func, args=None, kwargs=None, str=str, pretty=True, name=''):
    '''
    '''
    from .str import safe_str

    args = args if args else ()
    kwargs = kwargs if kwargs else {}
    name = '{}.{}'.format(get_mod(func), name) if name else full_funcname(func)

    if pretty:
        invocation = ', '.join([safe_str(arg) for arg in args])
        if kwargs:
            invocation += ', '
            invocation += ', '.join(['{}={}'.format(key, safe_str(value))
                                     for key, value in sorted(kwargs.items())])
    else:
        invocation = 'args={}, kwargs={}'.format(safe_str(args), safe_str(kwargs))

    msg = '***{}***: "{}" --- {}({})'.format(get_typename(exc),
                                             message(exc),
                                             name,
                                             invocation)
    elogger.error(msg)
674434
def unregisterStdErr(func):
    
    try:
        sys.stderr.hooks.remove(weakref.ref(func))
    except (AttributeError, ValueError):
        pass
924033
def run_func(self, func, load):
        '''
        
        '''
        # Don't honor private functions
        if func.startswith('__'):
            # TODO: return some error? Seems odd to return {}
            return {}, {'fun': 'send'}
        # Run the func
        if hasattr(self, func):
            try:
                start = time.time()
                ret = getattr(self, func)(load)
                log.trace(
                    'Master function call %s took %s seconds',
                    func, time.time() - start
                )
            except Exception:
                ret = ''
                log.error('Error in function %s:\n', func, exc_info=True)
        else:
            log.error(
                'Received function %s which is unavailable on the master, '
                'returning False', func
            )
            return False, {'fun': 'send'}
        # Don't encrypt the return value for the _return func
        # (we don't care about the return value, so why encrypt it?)
        if func == '_return':
            return ret, {'fun': 'send'}
        if func == '_pillar' and 'id' in load:
            if load.get('ver') != '2' and self.opts['pillar_version'] == 1:
                # Authorized to return old pillar proto
                return ret, {'fun': 'send'}
            return ret, {'fun': 'send_private', 'key': 'pillar', 'tgt': load['id']}
        # Encrypt the return
        return ret, {'fun': 'send'}
1029676
def action(source, func):
    
    if asyncio.iscoroutinefunction(func):
        async def innerfunc(arg):
            await func(arg)
            return arg
    else:
        def innerfunc(arg):
            func(arg)
            return arg
    return map.raw(source, innerfunc)
802649
def deprecated(func: Callable) -> Callable:
    """"""
    @functools.wraps(func)
    def _new_func(*args: Any, **kwargs: Any) -> Any:
        warnings.simplefilter('always', DeprecationWarning)  # turn off filter
        warnings.warn("Call to deprecated function {}.".format(func.__name__),
                      category=DeprecationWarning,
                      stacklevel=2)
        warnings.simplefilter('default', DeprecationWarning)  # reset filter
        return func(*args, **kwargs)
    return _new_func
580087
def graceful_ctrlc(func):
    
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except KeyboardInterrupt:
            exit(1)
    return wrapper
1129593
def di(self, func):
        
        func_name = func.__name__
        if func_name in self.exts:
            raise DuplicatedExtension
        self.exts[func_name] = func
        return func
557051
def run_with_router(func, *args, **kwargs):
    
    broker = mitogen.master.Broker()
    router = mitogen.master.Router(broker)
    try:
        return func(router, *args, **kwargs)
    finally:
        broker.shutdown()
        broker.join()
871637
def call(self, func, *args, **kwargs):
        
        wrapped = self.wrap(func)
        return wrapped(*args, **kwargs)
592831
def http(container = None):
    ""
    def decorator(func):
        @functools.wraps(func)
        def handler(self, event):
            return _handler(self if container is None else container, event, lambda env: func(self, env))
        return handler
    return decorator
764523
def wrap_exception(func: Callable) -> Callable:
    """"""
    try:
        # only do the wrapping if pygatt is installed.
        # otherwise it's pointless anyway
        from pygatt.backends.bgapi.exceptions import BGAPIError
        from pygatt.exceptions import NotConnectedError
    except ImportError:
        return func

    def _func_wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except BGAPIError as exception:
            raise BluetoothBackendException() from exception
        except NotConnectedError as exception:
            raise BluetoothBackendException() from exception

    return _func_wrapper
815541
def ctx_provider(self, func):
        
        func = to_coroutine(func)
        self.providers.append(func)
        return func
732061
def unregisterStdOut(func):
    
    try:
        sys.stdout.hooks.remove(weakref.ref(func))
    except (AttributeError, ValueError):
        pass
463288
def on_terminate(func):
    """"""
    def exit_function(*args):
        func()
        exit(0)
    signal.signal(signal.SIGTERM, exit_function)
1132282
def execute_function(self, func, *nargs, **kwargs):
        
        # makes a copy of the func
        import types
        fn = types.FunctionType(func.func_code,
                                func.func_globals.copy(),
                                name=func.func_name,
                                argdefs=func.func_defaults,
                                closure=func.func_closure)
        fn.func_globals.update(self.globals)

        error_class = Exception if config.catch_rex_errors else None

        try:
            return fn(*nargs, **kwargs)
        except RexError:
            raise
        except error_class as e:
            from inspect import getfile

            stack = traceback.format_exc()
            filename = getfile(func)

            raise RexError("Failed to exec %s:\n\n%s" % (filename, stack))
8750
def execstr_funckw(func):
    
    import utool as ut
    funckw = ut.get_func_kwargs(func)
    return ut.execstr_dict(funckw, explicit=True)