Example #1
0
    def show_result(self, result: object) -> None:
        """
        Show __repr__ for an `eval` result.
        """
        out_prompt = to_formatted_text(self.get_output_prompt())

        # If the repr is valid Python code, use the Pygments lexer.
        result_repr = repr(result)
        try:
            compile(result_repr, "", "eval")
        except SyntaxError:
            formatted_result_repr = to_formatted_text(result_repr)
        else:
            formatted_result_repr = to_formatted_text(
                PygmentsTokens(list(_lex_python_result(result_repr))))

        # If __pt_repr__ is present, take this. This can return
        # prompt_toolkit formatted text.
        if hasattr(result, "__pt_repr__"):
            try:
                formatted_result_repr = to_formatted_text(
                    getattr(result, "__pt_repr__")())
                if isinstance(formatted_result_repr, list):
                    formatted_result_repr = FormattedText(
                        formatted_result_repr)
            except:
                pass

        # Align every line to the prompt.
        line_sep = "\n" + " " * fragment_list_width(out_prompt)
        indented_repr: StyleAndTextTuples = []

        lines = list(split_lines(formatted_result_repr))

        for i, fragment in enumerate(lines):
            indented_repr.extend(fragment)

            # Add indentation separator between lines, not after the last line.
            if i != len(lines) - 1:
                indented_repr.append(("", line_sep))

        # Write output tokens.
        if self.enable_syntax_highlighting:
            formatted_output = merge_formatted_text(
                [out_prompt, indented_repr])
        else:
            formatted_output = FormattedText(out_prompt + [(
                "", fragment_list_to_text(formatted_result_repr))])

        print_formatted_text(
            formatted_output,
            style=self._current_style,
            style_transformation=self.style_transformation,
            include_default_pygments_style=False,
            output=self.app.output,
        )
        self.app.output.flush()
Example #2
0
def test_del_store_import():
	for test in (
		'a!.b',
		'a.b.c!.d',
	):
		del_ = f'del {test}'
		store = f'{test} = 1'

		for test in del_, store:
			print(test)
			ie.compile(test, mode='exec')
Example #3
0
def test_invalid_argument_syntax():
	for invalid in (
		'def foo(x!): pass',
		'def foo(*x!): pass',
		'def foo(**y!): pass',
		'def foo(*, z!): pass',
		# note space around equals sign:
		# class Y(Z!=1) is valid if Z.__ne__ returns a class
		'class Y(Z! = 1): pass',
	):
		with py.test.raises(SyntaxError):
			print(invalid)
			ie.compile(invalid, mode='exec')
Example #4
0
def test_invalid_del_store_import():
	for test in (
		'a!',
		'a.b!',
	):
		del_ = f'del {test}'
		store = f'{test} = 1'
		for test in del_, store:
			print(test)
			# we use Exception instead of SyntaxError because this error may be caught
			# by builtins.compile (raises ValueError) or ie.parse (raises SyntaxError)
			with py.test.raises(Exception):
				ie.compile(test, mode='exec')
Example #5
0
    def better_exec(script, globals_=None, locals_=None):
        parsed = import_expression.parse(script)
        base_function = "async def __evaluate_code(): pass"
        parsed_function = import_expression.parse(base_function)

        for node in parsed.body:
            ast.increment_lineno(node)

        def check_for_yield(payload):
            if isinstance(payload, (list, tuple)):
                for node_ in payload:
                    if check_for_yield(node_):
                        return True
            if isinstance(payload, (ast.Yield, ast.YieldFrom)):
                return True
            if hasattr(payload, 'body'):
                for node_ in payload.body:
                    if check_for_yield(node_):
                        return True
            if hasattr(payload, 'value'):
                if check_for_yield(payload.value):
                    return True
            return False

        if not check_for_yield(parsed.body):
            insert_returns(parsed.body)

        parsed_function.body[0].body = parsed.body

        import_expression.exec(
            import_expression.compile(parsed_function, filename="<evaluator>", mode='exec'),
            globals_, locals_
        )
Example #6
0
 def compile_with_flags(code: str, mode: str):
     " Compile code with the right compiler flags. "
     return compile(
         code,
         "<stdin>",
         mode,
         flags=self.get_compiler_flags(),
         dont_inherit=True,
     )
