Пример #1
0
    async def jsk_python(self, ctx: commands.Context, *,
                         argument: codeblock_converter):
        """
        Direct evaluation of Python code.
        """

        arg_dict = get_var_dict_from_ctx(ctx, Flags.SCOPE_PREFIX)
        arg_dict["_"] = self.last_result

        scope = self.scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(argument.content,
                                                 scope,
                                                 arg_dict=arg_dict)
                    async for send, result in AsyncSender(executor):
                        if result is None:
                            continue

                        self.last_result = result

                        send(await
                             self.jsk_python_result_handling(ctx, result))

        finally:
            scope.clear_intersection(arg_dict)
Пример #2
0
    async def jsk_python(self, ctx: commands.Context, *, argument: codeblock_converter):
        """
        Direct evaluation of Python code.
        """

        arg_dict = get_var_dict_from_ctx(ctx, SCOPE_PREFIX)
        arg_dict["_"] = self.last_result

        scope = self.scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(
                        argument.content, scope, arg_dict=arg_dict
                    )
                    async for send, result in AsyncSender(executor):
                        if result is None:
                            continue

                        self.last_result = result

                        if isinstance(result, discord.File):
                            send(await ctx.send(file=result))
                        elif isinstance(result, discord.Embed):
                            send(await ctx.send(embed=result))
                        elif isinstance(result, PaginatorInterface):
                            send(await result.send_to(ctx))
                        else:
                            if not isinstance(result, str):
                                # repr all non-strings
                                result = repr(result)

                            if len(result) > 2000:
                                # inconsistency here, results get wrapped in codeblocks when they are too large
                                #  but don't if they're not. probably not that bad, but noting for later review
                                paginator = WrappedPaginator(
                                    prefix="```py", suffix="```", max_size=1985
                                )

                                paginator.add_line(result)

                                interface = PaginatorInterface(
                                    ctx.bot, paginator, owner=ctx.author
                                )
                                send(await interface.send_to(ctx))
                            else:
                                if result.strip() == "":
                                    result = "\u200b"

                                send(
                                    await ctx.send(
                                        result.replace(
                                            self.bot.http.token,
                                            "[token omitted]",
                                        )
                                    )
                                )
        finally:
            scope.clear_intersection(arg_dict)
Пример #3
0
    async def jsk_python_inspect(self, ctx: commands.Context, *, argument: codeblock_converter):
        """
        Evaluation of Python code with inspect information.
        """

        arg_dict = get_var_dict_from_ctx(ctx, SCOPE_PREFIX)
        arg_dict["_"] = self.last_result

        scope = self.scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(argument.content, scope, arg_dict=arg_dict)
                    async for send, result in AsyncSender(executor):
                        self.last_result = result

                        header = repr(result).replace("``", "`\u200b`").replace(self.bot.http.token, "[token omitted]")

                        if len(header) > 485:
                            header = header[0:482] + "..."

                        paginator = WrappedPaginator(prefix=f"```prolog\n=== {header} ===\n", max_size=1985)

                        for name, res in all_inspections(result):
                            paginator.add_line(f"{name:16.16} :: {res}")

                        interface = PaginatorInterface(ctx.bot, paginator, owner=ctx.author)
                        send(await interface.send_to(ctx))
        finally:
            scope.clear_intersection(arg_dict)
Пример #4
0
async def python(event):
    message = event.message
    async with utils.ReplExceptionCatcher(message):
        async for send, x in AsyncSender(
                AsyncCodeExecutor(event.command_text,
                                  arg_dict=dict(
                                      event=event,
                                      telethon=telethon,
                                      tl=tl,
                                      message=message,
                                      _=event.client.last_python_result,
                                  ))):
            if x is not None:
                event.client.last_python_result = x

            if not isinstance(x, str):
                x = repr(x)

            if not x.strip():
                # represent nothingness, without actually sending nothing
                x = '\N{zero width space}'

            message = await message.reply(x)
            send(message)

        await event.reply('✅')
