diff options
| -rw-r--r-- | bot/cogs/codeblock/instructions.py | 4 | ||||
| -rw-r--r-- | bot/cogs/codeblock/parsing.py | 17 |
2 files changed, 17 insertions, 4 deletions
diff --git a/bot/cogs/codeblock/instructions.py b/bot/cogs/codeblock/instructions.py index c25b2af5d..56b85a34f 100644 --- a/bot/cogs/codeblock/instructions.py +++ b/bot/cogs/codeblock/instructions.py @@ -70,7 +70,7 @@ def _get_no_ticks_message(content: str) -> Optional[str]: """If `content` is Python/REPL code, return instructions on using code blocks.""" log.trace("Creating instructions for a missing code block.") - if parsing.is_repl_code(content) or parsing.is_python_code(content): + if parsing.is_python_code(content): example_blocks = _get_example("python") return ( "It looks like you're trying to paste code into this channel.\n\n" @@ -132,7 +132,7 @@ def _get_no_lang_message(content: str) -> Optional[str]: """ log.trace("Creating instructions for a missing language.") - if parsing.is_repl_code(content) or parsing.is_python_code(content): + if parsing.is_python_code(content): example_blocks = _get_example("python") # Note that _get_bad_ticks_message expects the first line to have two newlines. diff --git a/bot/cogs/codeblock/parsing.py b/bot/cogs/codeblock/parsing.py index 5b4cb9fdd..ea007b6f1 100644 --- a/bot/cogs/codeblock/parsing.py +++ b/bot/cogs/codeblock/parsing.py @@ -3,6 +3,7 @@ import ast import logging import re +import textwrap from typing import NamedTuple, Optional, Sequence from bot import constants @@ -98,7 +99,7 @@ def find_code_blocks(message: str) -> Optional[Sequence[CodeBlock]]: return code_blocks -def is_python_code(content: str) -> bool: +def _is_python_code(content: str) -> bool: """Return True if `content` is valid Python consisting of more than just expressions.""" log.trace("Checking if content is Python code.") try: @@ -120,7 +121,7 @@ def is_python_code(content: str) -> bool: return False -def is_repl_code(content: str, threshold: int = 3) -> bool: +def _is_repl_code(content: str, threshold: int = 3) -> bool: """Return True if `content` has at least `threshold` number of (I)Python REPL-like lines.""" log.trace(f"Checking if content is (I)Python REPL code using a threshold of {threshold}.") @@ -145,6 +146,18 @@ def is_repl_code(content: str, threshold: int = 3) -> bool: return False +def is_python_code(content: str) -> bool: + """Return True if `content` is valid Python code or (I)Python REPL output.""" + dedented = textwrap.dedent(content) + + # Parse AST twice in case _fix_indentation ends up breaking code due to its inaccuracies. + return ( + _is_python_code(dedented) + or _is_repl_code(dedented) + or _is_python_code(_fix_indentation(content)) + ) + + def parse_bad_language(content: str) -> Optional[BadLanguage]: """ Return information about a poorly formatted Python language in code block `content`. |