aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar MarkKoz <[email protected]>2020-06-28 18:21:54 -0700
committerGravatar MarkKoz <[email protected]>2020-06-28 18:24:22 -0700
commitd8b8c518db9fd8bc0d0eb43afe38845c710af9a2 (patch)
tree8ff94baf517c38640e3e6c2246cc879b25d17f2d
parentCode block: re-add indentation fixing function (diff)
Code block: dedent code before validating it
If it's indented too far, the AST parser will fail.
-rw-r--r--bot/cogs/codeblock/instructions.py4
-rw-r--r--bot/cogs/codeblock/parsing.py17
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`.