Пример #5
0
    async def jsk_python_inspect(self, ctx: commands.Context, *,
                                 argument: codeblock_converter):
        """
        Evaluation of Python code with inspect information.
        """

        arg_dict = get_var_dict_from_ctx(ctx, Flags.SCOPE_PREFIX)
        arg_dict["_"] = self.last_result

        scope = self.scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(argument.content,
                                                 scope,
                                                 arg_dict=arg_dict)
                    async for send, result in AsyncSender(executor):
                        self.last_result = result

                        header = repr(result).replace("``",
                                                      "`\u200b`").replace(
                                                          self.bot.http.token,
                                                          "[token omitted]")

                        if len(header) > 485:
                            header = header[0:482] + "..."

                        lines = [f"=== {header} ===", ""]

                        for name, res in all_inspections(result):
                            lines.append(f"{name:16.16} :: {res}")

                        docstring = (inspect.getdoc(result) or '').strip()

                        if docstring:
                            lines.append(f"\n=== Help ===\n\n{docstring}")

                        text = "\n".join(lines)

                        if use_file_check(ctx, len(
                                text)):  # File "full content" preview limit
                            send(await ctx.send(file=discord.File(
                                filename="inspection.prolog",
                                fp=io.BytesIO(text.encode('utf-8')))))
                        else:
                            paginator = WrappedPaginator(prefix="```prolog",
                                                         max_size=1985)

                            paginator.add_line(text)

                            interface = PaginatorInterface(ctx.bot,
                                                           paginator,
                                                           owner=ctx.author)
                            send(await interface.send_to(ctx))
        finally:
            scope.clear_intersection(arg_dict)
Пример #6
0
async def traverse(self, func):
    std = io.StringIO()
    with contextlib.redirect_stdout(std):
        if inspect.isasyncgenfunction(func):
            async for send, result in AsyncSender(func(*self.args)):
                if content := std.getvalue():
                    std.seek(0)
                    std.truncate(0)
                    yield content
                send((yield result))
        else:
Пример #7
0
    async def traverse(self, func):
        """
        Traverses an async function or generator, yielding each result.

        This function is private. The class should be used as an iterator instead of using this method.
        """

        if inspect.isasyncgenfunction(func):
            async for send, result in AsyncSender(func(*self.args)):
                send((yield result))
        else:
            yield await func(*self.args)
Пример #8
0
    async def jsk_python_inspect(self, ctx: commands.Context, *, argument: codeblock_converter):  # pylint: disable=too-many-locals
        """
        Evaluation of Python code with inspect information.
        """

        arg_dict = get_var_dict_from_ctx(ctx, SCOPE_PREFIX)
        arg_dict["_"] = self.last_result

        scope = self.scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(argument.content, scope, arg_dict=arg_dict)
                    async for send, result in AsyncSender(executor):
                        self.last_result = result

                        header = repr(result).replace("``", "`\u200b`").replace(self.bot.http.token, "[token omitted]")

                        if len(header) > 485:
                            header = header[0:482] + "..."

                        lines = [f"=== {header} ===", ""]

                        for name, res in all_inspections(result):
                            lines.append(f"{name:16.16} :: {res}")

                        text = "\n".join(lines)

                        # Guild's advertised limit minus 1KiB for the HTTP content
                        filesize_threshold = (ctx.guild.filesize_limit if ctx.guild else 8 * 1024 * 1024) - 1024

                        if len(text) < filesize_threshold:
                            send(await ctx.send(file=discord.File(
                                filename="inspection.prolog",
                                fp=io.BytesIO(text.encode('utf-8'))
                            )))
                        else:
                            paginator = WrappedPaginator(prefix="```prolog", max_size=1985)

                            paginator.add_line(text)

                            interface = PaginatorInterface(ctx.bot, paginator, owner=ctx.author)
                            send(await interface.send_to(ctx))
        finally:
            scope.clear_intersection(arg_dict)
Пример #9
0
    async def traverse(self, func):
        """
        Traverses an async function or generator, yielding each result.

        This function is private. The class should be used as an iterator instead of using this method.
        """

        try:
            if inspect.isasyncgenfunction(func):
                async for send, result in AsyncSender(func(*self.args)):
                    send((yield result))
            else:
                yield await func(*self.args)
        except Exception:
            # Falsely populate the linecache to make the REPL line appear in tracebacks
            linecache.cache['<repl>'] = (
                len(self.source),  # Source length
                None,  # Time modified (None bypasses expunge)
                [line + '\n' for line in self.source.splitlines()],  # Line list
                '<repl>'  # 'True' filename
            )

            raise
