示例#1
0
    async def run(self, rule_set: str, value: object) -> object:
        """
        Run a set of rules against a value, returning as required by your
        transformers. It follows these basic steps:

        * Iterate over the rules in the set. For each rule:

            * Check the predicate against the comparable in the rule and the
              given value

                * If the predicate returns True, run the transformer
                * If the transformer returns CONTINUE, move on to the next rule
                * If the transformer returns RETURN, return None and stop
                  processing
                * If the transformer returns a tuple and the first value is
                  RETURN, return the second value

            * If the predicate returns False, return False and stop processing

        :param rule_set: The set of rules to run
        :param value: The value you want to compare across your rules
        :return: What you get depends entirely on your rules; see above
        """

        _set = self.get_rule_set(rule_set)

        if _set is None:
            raise LookupError("No such rule set: {}".format(rule_set))

        for predicate, comparable, transformer in _set:
            if iscoroutinefunction(predicate):
                result = await predicate(value, comparable)
            else:
                result = predicate(value, comparable)

            if result:
                if iscoroutinefunction(transformer):
                    transformer_result = await transformer(value)
                else:
                    transformer_result = transformer(value)
            else:
                return False  # Rule wasn't matched

            if isinstance(transformer_result, tuple):
                # Updates the value being compared above
                t_r, value = transformer_result

                if t_r is TransformerResult.CONTINUE:
                    continue  # Continues with the updated value
                if t_r is TransformerResult.RETURN:
                    return value

            if transformer_result is TransformerResult.CONTINUE:
                continue
            if transformer_result is TransformerResult.RETURN:
                return

            raise NotImplementedError(
                "Unknown transformer result: {}".format(transformer_result)
            )
示例#2
0
 def AsyncBind(self,
               event_binder,
               async_callback,
               object,
               source=None,
               id=wx.ID_ANY,
               id2=wx.ID_ANY):
     """Bind a coroutine to a wx Event. Note that when wx object is destroyed, any coroutine still running will be cancelled automatically.
     """
     # We restrict the object to wx.Windows to be able to cancel the coroutines on EVT_WINDOW_DESTROY, even if wx.Bind works with any wx.EvtHandler
     if not isinstance(object, wx.Window):
         raise Exception("object must be a wx.Window")
     if not iscoroutinefunction(async_callback):
         raise Exception("async_callback is not a coroutine function")
     if object not in self.BoundObjects:
         self.BoundObjects[object] = defaultdict(list)
         object.Bind(wx.EVT_WINDOW_DESTROY,
                     lambda event: self.OnDestroy(event, object), object)
     self.BoundObjects[object][event_binder.typeId].append(async_callback)
     object.Bind(
         event_binder,
         lambda event: self.OnEvent(event, object, event_binder.typeId),
         source=source,
         id=id,
         id2=id2)
示例#3
0
    def _check_not_coroutine(self, callback, name):
        """Check whether the given callback is a coroutine or not."""
        from asyncio import coroutines

        if coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction(
                callback):
            raise TypeError("coroutines cannot be used with {}()".format(name))
示例#4
0
    def __init__(self, func: Optional[AsyncCallable] = None, **kwargs) -> None:
        if func is None or self.use_main:
            func = self.main
            self.__class__.use_main = True
            if Command.main.__doc__:
                del Command.main.__doc__
            if hasattr(func, "__doc_only__"):
                raise ValueError(
                    "main method must be overridded for subclass of disctools.commands.Command if func argument is None"
                )

        kwargs.setdefault("invoke_without_command", True)
        super().__init__(func, **kwargs)

        if hasattr(self, "pre_invoke"):
            self.before_invoke(self.pre_invoke)
        if hasattr(self, "post_invoke"):
            self.after_invoke(self.post_invoke)

        self.name = kwargs.get('name', str(self.__class__.__name__))

        try:
            self.cogcmd
        except AttributeError:
            self.cogcmd = None

        if hasattr(self, "on_error"):
            if not iscoroutinefunction(self.on_error):
                raise TypeError('The error handler must be a coroutine.')
