Exemple #1
0
async def test_ensure_awaitable():

    m = AsyncMock()

    def test():
        return m
    a = utils.ensure_awaitable(test)
    assert inspect.isawaitable(a)
    await a
    m.assert_called_once_with()

    m = AsyncMock()

    async def test():
        return await m
    a = utils.ensure_awaitable(test)
    assert inspect.isawaitable(a)
    await a
    m.assert_called_once_with()

    m = AsyncMock()

    async def test():
        return await m
    a = utils.ensure_awaitable(test())
    assert inspect.isawaitable(a)
    await a
    m.assert_called_once_with()

    with pytest.raises(TypeError):
        a = utils.ensure_awaitable("test()")
Exemple #2
0
    async def request_resource(self, type: Union[str, type], alias: str = 'default', *,
                               timeout: Union[int, None] = None):
        """
        Request a resource matching the given type and alias.

        If no such resource was found, this method will wait ``timeout`` seconds for it to become
        available. The timeout does not apply to resolving awaitables created by lazy resource
        creators.

        :param type: type of the requested resource
        :param alias: alias of the requested resource
        :param timeout: the timeout (in seconds; omit to use the context's default timeout)
        :return: the value contained by the requested resource (**NOT** a :class:`Resource`
            instance)
        :raises asphalt.core.context.ResourceNotFound: if the requested resource does not become
            available in the allotted time

        """
        assert check_argument_types()
        if not type:
            raise ValueError('type must be a type or a nonempty string')
        if not alias:
            raise ValueError('alias must be a nonempty string')

        resource_type = qualified_name(type) if not isinstance(type, str) else type
        timeout = timeout if timeout is not None else self.default_timeout
        assert timeout >= 0, 'timeout must be a positive integer'

        # Build a context chain from this context and its parents
        context_chain = [self]
        while context_chain[-1]._parent:
            context_chain.append(context_chain[-1]._parent)

        # First try to look up the resource in the context chain
        for ctx in context_chain:
            resource = ctx._resources.get(resource_type, {}).get(alias)
            if resource is not None:
                value = resource.get_value(self)
                return await value if isawaitable(value) else value

        # Listen to resource publish events in the whole chain and wait for the right kind of
        # resource to be published
        def resource_listener(event: ResourceEvent):
            if event.resource.alias == alias and resource_type in event.resource.types:
                future.set_result(event.resource)

        future = Future()
        for ctx in context_chain:
            ctx.resource_published.connect(resource_listener)

        try:
            resource = await wait_for(future, timeout)
        except TimeoutError:
            raise ResourceNotFound(resource_type, alias) from None
        else:
            value = resource.get_value(self)
            return await value if isawaitable(value) else value
        finally:
            for ctx in context_chain:
                ctx.resource_published.disconnect(resource_listener)
Exemple #3
0
    async def resolve(self, _next, _resource, _info, **kwargs):
        parent_name = _info.parent_type.name
        field_name = _info.field_name
        return_type = _info.return_type

        self.logger.log(
            self.level,
            f'Resolving {parent_name}.{field_name} expecting type {return_type}'
        )

        start_time = time.perf_counter()

        if inspect.isawaitable(_next):
            results = await _next(_resource, _info, **kwargs)
        else:
            results = _next(_resource, _info, **kwargs)

        if inspect.isawaitable(results):
            results = await results

        end_time = time.perf_counter()
        total_time = end_time - start_time
        self.logger.log(
            self.level,
            f'Field {parent_name}.{field_name} resolved: {results!r} in {total_time:.6f} seconds'
        )

        return results
def test_convert_generator_to_coroutine():
    def gen():
        yield 100

    assert not inspect.isawaitable(gen())

    coroutine(gen)
    assert inspect.isawaitable(gen())
Exemple #5
0
 async def save(self, force_insert=False, only=None):
     result = super().save(force_insert=force_insert, only=only)
     if self._meta.primary_key is not False:
         pk_value = self._get_pk_value()
         if inspect.isawaitable(pk_value):
             self._set_pk_value(await pk_value)
     if inspect.isawaitable(result):
         return await result
     return result
Exemple #6
0
    async def run_it(self, _next, _resource, _info, **kwargs):
        if inspect.isawaitable(_next):
            results = await _next(_resource, _info, **kwargs)
        else:
            results = _next(_resource, _info, **kwargs)

        if inspect.isawaitable(results):
            return await results
        return results
Exemple #7
0
    def test_Awaitable(self):
        def gen():
            yield

        #@types.coroutine
        #def coro():
        #    yield

        #async def new_coro():
        #    pass

        class Bar(object):
            def __await__(self):
                yield

        class MinimalCoro(Coroutine):
            def send(self, value):
                return value
            def throw(self, typ, val=None, tb=None):
                super(MinimalCoro, self).throw(typ, val, tb)
            def __await__(self):
                yield

        non_samples = [None, int(), gen(), object()]
        for x in non_samples:
            self.assertNotIsInstance(x, Awaitable)
            self.assertFalse(issubclass(type(x), Awaitable), repr(type(x)))
            self.assertFalse(inspect.isawaitable(x))

        samples = [Bar(), MinimalCoro()]
        for x in samples:
            self.assertIsInstance(x, Awaitable)
            self.assertTrue(issubclass(type(x), Awaitable))
            self.assertTrue(inspect.isawaitable(x))

        #c = coro()
        #self.assertIsInstance(c, Awaitable)
        #c.close() # awoid RuntimeWarning that coro() was not awaited

        #c = new_coro()
        #self.assertIsInstance(c, Awaitable)
        #c.close() # awoid RuntimeWarning that coro() was not awaited

        class CoroLike(object): pass
        Coroutine.register(CoroLike)
        self.assertTrue(inspect.isawaitable(CoroLike()))
        self.assertTrue(isinstance(CoroLike(), Awaitable))
        self.assertTrue(issubclass(CoroLike, Awaitable))
        CoroLike = None
        gc_collect() # Kill CoroLike to clean-up ABCMeta cache
Exemple #8
0
    async def _eval(self, ctx, *, code: str):
        """Extremely unsafe eval command.
        Stolen from someone, Unknown original author"""
        code = code.strip('` ')
        python = '```py\n{}\n```'

        env = {
            'bot': self.bot,
            'ctx': ctx,
            'message': ctx.message,
            'guild': ctx.guild,
            'channel': ctx.channel,
            'author': ctx.author
        }

        env.update(globals())

        try:
            result = eval(code, env)
            if inspect.isawaitable(result):
                result = await result
        except Exception as e:
            await ctx.send(python.format(type(e).__name__ + ': ' + str(e)))
            return

        await ctx.send(python.format(result))
Exemple #9
0
    async def debug(self, ctx, *, code : str):
        """Evaluates code."""
        code = code.strip('` ')
        python = '```py\n{}\n```'
        result = None

        env = {
            'bot': self.bot,
            'ctx': ctx,
            'message': ctx.message,
            'server': ctx.message.server,
            'channel': ctx.message.channel,
            'author': ctx.message.author
        }

        env.update(globals())

        try:
            result = eval(code, env)
            if inspect.isawaitable(result):
                result = await result
        except Exception as e:
            await self.bot.say(python.format(type(e).__name__ + ': ' + str(e)))
            return
        try:
            await self.bot.say(python.format(result))
        except discord.HTTPException:
            await self.bot.say("Result is too long for me to send")
        except:
            pass
Exemple #10
0
    async def run_eval(self, code, ctx):
        vals = globals()
        vals.update(dict(
            bot=self,
            message=ctx.message,
            ctx=ctx,
            guild=ctx.guild,
            channel=ctx.channel,
            author=ctx.author,
            code=code
        ))

        try:
            precompiled = compile(code, "<eval>", "eval")
            vals["compiled"] = precompiled
            result = eval(precompiled, vals)
        except SyntaxError as e:
            return f"```py\n{e.text}\n{'^':>{e.offset}}\n{type(e).__name__}: {e}\n```"
        except Exception as e:
            return f"```diff\n- {type(e).__name__}: {e}\n```"

        if isawaitable(result):
            result = await result

        result = str(result)
        if len(result) > 1900:
            gist = await self.upload_to_gist(result, "eval.py")
            return f"\N{WARNING SIGN} Output too long. View result at {gist}\n"
        else:
            return f"```py\n{result}\n```"
Exemple #11
0
    async def close(self, exception: BaseException = None) -> None:
        """
        Close this context and call any necessary resource teardown callbacks.

        If a teardown callback returns an awaitable, the return value is awaited on before calling
        any further teardown callbacks.

        All callbacks will be processed, even if some of them raise exceptions. If at least one
        callback raised an error, this method will raise a :exc:`~.TeardownError` at the end.

        After this method has been called, resources can no longer be requested or published on
        this context.

        :param exception: the exception, if any, that caused this context to be closed
        :raises .TeardownError: if one or more teardown callbacks raise an exception

        """
        self._check_closed()
        self._closed = True

        exceptions = []
        for callback, pass_exception in reversed(self._teardown_callbacks):
            try:
                retval = callback(exception) if pass_exception else callback()
                if isawaitable(retval):
                    await retval
            except Exception as e:
                exceptions.append(e)

        del self._teardown_callbacks
        if exceptions:
            raise TeardownError(exceptions)
