pydefine 1.0.0__py3-none-any.whl
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.
- pydefine/__init__.py +84 -0
- pydefine/cli.py +284 -0
- pydefine/core.py +456 -0
- pydefine/i18n.py +344 -0
- pydefine/mapping.py +1037 -0
- pydefine/utils.py +442 -0
- pydefine/version.py +20 -0
- pydefine-1.0.0.dist-info/METADATA +395 -0
- pydefine-1.0.0.dist-info/RECORD +13 -0
- pydefine-1.0.0.dist-info/WHEEL +5 -0
- pydefine-1.0.0.dist-info/entry_points.txt +3 -0
- pydefine-1.0.0.dist-info/licenses/LICENSE +21 -0
- pydefine-1.0.0.dist-info/top_level.txt +1 -0
pydefine/__init__.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pyDefine - Convert Python errors into beginner-friendly explanations
|
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
4
|
+
|
|
5
|
+
pyDefine is a pure-Python library that takes raw Python tracebacks and
|
|
6
|
+
exceptions and converts them into extremely simple, beginner-friendly
|
|
7
|
+
explanations with fix suggestions.
|
|
8
|
+
|
|
9
|
+
Basic usage:
|
|
10
|
+
|
|
11
|
+
>>> import pydefine
|
|
12
|
+
>>> result = pydefine.decode_traceback(some_traceback_string)
|
|
13
|
+
>>> print(result['simple_explanation'])
|
|
14
|
+
|
|
15
|
+
>>> try:
|
|
16
|
+
... 1 / 0
|
|
17
|
+
... except Exception as e:
|
|
18
|
+
... result = pydefine.decode_exception(e)
|
|
19
|
+
... print(result['simple_explanation'])
|
|
20
|
+
|
|
21
|
+
Full documentation is available at https://github.com/mdyahhya/pydefine
|
|
22
|
+
|
|
23
|
+
:copyright: (c) 2025 by Yahya.
|
|
24
|
+
:license: MIT, see LICENSE for more details.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
import sys
|
|
28
|
+
import traceback as tb_module
|
|
29
|
+
|
|
30
|
+
from .version import __version__
|
|
31
|
+
from .core import decode_traceback, decode_exception, safe_run, decode_traceback_file, explain, quick_decode
|
|
32
|
+
from .mapping import get_exception_info, EXCEPTION_MAP, list_all_exceptions, search_exceptions_by_tag, TOTAL_EXCEPTIONS, ALL_TAGS
|
|
33
|
+
from .utils import extract_error_info, format_output, tokenize_output, strip_ansi_codes, get_python_version, get_error_category, clean_traceback_text
|
|
34
|
+
from .cli import main as cli_main
|
|
35
|
+
from .i18n import translate_explanation, set_language, get_language, SUPPORTED_LANGUAGES
|
|
36
|
+
|
|
37
|
+
# Public API
|
|
38
|
+
__all__ = [
|
|
39
|
+
# Version
|
|
40
|
+
"__version__",
|
|
41
|
+
|
|
42
|
+
# Core functions
|
|
43
|
+
"decode_traceback",
|
|
44
|
+
"decode_exception",
|
|
45
|
+
"safe_run",
|
|
46
|
+
"decode_traceback_file",
|
|
47
|
+
"explain",
|
|
48
|
+
"quick_decode",
|
|
49
|
+
|
|
50
|
+
# Mapping functions
|
|
51
|
+
"get_exception_info",
|
|
52
|
+
"EXCEPTION_MAP",
|
|
53
|
+
"list_all_exceptions",
|
|
54
|
+
"search_exceptions_by_tag",
|
|
55
|
+
"TOTAL_EXCEPTIONS",
|
|
56
|
+
"ALL_TAGS",
|
|
57
|
+
|
|
58
|
+
# Utility functions
|
|
59
|
+
"extract_error_info",
|
|
60
|
+
"format_output",
|
|
61
|
+
"tokenize_output",
|
|
62
|
+
"strip_ansi_codes",
|
|
63
|
+
"get_python_version",
|
|
64
|
+
"get_error_category",
|
|
65
|
+
"clean_traceback_text",
|
|
66
|
+
|
|
67
|
+
# CLI
|
|
68
|
+
"cli_main",
|
|
69
|
+
|
|
70
|
+
# i18n
|
|
71
|
+
"translate_explanation",
|
|
72
|
+
"set_language",
|
|
73
|
+
"get_language",
|
|
74
|
+
"SUPPORTED_LANGUAGES",
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
# Display branding message on import
|
|
78
|
+
def _display_branding():
|
|
79
|
+
"""Print branding message when library is imported."""
|
|
80
|
+
branding = "\n⨠Powered by pyDefine ā Created by Yahya āØ\n"
|
|
81
|
+
print(branding, file=sys.stderr)
|
|
82
|
+
|
|
83
|
+
# Automatically display branding on import
|
|
84
|
+
_display_branding()
|
pydefine/cli.py
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
"""
|
|
2
|
+
pydefine.cli
|
|
3
|
+
~~~~~~~~~~~~
|
|
4
|
+
|
|
5
|
+
Command-line interface for pyDefine library.
|
|
6
|
+
|
|
7
|
+
Provides the 'pydefine-run' command to execute Python files with
|
|
8
|
+
automatic error decoding and beginner-friendly explanations.
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
pydefine-run script.py
|
|
12
|
+
pydefine-run --help
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
import argparse
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Optional
|
|
19
|
+
|
|
20
|
+
from .core import safe_run, decode_traceback_file, decode_exception
|
|
21
|
+
from .version import __version__, LIBRARY_NAME
|
|
22
|
+
from .mapping import list_all_exceptions, search_exceptions_by_tag, TOTAL_EXCEPTIONS
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run_file(filepath: str, verbose: bool = False) -> int:
|
|
26
|
+
"""
|
|
27
|
+
Execute a Python file with error decoding.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
filepath: Path to Python file to execute
|
|
31
|
+
verbose: Show detailed output
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Exit code (0 for success, 1 for error)
|
|
35
|
+
"""
|
|
36
|
+
file_path = Path(filepath)
|
|
37
|
+
|
|
38
|
+
if not file_path.exists():
|
|
39
|
+
print(f"ā Error: File '{filepath}' not found")
|
|
40
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya ")
|
|
41
|
+
return 1
|
|
42
|
+
|
|
43
|
+
if not file_path.suffix == '.py':
|
|
44
|
+
print(f"ā ļø Warning: File '{filepath}' doesn't have .py extension")
|
|
45
|
+
|
|
46
|
+
try:
|
|
47
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
48
|
+
code = f.read()
|
|
49
|
+
except Exception as e:
|
|
50
|
+
print(f"ā Error reading file: {e}")
|
|
51
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya ")
|
|
52
|
+
return 1
|
|
53
|
+
|
|
54
|
+
print(f"š Running: {filepath}")
|
|
55
|
+
print("ā" * 70)
|
|
56
|
+
|
|
57
|
+
# Run the code
|
|
58
|
+
result = safe_run(code, filename=str(file_path))
|
|
59
|
+
|
|
60
|
+
if result['success']:
|
|
61
|
+
# Success
|
|
62
|
+
if result.get('output'):
|
|
63
|
+
print(result['output'], end='')
|
|
64
|
+
print("\n" + "ā" * 70)
|
|
65
|
+
print("ā
Code executed successfully!")
|
|
66
|
+
if verbose:
|
|
67
|
+
print(f"š Exit code: 0")
|
|
68
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya ")
|
|
69
|
+
return 0
|
|
70
|
+
else:
|
|
71
|
+
# Error occurred
|
|
72
|
+
if result.get('output'):
|
|
73
|
+
print(result['output'], end='')
|
|
74
|
+
|
|
75
|
+
print("\n" + "=" * 70)
|
|
76
|
+
print(f"ā ERROR DETECTED")
|
|
77
|
+
print("=" * 70)
|
|
78
|
+
print()
|
|
79
|
+
|
|
80
|
+
# Print decoded error
|
|
81
|
+
emoji = result.get('emoji', 'ā')
|
|
82
|
+
error_type = result.get('error_type', 'UnknownError')
|
|
83
|
+
original_msg = result.get('original_message', '')
|
|
84
|
+
|
|
85
|
+
print(f"{emoji} {error_type}")
|
|
86
|
+
if original_msg:
|
|
87
|
+
print(f" Original message: {original_msg}")
|
|
88
|
+
print()
|
|
89
|
+
|
|
90
|
+
print("š What happened:")
|
|
91
|
+
explanation = result.get('simple_explanation', 'No explanation available')
|
|
92
|
+
for line in explanation.split('. '):
|
|
93
|
+
if line.strip():
|
|
94
|
+
print(f" ⢠{line.strip()}.")
|
|
95
|
+
print()
|
|
96
|
+
|
|
97
|
+
print("š” How to fix:")
|
|
98
|
+
fix = result.get('fix_suggestion', 'No suggestion available')
|
|
99
|
+
print(f" {fix}")
|
|
100
|
+
print()
|
|
101
|
+
|
|
102
|
+
if result.get('line_number') or result.get('file_name'):
|
|
103
|
+
print("š Error location:")
|
|
104
|
+
if result.get('file_name'):
|
|
105
|
+
print(f" File: {result['file_name']}")
|
|
106
|
+
if result.get('line_number'):
|
|
107
|
+
print(f" Line: {result['line_number']}")
|
|
108
|
+
print()
|
|
109
|
+
|
|
110
|
+
if verbose and result.get('tags'):
|
|
111
|
+
print(f"š·ļø Tags: {', '.join(result['tags'])}")
|
|
112
|
+
print()
|
|
113
|
+
|
|
114
|
+
print("ā" * 70)
|
|
115
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya")
|
|
116
|
+
return 1
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def list_exceptions_command(tag: Optional[str] = None) -> int:
|
|
120
|
+
"""
|
|
121
|
+
List all supported exceptions.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
tag: Optional tag to filter by
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Exit code (always 0)
|
|
128
|
+
"""
|
|
129
|
+
print(f"š {LIBRARY_NAME} - Supported Exceptions")
|
|
130
|
+
print("=" * 70)
|
|
131
|
+
|
|
132
|
+
if tag:
|
|
133
|
+
exceptions = search_exceptions_by_tag(tag)
|
|
134
|
+
print(f"\nš·ļø Exceptions with tag '{tag}': {len(exceptions)}")
|
|
135
|
+
print()
|
|
136
|
+
for exc in exceptions:
|
|
137
|
+
print(f" ⢠{exc}")
|
|
138
|
+
else:
|
|
139
|
+
exceptions = list_all_exceptions()
|
|
140
|
+
print(f"\nā
Total exceptions supported: {TOTAL_EXCEPTIONS}")
|
|
141
|
+
print()
|
|
142
|
+
print("Common exceptions:")
|
|
143
|
+
common = [
|
|
144
|
+
'SyntaxError', 'IndentationError', 'NameError', 'TypeError',
|
|
145
|
+
'ValueError', 'KeyError', 'IndexError', 'ZeroDivisionError',
|
|
146
|
+
'AttributeError', 'FileNotFoundError', 'ImportError', 'ModuleNotFoundError'
|
|
147
|
+
]
|
|
148
|
+
for exc in common:
|
|
149
|
+
print(f" ⢠{exc}")
|
|
150
|
+
|
|
151
|
+
print(f"\n... and {TOTAL_EXCEPTIONS - len(common)} more!")
|
|
152
|
+
print("\nUse --list-all to see complete list")
|
|
153
|
+
|
|
154
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya ")
|
|
155
|
+
return 0
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def list_all_exceptions_command() -> int:
|
|
159
|
+
"""List all exceptions in detail."""
|
|
160
|
+
print(f"š {LIBRARY_NAME} - All Supported Exceptions")
|
|
161
|
+
print("=" * 70)
|
|
162
|
+
print()
|
|
163
|
+
|
|
164
|
+
exceptions = list_all_exceptions()
|
|
165
|
+
|
|
166
|
+
# Group by category
|
|
167
|
+
from .utils import get_error_category
|
|
168
|
+
|
|
169
|
+
categories = {}
|
|
170
|
+
for exc in exceptions:
|
|
171
|
+
cat = get_error_category(exc)
|
|
172
|
+
if cat not in categories:
|
|
173
|
+
categories[cat] = []
|
|
174
|
+
categories[cat].append(exc)
|
|
175
|
+
|
|
176
|
+
for category, exc_list in sorted(categories.items()):
|
|
177
|
+
print(f"š {category} ({len(exc_list)} exceptions)")
|
|
178
|
+
for exc in sorted(exc_list):
|
|
179
|
+
print(f" ⢠{exc}")
|
|
180
|
+
print()
|
|
181
|
+
|
|
182
|
+
print(f"ā
Total: {TOTAL_EXCEPTIONS} exceptions")
|
|
183
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya")
|
|
184
|
+
return 0
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def decode_log_command(filepath: str) -> int:
|
|
188
|
+
"""
|
|
189
|
+
Decode a traceback from a log file.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
filepath: Path to log file containing traceback
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
Exit code
|
|
196
|
+
"""
|
|
197
|
+
print(f"š Decoding traceback from: {filepath}")
|
|
198
|
+
print("ā" * 70)
|
|
199
|
+
|
|
200
|
+
result = decode_traceback_file(filepath)
|
|
201
|
+
|
|
202
|
+
if not result.get('success', True):
|
|
203
|
+
# Print decoded error
|
|
204
|
+
print(result.get('formatted_output', 'Could not decode traceback'))
|
|
205
|
+
return 1
|
|
206
|
+
else:
|
|
207
|
+
print("ā
File decoded successfully")
|
|
208
|
+
return 0
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def main():
|
|
212
|
+
"""Main CLI entry point."""
|
|
213
|
+
parser = argparse.ArgumentParser(
|
|
214
|
+
prog='pydefine',
|
|
215
|
+
description=f'{LIBRARY_NAME} - Convert Python errors into beginner-friendly explanations',
|
|
216
|
+
epilog='Created by Yahya | https://github.com/mdyahhya/pydefine'
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
parser.add_argument(
|
|
220
|
+
'--version',
|
|
221
|
+
action='version',
|
|
222
|
+
version=f'{LIBRARY_NAME} {__version__}'
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
parser.add_argument(
|
|
226
|
+
'file',
|
|
227
|
+
nargs='?',
|
|
228
|
+
help='Python file to execute with error decoding'
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
parser.add_argument(
|
|
232
|
+
'-v', '--verbose',
|
|
233
|
+
action='store_true',
|
|
234
|
+
help='Show verbose output'
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
parser.add_argument(
|
|
238
|
+
'--list',
|
|
239
|
+
action='store_true',
|
|
240
|
+
help='List common supported exceptions'
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
parser.add_argument(
|
|
244
|
+
'--list-all',
|
|
245
|
+
action='store_true',
|
|
246
|
+
help='List all supported exceptions with categories'
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
parser.add_argument(
|
|
250
|
+
'--tag',
|
|
251
|
+
type=str,
|
|
252
|
+
help='Filter exceptions by tag (use with --list)'
|
|
253
|
+
)
|
|
254
|
+
|
|
255
|
+
parser.add_argument(
|
|
256
|
+
'--decode-log',
|
|
257
|
+
type=str,
|
|
258
|
+
metavar='FILE',
|
|
259
|
+
help='Decode a traceback from a log file'
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
args = parser.parse_args()
|
|
263
|
+
|
|
264
|
+
# Handle different commands
|
|
265
|
+
if args.list_all:
|
|
266
|
+
return list_all_exceptions_command()
|
|
267
|
+
|
|
268
|
+
if args.list:
|
|
269
|
+
return list_exceptions_command(args.tag)
|
|
270
|
+
|
|
271
|
+
if args.decode_log:
|
|
272
|
+
return decode_log_command(args.decode_log)
|
|
273
|
+
|
|
274
|
+
if args.file:
|
|
275
|
+
return run_file(args.file, verbose=args.verbose)
|
|
276
|
+
|
|
277
|
+
# No file provided, show help
|
|
278
|
+
parser.print_help()
|
|
279
|
+
print(f"\n Powered by {LIBRARY_NAME} ā Created by Yahya ")
|
|
280
|
+
return 0
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
if __name__ == '__main__':
|
|
284
|
+
sys.exit(main())
|