示例#5
0
文件: main.py 项目: zwg0106/sat
    def run_coroutine_threadsafe(self, coro, *args, **kargs):
        """ Submit a coroutine object to a given event loop.
        Return a concurrent.futures.Future to access the result.
        this method must be run in event loop
        """
        
        if not coroutines.iscoroutinefunction(coro):
            raise TypeError('A coroutine function is required')

        future = concurrent.futures.Future()

        #Future is asyncio.futures.Future
        def got_result(task):
            exception = task.exception()
            if exception is not None:
                future.set_exception(exception)
            else:
                future.set_result(task.result())

        def run_callback():
            """Run callback and store result."""
            try:
                task = asyncio.ensure_future(coro(*args, **kargs), loop=self.loop)
                task.add_done_callback(got_result)
            except Exception as exc:
                if future.set_running_or_notify_cancel():
                    future.set_exception(exc)
                else:
                    LOGGER.warning("Exception on lost future: ", exc_info=True)

        self.loop.call_soon_threadsafe(run_callback)
        return future
示例#6
0
    async def fire_event(self, event: Event) -> Event:
        """
        Fire an event, and call the handlers registered for it. This is a
        coroutine, and so needs to be awaited.

        Note that handlers are (by design) allowed to modify events. The
        event you passed in is returned in case you need to do any advanced
        coroutine processing.

        :param event: The event object to be fired.
        :return: The event object you passed in.
        """

        for identifier in event.identifiers:
            handlers = self.registered.get(identifier, [])
            for handler in handlers:
                if event.cancelled and not handler["cancelled"]:
                    continue
                if handler["filter"] and not handler["filter"](event):
                    continue

                func = handler["callable"]
                args = handler["args"]
                kwargs = handler["kwargs"]

                try:
                    if iscoroutinefunction(func):
                        await func(event, *args, **kwargs)
                    else:
                        func(event, *args, **kwargs)
                except Exception:
                    # TODO: Logging
                    raise
        return event
示例#7
0
async def call_as_coroutine(func, *args, **kwargs):
    """
    Function call and coroutine await abstraction.
    """
    if iscoroutinefunction(func):
        return await func(*args, **kwargs)
    else:
        return func(*args, **kwargs)
示例#8
0
    def validate(self):
        if self.method not in ALLOWED_METHODS:
            raise MethodNotAllowed("Method {method} is not allowed".format(method=self.method))

        if not callable(self.handler):
            raise HandlerIsNotCallable("Handler object {handler} is not callable".format(handler=self.handler))

        if not iscoroutinefunction(self.handler):
            raise HandlerIsNotCouroutine("Handler {handler} is not couroutine".format(handler=self.handler))
示例#9
0
 def run(self) -> None:
     cmd = self._get_cmd()
     cmd_output = self.execute_cmd(cmd)
     if iscoroutinefunction(self._func):
         import asyncio
         loop = asyncio.new_event_loop()
         asyncio.set_event_loop(loop)
         loop.run_until_complete(self._func(self._users, cmd_output))
         loop.close()
     else:
         self._func(self._users, cmd_output)
示例#10
0
    def _run_coroutine(self, coro, *args, **kwargs):
        print(locals())
        args = list(args)
        result = None
        if len(args) > 0 and type(args[-1]) is Task:
            task = args.pop()
            result = task.result()

        wrapper_coro = coro
        if not iscoroutinefunction(coro):
            wrapper_coro = coroutine(coro)

        ensure_future(wrapper_coro(result, *args, **kwargs))
示例#11
0
 def emit(self, type: EventType, data: Optional[dict] = None) -> None:
     """Emit event to all listeners."""
     for (callback, event_filter, resource_filter) in self._subscribers:
         if event_filter is not None and type not in event_filter:
             continue
         if (data is not None
                 and resource_filter is not None and ResourceTypes(
                     data.get("type")) not in resource_filter):
             continue
         if iscoroutinefunction(callback):
             asyncio.create_task(callback(type, data))
         else:
             callback(type, data)
