forked from IronLanguages/ironpython3
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path_warnings.cs
More file actions
270 lines (243 loc) · 11.5 KB
/
_warnings.cs
File metadata and controls
270 lines (243 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using IronPython.Runtime;
using IronPython.Runtime.Exceptions;
using IronPython.Runtime.Operations;
using IronPython.Runtime.Types;
using Microsoft.Scripting;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
[assembly: PythonModule("_warnings", typeof(IronPython.Modules.PythonWarnings))]
namespace IronPython.Modules {
public static class PythonWarnings {
public const string __doc__ = "Provides low-level functionality for reporting warnings";
private static readonly object _keyFields = new object();
private static readonly string _keyDefaultAction = "_defaultaction";
private static readonly string _keyFilters = "filters";
private static readonly string _keyOnceRegistry = "_onceregistry";
[SpecialName]
public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
PythonList defaultFilters = new PythonList();
defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.DeprecationWarning, null, 0));
defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.PendingDeprecationWarning, null, 0));
defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.ImportWarning, null, 0));
string bytesWarningAction = context.PythonOptions.BytesWarning switch {
Severity.Ignore => "ignore",
Severity.Warning => "default",
_ => "error"
};
defaultFilters.AddNoLock(PythonTuple.MakeTuple(bytesWarningAction, null, PythonExceptions.BytesWarning, null, 0));
context.GetOrCreateModuleState(_keyFields, () => {
dict.Add(_keyDefaultAction, "default");
dict.Add(_keyOnceRegistry, new PythonDictionary());
dict.Add(_keyFilters, defaultFilters);
return dict;
});
}
#region Public API
public static void _filters_mutated() { } // TODO: do something with this
public static void warn(CodeContext context, object message, PythonType category=null, int stacklevel=1) {
PythonContext pContext = context.LanguageContext;
PythonList argv = pContext.GetSystemStateValue("argv") as PythonList;
if (PythonOps.IsInstance(message, PythonExceptions.Warning)) {
category = DynamicHelpers.GetPythonType(message);
}
if (category == null) {
category = PythonExceptions.UserWarning;
}
if (!category.IsSubclassOf(PythonExceptions.Warning)) {
throw PythonOps.ValueError("category is not a subclass of Warning");
}
TraceBackFrame caller = null;
PythonDictionary globals;
int lineno;
if (context.LanguageContext.PythonOptions.Frames) {
try {
caller = SysModule._getframeImpl(context, stacklevel - 1);
} catch (ValueErrorException) { }
}
if (caller == null) {
globals = Builtin.globals(context) as PythonDictionary;
lineno = 1;
} else {
globals = caller.f_globals;
lineno = (int)caller.f_lineno;
}
string module;
string filename;
if (globals != null && globals.ContainsKey("__name__")) {
module = (string)globals.get("__name__");
} else {
module = "<string>";
}
filename = globals.get("__file__") as string;
if (filename == null || filename == "") {
if (module == "__main__") {
if (argv != null && argv.Count > 0) {
filename = argv[0] as string;
} else {
// interpreter lacks sys.argv
filename = "__main__";
}
}
if (filename == null || filename == "") {
filename = module;
}
}
PythonDictionary registry = (PythonDictionary)globals.setdefault("__warningregistry__", new PythonDictionary());
warn_explicit(context, message, category, filename, lineno, module, registry, globals);
}
public static void warn_explicit(CodeContext context, object message, PythonType category, string filename, int lineno, string module=null, PythonDictionary registry=null, object module_globals=null) {
PythonContext pContext = context.LanguageContext;
PythonDictionary fields = (PythonDictionary)pContext.GetModuleState(_keyFields);
object warnings = pContext.GetWarningsModule();
PythonExceptions.BaseException msg;
string text; // message text
if (string.IsNullOrEmpty(module)) {
module = (filename == null || filename == "") ? "<unknown>" : filename;
if (module.EndsWith(".py", StringComparison.Ordinal)) {
module = module.Substring(0, module.Length - 3);
}
}
if (registry == null) {
registry = new PythonDictionary();
}
if (PythonOps.IsInstance(message, PythonExceptions.Warning)) {
msg = (PythonExceptions.BaseException)message;
text = msg.ToString();
category = DynamicHelpers.GetPythonType(msg);
} else {
text = message.ToString();
msg = PythonExceptions.CreatePythonThrowable(category, message.ToString());
}
PythonTuple key = PythonTuple.MakeTuple(text, category, lineno);
if (registry.ContainsKey(key)) {
return;
}
string action = Converter.ConvertToString(fields[_keyDefaultAction]);
PythonTuple last_filter = null;
bool loop_break = false;
PythonList filters = (PythonList)fields[_keyFilters];
if (warnings != null) {
filters = PythonOps.GetBoundAttr(context, warnings, "filters") as PythonList;
if(filters == null) {
throw PythonOps.ValueError("_warnings.filters must be a list");
}
}
foreach (PythonTuple filter in filters) {
last_filter = filter;
action = (string)filter._data[0];
PythonRegex.Pattern fMsg = (PythonRegex.Pattern)filter._data[1];
PythonType fCat = (PythonType)filter._data[2];
PythonRegex.Pattern fMod = (PythonRegex.Pattern)filter._data[3];
int fLno = filter._data[4] switch {
int i => i,
BigInteger bi => (int)bi,
Extensible<BigInteger> ebi => (int)ebi.Value,
_ => throw PythonOps.TypeError("an integer is required")
};
if ((fMsg == null || fMsg.match(text) != null) &&
category.IsSubclassOf(fCat) &&
(fMod == null || fMod.match(module) != null) &&
(fLno == 0 || fLno == lineno)) {
loop_break = true;
break;
}
}
if (!loop_break) {
action = Converter.ConvertToString(fields[_keyDefaultAction]);
}
switch (action) {
case "ignore":
registry.Add(key, 1);
return;
case "error":
throw msg.GetClrException();
case "once":
registry.Add(key, 1);
PythonTuple onceKey = PythonTuple.MakeTuple(text, category);
PythonDictionary once_reg = (PythonDictionary)fields[_keyOnceRegistry];
if (once_reg.ContainsKey(onceKey)) {
return;
}
once_reg.Add(key, 1);
break;
case "always":
break;
case "module":
registry.Add(key, 1);
PythonTuple altKey = PythonTuple.MakeTuple(text, category, 0);
if (registry.ContainsKey(altKey)) {
return;
}
registry.Add(altKey, 1);
break;
case "default":
registry.Add(key, 1);
break;
default:
throw PythonOps.RuntimeError("Unrecognized action ({0}) in warnings.filters:\n {1}", action, last_filter);
}
if (warnings != null) {
object show_fxn = PythonOps.GetBoundAttr(context, warnings, "showwarning");
if(show_fxn != null) {
PythonCalls.Call(
context,
show_fxn,
msg, category, filename, lineno, null, null);
} else {
showwarning(context, msg, category, filename, lineno, null, null);
}
} else {
showwarning(context, msg, category, filename, lineno, null, null);
}
}
internal static string formatwarning(object message, PythonType category, string filename, int lineno, string line=null) {
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0}:{1}: {2}: {3}\n", filename, lineno, category.Name, message);
if (line == null && lineno > 0 && File.Exists(filename)) {
StreamReader reader = new StreamReader(filename);
for (int i = 0; i < lineno - 1; i++) {
reader.ReadLine();
}
line = reader.ReadLine();
}
if (line != null) {
sb.AppendFormat(" {0}\n", line.strip());
}
return sb.ToString();
}
internal static void showwarning(CodeContext context, object message, PythonType category, string filename, int lineno, object file=null, string line=null) {
string text = formatwarning(message, category, filename, lineno, line);
try {
if (file == null) {
PythonContext pContext = context.LanguageContext;
if (pContext.GetSystemStateValue("stderr") is PythonIOModule._IOBase stderr) {
stderr.write(context, text);
} else {
// use CLR stderr if python's is unavailable
Console.Error.Write(text);
}
} else {
if (file is PythonIOModule._IOBase) {
((PythonIOModule._IOBase)file).write(context, text);
} else if (file is TextWriter) {
((TextWriter)file).Write(text);
} // unrecognized file type - warning is lost
}
} catch (IOException) {
// invalid file - warning is lost
}
}
#endregion
}
}