Exemple #12
0
    def emit(self, record):
        """Emit record to slack channel using pycurl to avoid recurrence
        event logging (log logged record)
        """
        if record.message.startswith(MESSAGE):   # avoid cyrcular emit
            return

        cfg = self.app.config
        managers = cfg['SLACK_LINK_NAMES']
        text = ''
        data = {}
        if managers:
            text = ' '.join(('@%s' % m for m in managers))
            text = '%s\n\n' % text
            data['link_names'] = 1
        context_factory = cfg['LOG_CONTEXT_FACTORY']
        data['text'] = text
        if context_factory:
            ctx = context_factory(self)
            data['text'] += "\n" + context_text_formatter(ctx)
        data['text'] += "```\n%s\n```" % self.format(record)
        sessions = self.app.http()
        response = sessions.post(self.webhook_url,
                                 data=json.dumps(data))
        if isawaitable(response):
            ensure_future(self._emit(response), loop=sessions._loop)
        else:
            sessions._loop.call_soon(self._raise_error, response)
Exemple #13
0
async def request(url, *, headers=None, payload=None, method='GET', attr='json'):
    # Make sure our User Agent is what's set, and ensure it's sent even if no headers are passed
    if headers == None:
        headers = {}
    headers['User-Agent'] = config.user_agent

    # Try 5 times
    for i in range(5):
        try:
            # Create the session with our headeres
            with aiohttp.ClientSession(headers=headers) as session:
                # Make the request, based on the method, url, and paramaters given
                async with session.request(method, url, params=payload) as response:
                    # If the request wasn't successful, re-attempt
                    if response.status != 200:
                        continue

                    try:
                        # Get the attribute requested
                        return_value = getattr(response, attr)
                        # Next check if this can be called
                        if callable(return_value):
                            return_value = return_value()
                        # If this is awaitable, await it
                        if inspect.isawaitable(return_value):
                            return_value = await return_value

                        # Then return it
                        return return_value
                    except AttributeError:
                        # If an invalid attribute was requested, return None
                        return None
        # If an error was hit other than the one we want to catch, try again
        except:
            continue
Exemple #14
0
        async def do_dispatch():
            futures, exceptions = [], []
            for callback in listeners:
                try:
                    retval = callback(event)
                except Exception as e:
                    exceptions.append((callback, e))
                    if not return_future:
                        logger.exception('uncaught exception in event listener')
                else:
                    if isawaitable(retval):
                        if iscoroutine(retval):
                            retval = loop.create_task(retval)

                        futures.append((callback, retval))

            # For any callbacks that returned awaitables, wait for their completion and collect any
            # exceptions they raise
            for callback, awaitable in futures:
                try:
                    await awaitable
                except Exception as e:
                    exceptions.append((callback, e))
                    if not return_future:
                        logger.exception('uncaught exception in event listener')

            if exceptions and return_future:
                raise EventDispatchError(event, exceptions)
Exemple #15
0
def convert_yielded(yielded: _Yieldable) -> Future:
    """Convert a yielded object into a `.Future`.

    The default implementation accepts lists, dictionaries, and Futures.

    If the `~functools.singledispatch` library is available, this function
    may be extended to support additional types. For example::

        @convert_yielded.register(asyncio.Future)
        def _(asyncio_future):
            return tornado.platform.asyncio.to_tornado_future(asyncio_future)

    .. versionadded:: 4.1
    """
    if yielded is None or yielded is moment:
        return moment
    elif yielded is _null_future:
        return _null_future
    elif isinstance(yielded, (list, dict)):
        return multi(yielded)  # type: ignore
    elif is_future(yielded):
        return typing.cast(Future, yielded)
    elif isawaitable(yielded):
        return _wrap_awaitable(yielded)  # type: ignore
    else:
        raise BadYieldError("yielded unknown object %r" % (yielded,))
Exemple #16
0
    async def debug(self, ctx, *, code : str):
        print("OK")
        """Evaluates code."""
        code = code.strip('` ')
        python = '```py\n{}\n```'
        result = None

        env = {
            'bot': self.bot,
            'ctx': ctx,
            'message': ctx.message,
            'guild': ctx.message.guild,
            'channel': ctx.message.channel,
            'author': ctx.message.author,
            'redis': utils.redis
        }

        env.update(globals())

        try:
            result = eval(code, env)
            if inspect.isawaitable(result):
                result = await result
        except Exception as e:
            await ctx.send(python.format(type(e).__name__ + ': ' + str(e)))
            return

        if len(python.format(result)) >= 2000:
            msg = await utils.send_hastebin(python.format(result))
        else:
            msg = python.format(result)

        await ctx.send(msg)
Exemple #17
0
 async def _call(self):
     testMethod = self.testMethod
     testStartUp = getattr(self.test, 'startUp', lambda: None)
     testGetTime = getattr(self.test, 'getTime', lambda dt: dt)
     testGetInfo = getattr(self.test, 'getInfo', simple)
     testGetSummary = getattr(self.test, 'getSummary', simple)
     t = 0
     t2 = 0
     info = {'name': '%s.%s' % (self.test.__class__.__name__,
                                testMethod.__name__)}
     for r in range(self.repeat):
         DT = 0
         for r in range(self.number):
             testStartUp()
             start = default_timer()
             result = testMethod()
             if isawaitable(result):
                 await result
             delta = default_timer() - start
             dt = testGetTime(delta)
             testGetInfo(info, delta, dt)
             DT += dt
         t += DT
         t2 += DT*DT
     self.update_summary(info, self.repeat, t, t2)
     self.set_test_attribute('bench_info',
                             testGetSummary(info, self.repeat, t, t2))
Exemple #18
0
    async def _run_safe(self, test, method_name, test_timeout, error=None):
        exc = None
        self._check_abort()
        try:
            method = getattr(test, method_name)
            coro = method()
            # a coroutine
            if isawaitable(coro):
                test_timeout = get_test_timeout(method, test_timeout)
                with timeout(self._loop, test_timeout):
                    exc = await store_trace(coro)
            elif isgenerator(coro):
                raise InvalidTestFunction('test function returns a generator')
        except SkipTest as x:
            self.runner.addSkip(test, str(x))
            exc = None
            error = False
        except Exception as x:
            exc = TestFailure(x)

        if exc and not error:
            error = exc
            can_fail = allow_failure(method) or expecting_failure(method)
            self.add_failure(test, error, can_fail)

        return error
Exemple #19
0
    async def debug(self, ctx, *, code: str):
        """Lets the bot owner evaluate code."""
        code = code.strip('` ')
        python = '```py\n{}\n```'
        result = None

        env = {
            'bot': self.bot,
            'ctx': ctx,
            'message': ctx.message,
            'server': ctx.message.server,
            'channel': ctx.message.channel,
            'author': ctx.message.author
        }

        env.update(globals())

        try:
            result = eval(code, env)
            if inspect.isawaitable(result):
                result = await result
        except Exception as e:
            await self.bot.say(python.format(type(e).__name__ + ': ' + str(e)))
            return

        await self.bot.say(python.format(result))
Exemple #20
0
def main():
    print('-' * 80)
    print(str.format(
        '[*] coroutine is coroutine function => {}',
        inspect.iscoroutinefunction(coroutine)
    ))
    print(str.format(
        '[*] subcoroutine is coroutine function => {}',
        inspect.iscoroutinefunction(subcoroutine)
    ))
    sub1 = subcoroutine('Subroutine')
    print(str.format(
        '[*] sub1 is coroutine object => {}', inspect.iscoroutine(sub1)
    ))
    coro1 = coroutine('Coroutine')
    print(str.format(
        '[*] coro1 is coroutine object => {}', inspect.iscoroutine(coro1)
    ))

    print('-' * 80)
    print(str.format(
        '[*] CoroutineClass is sub-class of Awaitable class => {}',
        issubclass(CoroutineClass, Awaitable)
    ))
    c1 = CoroutineClass('Coroutine #1', ['A', 'B', 'C'])
    print(str.format(
        '[*] c1 is awaitable object => {}', inspect.isawaitable(c1)
    ))
    print(str.format(
        '[*] c1 is instance of Awaitable class => {}',
        isinstance(c1, Awaitable)
    ))

    print('-' * 80)
Exemple #21
0
    async def call(
        self,
        document: GraphQLSchema,
        request: typing.Any = None,
        variables: typing.Dict[str, typing.Any] = None
    ) -> ExecutionResult:
        """Preform a query against the schema.

        This is meant to be called in an asyncio.loop, if you are using a
        web framework that is synchronous use the `call_sync` method.
        """
        validation_errors = validate(self.schema, document)
        if validation_errors:
            return ExecutionResult(data=None, errors=validation_errors)

        context = self.get_context(request)
        result = execute(
            schema=self.schema,
            document=document,
            context_value=context,
            variable_values=variables,
            middleware=self.middleware,
        )
        if inspect.isawaitable(result):
            return await result
        return result