Example #7
0
 def _load_start_paths(self) -> None:
     " Start the Read-Eval-Print Loop. "
     if self._startup_paths:
         for path in self._startup_paths:
             if os.path.exists(path):
                 with open(path, "rb") as f:
                     code = compile(f.read(), path, "exec")
                     exec(code, self.get_globals(), self.get_locals())
             else:
                 output = self.app.output
                 output.write(
                     "WARNING | File not found: {}\n\n".format(path))
Example #8
0
def main():
    args = parser.parse_args()
    if sum((args.list_of_stdin, args.lines_of_stdin)) > 1:
        err('Pythonpy accepts at most one of [-x, -l] flags')
        sys.exit(1)

    if args.pre_cmd:
        import_expression.exec(args.pre_cmd)

    if not args.expression and args.post_cmd:
        import_expression.exec(args.post_cmd)
        sys.exit(0)

    stdin = map(str.rstrip, sys.stdin)  # ignore trailing newline

    if args.input_delimiter:
        split = re.compile(args.input_delimiter).split
        stdin = (split(l.rstrip()) for l in stdin)

    if args.output_delimiter:

        def fprint(x, join=args.output_delimiter.join):
            if x is not None:
                print(join(x))
    else:

        def fprint(x):
            if x is not None:
                print(x)

    code = import_expression.compile(args.expression, '<pythonpy expression>',
                                     'eval')

    if args.list_of_stdin:
        l = list(stdin)
        it = [import_expression.eval(code, dict(l=l))]
    elif args.lines_of_stdin:
        it = (import_expression.eval(code, dict(x=line)) for line in stdin)
    else:
        it = [import_expression.eval(code)]

    for x in it:
        try:
            it = [x] if isinstance(x, str) else iter(x)
        except TypeError:  # not iterable
            fprint(x)
        else:
            for x in it:
                fprint(x)

    if args.post_cmd:
        import_expression.exec(args.post_cmd)
Example #9
0
    def validate(self, document):
        """
        Check input for Python syntax errors.
        """
        text = document.text

        # If the input is single line, remove leading whitespace.
        # (This doesn't have to be a syntax error.)
        if len(text.splitlines()) == 1:
            text = text.strip()

        # When the input starts with Ctrl-Z, always accept. This means EOF in a
        # Python REPL.
        if text.startswith("\x1a"):
            return

        try:
            if self.get_compiler_flags:
                flags = self.get_compiler_flags()
            else:
                flags = 0
            flags |= PyCF_ALLOW_TOP_LEVEL_AWAIT
            compile(text, "<input>", "exec", flags=flags, dont_inherit=True)
        except SyntaxError as e:
            # Note, the 'or 1' for offset is required because Python 2.7
            # gives `None` as offset in case of '4=4' as input. (Looks like
            # fixed in Python 3.)
            index = document.translate_row_col_to_index(
                e.lineno - 1, (e.offset or 1) - 1)
            raise ValidationError(index, f"Syntax Error: {e}")
        except TypeError as e:
            # e.g. "compile() expected string without null bytes"
            raise ValidationError(0, str(e))
        except ValueError as e:
            # In Python 2, compiling "\x9" (an invalid escape sequence) raises
            # ValueError instead of SyntaxError.
            raise ValidationError(0, "Syntax Error: %s" % e)
Example #10
0
def main():
    args = parser.parse_args()
    if sum((args.list_of_stdin, args.lines_of_stdin)) > 1:
        err('Pythonpy accepts at most one of [-x, -l] flags')
        sys.exit(1)

    if args.pre_cmd:
        import_expression.exec(args.pre_cmd)

    if not args.expression and args.post_cmd:
        import_expression.exec(args.post_cmd)
        sys.exit(0)

    stdin = without_trailing(map(str.rstrip, sys.stdin),
                             trailing='')  # ignore trailing newline
    code = import_expression.compile(args.expression, '<pythonpy expression>',
                                     'eval')

    if args.list_of_stdin:
        l = list(stdin)
        it = [import_expression.eval(code, dict(l=l))]
    elif args.lines_of_stdin:
        it = (import_expression.eval(code, dict(x=line)) for line in stdin)
    else:
        it = [import_expression.eval(code)]

    for x in it:
        if x is None:
            continue

        try:
            it = [x] if isinstance(x, str) else iter(x)
        except TypeError:  # not iterable
            print(x)
        else:
            for x in it:
                print(x)

    if args.post_cmd:
        import_expression.exec(args.post_cmd)
