error-translator-cli-v2 1.0.7__tar.gz → 1.0.8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/PKG-INFO +1 -1
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/core.py +37 -25
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator_cli_v2.egg-info/PKG-INFO +1 -1
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/pyproject.toml +1 -1
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/tests/test_core.py +20 -2
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/README.md +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/__init__.py +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/ast_handlers.py +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/auto.py +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/cli.py +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/server.py +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator_cli_v2.egg-info/SOURCES.txt +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator_cli_v2.egg-info/dependency_links.txt +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator_cli_v2.egg-info/entry_points.txt +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator_cli_v2.egg-info/top_level.txt +0 -0
- {error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/setup.cfg +0 -0
|
@@ -1,50 +1,62 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import os
|
|
3
|
+
import re
|
|
4
|
+
import linecache
|
|
5
|
+
from functools import lru_cache
|
|
3
6
|
from .ast_handlers import AST_REGISTRY
|
|
4
7
|
|
|
8
|
+
|
|
9
|
+
@lru_cache(maxsize=1)
|
|
5
10
|
def load_rules():
|
|
6
|
-
"""
|
|
7
|
-
# Find the absolute path to the json file next to this script
|
|
11
|
+
"""Load the error rules from disk once and cache them."""
|
|
8
12
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
9
|
-
json_path = os.path.join(current_dir,
|
|
10
|
-
|
|
11
|
-
with open(json_path,
|
|
13
|
+
json_path = os.path.join(current_dir, "rules.json")
|
|
14
|
+
|
|
15
|
+
with open(json_path, "r", encoding="utf-8") as file:
|
|
12
16
|
return json.load(file)
|
|
13
17
|
|
|
18
|
+
|
|
19
|
+
@lru_cache(maxsize=1)
|
|
20
|
+
def compiled_rules():
|
|
21
|
+
"""Compile regex patterns once to avoid repeated work per translation."""
|
|
22
|
+
data = load_rules()
|
|
23
|
+
compiled = []
|
|
24
|
+
for rule in data["rules"]:
|
|
25
|
+
compiled.append((re.compile(rule["pattern"]), rule))
|
|
26
|
+
return compiled
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _extract_location(traceback_text: str) -> tuple[str, str]:
|
|
30
|
+
location_match = re.search(r'File\s+[\'"]?(.*?)[\'"]?,\s+line\s+(\d+)', traceback_text)
|
|
31
|
+
if not location_match:
|
|
32
|
+
return "Unknown File", "Unknown Line"
|
|
33
|
+
return location_match.group(1), location_match.group(2)
|
|
34
|
+
|
|
35
|
+
|
|
14
36
|
def translate_error(traceback_text: str) -> dict:
|
|
15
|
-
import re
|
|
16
|
-
import linecache # <-- NEW: Lazy import the linecache module
|
|
17
|
-
|
|
18
37
|
data = load_rules()
|
|
19
|
-
rules =
|
|
38
|
+
rules = compiled_rules()
|
|
20
39
|
default_error = data["default"]
|
|
21
40
|
|
|
22
|
-
lines = [line.strip() for line in traceback_text.strip().split(
|
|
41
|
+
lines = [line.strip() for line in traceback_text.strip().split("\n") if line.strip()]
|
|
23
42
|
if not lines:
|
|
24
43
|
return {"explanation": "No error text provided.", "fix": "Provide a valid Python error."}
|
|
25
|
-
|
|
44
|
+
|
|
26
45
|
actual_error_line = lines[-1]
|
|
27
46
|
|
|
28
|
-
|
|
29
|
-
file_name = location_match.group(1) if location_match else "Unknown File"
|
|
30
|
-
line_number = location_match.group(2) if location_match else "Unknown Line"
|
|
47
|
+
file_name, line_number = _extract_location(traceback_text)
|
|
31
48
|
|
|
32
|
-
# --- NEW CONTEXT ENGINE LOGIC ---
|
|
33
49
|
code_context = ""
|
|
34
50
|
if file_name != "Unknown File" and line_number != "Unknown Line":
|
|
35
51
|
try:
|
|
36
|
-
# linecache safely fetches the exact line of code as a string
|
|
37
52
|
raw_line = linecache.getline(file_name, int(line_number))
|
|
38
53
|
if raw_line:
|
|
39
|
-
code_context = raw_line.strip()
|
|
54
|
+
code_context = raw_line.strip()
|
|
40
55
|
except Exception:
|
|
41
|
-
pass
|
|
42
|
-
# --------------------------------
|
|
56
|
+
pass
|
|
43
57
|
|
|
44
|
-
for rule in rules:
|
|
45
|
-
pattern = re.compile(rule["pattern"])
|
|
58
|
+
for pattern, rule in rules:
|
|
46
59
|
match = pattern.search(actual_error_line)
|
|
47
|
-
|
|
48
60
|
if match:
|
|
49
61
|
extracted_values = list(match.groups())
|
|
50
62
|
fix_text = rule["fix"].format(*extracted_values)
|
|
@@ -61,7 +73,7 @@ def translate_error(traceback_text: str) -> dict:
|
|
|
61
73
|
"matched_error": actual_error_line,
|
|
62
74
|
"file": file_name,
|
|
63
75
|
"line": line_number,
|
|
64
|
-
"code": code_context
|
|
76
|
+
"code": code_context,
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
return {
|
|
@@ -70,5 +82,5 @@ def translate_error(traceback_text: str) -> dict:
|
|
|
70
82
|
"matched_error": actual_error_line,
|
|
71
83
|
"file": file_name,
|
|
72
84
|
"line": line_number,
|
|
73
|
-
"code": code_context
|
|
74
|
-
}
|
|
85
|
+
"code": code_context,
|
|
86
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import pytest
|
|
2
|
-
from error_translator.core import translate_error
|
|
2
|
+
from error_translator.core import translate_error, load_rules, compiled_rules
|
|
3
3
|
|
|
4
4
|
# --- 1. EDGE CASE TESTS ---
|
|
5
5
|
|
|
@@ -35,6 +35,24 @@ def test_unknown_error_fallback():
|
|
|
35
35
|
assert result["matched_error"] == "Something completely random went wrong here."
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def test_empty_input_returns_helpful_message():
|
|
39
|
+
result = translate_error(" \n ")
|
|
40
|
+
assert result["explanation"] == "No error text provided."
|
|
41
|
+
assert result["fix"] == "Provide a valid Python error."
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def test_rule_loading_is_cached():
|
|
45
|
+
first = load_rules()
|
|
46
|
+
second = load_rules()
|
|
47
|
+
assert first is second
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_compiled_rules_are_cached():
|
|
51
|
+
first = compiled_rules()
|
|
52
|
+
second = compiled_rules()
|
|
53
|
+
assert first is second
|
|
54
|
+
|
|
55
|
+
|
|
38
56
|
# --- 2. THE PARAMETERIZED ENGINE FOR ALL ERRORS ---
|
|
39
57
|
|
|
40
58
|
@pytest.mark.parametrize("mock_traceback, expected_in_explanation", [
|
|
@@ -128,4 +146,4 @@ def test_regex_extraction_for_supported_errors(mock_traceback, expected_in_expla
|
|
|
128
146
|
|
|
129
147
|
# 2. Prove the Context Engine successfully parsed the file location
|
|
130
148
|
assert result["file"] == "script.py"
|
|
131
|
-
assert result["line"] == "5"
|
|
149
|
+
assert result["line"] == "5"
|
|
File without changes
|
{error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/__init__.py
RENAMED
|
File without changes
|
{error_translator_cli_v2-1.0.7 → error_translator_cli_v2-1.0.8}/error_translator/ast_handlers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|