Exemple #22
0
def maybe_future(obj):
    """Return an asyncio Future

    Use instead of gen.maybe_future

    For our compatibility, this must accept:

    - asyncio coroutine (gen.maybe_future doesn't work in tornado < 5)
    - tornado coroutine (asyncio.ensure_future doesn't work)
    - scalar (asyncio.ensure_future doesn't work)
    - concurrent.futures.Future (asyncio.ensure_future doesn't work)
    - tornado Future (works both ways)
    - asyncio Future (works both ways)
    """
    if inspect.isawaitable(obj):
        # already awaitable, use ensure_future
        return asyncio.ensure_future(obj)
    elif isinstance(obj, concurrent.futures.Future):
        return asyncio.wrap_future(obj)
    else:
        # could also check for tornado.concurrent.Future
        # but with tornado >= 5 tornado.Future is asyncio.Future
        f = asyncio.Future()
        f.set_result(obj)
        return f
Exemple #23
0
def ensure_iterables(*iterables, loop=None):
    for iterable in iterables:
        if inspect.isawaitable(iterable):
            future = asyncio.ensure_future(iterable, loop=loop)
            yield future_iterator(future)
        else:
            yield iterable
Exemple #24
0
    async def process_function(self, function, *args):
        arg_list = [self.arg_cache.popleft() if not isinstance(arg, lexer.Token) else arg.source.strip() for arg in args]
        arg_names = ["EXTERNAL" + str(self.level) if not isinstance(arg, lexer.Token) else arg.name for arg in args]
        func_name = function.source

        if KEYWORD_REGEX.fullmatch(func_name) is None:
            raise InvalidFunctionNameError("Function names must be alphanumeric")

        self.log(f"[Process] Calling {func_name} with args {list(zip(arg_names, arg_list))}")

        if hasattr(self.tag_functions, func_name):
            if callable(getattr(self.tag_functions, func_name)):
                try:
                    func_result = getattr(self.tag_functions, func_name)(*arg_list)

                    if isawaitable(func_result):
                        func_result = await func_result

                    return "" if func_result is None else func_result
                except Exception as e:
                    return str(e) if self.tag_functions.fallback_text is None else str(self.tag_functions.fallback_text)
            else:
                raise ParserError("An error occurred.")
        else:
            raise NonExistantFunctionError(f"Function {func_name} doesn't exist")
Exemple #25
0
        def _as_future(obj, loop):
            if inspect.isawaitable(obj):
                return asyncio.ensure_future(obj, loop=loop)

            f = loop.create_future()
            f.set_result(obj)
            return f
Exemple #26
0
def convert_yielded(yielded):
    """Convert a yielded object into a `.Future`.

    The default implementation accepts lists, dictionaries, and Futures.

    If the `~functools.singledispatch` library is available, this function
    may be extended to support additional types. For example::

        @convert_yielded.register(asyncio.Future)
        def _(asyncio_future):
            return tornado.platform.asyncio.to_tornado_future(asyncio_future)

    .. versionadded:: 4.1
    """
    # Lists and dicts containing YieldPoints were handled earlier.
    if yielded is None:
        return moment
    elif isinstance(yielded, (list, dict)):
        return multi(yielded)
    elif is_future(yielded):
        return yielded
    elif isawaitable(yielded):
        return _wrap_awaitable(yielded)
    else:
        raise BadYieldError("yielded unknown object %r" % (yielded,))
 def begin_request(self):
     ctx = HTTPRequestResponseContext(self.parent_ctx, self.request)
     try:
         retval = self.func(ctx)
         if isawaitable(retval):
             ensure_future(retval).add_done_callback(self.process_return_value)
     except Exception as e:
         pass
Exemple #28
0
 def close(self):
     self.closed = True
     # there is no reason for sess.close to be a coroutine, and
     # in older versions of aiohttp, it isn't. In newer versions
     # close returns an awaitable whose only purpose is to warn you
     # if you don't await it, so... await it... I guess???
     aiohttp_is_silly = self.sess.close()
     if inspect.isawaitable(aiohttp_is_silly):
         asyncio.ensure_future(aiohttp_is_silly)
Exemple #29
0
 async def trigger_events(self, events, loop):
     """Trigger events (functions or async)
     :param events: one or more sync or async functions to execute
     :param loop: event loop
     """
     for event in events:
         result = event(loop)
         if isawaitable(result):
             await result
Exemple #30
0
async def coro_wrapper(proc, *a, **kw):
    """\
        This code is responsible for turning whatever callable you pass in
        into a "yield from"-style coroutine.
        """
    proc = proc(*a, **kw)
    if inspect.isawaitable(proc):
        proc = await proc
    return proc
 async def await_and_set_result(results, response_name, result):
     awaited_results = await results
     awaited_results[response_name] = (
         await result if isawaitable(result) else result)
     return awaited_results
 async def await_result():
     value = self.complete_value(return_type, field_nodes, info,
                                 path, await result)
     if isawaitable(value):
         return await value
     return value
Exemple #33
0
 def declines_a_dict_value():
     assert not isawaitable({})
     assert not is_awaitable({})
Exemple #34
0
    async def upload_file(self: 'TelegramClient',
                          file: 'hints.FileLike',
                          *,
                          part_size_kb: float = None,
                          file_name: str = None,
                          use_cache: type = None,
                          progress_callback: 'hints.ProgressCallback' = None,
                          file_size=None,
                          http_headers=None) -> 'types.TypeInputFile':
        """
        Uploads a file to Telegram's servers, without sending it.

        This method returns a handle (an instance of :tl:`InputFile` or
        :tl:`InputFileBig`, as required) which can be later used before
        it expires (they are usable during less than a day).

        Uploading a file will simply return a "handle" to the file stored
        remotely in the Telegram servers, which can be later used on. This
        will **not** upload the file to your own chat or any chat at all.

        Arguments
            file (`str` | `bytes` | `file`):
                The path of the file, byte array, or stream that will be sent.
                Note that if a byte array or a stream is given, a filename
                or its type won't be inferred, and it will be sent as an
                "unnamed application/octet-stream".

            part_size_kb (`int`, optional):
                Chunk size when uploading files. The larger, the less
                requests will be made (up to 512KB maximum).

            file_name (`str`, optional):
                The file name which will be used on the resulting InputFile.
                If not specified, the name will be taken from the ``file``
                and if this is not a `str`, it will be ``"unnamed"``.

            use_cache (`type`, optional):
                This parameter currently does nothing, but is kept for
                backward-compatibility (and it may get its use back in
                the future).

            progress_callback (`callable`, optional):
                A callback function accepting two parameters:
                ``(sent bytes, total)``.

        Returns
            :tl:`InputFileBig` if the file size is larger than 10MB,
            `InputSizedFile <telethon.tl.custom.inputsizedfile.InputSizedFile>`
            (subclass of :tl:`InputFile`) otherwise.

        Example
            .. code-block:: python

                # Photos as photo and document
                file = await client.upload_file('photo.jpg')
                await client.send_file(chat, file)                       # sends as photo
                await client.send_file(chat, file, force_document=True)  # sends as document

                file.name = 'not a photo.jpg'
                await client.send_file(chat, file, force_document=True)  # document, new name

                # As song or as voice note
                file = await client.upload_file('song.ogg')
                await client.send_file(chat, file)                   # sends as song
                await client.send_file(chat, file, voice_note=True)  # sends as voice note
        """
        if isinstance(file, (types.InputFile, types.InputFileBig)):
            return file  # Already uploaded

        if file_size is None:
            if isinstance(file, str):
                if os.path.isfile(file):
                    file_size = os.path.getsize(file)
                else:
                    stream = req.urlopen(file)
                    file_size = int(stream.headers['Content-Length'])
            elif isinstance(file, bytes):
                file_size = len(file)
            elif hasattr(file, 'tell') and hasattr(file, 'read') and hasattr(
                    file, 'seek'):
                # `aiofiles` shouldn't base `IOBase` because they change the
                # methods' definition. `seekable` would be `async` but since
                # we won't get to check that, there's no need to maybe-await.
                if isinstance(file, io.IOBase) and file.seekable():
                    pos = file.tell()
                else:
                    pos = None

                # TODO Don't load the entire file in memory always
                data = file.read()
                if inspect.isawaitable(data):
                    data = await data

                if pos is not None:
                    file.seek(pos)

                if not isinstance(data, bytes):
                    raise TypeError(
                        'file descriptor returned {}, not bytes (you must '
                        'open the file in bytes mode)'.format(type(data)))

                file = data
                file_size = len(file)

            else:
                raise Exception('file size required for uploading')

        # File will now either be a string or bytes
        if not part_size_kb:
            part_size_kb = utils.get_appropriated_part_size(file_size)

        if part_size_kb > 512:
            raise ValueError('The part size must be less or equal to 512KB')

        part_size = int(part_size_kb * 1024)
        if part_size % 1024 != 0:
            raise ValueError('The part size must be evenly divisible by 1024')

        # Set a default file name if None was specified
        file_id = helpers.generate_random_long()
        if not file_name:
            if isinstance(file, str):
                file_name = os.path.basename(file)
            else:
                file_name = str(file_id)

        # If the file name lacks extension, add it if possible.
        # Else Telegram complains with `PHOTO_EXT_INVALID_ERROR`
        # even if the uploaded image is indeed a photo.
        if not os.path.splitext(file_name)[-1]:
            file_name += utils._get_extension(file)

        # Determine whether the file is too big (over 10MB) or not
        # Telegram does make a distinction between smaller or larger files
        is_large = file_size > 10 * 1024 * 1024
        hash_md5 = hashlib.md5()
        if not is_large:
            # Calculate the MD5 hash before anything else.
            # As this needs to be done always for small files,
            # might as well do it before anything else and
            # check the cache.
            if isinstance(file, str) and os.path.isfile(file):
                with open(file, 'rb') as stream:
                    file = stream.read()
            elif hasattr(file, 'read'):
                if inspect.iscoroutinefunction(file.read):
                    file = await file.read()
                else:
                    file = file.read()
                    if inspect.isawaitable(file):
                        file = await file
            elif isinstance(file, str):
                get_req = req.Request(file, method='GET', headers=http_headers)
                with req.urlopen(get_req) as resp:
                    file = resp.read()
            hash_md5.update(file)

        part_count = (file_size + part_size - 1) // part_size
        self._log[__name__].info(
            'Uploading file of %d bytes in %d chunks of %d', file_size,
            part_count, part_size)

        if isinstance(file, str) and os.path.isfile(file):
            stream = open(file, mode='rb')
        elif hasattr(file, 'read'):
            stream = file
        elif isinstance(file, bytes):
            stream = BytesIO(file)
        else:
            get_req = req.Request(file, method='GET', headers=http_headers)
            stream = req.urlopen(get_req)

        for part_index in range(part_count):
            # Read the file by in chunks of size part_size
            # part = out_proc.stdout.read(part_size)
            part = None
            if hasattr(stream, 'read'):
                if inspect.iscoroutinefunction(stream.read):
                    part = await stream.read(part_size)
                else:
                    part = stream.read(part_size)
                    if inspect.isawaitable(part):
                        part = await part
            else:
                raise Exception(
                    "Failed read from stream, there aren't read attribute")
            # part = stream.read(part_size)
            if len(part) == 0:
                part_count = part_index
                break
            if len(part) != part_size and part_index != part_count - 1:
                part_count = part_index + 1
            # The SavePartRequest is different depending on whether
            # the file is too large or not (over or less than 10MB)
            if is_large:
                request = functions.upload.SaveBigFilePartRequest(
                    file_id, part_index, part_count, part)
            else:
                request = functions.upload.SaveFilePartRequest(
                    file_id, part_index, part)

            result = await self(request)
            if result:
                self._log[__name__].debug('Uploaded %d/%d', part_index + 1,
                                          part_count)
                if progress_callback:
                    r = progress_callback(stream.tell(), file_size)
                    if inspect.isawaitable(r):
                        await r
            else:
                raise RuntimeError(
                    'Failed to upload file part {}.'.format(part_index))

        if is_large:
            return types.InputFileBig(file_id, part_count, file_name)
        else:
            return custom.InputSizedFile(file_id,
                                         part_count,
                                         file_name,
                                         md5=hash_md5,
                                         size=file_size)
