python-discord / sir-robin

Our event bot, for managing community events.
MIT License
18 stars 14 forks source link

Pep 9001 Eval command #32

Open onerandomusername opened 2 years ago

onerandomusername commented 2 years ago

should be able to eval pep 9001 code in snekbox

this is possible and I have an idea to implement it

wookie184 commented 2 years ago

Sounds like it should be possible, but would require some unformatting which is a bit hacky. At this point it might just be easier and faster to wait for CPython to implement the PEP. Thoughts?

lemonyte commented 2 years ago

Here's a simple unblurplifier (unformatter) that turns PEP 9001 code back into valid Python. Is it hacky? Yes, but at least it works well enough to qualify for "if it's stupid but it works, it ain't stupid". Also has an option to format the output with Black so it looks like proper Python code rather than a total mess.

import re
import black

import_context_code = """
import importlib
class ImportContext:
    def __init__(self, name: str):
        self.name = name

    def __enter__(self):
        return importlib.import_module(self.name, package=__package__)

    def __exit__(self, exc_type, exc_value, exc_tb):
        pass
"""

def unblurplify(src: str, format: bool = False) -> str:
    """Format blurplified source code into valid Python code."""
    # Invert indents back to regular indentation
    src = invert_indents(src)
    # Inject ImportContext class to handle `with import ...` statements
    src = import_context_code + "\n" + src
    # Replace `unimport` with `del`
    src = re.sub(r"unimport", r"del", src)
    # Replace `sync def` with `sync`
    src = re.sub(r"\bsync\s+def", r"def", src)
    # Replace `import ...` statements with ImportContext class
    src = re.sub(r"\bwith\s+import\s+(\S+)\s+:", r"with ImportContext('\1') as \1:", src)
    # Replace `import ... as ...` statements with ImportContext class
    src = re.sub(r"\bwith\s+import\s+(\S+)\s+as\s+(\S+)\s+:", r"with ImportContext('\1') as \2:", src)
    # Remove type unannotations
    src = re.sub(r"!:\s*[^,)]*", r"", src)
    src = re.sub(r"!->\s*[^:]*", r"", src)
    if format:
        src = black.format_str(src, mode=black.Mode(line_length=120))
    return src