Example #11
0
def run_config(repl: PythonInput,
               config_file: str = "~/.ptpython/config.py") -> None:
    """
    Execute REPL config file.

    :param repl: `PythonInput` instance.
    :param config_file: Path of the configuration file.
    """
    # Expand tildes.
    config_file = os.path.expanduser(config_file)

    def enter_to_continue() -> None:
        input("\nPress ENTER to continue...")

    # Check whether this file exists.
    if not os.path.exists(config_file):
        print("Impossible to read %r" % config_file)
        enter_to_continue()
        return

    # Run the config file in an empty namespace.
    try:
        namespace: Dict[str, Any] = {}

        with open(config_file, "rb") as f:
            code = compile(f.read(), config_file, "exec")
            exec(code, namespace, namespace)

        # Now we should have a 'configure' method in this namespace. We call this
        # method with the repl as an argument.
        if "configure" in namespace:
            namespace["configure"](repl)

    except Exception:
        traceback.print_exc()
        enter_to_continue()
Example #12
0
    async def eval(self, ctx, *, code_string):
        if not self._env:
            self._env.update({"discord": discord,
                              "commands": commands, '_': None,
                              import_expression.constants.IMPORTER: importlib.import_module})
        self._env['ctx'] = ctx
        try:
            expr = import_expression.compile(code_string)
            ret = eval(expr, self._env)
        except SyntaxError:
            pass
        except Exception as exc:
            await ctx.message.add_reaction(self.bot.tick_no)
            return await ctx.send_as_paginator(format_exc(exc), codeblock=True)
        else:
            if inspect.isawaitable(ret):
                fut = asyncio.ensure_future(ret, loop=self.bot.loop)
                self._evals.append(fut)
                try:
                    with Timer(ctx.message):
                        ret = await asyncio.wait_for(fut, timeout=self._timeout)
                except Exception as exc:
                    await ctx.message.add_reaction(self.bot.tick_no)
                    return await ctx.send_as_paginator(format_exc(exc), codeblock=True)
                finally:
                    self._evals.remove(fut)
            await ctx.message.add_reaction(self.bot.tick_yes)
            if ret is None:
                return
            self._env['_'] = ret
            if isinstance(ret, discord.Embed):
                return await ctx.send(embed=ret)
            if not isinstance(ret, str):
                ret = repr(ret)
            return await ctx.send_as_paginator(ret, codeblock=self._send_in_codeblocks)
        code = f"""async def __func__():
    try:
{textwrap.indent(code_string, '        ')}
    finally:
        globals().update(locals())"""
        try:
            import_expression.exec(code, self._env)
        except Exception as exc:
            await ctx.message.add_reaction(self.bot.tick_no)
            return await ctx.send_as_paginator(format_exc(exc), codeblock=True)

        func = self._env.pop('__func__')
        fut = asyncio.ensure_future(func(), loop=self.bot.loop)
        self._evals.append(fut)
        try:
            with Timer(ctx.message):
                await asyncio.wait_for(fut, timeout=self._timeout)
        except asyncio.CancelledError:
            await ctx.message.add_reaction('\U0001f6d1')
            return
        except asyncio.TimeoutError:
            await ctx.message.add_reaction('\u23f0')
            return
        except Exception as exc:
            await ctx.message.add_reaction(self.bot.tick_no)
            return await ctx.send_as_paginator(format_exc(exc), codeblock=True)
        else:
            ret = fut.result()
        finally:
            self._evals.remove(fut)

        await ctx.message.add_reaction(self.bot.tick_yes)

        if ret is None:
            return

        self._env['_'] = ret

        if isinstance(ret, discord.Embed):
            return await ctx.send(embed=ret)

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

        return await ctx.send_as_paginator(ret, codeblock=self._send_in_codeblocks)