Exemple #35
0
 async def resolve(self, next_: Resolver, parent: Any,
                   info: GraphQLResolveInfo, **kwargs):
     result = next_(parent, info, **kwargs)
     if isawaitable(result):
         result = await result
     return result
Exemple #36
0
async def subscribe(
    schema: GraphQLSchema,
    data: Any,
    *,
    context_value: Optional[Any] = None,
    root_value: Optional[RootValue] = None,
    debug: bool = False,
    introspection: bool = True,
    logger: Optional[str] = None,
    validation_rules: Optional[ValidationRules] = None,
    error_formatter: ErrorFormatter = format_error,
    **kwargs,
) -> SubscriptionResult:
    try:
        validate_data(data)
        query, variables, operation_name = (
            data["query"],
            data.get("variables"),
            data.get("operationName"),
        )

        document = parse_query(query)

        if callable(validation_rules):
            validation_rules = cast(
                Optional[Sequence[RuleType]],
                validation_rules(context_value, document, data),
            )

        validation_errors = validate_query(schema,
                                           document,
                                           validation_rules,
                                           enable_introspection=introspection)
        if validation_errors:
            for error_ in validation_errors:  # mypy issue #5080
                log_error(error_, logger)
            return (
                False,
                [error_formatter(error, debug) for error in validation_errors],
            )

        if callable(root_value):
            root_value = root_value(context_value, document)
            if isawaitable(root_value):
                root_value = await root_value

        result = await _subscribe(
            schema,
            document,
            root_value=root_value,
            context_value=context_value,
            variable_values=variables,
            operation_name=operation_name,
            **kwargs,
        )
    except GraphQLError as error:
        log_error(error, logger)
        return False, [error_formatter(error, debug)]
    else:
        if isinstance(result, ExecutionResult):
            errors = cast(List[GraphQLError], result.errors)
            for error_ in errors:  # mypy issue #5080
                log_error(error_, logger)
            return False, [error_formatter(error, debug) for error in errors]
        return True, cast(AsyncGenerator, result)
Exemple #37
0
 def declines_a_boolean_value():
     assert not isawaitable(True)
     assert not is_awaitable(True)
Exemple #38
0
    async def edit_2fa(
            self: 'TelegramClient',
            current_password: str = None,
            new_password: str = None,
            *,
            hint: str = '',
            email: str = None,
            email_code_callback: typing.Callable[[int], str] = None) -> bool:
        """
        Changes the 2FA settings of the logged in user.

        Review carefully the parameter explanations before using this method.

        Note that this method may be *incredibly* slow depending on the
        prime numbers that must be used during the process to make sure
        that everything is safe.

        Has no effect if both current and new password are omitted.

        Arguments
            current_password (`str`, optional):
                The current password, to authorize changing to ``new_password``.
                Must be set if changing existing 2FA settings.
                Must **not** be set if 2FA is currently disabled.
                Passing this by itself will remove 2FA (if correct).

            new_password (`str`, optional):
                The password to set as 2FA.
                If 2FA was already enabled, ``current_password`` **must** be set.
                Leaving this blank or `None` will remove the password.

            hint (`str`, optional):
                Hint to be displayed by Telegram when it asks for 2FA.
                Leaving unspecified is highly discouraged.
                Has no effect if ``new_password`` is not set.

            email (`str`, optional):
                Recovery and verification email. If present, you must also
                set `email_code_callback`, else it raises ``ValueError``.

            email_code_callback (`callable`, optional):
                If an email is provided, a callback that returns the code sent
                to it must also be set. This callback may be asynchronous.
                It should return a string with the code. The length of the
                code will be passed to the callback as an input parameter.

                If the callback returns an invalid code, it will raise
                ``CodeInvalidError``.

        Returns
            `True` if successful, `False` otherwise.

        Example
            .. code-block:: python

                # Setting a password for your account which didn't have
                await client.edit_2fa(new_password='******')

                # Removing the password
                await client.edit_2fa(current_password='******')
        """
        if new_password is None and current_password is None:
            return False

        if email and not callable(email_code_callback):
            raise ValueError('email present without email_code_callback')

        pwd = await self(functions.account.GetPasswordRequest())
        pwd.new_algo.salt1 += os.urandom(32)
        assert isinstance(pwd, types.account.Password)
        if not pwd.has_password and current_password:
            current_password = None

        if current_password:
            password = pwd_mod.compute_check(pwd, current_password)
        else:
            password = types.InputCheckPasswordEmpty()

        if new_password:
            new_password_hash = pwd_mod.compute_digest(pwd.new_algo,
                                                       new_password)
        else:
            new_password_hash = b''

        try:
            await self(
                functions.account.UpdatePasswordSettingsRequest(
                    password=password,
                    new_settings=types.account.PasswordInputSettings(
                        new_algo=pwd.new_algo,
                        new_password_hash=new_password_hash,
                        hint=hint,
                        email=email,
                        new_secure_settings=None)))
        except errors.EmailUnconfirmedError as e:
            code = email_code_callback(e.code_length)
            if inspect.isawaitable(code):
                code = await code

            code = str(code)
            await self(functions.account.ConfirmPasswordEmailRequest(code))

        return True
