def _get_type(obj): if inspect.isclass(obj): return 'class' elif inspect.isroutine(obj): return 'async' if inspect.iscoroutinefunction( obj) or inspect.isasyncgenfunction(obj) else 'sync' else: return 'unknown'
def wrap(source): for name in dir(source): method = getattr(source, name) if not name.startswith("_"): if inspect.iscoroutinefunction( method) or inspect.isasyncgenfunction(method): async_to_sync(source, name)
def pytest_collection_modifyitems(items): """add asyncio marker to all async tests""" for item in items: if inspect.iscoroutinefunction(item.obj): item.add_marker('asyncio') if hasattr(inspect, 'isasyncgenfunction'): # double-check that we aren't mixing yield and async def assert not inspect.isasyncgenfunction(item.obj)
async def test_uninverted_experiment(experiment: Experiment): await run_until(experiment, ExperimentStates.Idle) assert inspect.isasyncgenfunction(experiment.scan_configuration.sequence) await experiment.messages.put(ExperimentTransitions.Start) await run_until(experiment, ExperimentStates.Idle) ZarrSaver.save_run.assert_called_once()
def isasyncgenfunction(obj: Any) -> bool: """Check if the object is async-gen function.""" if hasattr(obj, '__code__') and inspect.isasyncgenfunction(obj): # check obj.__code__ because isasyncgenfunction() crashes for custom method-like # objects on python3.7 (see https://github.com/sphinx-doc/sphinx/issues/9838) return True else: return False
def _un_wrap(source): for name in dir(source): if name.startswith("_"): continue wrapped = getattr(getattr(source, name), '__wrapped__', None) if wrapped and (inspect.iscoroutinefunction(wrapped) or inspect.isasyncgenfunction(wrapped)): _un_wrapper(source, name, wrapped)
async def __call__(self, *args, **kwargs): if inspect.isasyncgenfunction(self.method): async for item in self.method(*args, **kwargs): yield item else: for item in self.method(*args, **kwargs): yield item await self.mapping.delete(self.key(*args, **kwargs))
def __init__(self, func: Callable[..., Any], args, kwargs): if not inspect.isasyncgenfunction(func): raise RuntimeError( 'Context manager function must be async-generator') self._agen = func(*args, **kwargs) self.func = func self.args = args self.kwargs = kwargs
async def solve_generator( *, call: Callable, stack: AsyncExitStack, sub_values: Dict[str, Any] ) -> Any: if inspect.isgeneratorfunction(call): cm = contextmanager_in_threadpool(contextmanager(call)(**sub_values)) elif inspect.isasyncgenfunction(call): cm = asynccontextmanager(call)(**sub_values) return await stack.enter_async_context(cm)
def then(self, fn, deferred=False): result = Future(self._loop) if not deferred: deferred = inspect.iscoroutinefunction( fn) or inspect.isasyncgenfunction(fn) self.add_done_callback( lambda _: self._then_callback(fn, result, deferred=deferred)) return result
def iter_errors(self, instance, _schema=None): if _schema is None: _schema = self.schema if _schema is True: return elif _schema is False: yield exceptions.ValidationError( "False schema does not allow %r" % (instance, ), validator=None, validator_value=None, instance=instance, schema=_schema, ) return scope = id_of(_schema) if scope: self.resolver.push_scope(scope) try: ref = _schema.get(u"$ref") if ref is not None: validators = [(u"$ref", ref)] else: validators = iteritems(_schema) for k, v in validators: validator = self.VALIDATORS.get(k) if validator is None: continue if PY36 and inspect.isasyncgenfunction(validator): bp = AsyncValidationBreakpoint( coroutine=validator, value=v, validator=k, validator_value=v, instance=instance, schema=_schema, ) yield bp errors = bp.errors else: errors = validator(self, v, instance, _schema) or () for error in errors: # set details if not already set by the called fn error._set( validator=k, validator_value=v, instance=instance, schema=_schema, ) if k != u"$ref": error.schema_path.appendleft(k) yield error finally: if scope: self.resolver.pop_scope()
async def process(self): """Process new request.""" try: # Run preprocessors... for pre in self._pre: if await _run_filters(pre.filters): await _call_or_await(pre.handler) anext = False scope = _user_scope() handler = None # if have user scope, try find handler that wait continue # processing through async generators mechanism. if scope: handler = await self.__find_waiter(scope) if handler: anext = True # Find handler from handlers list. if not handler: for hdlr in self._handlers: if await _run_filters(hdlr.filters): handler = hdlr break # No handlers found. Exiting. if not handler: raise HandlerNotFoundError # Run handler... if isasyncgenfunction(handler.handler) or isasyncgen(handler.handler): # handler is async generator... if not scope: emsg = f'Found async generator `{handler.handler.__name__}` but user_scope' \ f'is undefined for update `{context.update.update_id}`' raise TypeError(emsg) await self.__run_generator(anext, handler, scope) else: # This is normal handler. r = handler.handler() if isawaitable(r): await r # Run postprocessors... for post in self._post: if await _run_filters(post.filters): await _call_or_await(post.handler) # Cleanup waiters: current = int(time()) if current > self.__last_waiters_check + self.__watires_lifetime_check: self.__last_waiters_check = current _ = asyncio.create_task(self.__waiters_cleanup(current)) except HandlerNotFoundError: logger.warning('Handler not found for update:\n%s', replace(context.update, raw=dict()))
def wrap(f): if inspect.isasyncgenfunction(f): ff = asyncio_extras.async_contextmanager(f) ff._isasync = True # noinspection PyTypeChecker return deco(ff) else: return deco(contextlib.contextmanager(f))
async def run(self): '''run the engine''' # setup future queue self._queued_events = deque() self._queued_targeted_events = deque() # await all connections await asyncio.gather(*(asyncio.create_task(exch.connect()) for exch in self.exchanges)) await asyncio.gather(*(asyncio.create_task(exch.instruments()) for exch in self.exchanges)) # send start event to all callbacks await self.processEvent(Event(type=EventType.START, target=None)) # **************** # # Main event loop # **************** # async with merge( *(exch.tick() for exch in self.exchanges + [self] if inspect.isasyncgenfunction(exch.tick))).stream() as stream: # stream through all events async for event in stream: # tick exchange event to handlers await self.processEvent(event) # TODO move out of critical path if self._offline(): # use time of last event self._latest = event.target.timestamp if hasattr( event, 'target') and hasattr( event.target, 'timestamp') else self._latest else: # use now self._latest = datetime.now() # process any secondary events while self._queued_events: event = self._queued_events.popleft() await self.processEvent(event) # process any secondary callback-targeted events (e.g. order fills) # these need to route to a specific callback, # rather than all callbacks while self._queued_targeted_events: strat, event = self._queued_targeted_events.popleft() # send to the generating strategy await self.processEvent(event, strat) # process any periodics await asyncio.gather( *(asyncio.create_task(p.execute(self._latest)) for p in self.manager._periodics)) # Before engine shutdown, send an exit event await self.processEvent(Event(type=EventType.EXIT, target=None))
def add_route(app, fn): method = getattr(fn, '__method__', None) path = getattr(fn, '__route__', None) if parse is None or method is None: raise ValueError('@get or @post not defined in %s.' % str(fn)) if not asyncio.iscoroutinefunction(fn) and inspect.isasyncgenfunction(fn): fn = asyncio.coroutine(fn) logging.info('add route %s %s ==> %s(%s)' % (method, path, fn.__name__, ''.join(inspect.signature(fn).parameters.keys()))) app.router.add_route(method, path, RequestHandler(app, fn))
def __call__(self, implementation: Callable) -> Callable: if not isasyncgenfunction(implementation): raise NonAsyncGeneratorSubscription( "The subscription `{}` given is not an awaitable " "generator.".format(repr(implementation))) SchemaRegistry.register_subscription(self._schema_name, self) self._implementation = implementation return implementation
def whatis(self, arguments): """Prints the type of the argument. Usage: whatis <name>... """ arg = " ".join(arguments["argv"][1:]) try: value = eval(arg, self._obj.curframe.f_globals, self._obj.curframe.f_locals) except: # noqa v = sys.exc_info()[1] self._ui.printf('*** %R{}%N: {}\n'.format(type(v).__name__, v)) return if inspect.ismodule(value): self._ui.print(str(value)) elif inspect.isasyncgenfunction(value): self._ui.print('Async Gen function:', value.__name__, inspect.signature(value)) elif inspect.isasyncgen(value): self._ui.print('Async Gen:', value.__name__, inspect.signature(value)) elif inspect.iscoroutine(value): self._ui.print('Coroutine:', value) self._ui.print(' state:', inspect.getcoroutinestate(value)) if inspect.isawaitable(value): self._ui.print(' and awaitable.') self._ui.print(' stack:', _coroutine_format_stack(value, complete=False)) elif inspect.isgenerator(value): self._ui.print('Generator:', value) self._ui.print(' state:', inspect.getgeneratorstate(value)) if inspect.isawaitable(value): self._ui.print(' and awaitable.') elif inspect.iscoroutinefunction(value): self._ui.print('Coroutine function:', value.__name__, inspect.signature(value)) elif inspect.isgeneratorfunction(value): self._ui.print('Generator function:', value.__name__, inspect.signature(value)) elif inspect.isfunction(value): self._ui.print('Function:', value.__name__, inspect.signature(value)) elif inspect.ismethod(value): self._ui.print('Method:', value.__name__, inspect.signature(value)) elif inspect.iscode(value): self._ui.print('Code object:', value.co_name) elif inspect.isclass(value): self._ui.print('Class:', value.__name__) elif inspect.ismethoddescriptor(value): self._ui.print('Method descriptor:', value.__name__) elif inspect.isdatadescriptor(value): self._ui.print('Data descriptor:', value.__name__) # None of the above... else: self._ui.print(repr(type(value)))
def wrapper(func): # Handle async case. Func should be an async context manager if the # function was defined using `async def` rather than just `def` is_async = False if inspect.isasyncgenfunction(func): func = contextlib.asynccontextmanager(func) is_async = True @contextlib.asynccontextmanager async def wrapped(*args, **kwargs): async with func( *ContextManagedWrapperSource.remove_self_from_args( args), **kwargs, ) as source: yield source elif inspect.isgeneratorfunction(func): func = contextlib.contextmanager(func) @contextlib.contextmanager def wrapped(*args, **kwargs): with func( *ContextManagedWrapperSource.remove_self_from_args( args), **kwargs, ) as source: yield source else: raise FunctionMustBeGenerator(f"{func} does not 'yield'") # Wrap with functools wrapped = functools.wraps(func)(wrapped) # Create a new class whose name is the entry point name in camel case # with the suffix added. Whose parent class is # ContextManagedWrapperSource. # Create a new config class (@config) and set it as the CONFIG property # of the class we're creating. This will be used to configure the source # The properties of the config class will be taken from the arguments of # the function we are wrapping. # ContextManagedWrapperSource will call the WRAPPED function, which is # our func, and pass it the values of the properties of the config # class. # It will call it as an async context manager if IS_ASYNC is True. wrapped.source = entrypoint(entrypoint_name)(type( class_name, (ContextManagedWrapperSource, ), { "CONFIG": make_config_inspect(class_name + "Config", func), "WRAPPED": wrapped, "IS_ASYNC": is_async, }, )) return wrapped
def funcdef(self) -> str: """ The string of keywords used to define the function, i.e. `"def"` or `"async def"`. """ if inspect.iscoroutinefunction(self.obj) or inspect.isasyncgenfunction( self.obj): return "async def" else: return "def"
def pytest_pyfunc_call(pyfuncitem): """Run launch_pytest test coroutines and functions in an event loop.""" if not is_launch_test(pyfuncitem): yield return func = pyfuncitem.obj if has_shutdown_kwarg(pyfuncitem) and need_shutdown_test_item(func): error_msg = ( 'generator or async generator based launch test items cannot be marked with' ' shutdown=True') fail(error_msg) yield return shutdown_test = is_shutdown_test(pyfuncitem) fixture = get_launch_test_fixture(pyfuncitem) scope = fixture._pytestfixturefunction.scope event_loop = pyfuncitem.funcargs['event_loop'] ls = pyfuncitem.funcargs['launch_service'] auto_shutdown = fixture._launch_pytest_fixture_options['auto_shutdown'] on_shutdown = functools.partial( finalize_launch_service, ls, eprefix=f'When running test {func.__name__}', auto_shutdown=auto_shutdown) before_test = on_shutdown if shutdown_test else None if inspect.iscoroutinefunction(func): pyfuncitem.obj = wrap_coroutine(func, event_loop, before_test) elif inspect.isgeneratorfunction(func): if scope != 'function': shutdown_item = pyfuncitem._launch_pytest_shutdown_item pyfuncitem.obj, shutdown_item.obj = (wrap_generator( func, event_loop, on_shutdown)) shutdown_item._fixtureinfo = shutdown_item.session._fixturemanager.getfixtureinfo( shutdown_item, shutdown_item.obj, shutdown_item.cls, funcargs=True) else: pyfuncitem.obj = wrap_generator_fscope(func, event_loop, on_shutdown) elif inspect.isasyncgenfunction(func): if scope != 'function': shutdown_item = pyfuncitem._launch_pytest_shutdown_item pyfuncitem.obj, shutdown_item.obj = (wrap_asyncgen( func, event_loop, on_shutdown)) shutdown_item._fixtureinfo = shutdown_item.session._fixturemanager.getfixtureinfo( shutdown_item, shutdown_item.obj, shutdown_item.cls, funcargs=True) else: pyfuncitem.obj = wrap_asyncgen_fscope(func, event_loop, on_shutdown) elif not getattr(pyfuncitem.obj, '_launch_pytest_wrapped', False): pyfuncitem.obj = wrap_func(func, event_loop, before_test) yield
def get_dependant( *, path: str, call: Callable, name: str = None, security_scopes: List[str] = None, use_cache: bool = True, ) -> Dependant: path_param_names = get_path_param_names(path) endpoint_signature = get_typed_signature(call) signature_params = endpoint_signature.parameters if inspect.isgeneratorfunction(call) or inspect.isasyncgenfunction(call): check_dependency_contextmanagers() dependant = Dependant(call=call, name=name, path=path, use_cache=use_cache) for param_name, param in signature_params.items(): if isinstance(param.default, params.Depends): sub_dependant = get_param_sub_dependant( param=param, path=path, security_scopes=security_scopes) dependant.dependencies.append(sub_dependant) for param_name, param in signature_params.items(): if isinstance(param.default, params.Depends): continue if add_non_field_param_to_dependency(param=param, dependant=dependant): continue param_field = get_param_field(param=param, default_field_info=params.Query, param_name=param_name) if param_name in path_param_names: assert is_scalar_field( field=param_field ), f"Path params must be of one of the supported types" if isinstance(param.default, params.Path): ignore_default = False else: ignore_default = True param_field = get_param_field( param=param, param_name=param_name, default_field_info=params.Path, force_type=params.ParamTypes.path, ignore_default=ignore_default, ) add_param_to_fields(field=param_field, dependant=dependant) elif is_scalar_field(field=param_field): add_param_to_fields(field=param_field, dependant=dependant) elif isinstance( param.default, (params.Query, params.Header)) and is_scalar_sequence_field(param_field): add_param_to_fields(field=param_field, dependant=dependant) else: field_info = get_field_info(param_field) assert isinstance( field_info, params.Body ), f"Param: {param_field.name} can only be a request body, using Body(...)" dependant.body_params.append(param_field) return dependant
def stream(self, func: StreamFunc) -> StreamFunc: """Stream the response. Should be used to decorate a no-argument asynchronous generator function. """ assert inspect.isasyncgenfunction(func) self._stream = func() return func
def get_class_results(lookup: Dict[str, List[str]], modulename: str, name: str, fullname: str) -> Dict[str, List[TableElement]]: module = importlib.import_module(modulename) cls = getattr(module, name) groups: Dict[str, List[TableElement]] = { _('Attributes'): [], _('Methods'): [], } try: members = lookup[fullname] except KeyError: return groups for attr in members: attrlookup = f'{fullname}.{attr}' key = _('Attributes') badge = None label = attr value = None for base in cls.__mro__: value = base.__dict__.get(attr) if value is not None: break if value is not None: doc = value.__doc__ or '' if inspect.iscoroutinefunction(value) or doc.startswith('|coro|'): key = _('Methods') badge = attributetablebadge('async', 'async') badge['badge-type'] = _('coroutine') elif isinstance(value, classmethod): key = _('Methods') label = f'{name}.{attr}' badge = attributetablebadge('cls', 'cls') badge['badge-type'] = _('classmethod') elif inspect.isfunction(value): if doc.startswith(('A decorator', 'A shortcut decorator')): # finicky but surprisingly consistent key = _('Methods') badge = attributetablebadge('@', '@') badge['badge-type'] = _('decorator') elif inspect.isasyncgenfunction(value): key = _('Methods') badge = attributetablebadge('async for', 'async for') badge['badge-type'] = _('async iterable') else: key = _('Methods') badge = attributetablebadge('def', 'def') badge['badge-type'] = _('method') groups[key].append( TableElement(fullname=attrlookup, label=label, badge=badge)) return groups
def is_docable(attr): if isinstance(attr, inspect.Attribute): member = attr.object else: member = attr if isinstance(member, commands.Command) or isinstance(member, dutils.EventLoop): return True return inspect.iscoroutinefunction(member) or inspect.isfunction(member) or inspect.ismethod(member) or \ inspect.isasyncgenfunction(member) or inspect.isgeneratorfunction(member) or inspect.isclass(member) or \ isinstance(member, property)
def _ensure_future(self, func, *args, **kwds): if not inspect.iscoroutinefunction( func) and not inspect.isasyncgenfunction(func): assert callable(func), ( "_ensure_future first parameter must be callable or a coroutine, got" f" {type(func)}") return Future(self), func, args, kwds else: task = _Task(self, func, *args, **kwds) return task, task.step, tuple(), dict()
def convert_fixtures(fixturedef, request, node): """Used to replace async fixtures""" if not hasattr(fixturedef, "func"): return if inspect.iscoroutinefunction(fixturedef.func): convert_async_coroutine_fixture(fixturedef, request, node) elif inspect.isasyncgenfunction(fixturedef.func): convert_async_gen_fixture(fixturedef, request, node)
def wrapper(*args, anyio_backend, **kwargs): # type: ignore[no-untyped-def] backend_name, backend_options = extract_backend_and_options(anyio_backend) if has_backend_arg: kwargs["anyio_backend"] = anyio_backend with get_runner(backend_name, backend_options) as runner: if isasyncgenfunction(func): yield from runner.run_asyncgen_fixture(func, kwargs) else: yield runner.run_fixture(func, kwargs)
def _read_device(config: dict[str, Any]) -> AsyncGenerator[Any, None]: on_read: partial timeout: float on_read, timeout = config["on_read"] if inspect.isasyncgenfunction(on_read.func): return stream.iterate(on_read()) | pipe.timeout(timeout) return (stream.repeat(config["on_read"], interval=config["interval"]) | pipe.starmap(lambda func, timeout: stream.just(func()) | pipe .timeout(timeout)) | pipe.concat(task_limit=1))
def pytest_fixture_setup(fixturedef): # type: ignore[no-untyped-def] """Set up pytest fixture. Allow fixtures to be coroutines. Run coroutine fixtures in an event loop. """ func = fixturedef.func if inspect.isasyncgenfunction(func): # async generator fixture is_async_gen = True elif asyncio.iscoroutinefunction(func): # regular async fixture is_async_gen = False else: # not an async fixture, nothing to do return strip_request = False if "request" not in fixturedef.argnames: fixturedef.argnames += ("request",) strip_request = True def wrapper(*args, **kwargs): # type: ignore[no-untyped-def] request = kwargs["request"] if strip_request: del kwargs["request"] # if neither the fixture nor the test use the 'loop' fixture, # 'getfixturevalue' will fail because the test is not parameterized # (this can be removed someday if 'loop' is no longer parameterized) if "loop" not in request.fixturenames: raise Exception( "Asynchronous fixtures must depend on the 'loop' fixture or " "be used in tests depending from it." ) _loop = request.getfixturevalue("loop") if is_async_gen: # for async generators, we need to advance the generator once, # then advance it again in a finalizer gen = func(*args, **kwargs) def finalizer(): # type: ignore[no-untyped-def] try: return _loop.run_until_complete(gen.__anext__()) except StopAsyncIteration: pass request.addfinalizer(finalizer) return _loop.run_until_complete(gen.__anext__()) else: return _loop.run_until_complete(func(*args, **kwargs)) fixturedef.func = wrapper
def pytest_collection_modifyitems(items): """This function is automatically run by pytest passing all collected test functions. We use it to add asyncio marker to all async tests and assert we don't use test functions that are async generators which wouldn't make sense. """ for item in items: if inspect.iscoroutinefunction(item.obj): item.add_marker('asyncio') assert not inspect.isasyncgenfunction(item.obj)
def _test_client_method(self, client: Callable, name: str) -> None: self.assertTrue(client is not None, f"{name} should have a client method") self.assertTrue( iscoroutinefunction(client) or isasyncgenfunction(client), f"The client method of {name} should be a coroutine", ) self.assertTrue( _takes_client(client), f"The client method of {name} should take a CompanionClient", )
def _is_async(self): """ Returns whether is function is asynchronous, either as a coroutine or an async generator. """ try: # Both of these are required because coroutines aren't classified as # async generators and vice versa. return inspect.iscoroutinefunction(self.func) or inspect.isasyncgenfunction( self.func ) except AttributeError: return False
def isasyncgenfunction(obj): if hasattr(inspect, "isasyncgenfunction"): if inspect.isasyncgenfunction(obj): return True return getattr(obj, "_async_gen_function", -1) == id(obj)
def isasyncgenfunction(obj): if hasattr(inspect, 'isasyncgenfunction'): return inspect.isasyncgenfunction(obj) return False