示例#12
0
 def AsyncBind(self, event_binder, async_callback, object):
     """Bind a coroutine to a wx Event. Note that when wx object is destroyed, any coroutine still running will be cancelled automatically.
     """
     if not iscoroutinefunction(async_callback):
         raise Exception("async_callback is not a coroutine function")
     if object not in self.BoundObjects:
         self.BoundObjects[object] = defaultdict(list)
         object.Bind(wx.EVT_WINDOW_DESTROY,
                     lambda event: self.OnDestroy(event, object))
     self.BoundObjects[object][event_binder.typeId].append(async_callback)
     object.Bind(
         event_binder,
         lambda event: self.OnEvent(event, object, event_binder.typeId))
示例#13
0
    def actual_decorator(func: callable):
        if iscoroutine(func) or iscoroutinefunction(func):

            @functools.wraps(func)
            @astd.lru_cache(maxsize=max_size)
            async def deco(*args, **kwargs):
                return await func(*args, **kwargs)
        else:

            @functools.wraps(func)
            @functools.lru_cache(maxsize=max_size)
            def deco(*args, **kwargs):
                return func(*args, **kwargs)

        return deco
示例#14
0
    def _run_signals(self, name, func, *args, **kwargs):
        pre_signal = getattr(self, 'pre_{}'.format(name), None)
        post_signal = getattr(self, 'post_{}'.format(name), None)

        if pre_signal:
            self._run_coroutine(pre_signal, *args, **kwargs)

        wrapped_func = func
        if not iscoroutinefunction(func):
            wrapped_func = coroutine(func)

        future = ensure_future(wrapped_func(*args, **kwargs))
        if post_signal:
            future.add_done_callback(
                partial(self._run_coroutine, post_signal, *args, **kwargs))
        return future
示例#15
0
def _run(*, work, context, **kwargs):
    """Run in current scope."""
    import asyncio
    from asyncio.coroutines import iscoroutine, iscoroutinefunction

    # TODO: Allow custom dispatcher hook.
    if iscoroutinefunction(context.run):

        logger.debug('Creating coroutine object for workflow dispatcher.')
        # TODO: Handle in context.run() via full dispatcher implementation.
        try:
            if callable(work):
                handle = work(**kwargs)
        except Exception as e:
            logger.exception(
                'Uncaught exception in scalems.run() processing work: ' +
                str(e))
            raise e
        # TODO:
        # coro = context.run(work, **kwargs)
        try:
            coro = context.run()
        except Exception as e:
            logger.exception(
                'Uncaught exception in scalems.run() calling context.run(): ' +
                str(e))
            raise e

        logger.debug('Starting asyncio.run()')
        # Manage event loop directly, since asyncio.run() doesn't seem to always clean it up right.
        # TODO: Check for existing event loop.
        loop = asyncio.get_event_loop()
        try:
            task = loop.create_task(coro)
            result = loop.run_until_complete(task)
        finally:
            loop.close()
        assert loop.is_closed()

        logger.debug('Finished asyncio.run()')
    else:
        logger.debug('Starting context.run() without asyncio wrapper')
        result = context.run(work, **kwargs)
        logger.debug('Finished context.run()')
    return result
示例#16
0
# dir(asyncio)
"""
1. 初步来看dir(asyncio)的输出结果, asyncio存在归并threading与queue的野心
2. 或者说, asyncio可能希望, 开发者可以很方便地将原来的threading框架转化为coroutine框架
"""


async def say_something():
    for _ in range(2):
        # print(f"now it's {time.strftime('%H:%M:%S')}")
        print(f"now it's {time.strftime('%X')}")
        await asyncio.sleep(1)  # 可以注释掉
    return 0

