Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 63 additions & 29 deletions pyleet/testcase_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,48 @@
from .datastructures import get_deserializer


def _plain_text(content):
lines = content.splitlines()
cases = []
for line in lines:
line = line.strip()
if not line or line.startswith("#"):
continue # skip empty lines and comments
try:
parsed = ast.literal_eval(line)
# Expect tuple: (input_args, expected_output)
if not isinstance(parsed, tuple) or len(parsed) != 2:
raise ValueError(f"Invalid test case format: {line}")
input_args, expected = parsed
cases.append((input_args, expected))
except Exception as e:
raise ValueError(f"Failed to parse test case line: {line}\nError: {e}")
return cases


def _plain_text_input(content):
"""from leetgo format: https://github.com/j178/leetgo?tab=readme-ov-file#testcasestxt"""
raw_cases = content.split("\n\n")
_cases = []
for raw_case in raw_cases:
if "input:" not in raw_case and "output:" not in raw_case:
raise ValueError("Invalid input file")

lines = raw_case.splitlines()
input_data = []
output_data = []
res = None
for ln in lines:
if "input:" in ln:
res = input_data
elif "output:" in ln:
res = output_data
elif res is not None:
res.append(json.loads(ln))
_cases.append([input_data, output_data[0]])
return _cases


def load_test_cases(file_path):
"""
Load test cases from the given file path.
Expand All @@ -23,7 +65,7 @@ def load_test_cases(file_path):
if not os.path.exists(file_path):
raise FileNotFoundError(f"Test case file not found: {file_path}")

with open(file_path, 'r', encoding='utf-8') as f:
with open(file_path, "r", encoding="utf-8") as f:
content = f.read().strip()

# Try JSON first
Expand All @@ -34,23 +76,13 @@ def load_test_cases(file_path):
pass # Not JSON, try plain text

# Fallback: parse as plain text, line by line
lines = content.splitlines()
cases = []
for line in lines:
line = line.strip()
if not line or line.startswith('#'):
continue # skip empty lines and comments
try:
parsed = ast.literal_eval(line)
# Expect tuple: (input_args, expected_output)
if not isinstance(parsed, tuple) or len(parsed) != 2:
raise ValueError(f"Invalid test case format: {line}")
input_args, expected = parsed
cases.append((input_args, expected))
except Exception as e:
raise ValueError(
f"Failed to parse test case line: {line}\nError: {e}")
return cases
try:
# First, try the new leetgo format
return _plain_text_input(content)
except Exception:
# If that fails, fall back to the original plain text format.
# The _plain_text function will raise a ValueError if it also fails.
return _plain_text(content)


def _deserialize_recursive(item):
Expand All @@ -73,7 +105,8 @@ def _deserialize_recursive(item):
except Exception as e:
# Add context to the error
raise ValueError(
f"Error deserializing type '{key}' with data '{data}': {e}") from e
f"Error deserializing type '{key}' with data '{data}': {e}"
) from e
else:
# Not a custom type, handle as regular dictionary
return {k: _deserialize_recursive(v) for k, v in item.items()}
Expand Down Expand Up @@ -108,11 +141,12 @@ def process_test_cases(testcases):
# Direct tuple format: (input_args, expected)
input_args, expected = entry
elif isinstance(entry, dict):
if 'input' not in entry or 'expected' not in entry:
if "input" not in entry or "expected" not in entry:
raise ValueError(
f"Test case dict missing 'input' or 'expected': {entry}")
input_args = entry['input']
expected = entry['expected']
f"Test case dict missing 'input' or 'expected': {entry}"
)
input_args = entry["input"]
expected = entry["expected"]
elif isinstance(entry, list) and len(entry) == 2:
input_args, expected = entry
else:
Expand Down Expand Up @@ -146,16 +180,16 @@ def _parse_json_cases(data):
"""
cases = []
if not isinstance(data, list):
raise ValueError(
"JSON test case file must contain a list of test cases")
raise ValueError("JSON test case file must contain a list of test cases")

for entry in data:
if isinstance(entry, dict):
if 'input' not in entry or 'expected' not in entry:
if "input" not in entry or "expected" not in entry:
raise ValueError(
f"Test case dict missing 'input' or 'expected': {entry}")
input_args = entry['input']
expected = entry['expected']
f"Test case dict missing 'input' or 'expected': {entry}"
)
input_args = entry["input"]
expected = entry["expected"]
elif isinstance(entry, list) and len(entry) == 2:
input_args, expected = entry
else:
Expand Down