4
4
as well as the IActiveScriptError interface code.
5
5
"""
6
6
7
+ from __future__ import annotations
8
+
7
9
import re
8
10
import traceback
11
+ import warnings
12
+ from types import TracebackType
9
13
10
14
import pythoncom
11
15
import win32com .server .util
12
16
import winerror
13
17
from win32com .axscript import axscript
14
18
from win32com .server .exception import COMException
19
+ from win32comext .axscript .client .debug import DebugManager
20
+ from win32comext .axscript .client .framework import AXScriptCodeBlock , COMScript
21
+ from win32comext .axscript .server .axsite import AXSite
15
22
16
23
debugging = 0
17
24
18
25
19
- def FormatForAX (text ):
26
+ def FormatForAX (text : str ):
20
27
"""Format a string suitable for an AX Host"""
21
28
# Replace all " with ', so it works OK in HTML (ie, ASP)
22
29
return ExpandTabs (AddCR (text ))
23
30
24
31
25
- def ExpandTabs (text ):
32
+ def ExpandTabs (text : str ):
26
33
return re .sub (r"\t" , " " , text )
27
34
28
35
29
- def AddCR (text ):
36
+ def AddCR (text : str ):
30
37
return re .sub (r"\n" , "\r \n " , text )
31
38
32
39
@@ -45,7 +52,7 @@ def _query_interface_(self, iid):
45
52
print ("IActiveScriptError QI - unknown IID" , iid )
46
53
return 0
47
54
48
- def _SetExceptionInfo (self , exc ):
55
+ def _SetExceptionInfo (self , exc : AXScriptException ):
49
56
self .exception = exc
50
57
51
58
def GetSourceLineText (self ):
@@ -72,14 +79,27 @@ class AXScriptException(COMException):
72
79
object.
73
80
"""
74
81
75
- def __init__ (self , site , codeBlock , exc_type , exc_value , exc_traceback ):
82
+ def __init__ (
83
+ self ,
84
+ site : COMScript ,
85
+ codeBlock : AXScriptCodeBlock | None ,
86
+ exc_type : None = None ,
87
+ exc_value : BaseException | None = None ,
88
+ exc_traceback : None = None ,
89
+ ):
76
90
# set properties base class shares via base ctor...
77
91
super ().__init__ (
78
92
description = "Unknown Exception" ,
79
93
scode = winerror .DISP_E_EXCEPTION ,
80
94
source = "Python ActiveX Scripting Engine" ,
81
95
)
82
96
97
+ if exc_type is not None or exc_traceback is not None :
98
+ warnings .warn (
99
+ "`exc_type` and `exc_traceback` were redundant and are now unused." ,
100
+ category = DeprecationWarning ,
101
+ )
102
+
83
103
# And my other values...
84
104
if codeBlock is None :
85
105
self .sourceContext = 0
@@ -89,18 +109,18 @@ def __init__(self, site, codeBlock, exc_type, exc_value, exc_traceback):
89
109
self .startLineNo = codeBlock .startLineNumber
90
110
self .linetext = ""
91
111
92
- self .__BuildFromException (site , exc_type , exc_value , exc_traceback )
112
+ self .__BuildFromException (site , exc_value )
93
113
94
- def __BuildFromException (self , site , type , value , tb ):
114
+ def __BuildFromException (self , site : COMScript , value : BaseException | None ):
95
115
if debugging :
96
116
import linecache
97
117
98
118
linecache .clearcache ()
99
119
try :
100
- if issubclass ( type , SyntaxError ):
120
+ if isinstance ( value , SyntaxError ):
101
121
self ._BuildFromSyntaxError (value )
102
122
else :
103
- self ._BuildFromOther (site , type , value , tb )
123
+ self ._BuildFromOther (site , value )
104
124
except : # Error extracting traceback info!!!
105
125
traceback .print_exc ()
106
126
# re-raise.
@@ -111,13 +131,16 @@ def _BuildFromSyntaxError(self, exc: SyntaxError):
111
131
msg = exc .msg or "Unknown Error"
112
132
offset = exc .offset or 0
113
133
line = exc .text or ""
134
+ lineno = exc .lineno or 0
114
135
115
136
self .description = FormatForAX (msg )
116
- self .lineno = exc . lineno
137
+ self .lineno = lineno
117
138
self .colno = offset - 1
118
139
self .linetext = ExpandTabs (line .rstrip ())
119
140
120
- def _BuildFromOther (self , site , exc_type , value , tb ):
141
+ def _BuildFromOther (self , site : COMScript , value : BaseException | None ):
142
+ tb = value .__traceback__ if value else None
143
+ exc_type = type (value ) if value else None
121
144
self .colno = - 1
122
145
self .lineno = 0
123
146
if debugging : # Full traceback if debugging.
@@ -132,7 +155,6 @@ def _BuildFromOther(self, site, exc_type, value, tb):
132
155
"r_reload" ,
133
156
"r_open" ,
134
157
] # hide from these functions down in the traceback.
135
- depth = None
136
158
tb_top = tb
137
159
while tb_top :
138
160
filename , lineno , name , line = self .ExtractTracebackInfo (tb_top , site )
@@ -141,8 +163,7 @@ def _BuildFromOther(self, site, exc_type, value, tb):
141
163
tb_top = tb_top .tb_next
142
164
format_items = []
143
165
if tb_top : # found one.
144
- depth = 0
145
- tb_look = tb_top
166
+ tb_look : TracebackType | None = tb_top
146
167
# Look down for our bottom
147
168
while tb_look :
148
169
filename , lineno , name , line = self .ExtractTracebackInfo (tb_look , site )
@@ -155,15 +176,14 @@ def _BuildFromOther(self, site, exc_type, value, tb):
155
176
self .lineno = lineno
156
177
self .linetext = line
157
178
format_items .append ((filename , lineno , name , line ))
158
- depth = depth + 1
159
179
tb_look = tb_look .tb_next
160
180
else :
161
- depth = None
162
181
tb_top = tb
163
182
164
183
bits = ["Traceback (most recent call last):\n " ]
165
- bits .extend (traceback .format_list (format_items ))
166
- if exc_type == pythoncom .com_error :
184
+ # Fixed in https://github.com/python/typeshed/pull/11675 , to be included in next mypy release
185
+ bits .extend (traceback .format_list (format_items )) # type: ignore[arg-type]
186
+ if isinstance (value , pythoncom .com_error ):
167
187
desc = f"{ value .strerror } (0x{ value .hresult :x} )"
168
188
if (
169
189
value .hresult == winerror .DISP_E_EXCEPTION
@@ -176,23 +196,17 @@ def _BuildFromOther(self, site, exc_type, value, tb):
176
196
bits .extend (traceback .format_exception_only (exc_type , value ))
177
197
178
198
self .description = ExpandTabs ("" .join (bits ))
179
- # Clear tracebacks etc.
180
- tb = tb_top = tb_look = None
181
199
182
- def ExtractTracebackInfo (self , tb , site ):
200
+ def ExtractTracebackInfo (self , tb : TracebackType , site : COMScript ):
183
201
import linecache
184
202
185
- f = tb .tb_frame
186
203
lineno = tb .tb_lineno
187
- co = f .f_code
204
+ co = tb . tb_frame .f_code
188
205
filename = co .co_filename
189
206
name = co .co_name
190
- line = linecache .getline (filename , lineno )
207
+ line : str | None = linecache .getline (filename , lineno )
191
208
if not line :
192
- try :
193
- codeBlock = site .scriptCodeBlocks [filename ]
194
- except KeyError :
195
- codeBlock = None
209
+ codeBlock = site .scriptCodeBlocks .get (filename )
196
210
if codeBlock :
197
211
# Note: 'line' will now be unicode.
198
212
line = codeBlock .GetLineNo (lineno )
@@ -206,15 +220,19 @@ def __repr__(self):
206
220
return "AXScriptException Object with description:" + self .description
207
221
208
222
209
- def ProcessAXScriptException (scriptingSite , debugManager , exceptionInstance ):
223
+ def ProcessAXScriptException (
224
+ scriptingSite : AXSite ,
225
+ debugManager : DebugManager ,
226
+ exceptionInstance : AXScriptException ,
227
+ ):
210
228
"""General function to handle any exception in AX code
211
229
212
230
This function creates an instance of our IActiveScriptError interface, and
213
231
gives it to the host, along with out exception class. The host will
214
232
likely call back on the IActiveScriptError interface to get the source text
215
233
and other information not normally in COM exceptions.
216
234
"""
217
- # traceback.print_exc()
235
+ # traceback.print_exc()
218
236
instance = IActiveScriptError ()
219
237
instance ._SetExceptionInfo (exceptionInstance )
220
238
gateway = win32com .server .util .wrap (instance , axscript .IID_IActiveScriptError )
0 commit comments