print("say_something 是一个协程函数吗? %s" %
      ('是' if iscoroutinefunction(say_something) else '否'))
# ret = asyncio.run(say_something())
# print(f"say_something 的结果是: {ret}")
"""
1. async 与 await构成了一个协程函数
2. async函数不一定非要有await
3. asyncio.run可以运行一个协程函数
    1. 它运行时会创建一个event loop
    2. 当函数结束时, 会关闭这个loop
    3. event loop一个“线程”中只能有一个
    4. 理想情况下, python推荐我们将它作为main的入口, 并且只调用一次
"""

# 三种方式运行coroutine的机制
# run create_task
示例#17
0
 def _check_not_coroutine(self, callback, name):
     """Check whether the given callback is a coroutine or not."""
     if (coroutines.iscoroutine(callback) or coroutines.iscoroutinefunction(callback)):
         raise TypeError("coroutines cannot be used with {}()".format(name))
示例#18
0
    async def _handle_event(self, evt_type: EventType,
                            evt_data: Optional[dict]) -> None:
        """Handle incoming event for this resource from the EventStream."""
        if evt_data is None:
            return
        item_id = evt_data.get("rid", evt_data["id"])
        if evt_type == EventType.RESOURCE_ADDED:
            # new item added
            try:
                cur_item = self._items[item_id] = dataclass_from_dict(
                    self.item_cls, evt_data)
            except (KeyError, ValueError, TypeError) as exc:
                # In an attempt to not completely crash when a single resource can't be parsed
                # due to API schema mismatches, bugs in Hue or other factors, we allow some
                # resources to be skipped. This only works for resources that are not dependees
                # for other resources so we define this in the controller level.
                if not self.allow_parser_error:
                    raise exc
                self._logger.error(
                    "Unable to parse resource, please report this to the authors of aiohue.",
                    exc_info=exc,
                )
                return
        elif evt_type == EventType.RESOURCE_DELETED:
            # existing item deleted
            cur_item = self._items.pop(item_id, evt_data)
        elif evt_type == EventType.RESOURCE_UPDATED:
            # existing item updated
            cur_item = self._items.get(item_id)
            if cur_item is None:
                # should not be possible but just in case
                # if this does happen often we should consider fetching the full object
                self._logger.warning("received update for unknown item %s",
                                     item_id)
                return
            # update the existing data with the changed keys/data
            updated_keys = update_dataclass(cur_item, evt_data)
            # do not forward update event if no keys were updated
            if len(updated_keys
                   ) == 0 and self.item_type != ResourceTypes.BUTTON:
                return
            # Do not forward update events for button resource if
            # the button feature is missing in event data in an attempt to prevent
            # ghost events at bridge reboots/firmware updates.
            # in fact this is a feature request to Signify to handle these stateless
            # device events in a different way:
            # https://developers.meethue.com/forum/t/differentiate-stateless-events/6627
            if self.item_type == ResourceTypes.BUTTON and not evt_data.get(
                    "button"):
                return
        else:
            # ignore all other events
            return

        subscribers = (self._subscribers.get(item_id, []) +
                       self._subscribers[ID_FILTER_ALL])
        for (callback, event_filter) in subscribers:
            if event_filter is not None and evt_type not in event_filter:
                continue
            # dispatch the full resource object to the callback
            if iscoroutinefunction(callback):
                asyncio.create_task(callback(evt_type, cur_item))
            else:
                callback(evt_type, cur_item)
示例#19
0
 def _check_not_coroutine(self, callback, name):
     from asyncio import coroutines
     if (coroutines.iscoroutine(callback) or
             coroutines.iscoroutinefunction(callback)):
         raise TypeError("coroutines cannot be used with {}()".format(name))
示例#20
0
async def run_async_or_thread(handler: Callable, *args: Any,
                              **kwargs: Any) -> Any:
    if iscoroutinefunction(handler):
        return await handler(*args, **kwargs)
    return await run_in_threadpool(handler, *args, **kwargs)