Exemple #39
0
    async def repl(self, ctx):
        """Launches an interactive REPL session."""
        variables = {
            'ctx': ctx,
            'bot': self.bot,
            'message': ctx.message,
            'guild': ctx.guild,
            'channel': ctx.channel,
            'author': ctx.author,
            '_': None,
        }

        if ctx.channel.id in self.sessions:
            await ctx.send(
                'Already running a REPL session in this channel. Exit it with `quit`.'
            )
            return

        self.sessions.add(ctx.channel.id)
        await ctx.send(
            'Enter code to execute or evaluate. `exit()` or `quit` to exit.')

        def check(m):
            return m.author.id == ctx.author.id and \
                   m.channel.id == ctx.channel.id and \
                   m.content.startswith('`')

        while True:
            try:
                response = await self.bot.wait_for('message',
                                                   check=check,
                                                   timeout=10.0 * 60.0)
            except asyncio.TimeoutError:
                await ctx.send('Exiting REPL session.')
                self.sessions.remove(ctx.channel.id)
                break

            cleaned = self.cleanup_code(response.content)

            if cleaned in ('quit', 'exit', 'exit()'):
                await ctx.send('Exiting.')
                self.sessions.remove(ctx.channel.id)
                return

            executor = exec
            if cleaned.count('\n') == 0:
                # single statement, potentially 'eval'
                try:
                    code = compile(cleaned, '<repl session>', 'eval')
                except SyntaxError:
                    pass
                else:
                    executor = eval

            if executor is exec:
                try:
                    code = compile(cleaned, '<repl session>', 'exec')
                except SyntaxError as e:
                    await ctx.send(self.get_syntax_error(e))
                    continue

            variables['message'] = response

            fmt = None
            stdout = io.StringIO()

            try:
                with contextlib.redirect_stdout(stdout):
                    result = executor(code, variables)
                    if inspect.isawaitable(result):
                        result = await result
            except Exception as e:
                value = stdout.getvalue()
                fmt = f'```py\n{value}{traceback.format_exc()}\n```'
            else:
                value = stdout.getvalue()
                if result is not None:
                    fmt = f'```py\n{value}{result}\n```'
                    variables['_'] = result
                elif value:
                    fmt = f'```py\n{value}\n```'

            try:
                if fmt is not None:
                    if len(fmt) > 2000:
                        await ctx.send('Content too big to be printed.')
                    else:
                        await ctx.send(fmt)
            except discord.Forbidden:
                pass
            except discord.HTTPException as e:
                await ctx.send(f'Unexpected error: `{e}`')
Exemple #40
0
    def declines_a_coroutine_function():
        async def some_coroutine():
            return True  # pragma: no cover

        assert not isawaitable(some_coroutine)
        assert not is_awaitable(some_coroutine)
Exemple #41
0
    def declines_a_normal_generator_object():
        def some_generator():
            yield True  # pragma: no cover

        assert not isawaitable(some_generator())
        assert not is_awaitable(some_generator())
Exemple #42
0
    def declines_a_normal_function():
        def some_function():
            return True

        assert not isawaitable(some_function())
        assert not is_awaitable(some_function)
Exemple #43
0
 def declines_a_lambda_function():
     assert not isawaitable(lambda: True)  # pragma: no cover
     assert not is_awaitable(lambda: True)  # pragma: no cover
    def handleEndpointMessage(self, msg):
        body, frm = msg
        logger.debug("Message received (from -> {}): {}".format(frm, body))
        if isinstance(frm, bytes):
            frm = frm.decode()
        for reqFieldName in (TYPE, f.REQ_ID.nm):
            reqFieldValue = body.get(reqFieldName)
            if not reqFieldValue:
                errorMsg = "{} not specified in message: {}".format(
                    reqFieldName, body)
                self.notifyToRemoteCaller(EVENT_NOTIFY_MSG, errorMsg,
                                          self.wallet.defaultId, frm)
                logger.warning("{}".format(errorMsg))
                return

        typ = body.get(TYPE)
        link = self.wallet.getLinkInvitationByTarget(body.get(f.IDENTIFIER.nm))

        # If accept invite is coming the first time, then use the default
        # identifier of the wallet since link wont be created
        if typ == ACCEPT_INVITE and link is None:
            localIdr = self.wallet.defaultId
        else:
            # if accept invite is not the message type
            # and we are still missing link, then return the error
            if link is None:
                linkNotCreated = '    Error processing {}. ' \
                                 'Link is not yet created.'.format(typ)
                self.notifyToRemoteCaller(EVENT_NOTIFY_MSG, linkNotCreated,
                                          self.wallet.defaultId, frm)
                return

            localIdr = link.localIdentifier

        if typ in self.lockedMsgs:
            try:
                self.verifySignature(body)
            except SignatureRejected:
                self.sendSigVerifResponseMsg("\nSignature rejected.", frm, typ,
                                             localIdr)
                return
        reqId = body.get(f.REQ_ID.nm)

        oldResps = self.rcvdMsgStore.get(reqId)
        if oldResps:
            oldResps.append(msg)
        else:
            self.rcvdMsgStore[reqId] = [msg]

        # TODO: Question: Should we sending an acknowledgement for every message?
        # We are sending, ACKs for "signature accepted" messages too
        self.sendSigVerifResponseMsg("\nSignature accepted.", frm, typ,
                                     localIdr)

        handler = self.msgHandlers.get(typ)
        if handler:
            # TODO we should verify signature here
            frmHa = self.endpoint.getHa(frm)
            # `frmHa` can be None
            res = handler((body, (frm, frmHa)))
            if inspect.isawaitable(res):
                self.loop.call_soon(asyncio.ensure_future, res)
        else:
            raise NotImplementedError(
                "No type handle found for {} message".format(typ))
Exemple #45
0
 async def _process(self, msg: Any):
     result = self._process_sync(msg)
     return await result if isawaitable(result) else result
Exemple #46
0
 def declines_an_object_instance():
     assert not isawaitable(object())
     assert not is_awaitable(object())
Exemple #47
0
    async def _start(self: 'TelegramClient', phone, password, bot_token,
                     force_sms, code_callback, first_name, last_name,
                     max_attempts):
        if not self.is_connected():
            await self.connect()

        # Rather than using `is_user_authorized`, use `get_me`. While this is
        # more expensive and needs to retrieve more data from the server, it
        # enables the library to warn users trying to login to a different
        # account. See #1172.
        me = await self.get_me()
        if me is not None:
            # The warnings here are on a best-effort and may fail.
            if bot_token:
                # bot_token's first part has the bot ID, but it may be invalid
                # so don't try to parse as int (instead cast our ID to string).
                if bot_token[:bot_token.find(':')] != str(me.id):
                    warnings.warn(
                        'the session already had an authorized user so it did '
                        'not login to the bot account using the provided '
                        'bot_token (it may not be using the user you expect)')
            elif phone and not callable(
                    phone) and utils.parse_phone(phone) != me.phone:
                warnings.warn(
                    'the session already had an authorized user so it did '
                    'not login to the user account using the provided '
                    'phone (it may not be using the user you expect)')

            return self

        if not bot_token:
            # Turn the callable into a valid phone number (or bot token)
            while callable(phone):
                value = phone()
                if inspect.isawaitable(value):
                    value = await value

                if ':' in value:
                    # Bot tokens have 'user_id:access_hash' format
                    bot_token = value
                    break

                phone = utils.parse_phone(value) or phone

        if bot_token:
            await self.sign_in(bot_token=bot_token)
            return self

        me = None
        attempts = 0
        two_step_detected = False

        await self.send_code_request(phone, force_sms=force_sms)
        sign_up = False  # assume login
        while attempts < max_attempts:
            try:
                value = code_callback()
                if inspect.isawaitable(value):
                    value = await value

                # Since sign-in with no code works (it sends the code)
                # we must double-check that here. Else we'll assume we
                # logged in, and it will return None as the User.
                if not value:
                    raise errors.PhoneCodeEmptyError(request=None)

                if sign_up:
                    me = await self.sign_up(value, first_name, last_name)
                else:
                    # Raises SessionPasswordNeededError if 2FA enabled
                    me = await self.sign_in(phone, code=value)
                break
            except errors.SessionPasswordNeededError:
                two_step_detected = True
                break
            except errors.PhoneNumberOccupiedError:
                sign_up = False
            except errors.PhoneNumberUnoccupiedError:
                sign_up = True
            except (errors.PhoneCodeEmptyError, errors.PhoneCodeExpiredError,
                    errors.PhoneCodeHashEmptyError,
                    errors.PhoneCodeInvalidError):
                print('Invalid code. Please try again.', file=sys.stderr)

            attempts += 1
        else:
            raise RuntimeError(
                '{} consecutive sign-in attempts failed. Aborting'.format(
                    max_attempts))

        if two_step_detected:
            if not password:
                raise ValueError(
                    "Two-step verification is enabled for this account. "
                    "Please provide the 'password' argument to 'start()'.")

            if callable(password):
                for _ in range(max_attempts):
                    try:
                        value = password()
                        if inspect.isawaitable(value):
                            value = await value

                        me = await self.sign_in(phone=phone, password=value)
                        break
                    except errors.PasswordHashInvalidError:
                        print('Invalid password. Please try again',
                              file=sys.stderr)
                else:
                    raise errors.PasswordHashInvalidError(request=None)
            else:
                me = await self.sign_in(phone=phone, password=password)

        # We won't reach here if any step failed (exit by exception)
        signed, name = 'Signed in successfully as', utils.get_display_name(me)
        try:
            print(signed, name)
        except UnicodeEncodeError:
            # Some terminals don't support certain characters
            print(
                signed,
                name.encode('utf-8', errors='ignore').decode('ascii',
                                                             errors='ignore'))

        return self
