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 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())