orionis 0.213.1__py3-none-any.whl → 0.216.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.
- orionis/framework.py +1 -1
- orionis/luminate/console/output/console.py +2 -2
- orionis/luminate/support/inspection/contracts/__init__.py +0 -0
- orionis/luminate/support/inspection/contracts/reflection.py +187 -0
- orionis/luminate/support/inspection/contracts/reflexion_abstract.py +265 -0
- orionis/luminate/support/inspection/reflection.py +2 -1
- orionis/luminate/support/inspection/reflexion_abstract.py +2 -1
- orionis/luminate/support/parsers/__init__.py +0 -0
- orionis/luminate/support/parsers/contracts/__init__.py +0 -0
- orionis/luminate/support/parsers/contracts/exception_parser.py +38 -0
- orionis/luminate/support/parsers/exception_parser.py +107 -0
- orionis/luminate/support/standard/__init__.py +0 -0
- orionis/luminate/support/standard/contracts/__init__.py +0 -0
- orionis/luminate/support/standard/contracts/std.py +127 -0
- orionis/luminate/support/standard/std.py +137 -0
- {orionis-0.213.1.dist-info → orionis-0.216.0.dist-info}/METADATA +1 -1
- {orionis-0.213.1.dist-info → orionis-0.216.0.dist-info}/RECORD +27 -14
- tests/support/parsers/__init__.py +0 -0
- tests/support/parsers/fakes/__init__.py +0 -0
- tests/support/parsers/fakes/fake_custom_error.py +27 -0
- tests/support/parsers/test_exception_parser.py +59 -0
- tests/support/standard/__init__.py +0 -0
- tests/support/standard/test_std.py +58 -0
- orionis/luminate/contracts/support/std.py +0 -43
- orionis/luminate/support/exception_parse.py +0 -47
- orionis/luminate/support/reflection.py +0 -390
- orionis/luminate/support/std.py +0 -53
- {orionis-0.213.1.dist-info → orionis-0.216.0.dist-info}/LICENCE +0 -0
- {orionis-0.213.1.dist-info → orionis-0.216.0.dist-info}/WHEEL +0 -0
- {orionis-0.213.1.dist-info → orionis-0.216.0.dist-info}/entry_points.txt +0 -0
- {orionis-0.213.1.dist-info → orionis-0.216.0.dist-info}/top_level.txt +0 -0
orionis/framework.py
CHANGED
@@ -4,7 +4,7 @@ import os
|
|
4
4
|
import sys
|
5
5
|
from orionis.luminate.console.output.styles import ANSIColors
|
6
6
|
from orionis.luminate.contracts.console.output.console import IConsole
|
7
|
-
from orionis.luminate.support.
|
7
|
+
from orionis.luminate.support.parsers.exception_parser import ExceptionParser
|
8
8
|
|
9
9
|
class Console(IConsole):
|
10
10
|
"""
|
@@ -533,7 +533,7 @@ class Console(IConsole):
|
|
533
533
|
This method prints the exception type, message, and a detailed stack trace.
|
534
534
|
"""
|
535
535
|
|
536
|
-
errors =
|
536
|
+
errors = ExceptionParser(e).toDict()
|
537
537
|
error_type = str(errors.get("error_type")).split(".")[-1]
|
538
538
|
error_message = str(errors.get("error_message")).replace(error_type, "").replace("[]", "").strip()
|
539
539
|
stack_trace = errors.get("stack_trace")
|
File without changes
|
@@ -0,0 +1,187 @@
|
|
1
|
+
import abc
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from typing import Any, Type, TypeVar
|
4
|
+
|
5
|
+
T = TypeVar('T')
|
6
|
+
ABC = TypeVar('ABC', bound=abc.ABC)
|
7
|
+
|
8
|
+
class IReflection(ABC):
|
9
|
+
"""Interface for a static reflection factory class.
|
10
|
+
|
11
|
+
Defines the contract for creating various types of reflection objects
|
12
|
+
that encapsulate different aspects of Python's reflection capabilities.
|
13
|
+
"""
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
@abstractmethod
|
17
|
+
def instance(instance: Any):
|
18
|
+
"""Create a reflection object for a class instance.
|
19
|
+
|
20
|
+
Parameters
|
21
|
+
----------
|
22
|
+
instance : Any
|
23
|
+
The instance to reflect upon
|
24
|
+
|
25
|
+
Returns
|
26
|
+
-------
|
27
|
+
ReflexionInstance
|
28
|
+
A reflection object encapsulating the instance
|
29
|
+
|
30
|
+
Raises
|
31
|
+
------
|
32
|
+
TypeError
|
33
|
+
If the input is not an object instance
|
34
|
+
ValueError
|
35
|
+
If the instance is from builtins, abc, or __main__
|
36
|
+
"""
|
37
|
+
pass
|
38
|
+
|
39
|
+
@staticmethod
|
40
|
+
@abstractmethod
|
41
|
+
def instanceWithAbstract(instance: Any, abstract: Type[ABC]):
|
42
|
+
"""Create a reflection object for a class instance with its abstract parent.
|
43
|
+
|
44
|
+
Parameters
|
45
|
+
----------
|
46
|
+
instance : Any
|
47
|
+
The instance to reflect upon
|
48
|
+
abstract : Type[ABC]
|
49
|
+
The abstract parent class
|
50
|
+
|
51
|
+
Returns
|
52
|
+
-------
|
53
|
+
ReflexionInstanceWithAbstract
|
54
|
+
A reflection object encapsulating the instance and its abstract parent
|
55
|
+
|
56
|
+
Raises
|
57
|
+
------
|
58
|
+
TypeError
|
59
|
+
If the instance is not an object or abstract is not a class
|
60
|
+
ValueError
|
61
|
+
If the instance is invalid or abstract is not actually abstract
|
62
|
+
"""
|
63
|
+
pass
|
64
|
+
|
65
|
+
@staticmethod
|
66
|
+
@abstractmethod
|
67
|
+
def abstract(abstract: Type[ABC]):
|
68
|
+
"""Create a reflection object for an abstract class.
|
69
|
+
|
70
|
+
Parameters
|
71
|
+
----------
|
72
|
+
abstract : Type[ABC]
|
73
|
+
The abstract class to reflect upon
|
74
|
+
|
75
|
+
Returns
|
76
|
+
-------
|
77
|
+
ReflexionAbstract
|
78
|
+
A reflection object encapsulating the abstract class
|
79
|
+
|
80
|
+
Raises
|
81
|
+
------
|
82
|
+
TypeError
|
83
|
+
If the input is not a class
|
84
|
+
ValueError
|
85
|
+
If the class is not abstract
|
86
|
+
"""
|
87
|
+
pass
|
88
|
+
|
89
|
+
@staticmethod
|
90
|
+
@abstractmethod
|
91
|
+
def concrete(concrete: Type[T]):
|
92
|
+
"""Create a reflection object for a concrete class.
|
93
|
+
|
94
|
+
Parameters
|
95
|
+
----------
|
96
|
+
concrete : Type[T]
|
97
|
+
The concrete class to reflect upon
|
98
|
+
|
99
|
+
Returns
|
100
|
+
-------
|
101
|
+
ReflexionConcrete
|
102
|
+
A reflection object encapsulating the concrete class
|
103
|
+
|
104
|
+
Raises
|
105
|
+
------
|
106
|
+
TypeError
|
107
|
+
If the input is not a class
|
108
|
+
ValueError
|
109
|
+
If the class is abstract or cannot be instantiated
|
110
|
+
"""
|
111
|
+
pass
|
112
|
+
|
113
|
+
@staticmethod
|
114
|
+
@abstractmethod
|
115
|
+
def concreteWithAbstract(concrete: Type[T], abstract: Type[ABC]):
|
116
|
+
"""Create a reflection object for a concrete class with its abstract parent.
|
117
|
+
|
118
|
+
Parameters
|
119
|
+
----------
|
120
|
+
concrete : Type[T]
|
121
|
+
The concrete class to reflect upon
|
122
|
+
abstract : Type[ABC]
|
123
|
+
The abstract parent class
|
124
|
+
|
125
|
+
Returns
|
126
|
+
-------
|
127
|
+
ReflexionConcreteWithAbstract
|
128
|
+
A reflection object encapsulating both classes
|
129
|
+
|
130
|
+
Raises
|
131
|
+
------
|
132
|
+
TypeError
|
133
|
+
If either input is not a class
|
134
|
+
ValueError
|
135
|
+
If concrete is not instantiable or abstract is not actually abstract
|
136
|
+
"""
|
137
|
+
pass
|
138
|
+
|
139
|
+
@staticmethod
|
140
|
+
@abstractmethod
|
141
|
+
def module(module: str):
|
142
|
+
"""Create a reflection object for a module.
|
143
|
+
|
144
|
+
Parameters
|
145
|
+
----------
|
146
|
+
module : str
|
147
|
+
The module name to reflect upon
|
148
|
+
|
149
|
+
Returns
|
150
|
+
-------
|
151
|
+
ReflexionModule
|
152
|
+
A reflection object encapsulating the module
|
153
|
+
|
154
|
+
Raises
|
155
|
+
------
|
156
|
+
TypeError
|
157
|
+
If the input is not a string
|
158
|
+
ValueError
|
159
|
+
If the module cannot be imported
|
160
|
+
"""
|
161
|
+
pass
|
162
|
+
|
163
|
+
@staticmethod
|
164
|
+
@abstractmethod
|
165
|
+
def moduleWithClassName(module: str, class_name: str):
|
166
|
+
"""Create a reflection object for a module with a specific class name.
|
167
|
+
|
168
|
+
Parameters
|
169
|
+
----------
|
170
|
+
module : str
|
171
|
+
The module name to reflect upon
|
172
|
+
class_name : str
|
173
|
+
The class name to look for in the module
|
174
|
+
|
175
|
+
Returns
|
176
|
+
-------
|
177
|
+
ReflexionModuleWithClassName
|
178
|
+
A reflection object encapsulating both the module and class name
|
179
|
+
|
180
|
+
Raises
|
181
|
+
------
|
182
|
+
TypeError
|
183
|
+
If either input is not a string
|
184
|
+
ValueError
|
185
|
+
If the module cannot be imported or the class doesn't exist in it
|
186
|
+
"""
|
187
|
+
pass
|
@@ -0,0 +1,265 @@
|
|
1
|
+
import abc
|
2
|
+
import inspect
|
3
|
+
from abc import ABC, abstractmethod
|
4
|
+
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar
|
5
|
+
|
6
|
+
class IReflexionAbstract(ABC):
|
7
|
+
"""Interface for abstract class reflection operations.
|
8
|
+
|
9
|
+
Defines the contract for inspecting and analyzing abstract classes,
|
10
|
+
including their methods, properties, inheritance, and metadata.
|
11
|
+
"""
|
12
|
+
|
13
|
+
@abstractmethod
|
14
|
+
def getClassName(self) -> str:
|
15
|
+
"""Get the name of the abstract class.
|
16
|
+
|
17
|
+
Returns
|
18
|
+
-------
|
19
|
+
str
|
20
|
+
The class name
|
21
|
+
"""
|
22
|
+
pass
|
23
|
+
|
24
|
+
@abstractmethod
|
25
|
+
def getModuleName(self) -> str:
|
26
|
+
"""Get the module name where the abstract class is defined.
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
str
|
31
|
+
The module name
|
32
|
+
"""
|
33
|
+
pass
|
34
|
+
|
35
|
+
@abstractmethod
|
36
|
+
def getAbstractMethods(self) -> Set[str]:
|
37
|
+
"""Get names of all abstract methods required by the class.
|
38
|
+
|
39
|
+
Returns
|
40
|
+
-------
|
41
|
+
Set[str]
|
42
|
+
Set of abstract method names (excluding properties)
|
43
|
+
"""
|
44
|
+
pass
|
45
|
+
|
46
|
+
@abstractmethod
|
47
|
+
def getAbstractProperties(self) -> Set[str]:
|
48
|
+
"""Get names of all abstract properties required by the class.
|
49
|
+
|
50
|
+
Returns
|
51
|
+
-------
|
52
|
+
Set[str]
|
53
|
+
Set of abstract property names
|
54
|
+
"""
|
55
|
+
pass
|
56
|
+
|
57
|
+
@abstractmethod
|
58
|
+
def getConcreteMethods(self) -> Dict[str, Callable]:
|
59
|
+
"""Get all implemented concrete methods in the abstract class.
|
60
|
+
|
61
|
+
Returns
|
62
|
+
-------
|
63
|
+
Dict[str, Callable]
|
64
|
+
Dictionary mapping method names to their implementations
|
65
|
+
"""
|
66
|
+
pass
|
67
|
+
|
68
|
+
@abstractmethod
|
69
|
+
def getStaticMethods(self) -> List[str]:
|
70
|
+
"""Get names of all static methods in the class.
|
71
|
+
|
72
|
+
Returns
|
73
|
+
-------
|
74
|
+
List[str]
|
75
|
+
List of static method names
|
76
|
+
"""
|
77
|
+
pass
|
78
|
+
|
79
|
+
@abstractmethod
|
80
|
+
def getClassMethods(self) -> List[str]:
|
81
|
+
"""Get names of all class methods in the abstract class.
|
82
|
+
|
83
|
+
Returns
|
84
|
+
-------
|
85
|
+
List[str]
|
86
|
+
List of class method names
|
87
|
+
"""
|
88
|
+
pass
|
89
|
+
|
90
|
+
@abstractmethod
|
91
|
+
def getProperties(self) -> List[str]:
|
92
|
+
"""Get names of all properties in the abstract class.
|
93
|
+
|
94
|
+
Returns
|
95
|
+
-------
|
96
|
+
List[str]
|
97
|
+
List of property names
|
98
|
+
"""
|
99
|
+
pass
|
100
|
+
|
101
|
+
@abstractmethod
|
102
|
+
def getMethodSignature(self, methodName: str) -> inspect.Signature:
|
103
|
+
"""Get the signature of a specific method.
|
104
|
+
|
105
|
+
Parameters
|
106
|
+
----------
|
107
|
+
methodName : str
|
108
|
+
Name of the method to inspect
|
109
|
+
|
110
|
+
Returns
|
111
|
+
-------
|
112
|
+
inspect.Signature
|
113
|
+
The method signature
|
114
|
+
|
115
|
+
Raises
|
116
|
+
------
|
117
|
+
AttributeError
|
118
|
+
If the method doesn't exist
|
119
|
+
"""
|
120
|
+
pass
|
121
|
+
|
122
|
+
@abstractmethod
|
123
|
+
def getPropertySignature(self, propertyName: str) -> inspect.Signature:
|
124
|
+
"""Get the signature of a property's getter method.
|
125
|
+
|
126
|
+
Parameters
|
127
|
+
----------
|
128
|
+
propertyName : str
|
129
|
+
Name of the property to inspect
|
130
|
+
|
131
|
+
Returns
|
132
|
+
-------
|
133
|
+
inspect.Signature
|
134
|
+
The getter signature
|
135
|
+
|
136
|
+
Raises
|
137
|
+
------
|
138
|
+
AttributeError
|
139
|
+
If the property doesn't exist or has no getter
|
140
|
+
"""
|
141
|
+
pass
|
142
|
+
|
143
|
+
@abstractmethod
|
144
|
+
def getDocstring(self) -> Optional[str]:
|
145
|
+
"""Get the class docstring.
|
146
|
+
|
147
|
+
Returns
|
148
|
+
-------
|
149
|
+
Optional[str]
|
150
|
+
The docstring if available
|
151
|
+
"""
|
152
|
+
pass
|
153
|
+
|
154
|
+
@abstractmethod
|
155
|
+
def getBaseAbstractClasses(self) -> Tuple[Type[ABC], ...]:
|
156
|
+
"""Get direct abstract base classes.
|
157
|
+
|
158
|
+
Returns
|
159
|
+
-------
|
160
|
+
Tuple[Type[ABC], ...]
|
161
|
+
Tuple of abstract base classes
|
162
|
+
"""
|
163
|
+
pass
|
164
|
+
|
165
|
+
@abstractmethod
|
166
|
+
def getInterfaceMethods(self) -> Dict[str, inspect.Signature]:
|
167
|
+
"""Get all abstract methods with their signatures.
|
168
|
+
|
169
|
+
Returns
|
170
|
+
-------
|
171
|
+
Dict[str, inspect.Signature]
|
172
|
+
Dictionary mapping method names to their signatures
|
173
|
+
"""
|
174
|
+
pass
|
175
|
+
|
176
|
+
@abstractmethod
|
177
|
+
def isSubclassOf(self, abstract_class: Type[ABC]) -> bool:
|
178
|
+
"""Check inheritance relationship with another abstract class.
|
179
|
+
|
180
|
+
Parameters
|
181
|
+
----------
|
182
|
+
abstract_class : Type[ABC]
|
183
|
+
The abstract class to check against
|
184
|
+
|
185
|
+
Returns
|
186
|
+
-------
|
187
|
+
bool
|
188
|
+
True if this class inherits from the given abstract class
|
189
|
+
"""
|
190
|
+
pass
|
191
|
+
|
192
|
+
@abstractmethod
|
193
|
+
def getSourceCode(self) -> Optional[str]:
|
194
|
+
"""Get the class source code.
|
195
|
+
|
196
|
+
Returns
|
197
|
+
-------
|
198
|
+
Optional[str]
|
199
|
+
The source code if available
|
200
|
+
"""
|
201
|
+
pass
|
202
|
+
|
203
|
+
@abstractmethod
|
204
|
+
def getFileLocation(self) -> Optional[str]:
|
205
|
+
"""Get the file where the class is defined.
|
206
|
+
|
207
|
+
Returns
|
208
|
+
-------
|
209
|
+
Optional[str]
|
210
|
+
File path if available
|
211
|
+
"""
|
212
|
+
pass
|
213
|
+
|
214
|
+
@abstractmethod
|
215
|
+
def getAnnotations(self) -> Dict[str, Any]:
|
216
|
+
"""Get type annotations for the class.
|
217
|
+
|
218
|
+
Returns
|
219
|
+
-------
|
220
|
+
Dict[str, Any]
|
221
|
+
Dictionary of attribute annotations
|
222
|
+
"""
|
223
|
+
pass
|
224
|
+
|
225
|
+
@abstractmethod
|
226
|
+
def getDecorators(self, method_name: str) -> List[str]:
|
227
|
+
"""Get decorators applied to a specific method.
|
228
|
+
|
229
|
+
Parameters
|
230
|
+
----------
|
231
|
+
method_name : str
|
232
|
+
Name of the method to inspect
|
233
|
+
|
234
|
+
Returns
|
235
|
+
-------
|
236
|
+
List[str]
|
237
|
+
List of decorator names
|
238
|
+
"""
|
239
|
+
pass
|
240
|
+
|
241
|
+
@abstractmethod
|
242
|
+
def isProtocol(self) -> bool:
|
243
|
+
"""Check if the class is a Protocol.
|
244
|
+
|
245
|
+
Returns
|
246
|
+
-------
|
247
|
+
bool
|
248
|
+
True if this is a Protocol class
|
249
|
+
"""
|
250
|
+
pass
|
251
|
+
|
252
|
+
@abstractmethod
|
253
|
+
def getRequiredAttributes(self) -> Set[str]:
|
254
|
+
"""For Protocol classes, get required attributes.
|
255
|
+
|
256
|
+
Returns
|
257
|
+
-------
|
258
|
+
Set[str]
|
259
|
+
Set of required attribute names
|
260
|
+
|
261
|
+
Notes
|
262
|
+
-----
|
263
|
+
Returns empty set for non-Protocol classes
|
264
|
+
"""
|
265
|
+
pass
|
@@ -1,5 +1,6 @@
|
|
1
1
|
import abc
|
2
2
|
from typing import Any, Type, TypeVar
|
3
|
+
from orionis.luminate.contracts.support.reflection import IReflection
|
3
4
|
from orionis.luminate.support.inspection.functions import (
|
4
5
|
_ensure_abstract_class,
|
5
6
|
_ensure_instantiable_class,
|
@@ -18,7 +19,7 @@ from orionis.luminate.support.inspection.reflexion_module_with_classname import
|
|
18
19
|
T = TypeVar('T')
|
19
20
|
ABC = TypeVar('ABC', bound=abc.ABC)
|
20
21
|
|
21
|
-
class Reflection:
|
22
|
+
class Reflection(IReflection):
|
22
23
|
"""A static class providing factory methods for creating reflection objects.
|
23
24
|
|
24
25
|
This class provides methods to create various types of reflection objects
|
@@ -3,10 +3,11 @@ import ast
|
|
3
3
|
import inspect
|
4
4
|
import types
|
5
5
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, TypeVar
|
6
|
+
from orionis.luminate.support.inspection.contracts.reflexion_abstract import IReflexionAbstract
|
6
7
|
|
7
8
|
ABC = TypeVar('ABC', bound=abc.ABC)
|
8
9
|
|
9
|
-
class ReflexionAbstract:
|
10
|
+
class ReflexionAbstract(IReflexionAbstract):
|
10
11
|
"""A reflection object encapsulating an abstract class.
|
11
12
|
|
12
13
|
Parameters
|
File without changes
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
from typing import Any, Dict
|
3
|
+
|
4
|
+
class IExceptionParser(ABC):
|
5
|
+
"""
|
6
|
+
Abstract base interface for classes that parse exceptions
|
7
|
+
into a structured dictionary format.
|
8
|
+
"""
|
9
|
+
|
10
|
+
@property
|
11
|
+
@abstractmethod
|
12
|
+
def raw_exception(self) -> Exception:
|
13
|
+
"""
|
14
|
+
Get the original exception object.
|
15
|
+
|
16
|
+
Returns
|
17
|
+
-------
|
18
|
+
Exception
|
19
|
+
The raw exception instance.
|
20
|
+
"""
|
21
|
+
pass
|
22
|
+
|
23
|
+
@abstractmethod
|
24
|
+
def toDict(self) -> Dict[str, Any]:
|
25
|
+
"""
|
26
|
+
Serialize the exception into a dictionary.
|
27
|
+
|
28
|
+
Returns
|
29
|
+
-------
|
30
|
+
dict
|
31
|
+
A structured representation of the exception including details such as:
|
32
|
+
- error_type
|
33
|
+
- error_message
|
34
|
+
- error_code
|
35
|
+
- stack_trace
|
36
|
+
- cause (if any)
|
37
|
+
"""
|
38
|
+
pass
|
@@ -0,0 +1,107 @@
|
|
1
|
+
import traceback
|
2
|
+
from typing import Any, Dict, List, Optional, Union
|
3
|
+
from orionis.luminate.support.parsers.contracts.exception_parser import IExceptionParser
|
4
|
+
|
5
|
+
class ExceptionParser(IExceptionParser):
|
6
|
+
"""
|
7
|
+
A utility class to parse an exception and convert it into a structured dictionary.
|
8
|
+
"""
|
9
|
+
|
10
|
+
def __init__(self, exception: Exception) -> None:
|
11
|
+
"""
|
12
|
+
Initialize the ExceptionParser with the given exception.
|
13
|
+
|
14
|
+
Parameters
|
15
|
+
----------
|
16
|
+
exception : Exception
|
17
|
+
The exception to be parsed.
|
18
|
+
"""
|
19
|
+
self.__exception = exception
|
20
|
+
|
21
|
+
@property
|
22
|
+
def raw_exception(self) -> Exception:
|
23
|
+
"""
|
24
|
+
Get the original exception object.
|
25
|
+
|
26
|
+
Returns
|
27
|
+
-------
|
28
|
+
Exception
|
29
|
+
The raw exception instance.
|
30
|
+
"""
|
31
|
+
return self.__exception
|
32
|
+
|
33
|
+
def toDict(self) -> Dict[str, Any]:
|
34
|
+
"""
|
35
|
+
Serialize the exception into a dictionary format.
|
36
|
+
|
37
|
+
Returns
|
38
|
+
-------
|
39
|
+
dict
|
40
|
+
A dictionary containing:
|
41
|
+
- 'error_type': The type of exception.
|
42
|
+
- 'error_message': The complete traceback string.
|
43
|
+
- 'error_code': Custom error code, if available.
|
44
|
+
- 'stack_trace': A list of frames in the stack trace, each with:
|
45
|
+
- 'filename': File where the error occurred.
|
46
|
+
- 'lineno': Line number.
|
47
|
+
- 'name': Function or method name.
|
48
|
+
- 'line': The source line of code.
|
49
|
+
- 'cause': A nested dictionary representing the original cause (if any).
|
50
|
+
"""
|
51
|
+
tb = traceback.TracebackException.from_exception(self.__exception, capture_locals=False)
|
52
|
+
|
53
|
+
return {
|
54
|
+
"error_type": tb.exc_type.__name__ if tb.exc_type else "Unknown",
|
55
|
+
"error_message": str(tb).strip(),
|
56
|
+
"error_code": getattr(self.__exception, "code", None),
|
57
|
+
"stack_trace": self.__parse_stack(tb.stack),
|
58
|
+
"cause": self.__parse_cause(self.__exception.__cause__) if self.__exception.__cause__ else None
|
59
|
+
}
|
60
|
+
|
61
|
+
def __parse_stack(self, stack: traceback.StackSummary) -> List[Dict[str, Union[str, int, None]]]:
|
62
|
+
"""
|
63
|
+
Helper method to parse the stack trace.
|
64
|
+
|
65
|
+
Parameters
|
66
|
+
----------
|
67
|
+
stack : traceback.StackSummary
|
68
|
+
The summary of the stack.
|
69
|
+
|
70
|
+
Returns
|
71
|
+
-------
|
72
|
+
list of dict
|
73
|
+
A list of dictionaries with detailed frame information.
|
74
|
+
"""
|
75
|
+
return [
|
76
|
+
{
|
77
|
+
"filename": frame.filename,
|
78
|
+
"lineno": frame.lineno,
|
79
|
+
"name": frame.name,
|
80
|
+
"line": frame.line
|
81
|
+
}
|
82
|
+
for frame in stack
|
83
|
+
]
|
84
|
+
|
85
|
+
def __parse_cause(self, cause: Optional[BaseException]) -> Optional[Dict[str, Any]]:
|
86
|
+
"""
|
87
|
+
Recursively parse the cause of an exception, if available.
|
88
|
+
|
89
|
+
Parameters
|
90
|
+
----------
|
91
|
+
cause : BaseException or None
|
92
|
+
The original cause of the exception.
|
93
|
+
|
94
|
+
Returns
|
95
|
+
-------
|
96
|
+
dict or None
|
97
|
+
A dictionary with the cause information or None if no cause exists.
|
98
|
+
"""
|
99
|
+
if not isinstance(cause, BaseException):
|
100
|
+
return None
|
101
|
+
|
102
|
+
cause_tb = traceback.TracebackException.from_exception(cause)
|
103
|
+
return {
|
104
|
+
"error_type": cause_tb.exc_type.__name__ if cause_tb.exc_type else "Unknown",
|
105
|
+
"error_message": str(cause_tb).strip(),
|
106
|
+
"stack_trace": self.__parse_stack(cause_tb.stack)
|
107
|
+
}
|
File without changes
|
File without changes
|