Exemple #48
0
    async def repl(self, ctx, *, name: str = None):
        """Head on impact with an interactive python shell."""
        # TODO Minimize local variables
        # TODO Minimize branches

        session = ctx.message.channel.id

        embed = discord.Embed(
            description="_Enter code to execute or evaluate. "
            "`exit()` or `quit` to exit._",
            timestamp=datetime.datetime.now())

        embed.set_footer(
            text="Interactive Python Shell",
            icon_url="https://upload.wikimedia.org/wikipedia/commons/thumb"
            "/c/c3/Python-logo-notext.svg/1024px-Python-logo-notext.svg.png")

        if name is not None:
            embed.title = name.strip(" ")

        history = collections.OrderedDict()

        variables = {
            'ctx': ctx,
            'bot': self.bot,
            'message': ctx.message,
            'server': ctx.message.guild,
            'channel': ctx.message.channel,
            'author': ctx.message.author,
            'discord': discord,
            '_': None
        }

        if session in self.repl_sessions:
            error_embed = discord.Embed(
                color=15746887,
                description="**Error**: "
                "_Shell is already running in channel._")
            await ctx.send(embed=error_embed)
            return

        shell = await ctx.send(embed=embed)

        self.repl_sessions[session] = shell
        self.repl_embeds[shell] = embed

        while True:
            response = await self.bot.wait_for(
                'message',
                check=lambda m: m.content.startswith('`') and m.author == ctx.
                author and m.channel == ctx.channel)
            cleaned = self._cleanup_code(response.content)
            shell = self.repl_sessions[session]

            # Regular Bot Method
            try:
                await ctx.message.channel.fetch_message(
                    self.repl_sessions[session].id)
            except discord.NotFound:
                new_shell = await ctx.send(embed=self.repl_embeds[shell])
                self.repl_sessions[session] = new_shell

                embed = self.repl_embeds[shell]
                del self.repl_embeds[shell]
                self.repl_embeds[new_shell] = embed

                shell = self.repl_sessions[session]

            try:
                await response.delete()
            except discord.Forbidden:
                pass

            if len(self.repl_embeds[shell].fields) >= 7:
                self.repl_embeds[shell].remove_field(0)

            if cleaned in ('quit', 'exit', 'exit()'):
                self.repl_embeds[shell].color = 16426522

                if self.repl_embeds[shell].title is not discord.Embed.Empty:
                    history_string = "History for {}\n\n\n".format(
                        self.repl_embeds[shell].title)
                else:
                    history_string = "History for latest session\n\n\n"

                for item in history.keys():
                    history_string += ">>> {}\n{}\n\n".format(
                        item, history[item])

                haste_url = await self.online.hastebin(history_string)
                return_msg = "[`Leaving shell session. "\
                    "History hosted on hastebin.`]({})".format(
                        haste_url)

                self.repl_embeds[shell].add_field(
                    name="`>>> {}`".format(cleaned),
                    value=return_msg,
                    inline=False)

                await self.repl_sessions[session].edit(
                    embed=self.repl_embeds[shell])

                del self.repl_embeds[shell]
                del self.repl_sessions[session]
                return

            executor = exec
            if cleaned.count('\n') == 0:
                # single statement, potentially 'eval'
                try:
                    code = compile(cleaned, '<repl session>', 'eval')
                except SyntaxError:
                    pass
                else:
                    executor = eval

            if executor is exec:
                try:
                    code = compile(cleaned, '<repl session>', 'exec')
                except SyntaxError as err:
                    self.repl_embeds[shell].color = 15746887

                    return_msg = self._get_syntax_error(err)

                    history[cleaned] = return_msg

                    if len(cleaned) > 800:
                        cleaned = "<Too big to be printed>"
                    if len(return_msg) > 800:
                        haste_url = await self.online.hastebin(return_msg)
                        return_msg = "[`SyntaxError too big to be printed. "\
                            "Hosted on hastebin.`]({})".format(
                                haste_url)

                    self.repl_embeds[shell].add_field(
                        name="`>>> {}`".format(cleaned),
                        value=return_msg,
                        inline=False)

                    await self.repl_sessions[session].edit(
                        embed=self.repl_embeds[shell])
                    continue

            variables['message'] = response

            fmt = None
            stdout = io.StringIO()

            try:
                with redirect_stdout(stdout):
                    result = executor(code, variables)
                    if inspect.isawaitable(result):
                        result = await result
            except Exception as err:
                self.repl_embeds[shell].color = 15746887
                value = stdout.getvalue()
                fmt = '```py\n{}{}\n```'.format(value, traceback.format_exc())
            else:
                self.repl_embeds[shell].color = 4437377

                value = stdout.getvalue()

                if result is not None:
                    fmt = '```py\n{}{}\n```'.format(value, result)

                    variables['_'] = result
                elif value:
                    fmt = '```py\n{}\n```'.format(value)

            history[cleaned] = fmt

            if len(cleaned) > 800:
                cleaned = "<Too big to be printed>"

            try:
                if fmt is not None:
                    if len(fmt) >= 800:
                        haste_url = await self.online.hastebin(fmt)
                        self.repl_embeds[shell].add_field(
                            name="`>>> {}`".format(cleaned),
                            value="[`Content too big to be printed. "
                            "Hosted on hastebin.`]({})".format(haste_url),
                            inline=False)

                        await self.repl_sessions[session].edit(
                            embed=self.repl_embeds[shell])
                    else:
                        self.repl_embeds[shell].add_field(
                            name="`>>> {}`".format(cleaned),
                            value=fmt,
                            inline=False)

                        await self.repl_sessions[session].edit(
                            embed=self.repl_embeds[shell])
                else:
                    self.repl_embeds[shell].add_field(
                        name="`>>> {}`".format(cleaned),
                        value="`Empty response, assumed successful.`",
                        inline=False)

                    await self.repl_sessions[session].edit(
                        embed=self.repl_embeds[shell])

            except discord.Forbidden:
                pass

            except discord.HTTPException as err:
                error_embed = discord.Embed(
                    color=15746887, description='**Error**: _{}_'.format(err))
                await ctx.send(embed=error_embed)
 async def get_formatted_args(self, kwargs):
     args = self.format_args(**kwargs)
     if inspect.isawaitable(args):
         args = await args
     return args