Example #13
0
def test_invalid_attribute_syntax():
	for invalid in invalid_attribute_cases:
		print(invalid)  # in case it does not raise and we want to see what failed
		with py.test.raises(SyntaxError):
			ie.compile(invalid)
Example #14
0
def test_valid_string_literals():
	for invalid in invalid_attribute_cases:
		valid = f'"{invalid}"'
		print(valid)
		ie.compile(valid)
Example #15
0
def test_kwargs():
	# See https://github.com/bmintz/import-expression-parser/issues/1
	ie.compile('f(**a)', mode='eval')

	import collections
	assert ie.eval('dict(x=collections!)')['x'] is collections
Example #16
0
    async def eval(self, ctx, *, code_string):
        """
        evaluates some code. Do not run this unless you know what you are doing!
        """
        """
        The code used in this command is licensed under AGPLv3 clause.
        Modification or distribution without permission is not granted unless it works with the License.

        XuaTheGrate - the owner of this code - has granted explicit permission for me to use this code within amalna.

        The original source code can be located here: https://github.com/iDevision/MostDefinitelyGrant2/blob/master/cogs/dev.py
        A copy of the AGPLv3 License can be located here: https://github.com/iDevision/MostDefinitelyGrant2/blob/master/LICENSE.md
        """
        if not self._env:
            self._env.update({
                "discord": discord,
                "twitchio": twitchio,
                "bot": self.bot,
                "twitch_streamer": self.core.twitch_streamer,
                "twitch_bot": self.core.twitch_bot,
                "db": self.core.db,
                "commands": commands,
                '_': None,
                import_expression.constants.IMPORTER: importlib.import_module})

        self._env['ctx'] = ctx

        try:
            expr = import_expression.compile(code_string)
            ret = eval(expr, self._env)
        except SyntaxError:
            pass

        except Exception as exc:
            await ctx.message.add_reaction(self.bot.tick_no)
            return await ctx.paginate("".join(traceback.format_exception(type(exc), exc, exc.__traceback__)), codeblocks=True)

        else:
            if inspect.isawaitable(ret):
                fut = asyncio.ensure_future(ret, loop=self.bot.loop)
                self._evals.append(fut)
                try:
                    with Timer(ctx.message):
                        ret = await asyncio.wait_for(fut, timeout=self._timeout)

                except Exception as exc:
                    await ctx.message.add_reaction(self.bot.tick_no)
                    return await ctx.paginate("".join(traceback.format_exception(type(exc), exc, exc.__traceback__)), codeblocks=True)

                finally:
                    self._evals.remove(fut)

            await ctx.message.add_reaction(self.bot.tick_yes)
            if ret is None:
                return

            self._env['_'] = ret
            if isinstance(ret, discord.Embed):
                return await ctx.send(embed=ret)

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

            return await ctx.paginate(ret, codeblock=self._send_in_codeblocks)

        code = f"""async def __func__():
    try:
{textwrap.indent(code_string, '        ')}
    finally:
        globals().update(locals())"""
        try:
            import_expression.exec(code, self._env)
        except Exception as exc:
            await ctx.message.add_reaction(self.bot.tick_no)
            return await ctx.paginate("".join(traceback.format_exception(type(exc), exc, exc.__traceback__)),
                                      codeblocks=True)

        func = self._env.pop('__func__')
        fut = asyncio.ensure_future(func(), loop=self.bot.loop)
        self._evals.append(fut)
        try:
            with Timer(ctx.message):
                await asyncio.wait_for(fut, timeout=self._timeout)

        except asyncio.CancelledError:
            await ctx.message.add_reaction('\U0001f6d1')
            return

        except asyncio.TimeoutError:
            await ctx.message.add_reaction('\u23f0')
            return

        except Exception as exc:
            await ctx.message.add_reaction(self.bot.tick_no)
            return await ctx.paginate("".join(traceback.format_exception(type(exc), exc, exc.__traceback__)),
                                      codeblocks=True)

        else:
            ret = fut.result()
        finally:
            self._evals.remove(fut)

        await ctx.message.add_reaction(self.bot.tick_yes)

        if ret is None:
            return

        self._env['_'] = ret

        if isinstance(ret, discord.Embed):
            return await ctx.send(embed=ret)

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

        return await ctx.paginate(ret, codeblocks=self._send_in_codeblocks)