Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/docutils/utils/error_reporting.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 #!/usr/bin/env python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # :Id: $Id: error_reporting.py 8367 2019-08-27 12:09:56Z milde $ | |
5 # :Copyright: © 2011 Günter Milde. | |
6 # :License: Released under the terms of the `2-Clause BSD license`_, in short: | |
7 # | |
8 # Copying and distribution of this file, with or without modification, | |
9 # are permitted in any medium without royalty provided the copyright | |
10 # notice and this notice are preserved. | |
11 # This file is offered as-is, without any warranty. | |
12 # | |
13 # .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause | |
14 | |
15 """ | |
16 Error reporting should be safe from encoding/decoding errors. | |
17 However, implicit conversions of strings and exceptions like | |
18 | |
19 >>> u'%s world: %s' % ('H\xe4llo', Exception(u'H\xe4llo') | |
20 | |
21 fail in some Python versions: | |
22 | |
23 * In Python <= 2.6, ``unicode(<exception instance>)`` uses | |
24 `__str__` and fails with non-ASCII chars in`unicode` arguments. | |
25 (work around http://bugs.python.org/issue2517): | |
26 | |
27 * In Python 2, unicode(<exception instance>) fails, with non-ASCII | |
28 chars in arguments. (Use case: in some locales, the errstr | |
29 argument of IOError contains non-ASCII chars.) | |
30 | |
31 * In Python 2, str(<exception instance>) fails, with non-ASCII chars | |
32 in `unicode` arguments. | |
33 | |
34 The `SafeString`, `ErrorString` and `ErrorOutput` classes handle | |
35 common exceptions. | |
36 """ | |
37 | |
38 import codecs | |
39 import sys | |
40 | |
41 # Guess the locale's encoding. | |
42 # If no valid guess can be made, locale_encoding is set to `None`: | |
43 try: | |
44 import locale # module missing in Jython | |
45 except ImportError: | |
46 locale_encoding = None | |
47 else: | |
48 try: | |
49 locale_encoding = locale.getlocale()[1] or locale.getdefaultlocale()[1] | |
50 # locale.getpreferredencoding([do_setlocale=True|False]) | |
51 # has side-effects | might return a wrong guess. | |
52 # (cf. Update 1 in http://stackoverflow.com/questions/4082645/using-python-2-xs-locale-module-to-format-numbers-and-currency) | |
53 except ValueError as error: # OS X may set UTF-8 without language code | |
54 # see http://bugs.python.org/issue18378 | |
55 # and https://sourceforge.net/p/docutils/bugs/298/ | |
56 if "unknown locale: UTF-8" in error.args: | |
57 locale_encoding = "UTF-8" | |
58 else: | |
59 locale_encoding = None | |
60 except: # any other problems determining the locale -> use None | |
61 locale_encoding = None | |
62 try: | |
63 codecs.lookup(locale_encoding or '') # None -> '' | |
64 except LookupError: | |
65 locale_encoding = None | |
66 | |
67 | |
68 if sys.version_info >= (3, 0): | |
69 unicode = str # noqa | |
70 | |
71 | |
72 class SafeString(object): | |
73 """ | |
74 A wrapper providing robust conversion to `str` and `unicode`. | |
75 """ | |
76 | |
77 def __init__(self, data, encoding=None, encoding_errors='backslashreplace', | |
78 decoding_errors='replace'): | |
79 self.data = data | |
80 self.encoding = (encoding or getattr(data, 'encoding', None) or | |
81 locale_encoding or 'ascii') | |
82 self.encoding_errors = encoding_errors | |
83 self.decoding_errors = decoding_errors | |
84 | |
85 | |
86 def __str__(self): | |
87 try: | |
88 return str(self.data) | |
89 except UnicodeEncodeError: | |
90 if isinstance(self.data, Exception): | |
91 args = [str(SafeString(arg, self.encoding, | |
92 self.encoding_errors)) | |
93 for arg in self.data.args] | |
94 return ', '.join(args) | |
95 if isinstance(self.data, unicode): | |
96 if sys.version_info > (3, 0): | |
97 return self.data | |
98 else: | |
99 return self.data.encode(self.encoding, | |
100 self.encoding_errors) | |
101 raise | |
102 | |
103 def __unicode__(self): | |
104 """ | |
105 Return unicode representation of `self.data`. | |
106 | |
107 Try ``unicode(self.data)``, catch `UnicodeError` and | |
108 | |
109 * if `self.data` is an Exception instance, work around | |
110 http://bugs.python.org/issue2517 with an emulation of | |
111 Exception.__unicode__, | |
112 | |
113 * else decode with `self.encoding` and `self.decoding_errors`. | |
114 """ | |
115 try: | |
116 u = unicode(self.data) | |
117 if isinstance(self.data, EnvironmentError): | |
118 u = u.replace(": u'", ": '") # normalize filename quoting | |
119 return u | |
120 except UnicodeError as error: # catch ..Encode.. and ..Decode.. errors | |
121 if isinstance(self.data, EnvironmentError): | |
122 return u"[Errno %s] %s: '%s'" % (self.data.errno, | |
123 SafeString(self.data.strerror, self.encoding, | |
124 self.decoding_errors), | |
125 SafeString(self.data.filename, self.encoding, | |
126 self.decoding_errors)) | |
127 if isinstance(self.data, Exception): | |
128 args = [unicode(SafeString(arg, self.encoding, | |
129 decoding_errors=self.decoding_errors)) | |
130 for arg in self.data.args] | |
131 return u', '.join(args) | |
132 if isinstance(error, UnicodeDecodeError): | |
133 return unicode(self.data, self.encoding, self.decoding_errors) | |
134 raise | |
135 | |
136 class ErrorString(SafeString): | |
137 """ | |
138 Safely report exception type and message. | |
139 """ | |
140 def __str__(self): | |
141 return '%s: %s' % (self.data.__class__.__name__, | |
142 super(ErrorString, self).__str__()) | |
143 | |
144 def __unicode__(self): | |
145 return u'%s: %s' % (self.data.__class__.__name__, | |
146 super(ErrorString, self).__unicode__()) | |
147 | |
148 | |
149 class ErrorOutput(object): | |
150 """ | |
151 Wrapper class for file-like error streams with | |
152 failsave de- and encoding of `str`, `bytes`, `unicode` and | |
153 `Exception` instances. | |
154 """ | |
155 | |
156 def __init__(self, stream=None, encoding=None, | |
157 encoding_errors='backslashreplace', | |
158 decoding_errors='replace'): | |
159 """ | |
160 :Parameters: | |
161 - `stream`: a file-like object, | |
162 a string (path to a file), | |
163 `None` (write to `sys.stderr`, default), or | |
164 evaluating to `False` (write() requests are ignored). | |
165 - `encoding`: `stream` text encoding. Guessed if None. | |
166 - `encoding_errors`: how to treat encoding errors. | |
167 """ | |
168 if stream is None: | |
169 stream = sys.stderr | |
170 elif not(stream): | |
171 stream = False | |
172 # if `stream` is a file name, open it | |
173 elif isinstance(stream, str): | |
174 stream = open(stream, 'w') | |
175 elif isinstance(stream, unicode): | |
176 stream = open(stream.encode(sys.getfilesystemencoding()), 'w') | |
177 | |
178 self.stream = stream | |
179 """Where warning output is sent.""" | |
180 | |
181 self.encoding = (encoding or getattr(stream, 'encoding', None) or | |
182 locale_encoding or 'ascii') | |
183 """The output character encoding.""" | |
184 | |
185 self.encoding_errors = encoding_errors | |
186 """Encoding error handler.""" | |
187 | |
188 self.decoding_errors = decoding_errors | |
189 """Decoding error handler.""" | |
190 | |
191 def write(self, data): | |
192 """ | |
193 Write `data` to self.stream. Ignore, if self.stream is False. | |
194 | |
195 `data` can be a `string`, `unicode`, or `Exception` instance. | |
196 """ | |
197 if self.stream is False: | |
198 return | |
199 if isinstance(data, Exception): | |
200 data = unicode(SafeString(data, self.encoding, | |
201 self.encoding_errors, self.decoding_errors)) | |
202 try: | |
203 self.stream.write(data) | |
204 except UnicodeEncodeError: | |
205 self.stream.write(data.encode(self.encoding, self.encoding_errors)) | |
206 except TypeError: | |
207 if isinstance(data, unicode): # passed stream may expect bytes | |
208 self.stream.write(data.encode(self.encoding, | |
209 self.encoding_errors)) | |
210 return | |
211 if self.stream in (sys.stderr, sys.stdout): | |
212 self.stream.buffer.write(data) # write bytes to raw stream | |
213 else: | |
214 self.stream.write(unicode(data, self.encoding, | |
215 self.decoding_errors)) | |
216 | |
217 def close(self): | |
218 """ | |
219 Close the error-output stream. | |
220 | |
221 Ignored if the stream is` sys.stderr` or `sys.stdout` or has no | |
222 close() method. | |
223 """ | |
224 if self.stream in (sys.stdout, sys.stderr): | |
225 return | |
226 try: | |
227 self.stream.close() | |
228 except AttributeError: | |
229 pass |