Exemple #50
0
async def serialize_property(value: 'Input[Any]',
                             deps: List['Resource'],
                             input_transformer: Optional[Callable[[str], str]] = None,
                             typ: Optional[type] = None,
                             keep_output_values: Optional[bool] = None) -> Any:
    """
    Serializes a single Input into a form suitable for remoting to the engine, awaiting
    any futures required to do so.

    When `typ` is specified, the metadata from the type is used to translate Python snake_case
    names to Pulumi camelCase names, rather than using the `input_transformer`.

    If `keep_output_values` is true and the monitor supports output values, they will be kept.
    """

    # Set typ to T if it's Optional[T], Input[T], or InputType[T].
    typ = _types.unwrap_type(typ) if typ else typ

    # If the typ is Any, set it to None to treat it as if we don't have any type information,
    # to avoid raising errors about unexpected types, since it could be any type.
    if typ is Any:
        typ = None

    # Exclude some built-in types that are instances of Sequence that we don't want to treat as sequences here.
    # From: https://github.com/python/cpython/blob/master/Lib/_collections_abc.py
    if isinstance(value, abc.Sequence) and not isinstance(value, (tuple, str, range, memoryview, bytes, bytearray)):
        element_type = _get_list_element_type(typ)
        props = []
        for elem in value:
            props.append(await serialize_property(elem, deps, input_transformer, element_type, keep_output_values))

        return props

    if known_types.is_unknown(value):
        return UNKNOWN

    if known_types.is_resource(value):
        resource = cast('Resource', value)

        is_custom = known_types.is_custom_resource(value)
        resource_id = cast('CustomResource', value).id if is_custom else None

        # If we're retaining resources, serialize the resource as a reference.
        if await settings.monitor_supports_resource_references():
            res = {
                _special_sig_key: _special_resource_sig,
                "urn": await serialize_property(resource.urn, deps, input_transformer, keep_output_values=False)
            }
            if is_custom:
                res["id"] = await serialize_property(resource_id, deps, input_transformer, keep_output_values=False)
            return res

        # Otherwise, serialize the resource as either its ID (for custom resources) or its URN (for component resources)
        return await serialize_property(resource_id if is_custom else resource.urn, deps, input_transformer,
            keep_output_values=False)

    if known_types.is_asset(value):
        # Serializing an asset requires the use of a magical signature key, since otherwise it would
        # look like any old weakly typed object/map when received by the other side of the RPC
        # boundary.
        obj = {
            _special_sig_key: _special_asset_sig
        }

        if hasattr(value, "path"):
            file_asset = cast('FileAsset', value)
            obj["path"] = await serialize_property(file_asset.path, deps, input_transformer, keep_output_values=False)
        elif hasattr(value, "text"):
            str_asset = cast('StringAsset', value)
            obj["text"] = await serialize_property(str_asset.text, deps, input_transformer, keep_output_values=False)
        elif hasattr(value, "uri"):
            remote_asset = cast('RemoteAsset', value)
            obj["uri"] = await serialize_property(remote_asset.uri, deps, input_transformer, keep_output_values=False)
        else:
            raise AssertionError(f"unknown asset type: {value!r}")

        return obj

    if known_types.is_archive(value):
        # Serializing an archive requires the use of a magical signature key, since otherwise it
        # would look like any old weakly typed object/map when received by the other side of the RPC
        # boundary.
        obj = {
            _special_sig_key: _special_archive_sig
        }

        if hasattr(value, "assets"):
            asset_archive = cast('AssetArchive', value)
            obj["assets"] = await serialize_property(asset_archive.assets, deps, input_transformer,
                keep_output_values=False)
        elif hasattr(value, "path"):
            file_archive = cast('FileArchive', value)
            obj["path"] = await serialize_property(file_archive.path, deps, input_transformer, keep_output_values=False)
        elif hasattr(value, "uri"):
            remote_archive = cast('RemoteArchive', value)
            obj["uri"] = await serialize_property(remote_archive.uri, deps, input_transformer, keep_output_values=False)
        else:
            raise AssertionError(f"unknown archive type: {value!r}")

        return obj

    if inspect.isawaitable(value):
        # Coroutines and Futures are both awaitable. Coroutines need to be scheduled.
        # asyncio.ensure_future returns futures verbatim while converting coroutines into
        # futures by arranging for the execution on the event loop.
        #
        # The returned future can then be awaited to yield a value, which we'll continue
        # serializing.
        awaitable = cast('Any', value)
        future_return = await asyncio.ensure_future(awaitable)
        return await serialize_property(future_return, deps, input_transformer, typ, keep_output_values)

    if known_types.is_output(value):
        output = cast('Output', value)
        value_resources: Set['Resource'] = await output.resources()
        deps.extend(value_resources)

        # When serializing an Output, we will either serialize it as its resolved value or the
        # "unknown value" sentinel. We will do the former for all outputs created directly by user
        # code (such outputs always resolve isKnown to true) and for any resource outputs that were
        # resolved with known values.
        is_known = await output._is_known
        is_secret = await output._is_secret
        promise_deps: List['Resource'] = []
        value = await serialize_property(output.future(), promise_deps, input_transformer, typ, keep_output_values=False)
        deps.extend(promise_deps)
        value_resources.update(promise_deps)

        if keep_output_values and await settings.monitor_supports_output_values():
            urn_deps: List['Resource'] = []
            for resource in value_resources:
                await serialize_property(resource.urn, urn_deps, input_transformer, keep_output_values=False)
            promise_deps.extend(set(urn_deps))
            value_resources.update(urn_deps)

            dependencies = await _expand_dependencies(value_resources, None)

            output_value: Dict[str, Any] = {
                _special_sig_key: _special_output_value_sig
            }

            if is_known:
                output_value["value"] = value
            if is_secret:
                output_value["secret"] = is_secret
            if dependencies:
                output_value["dependencies"] = sorted(dependencies)

            return output_value

        if not is_known:
            return UNKNOWN
        if is_secret and await settings.monitor_supports_secrets():
            # Serializing an output with a secret value requires the use of a magical signature key,
            # which the engine detects.
            return {
                _special_sig_key: _special_secret_sig,
                "value": value
            }
        return value

    # If value is an input type, convert it to a dict.
    value_cls = type(value)
    if _types.is_input_type(value_cls):
        value = _types.input_type_to_dict(value)
        types = _types.input_type_types(value_cls)

        return {
            k: await serialize_property(v, deps, input_transformer, types.get(k), keep_output_values)
            for k, v in value.items()
        }

    if isinstance(value, abc.Mapping):
        # Default implementation of get_type that always returns None.
        get_type: Callable[[str], Optional[type]] = lambda k: None
        # Key translator.
        translate = input_transformer

        # If we have type information, we'll use it to do name translations rather than using
        # any passed-in input_transformer.
        if typ is not None:
            if _types.is_input_type(typ):
                # If it's intended to be an input type, translate using the type's metadata.
                py_name_to_pulumi_name = _types.input_type_py_to_pulumi_names(typ)
                types = _types.input_type_types(typ)
                translate = lambda k: py_name_to_pulumi_name.get(k) or k
                get_type = types.get
            else:
                # Otherwise, don't do any translation of user-defined dict keys.
                origin = _types.get_origin(typ)
                if typ is dict or origin in {dict, Dict, Mapping, abc.Mapping}:
                    args = _types.get_args(typ)
                    if len(args) == 2 and args[0] is str:
                        get_type = lambda k: args[1]
                        translate = None
                else:
                    translate = None
                    # Note: Alternatively, we could assert here that we expected a dict type but got some other type,
                    # but there are cases where we've historically allowed a user-defined dict value to be passed even
                    # though the type annotation isn't a dict type (e.g. the `aws.s3.BucketPolicy.policy` input property
                    # is currently typed as `pulumi.Input[str]`, but we've allowed a dict to be passed, which will
                    # "magically" work at runtime because the provider will convert the dict value to a JSON string).
                    # Ideally, we'd update the type annotations for such cases to reflect that a dict could be passed,
                    # but we haven't done that yet and want these existing cases to continue to work as they have
                    # before.

        obj = {}
        # Don't use value.items() here, as it will error in the case of outputs with an `items` property.
        for k in value:
            transformed_key = k
            if translate is not None:
                transformed_key = translate(k)
                if settings.excessive_debug_output:
                    log.debug(f"transforming input property: {k} -> {transformed_key}")
            obj[transformed_key] = await serialize_property(value[k], deps, input_transformer,
                get_type(transformed_key), keep_output_values)

        return obj

    # Ensure that we have a value that Protobuf understands.
    if not isLegalProtobufValue(value):
        raise ValueError(f"unexpected input of type {type(value).__name__}")

    return value
Exemple #51
0
    async def request_resource(self,
                               type: Union[str, type],
                               alias: str = 'default',
                               *,
                               timeout: Union[int, None] = None):
        """
        Request a resource matching the given type and alias.

        If no such resource was found, this method will wait ``timeout`` seconds for it to become
        available. The timeout does not apply to resolving awaitables created by lazy resource
        creators.

        :param type: type of the requested resource
        :param alias: alias of the requested resource
        :param timeout: the timeout (in seconds; omit to use the context's default timeout)
        :return: the value contained by the requested resource (**NOT** a :class:`Resource`
            instance)
        :raises asphalt.core.context.ResourceNotFound: if the requested resource does not become
            available in the allotted time

        """
        assert check_argument_types()
        if not type:
            raise ValueError('type must be a type or a nonempty string')
        if not alias:
            raise ValueError('alias must be a nonempty string')

        resource_type = qualified_name(type) if not isinstance(type,
                                                               str) else type
        timeout = timeout if timeout is not None else self.default_timeout
        assert timeout >= 0, 'timeout must be a positive integer'

        # Build a context chain from this context and its parents
        context_chain = [self]
        while context_chain[-1]._parent:
            context_chain.append(context_chain[-1]._parent)

        # First try to look up the resource in the context chain
        for ctx in context_chain:
            resource = ctx._resources.get(resource_type, {}).get(alias)
            if resource is not None:
                value = resource.get_value(self)
                return await value if isawaitable(value) else value

        # Listen to resource publish events in the whole chain and wait for the right kind of
        # resource to be published
        def resource_listener(event: ResourceEvent):
            if event.resource.alias == alias and resource_type in event.resource.types:
                future.set_result(event.resource)

        future = Future()
        for ctx in context_chain:
            ctx.resource_published.connect(resource_listener)

        try:
            resource = await wait_for(future, timeout)
        except TimeoutError:
            raise ResourceNotFound(resource_type, alias) from None
        else:
            value = resource.get_value(self)
            return await value if isawaitable(value) else value
        finally:
            for ctx in context_chain:
                ctx.resource_published.disconnect(resource_listener)