Пример #10
0
    async def jsk_python(self, ctx: commands.Context, *, argument: codeblock_converter):
        """
        Direct evaluation of Python code.
        """

        arg_dict = get_var_dict_from_ctx(ctx, SCOPE_PREFIX)
        arg_dict["_"] = self.last_result

        scope = self.scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(argument.content, scope, arg_dict=arg_dict)
                    async for send, result in AsyncSender(executor):
                        if result is None:
                            continue

                        self.last_result = result

                        if isinstance(result, discord.File):
                            send(await ctx.send(file=result))
                        elif isinstance(result, discord.Embed):
                            send(await ctx.send(embed=result))
                        elif isinstance(result, PaginatorInterface):
                            send(await result.send_to(ctx))
                        else:
                            if not isinstance(result, str):
                                # repr all non-strings
                                result = repr(result)

                            # Guild's advertised limit minus 1KiB for the HTTP content
                            filesize_threshold = (ctx.guild.filesize_limit if ctx.guild else 8 * 1024 * 1024) - 1024

                            if len(result) <= 2000:
                                if result.strip() == '':
                                    result = "\u200b"

                                send(await ctx.send(result.replace(self.bot.http.token, "[token omitted]")))

                            elif len(result) < filesize_threshold:
                                # Discord's desktop and web client now supports an interactive file content
                                #  display for files encoded in UTF-8.
                                # Since this avoids escape issues and is more intuitive than pagination for
                                #  long results, it will now be prioritized over PaginatorInterface if the
                                #  resultant content is below the filesize threshold
                                send(await ctx.send(file=discord.File(
                                    filename="output.py",
                                    fp=io.BytesIO(result.encode('utf-8'))
                                )))

                            else:
                                # inconsistency here, results get wrapped in codeblocks when they are too large
                                #  but don't if they're not. probably not that bad, but noting for later review
                                paginator = WrappedPaginator(prefix='```py', suffix='```', max_size=1985)

                                paginator.add_line(result)

                                interface = PaginatorInterface(ctx.bot, paginator, owner=ctx.author)
                                send(await interface.send_to(ctx))

        finally:
            scope.clear_intersection(arg_dict)
Пример #11
0
    async def _dev_python(self, ctx, *, code: codeblock_converter):
        '''
        Evaluate python code
        '''
        arg_dict = get_var_dict_from_ctx(ctx, "")
        arg_dict["_"] = self.last_result

        scope = self._scope

        try:
            async with ReplResponseReactor(ctx.message):
                with self.submit(ctx):
                    executor = AsyncCodeExecutor(code.content,
                                                 scope,
                                                 arg_dict=arg_dict)
                    async for send, result in AsyncSender(executor):
                        if result is None:
                            continue

                        self.last_result = result

                        if isinstance(result, discord.File):
                            send(await ctx.reply(file=result))
                        elif isinstance(result, discord.Embed):
                            send(await ctx.reply(embed=result))
                        elif isinstance(result, PaginatorInterface):
                            send(await result.send_to(ctx))
                        else:
                            if not isinstance(result, str):
                                result = repr(result)

                            if len(result) > 2000:
                                result = result.replace("`", "`\u200b")
                                width = 2000
                                pages = [
                                    result[i:i + width]
                                    for i in range(0, len(result), width)
                                ]

                                for page in pages:
                                    embed = discord.Embed(
                                        description=f"```py\n{page}```",
                                        colour=discord.Colour.teal())
                                    pages[pages.index(page)] = embed

                                embedpaginator = paginator(
                                    ctx, remove_reactions=True)
                                embedpaginator.add_reaction(
                                    "\U000023ea", "first")
                                embedpaginator.add_reaction(
                                    "\U000025c0", "back")
                                embedpaginator.add_reaction(
                                    "\U0001f5d1", "delete")
                                embedpaginator.add_reaction(
                                    "\U000025b6", "next")
                                embedpaginator.add_reaction(
                                    "\U000023e9", "last")
                                send(await embedpaginator.send(pages))

                            else:
                                if result.strip() == '':
                                    result = "\u200b"

                                embed = discord.Embed(
                                    description=
                                    f"```py\n{result.replace(self.bot.http.token, '[token]')}```",
                                    colour=discord.Colour.teal())

                                send(await ctx.reply(embed=embed,
                                                     mention_author=False))
        finally:
            scope.clear_intersection(arg_dict)