PageRenderTime 1ms CodeModel.GetById 21ms app.highlight 6ms RepoModel.GetById 0ms app.codeStats 1ms

/DLR_Main/Languages/IronPython/IronPython.Modules/_warnings.cs

https://bitbucket.org/mdavid/dlr
C# | 262 lines | 221 code | 24 blank | 17 comment | 72 complexity | e77d4d6388187b2dd124595eefd2ec61 MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the  Apache License, Version 2.0, please send an email to 
  8 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 *
 14 * ***************************************************************************/
 15
 16using System;
 17using System.Collections.Generic;
 18using System.IO;
 19using System.Runtime.CompilerServices;
 20using System.Runtime.InteropServices;
 21using System.Text;
 22using System.Text.RegularExpressions;
 23using IronPython.Runtime;
 24using IronPython.Runtime.Exceptions;
 25using IronPython.Runtime.Operations;
 26using IronPython.Runtime.Types;
 27using Microsoft.Scripting;
 28using Microsoft.Scripting.Runtime;
 29
 30[assembly: PythonModule("_warnings", typeof(IronPython.Modules.PythonWarnings))]
 31namespace IronPython.Modules {
 32    public static class PythonWarnings {
 33        public const string __doc__ = "Provides low-level functionality for reporting warnings";
 34
 35        private static readonly object _keyFields = new object();
 36        private static readonly string _keyDefaultAction = "default_action";
 37        private static readonly string _keyFilters = "filters";
 38        private static readonly string _keyOnceRegistry = "once_registry";
 39
 40        [SpecialName]
 41        public static void PerformModuleReload(PythonContext/*!*/ context, PythonDictionary/*!*/ dict) {
 42            List defaultFilters = new List();
 43            if (context.PythonOptions.WarnPython30) {
 44                defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.DeprecationWarning, null, 0));
 45            }
 46            defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.PendingDeprecationWarning, null, 0));
 47            defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.ImportWarning, null, 0));
 48            defaultFilters.AddNoLock(PythonTuple.MakeTuple("ignore", null, PythonExceptions.BytesWarning, null, 0));
 49
 50            context.GetOrCreateModuleState(_keyFields, () => {
 51                dict.Add(_keyDefaultAction, "default");
 52                dict.Add(_keyOnceRegistry, new PythonDictionary());
 53                dict.Add(_keyFilters, defaultFilters);
 54                return dict;
 55            });
 56        }
 57
 58        #region Public API
 59
 60        public static void warn(CodeContext context, object message, [DefaultParameterValue(null)]PythonType category, [DefaultParameterValue(1)]int stacklevel) {
 61            PythonContext pContext = PythonContext.GetContext(context);
 62            List argv = pContext.GetSystemStateValue("argv") as List;
 63            PythonDictionary dict = pContext.GetSystemStateValue("__dict__") as PythonDictionary;
 64
 65            if (PythonOps.IsInstance(message, PythonExceptions.Warning)) {
 66                category = DynamicHelpers.GetPythonType(message);
 67            }
 68            if (category == null) {
 69                category = PythonExceptions.UserWarning;
 70            }
 71            if (!category.IsSubclassOf(PythonExceptions.Warning)) {
 72                throw PythonOps.ValueError("category is not a subclass of Warning");
 73            }
 74
 75            TraceBackFrame caller = null;
 76            PythonDictionary globals;
 77            int lineno;
 78            if (PythonContext.GetContext(context).PythonOptions.Frames) {
 79                try {
 80                    caller = SysModule._getframeImpl(context, stacklevel);
 81                } catch (ValueErrorException) { }
 82            }
 83            if (caller == null) {
 84                globals = Builtin.globals(context) as PythonDictionary;
 85                lineno = 1;
 86            } else {
 87                globals = caller.f_globals;
 88                lineno = (int)caller.f_lineno;
 89            }
 90
 91            string module;
 92            string filename;
 93            if (globals != null && globals.ContainsKey("__name__")) {
 94                module = (string)globals.get("__name__");
 95            } else {
 96                module = "<string>";
 97            }
 98
 99            filename = globals.get("__file__") as string;
100            if (filename == null || filename == "") {
101                if (module == "__main__") {
102                    if (argv != null && argv.Count > 0) {
103                        filename = argv[0] as string;
104                    } else {
105                        // interpreter lacks sys.argv
106                        filename = "__main__";
107                    }
108                }
109                if (filename == null || filename == "") {
110                    filename = module;
111                }
112            }
113
114            PythonDictionary registry = (PythonDictionary)globals.setdefault("__warningregistry__", new PythonDictionary());
115            warn_explicit(context, message, category, filename, lineno, module, registry, globals);
116        }
117
118        public static void warn_explicit(CodeContext context, object message, PythonType category, string filename, int lineno, [DefaultParameterValue(null)]string module, [DefaultParameterValue(null)]PythonDictionary registry, [DefaultParameterValue(null)]object module_globals) {
119            PythonContext pContext = PythonContext.GetContext(context);
120            PythonDictionary fields = (PythonDictionary)pContext.GetModuleState(_keyFields);
121            PythonExceptions.BaseException msg;
122            string text; // message text
123
124            if (string.IsNullOrEmpty(module)) {
125                module = (filename == null || filename == "") ? "<unknown>" : filename;
126                if (module.EndsWith(".py")) {
127                    module = module.Substring(0, module.Length - 3);
128                }
129            }
130            if (registry == null) {
131                registry = new PythonDictionary();
132            }
133            if (PythonOps.IsInstance(message, PythonExceptions.Warning)) {
134                msg = (PythonExceptions.BaseException)message;
135                text = msg.ToString();
136                category = DynamicHelpers.GetPythonType(msg);
137            } else {
138                text = message.ToString();
139                msg = PythonExceptions.CreatePythonThrowable(category, message.ToString());
140            }
141
142            PythonTuple key = PythonTuple.MakeTuple(text, category, lineno);
143            if (registry.ContainsKey(key)) {
144                return;
145            }
146
147            string action = Converter.ConvertToString(fields[_keyDefaultAction]);
148            PythonTuple last_filter = null;
149            bool loop_break = false;
150            foreach (PythonTuple filter in (List)fields[_keyFilters]) {
151                last_filter = filter;
152                action = (string)filter._data[0];
153                PythonRegex.RE_Pattern fMsg = (PythonRegex.RE_Pattern)filter._data[1];
154                PythonType fCat = (PythonType)filter._data[2];
155                PythonRegex.RE_Pattern fMod = (PythonRegex.RE_Pattern)filter._data[3];
156                int fLno;
157                if (filter._data[4] is int) {
158                    fLno = (int)filter._data[4];
159                } else {
160                    fLno = (Extensible<int>)filter._data[4];
161                }
162
163                if ((fMsg == null || fMsg.match(text) != null) &&
164                    category.IsSubclassOf(fCat) &&
165                    (fMod == null || fMod.match(module) != null) &&
166                    (fLno == 0 || fLno == lineno)) {
167                    loop_break = true;
168                    break;
169                }
170            }
171            if (!loop_break) {
172                action = Converter.ConvertToString(fields[_keyDefaultAction]);
173            }
174
175            switch (action) {
176                case "ignore":
177                    registry.Add(key, 1);
178                    return;
179                case "error":
180                    throw msg.GetClrException();
181                case "once":
182                    registry.Add(key, 1);
183                    PythonTuple onceKey = PythonTuple.MakeTuple(text, category);
184                    PythonDictionary once_reg = (PythonDictionary)fields[_keyOnceRegistry];
185                    if (once_reg.ContainsKey(onceKey)) {
186                        return;
187                    }
188                    once_reg.Add(key, 1);
189                    break;
190                case "always":
191                    break;
192                case "module":
193                    registry.Add(key, 1);
194                    PythonTuple altKey = PythonTuple.MakeTuple(text, category, 0);
195                    if (registry.ContainsKey(altKey)) {
196                        return;
197                    }
198                    registry.Add(altKey, 1);
199                    break;
200                case "default":
201                    registry.Add(key, 1);
202                    break;
203                default:
204                    throw PythonOps.RuntimeError("Unrecognized action ({0}) in warnings.filters:\n {1}", action, last_filter);
205            }
206
207            object warnings = pContext.GetWarningsModule();
208            if (warnings != null) {
209                PythonCalls.Call(
210                    context,
211                    PythonOps.GetBoundAttr(context, warnings, "showwarning"),
212                    msg, category, filename, lineno, null, null);
213            } else {
214                showwarning(context, msg, category, filename, lineno, null, null);
215            }
216        }
217
218        internal static string formatwarning(object message, PythonType category, string filename, int lineno, [DefaultParameterValue(null)]string line) {
219            StringBuilder sb = new StringBuilder();
220            sb.AppendFormat("{0}:{1}: {2}: {3}\n", filename, lineno, category.Name, message);
221            if (line == null && lineno > 0 && File.Exists(filename)) {
222                StreamReader reader = new StreamReader(filename);
223                for (int i = 0; i < lineno - 1; i++) {
224                    reader.ReadLine();
225                }
226                line = reader.ReadLine();
227            }
228            if (line != null) {
229                sb.AppendFormat("  {0}\n", line.strip());
230            }
231            return sb.ToString();
232        }
233
234        internal static void showwarning(CodeContext context, object message, PythonType category, string filename, int lineno, [DefaultParameterValue(null)]object file, [DefaultParameterValue(null)]string line) {
235            string text = formatwarning(message, category, filename, lineno, line);
236
237            try {
238                if (file == null) {
239                    PythonContext pContext = PythonContext.GetContext(context);
240                    PythonFile stderr = pContext.GetSystemStateValue("stderr") as PythonFile;
241                    if (stderr != null) {
242                        stderr.write(text);
243                    } else {
244                        // use CLR stderr if python's is unavailable
245                        Console.Error.Write(text);
246                    }
247                } else {
248                    if (file is PythonFile) {
249                        ((PythonFile)file).write(text);
250                    } else if (file is TextWriter) {
251                        ((TextWriter)file).Write(text);
252                    } // unrecognized file type - warning is lost
253                }
254            } catch (IOException) {
255                // invalid file - warning is lost
256            }
257        }
258
259
260        #endregion
261    }
262}