Exemple #52
0
    async def repl(self, ctx):
        msg = ctx.message

        variables = {
            'ctx': ctx,
            'bot': self.bot,
            'message': msg,
            'server': msg.server,
            'channel': msg.channel,
            'author': msg.author,
            '_': None,
        }

        if msg.channel.id in self.sessions:
            await self.bot.say(
                'Already running a REPL session in this channel. Exit it with `quit`.'
            )
            return

        self.sessions.add(msg.channel.id)
        await self.bot.say(
            'Enter code to execute or evaluate. `exit()` or `quit` to exit.')
        while True:
            response = await self.bot.wait_for_message(
                author=msg.author,
                channel=msg.channel,
                check=lambda m: m.content.startswith('`'))

            cleaned = self.cleanup_code(response.content)

            if cleaned in ('quit', 'exit', 'exit()'):
                await self.bot.say('Exiting.')
                self.sessions.remove(msg.channel.id)
                return

            executor = exec
            if cleaned.count('\n') == 0:
                # single statement, potentially 'eval'
                try:
                    code = compile(cleaned, '<repl session>', 'eval')
                except SyntaxError:
                    pass
                else:
                    executor = eval

            if executor is exec:
                try:
                    code = compile(cleaned, '<repl session>', 'exec')
                except SyntaxError as e:
                    await self.bot.say(self.get_syntax_error(e))
                    continue

            variables['message'] = response

            fmt = None
            stdout = io.StringIO()

            try:
                with redirect_stdout(stdout):
                    result = executor(code, variables)
                    if inspect.isawaitable(result):
                        result = await result
            except Exception as e:
                value = stdout.getvalue()
                fmt = '```py\n{}{}\n```'.format(value, traceback.format_exc())
            else:
                value = stdout.getvalue()
                if result is not None:
                    fmt = '```py\n{}{}\n```'.format(value, result)
                    variables['_'] = result
                elif value:
                    fmt = '```py\n{}\n```'.format(value)

            try:
                if fmt is not None:
                    if len(fmt) > 2000:
                        await self.bot.send_message(
                            msg.channel, 'Content too big to be printed.')
                    else:
                        await self.bot.send_message(msg.channel, fmt)
            except discord.Forbidden:
                pass
            except discord.HTTPException as e:
                await self.bot.send_message(msg.channel,
                                            'Unexpected error: `{}`'.format(e))
Exemple #53
0
    async def dispatch_shell(self, msg):
        """dispatch shell requests"""

        # flush control queue before handling shell requests
        await self._flush_control_queue()

        idents, msg = self.session.feed_identities(msg, copy=False)
        try:
            msg = self.session.deserialize(msg, content=True, copy=False)
        except Exception:
            self.log.error("Invalid Message", exc_info=True)
            return

        # Set the parent message for side effects.
        self.set_parent(idents, msg, channel='shell')
        self._publish_status('busy', 'shell')

        msg_type = msg['header']['msg_type']

        # Only abort execute requests
        if self._aborting and msg_type == 'execute_request':
            self._send_abort_reply(self.shell_stream, msg, idents)
            self._publish_status('idle', 'shell')
            # flush to ensure reply is sent before
            # handling the next request
            self.shell_stream.flush(zmq.POLLOUT)
            return

        # Print some info about this message and leave a '--->' marker, so it's
        # easier to trace visually the message chain when debugging.  Each
        # handler prints its message at the end.
        self.log.debug('\n*** MESSAGE TYPE:%s***', msg_type)
        self.log.debug('   Content: %s\n   --->\n   ', msg['content'])

        if not self.should_handle(self.shell_stream, msg, idents):
            return

        handler = self.shell_handlers.get(msg_type, None)
        if handler is None:
            self.log.warning("Unknown message type: %r", msg_type)
        else:
            self.log.debug("%s: %s", msg_type, msg)
            try:
                self.pre_handler_hook()
            except Exception:
                self.log.debug("Unable to signal in pre_handler_hook:", exc_info=True)
            try:
                result = handler(self.shell_stream, idents, msg)
                if inspect.isawaitable(result):
                    await result
            except Exception:
                self.log.error("Exception in message handler:", exc_info=True)
            except KeyboardInterrupt:
                # Ctrl-c shouldn't crash the kernel here.
                self.log.error("KeyboardInterrupt caught in kernel.")
            finally:
                try:
                    self.post_handler_hook()
                except Exception:
                    self.log.debug("Unable to signal in post_handler_hook:", exc_info=True)

        sys.stdout.flush()
        sys.stderr.flush()
        self._publish_status('idle', 'shell')
        # flush to ensure reply is sent before
        # handling the next request
        self.shell_stream.flush(zmq.POLLOUT)
Exemple #54
0
    async def handle_request(self, request, write_callback, stream_callback):
        """Take a request from the HTTP Server and return a response object
        to be sent back The HTTP Server only expects a response object, so
        exception handling must be done here

        :param request: HTTP Request object
        :param write_callback: Synchronous response function to be
            called with the response as the only argument
        :param stream_callback: Coroutine that handles streaming a
            StreamingHTTPResponse if produced by the handler.

        :return: Nothing
        """
        # Define `response` var here to remove warnings about
        # allocation before assignment below.
        response = None
        cancelled = False
        try:
            # -------------------------------------------- #
            # Request Middleware
            # -------------------------------------------- #

            request.app = self
            response = await self._run_request_middleware(request)
            # No middleware results
            if not response:
                # -------------------------------------------- #
                # Execute Handler
                # -------------------------------------------- #

                # Fetch handler from router
                handler, args, kwargs, uri = self.router.get(request)

                request.uri_template = uri
                if handler is None:
                    raise ServerError(
                        ("'None' was returned while requesting a "
                         "handler from the router"))

                # Run response handler
                response = handler(request, *args, **kwargs)
                if isawaitable(response):
                    response = await response
        except CancelledError:
            # If response handler times out, the server handles the error
            # and cancels the handle_request job.
            # In this case, the transport is already closed and we cannot
            # issue a response.
            response = None
            cancelled = True
        except Exception as e:
            # -------------------------------------------- #
            # Response Generation Failed
            # -------------------------------------------- #

            try:
                response = self.error_handler.response(request, e)
                if isawaitable(response):
                    response = await response
            except Exception as e:
                if isinstance(e, SanicException):
                    response = self.error_handler.default(request=request,
                                                          exception=e)
                elif self.debug:
                    response = HTTPResponse(
                        "Error while handling error: {}\nStack: {}".format(
                            e, format_exc()), status=500)
                else:
                    response = HTTPResponse(
                        "An error occurred while handling an error",
                        status=500)
        finally:
            # -------------------------------------------- #
            # Response Middleware
            # -------------------------------------------- #
            # Don't run response middleware if response is None
            if response is not None:
                try:
                    response = await self._run_response_middleware(request,
                                                                   response)
                except CancelledError:
                    # Response middleware can timeout too, as above.
                    response = None
                    cancelled = True
                except BaseException:
                    error_logger.exception(
                        'Exception occurred in one of response '
                        'middleware handlers'
                    )
            if cancelled:
                raise CancelledError()

        # pass the response to the correct callback
        if isinstance(response, StreamingHTTPResponse):
            await stream_callback(response)
        else:
            write_callback(response)
Exemple #55
0
    async def recognizes_a_coroutine_object():
        async def some_coroutine():
            return False  # pragma: no cover

        assert isawaitable(some_coroutine())
        assert is_awaitable(some_coroutine())
Exemple #56
0
 def declines_a_string_value():
     assert not isawaitable("some_string")
     assert not is_awaitable("some_string")
Exemple #57
0
 def declines_the_none_value():
     assert not isawaitable(None)
     assert not is_awaitable(None)
Exemple #58
0
    def declines_an_async_generator():
        async def some_async_generator():
            yield True  # pragma: no cover

        assert not isawaitable(some_async_generator())
        assert not is_awaitable(some_async_generator())
Exemple #59
0
 def declines_the_type_class():
     assert not isawaitable(type)
     assert not is_awaitable(type)
Exemple #60
0
async def graphql(
    schema: GraphQLSchema,
    data: Any,
    *,
    context_value: Optional[Any] = None,
    root_value: Optional[RootValue] = None,
    debug: bool = False,
    introspection: bool = True,
    logger: Optional[str] = None,
    validation_rules: Optional[ValidationRules] = None,
    error_formatter: ErrorFormatter = format_error,
    middleware: Optional[MiddlewareManager] = None,
    extensions: Optional[List[Type[Extension]]] = None,
    **kwargs,
) -> GraphQLResult:
    extension_manager = ExtensionManager(extensions, context_value)

    with extension_manager.request():
        try:
            validate_data(data)
            query, variables, operation_name = (
                data["query"],
                data.get("variables"),
                data.get("operationName"),
            )

            document = parse_query(query)

            if callable(validation_rules):
                validation_rules = cast(
                    Optional[Sequence[RuleType]],
                    validation_rules(context_value, document, data),
                )

            validation_errors = validate_query(
                schema,
                document,
                validation_rules,
                enable_introspection=introspection)
            if validation_errors:
                return handle_graphql_errors(
                    validation_errors,
                    logger=logger,
                    error_formatter=error_formatter,
                    debug=debug,
                    extension_manager=extension_manager,
                )

            if callable(root_value):
                root_value = root_value(context_value, document)
                if isawaitable(root_value):
                    root_value = await root_value

            result = execute(
                schema,
                document,
                root_value=root_value,
                context_value=context_value,
                variable_values=variables,
                operation_name=operation_name,
                execution_context_class=ExecutionContext,
                middleware=extension_manager.as_middleware_manager(middleware),
                **kwargs,
            )

            if isawaitable(result):
                result = await cast(Awaitable[ExecutionResult], result)
        except GraphQLError as error:
            return handle_graphql_errors(
                [error],
                logger=logger,
                error_formatter=error_formatter,
                debug=debug,
                extension_manager=extension_manager,
            )
        else:
            return handle_query_result(
                result,
                logger=logger,
                error_formatter=error_formatter,
                debug=debug,
                extension_manager=extension_manager,
            )