40 This file is generated automatically based `stderr_replacement.py` while `debug_tools` 41 library/package is being developed. 43 If you developing the `debug_tools` library, please do not edit this file, but the file 44 `stderr_replacement.py` and run `logger.py` function `create_stdout_handler()` by 45 uncommenting it on `all/debug_tools/logger.py` file. 53 from logging
import StreamHandler
65 In case of reloading this module, never recapture the current `sys.stdout`. 67 When disabling this with unlock, it will only restore the standard behavior of the `stdout` 68 stream. However, the attached logger will cannot be detached never because someone else can 69 have a reference to its older version. This is why this is a global singleton which can 72 How do I duplicate sys.stdout to a log file in python? 73 https://stackoverflow.com/questions/616645/how-do-i-duplicate-sys-stdout-to-a-log-file-in-python 75 How to redirect stdout and stdout to logger in Python 76 https://stackoverflow.com/questions/19425736/how-to-redirect-stdout-and-stdout-to-logger-in-python 78 Set a Read-Only Attribute in Python? 79 https://stackoverflow.com/questions/24497316/set-a-read-only-attribute-in-python 86 Attach this singleton logger to the `sys.stdout` permanently. 88 global _stdout_singleton
89 global _stdout_default
90 global _stdout_default_class_type
94 if not sys.__stdout__:
95 sys.__stdout__ = sys.stdout
99 _stdout_default_class_type
103 _stdout_default = sys.stdout
105 _stdout_default_class_type = type( _stdout_default )
111 _stdout_write = _stdout_default.write
113 logger_call = logger._log_clean
114 clean_formatter = logger.clean_formatter
116 global _sys_stdout_write
117 global _sys_stdout_write_hidden
119 if sys.version_info <= (3,2):
121 def customEmit(self, record):
124 https://stackoverflow.com/questions/12699645/how-can-i-suppress-newline-in-python-logging-module 126 If a formatter is specified, it is used to format the record. 127 The record is then written to the stream with a trailing newline. If 128 exception information is present, it is formatted using 129 traceback.print_exception and appended to the stream. If the stream 130 has an 'encoding' attribute, it is used to determine how to do the 131 output to the stream. 134 msg = self.format(record)
138 stream.write(fs % (msg, self.terminator))
141 if (isinstance(msg, unicode)
and 142 getattr(stream,
'encoding',
None)):
145 stream.write(ufs % (msg, self.terminator))
146 except UnicodeEncodeError:
153 stream.write((ufs % (msg, self.terminator)).encode(stream.encoding))
155 stream.write(fs % (msg, self.terminator))
157 stream.write(fs % (msg.encode(
"UTF-8"), self.terminator))
159 except (KeyboardInterrupt, SystemExit):
162 self.handleError(record)
164 logging.StreamHandler.terminator =
'\n' 165 setattr(StreamHandler, StreamHandler.emit.__name__, customEmit)
168 def _sys_stdout_write_hidden(msg, *args, **kwargs):
170 Suppress newline in Python logging module 171 https://stackoverflow.com/questions/7168790/suppress-newline-in-python-logging-module 176 _stdout_write( msg, *args, **kwargs )
178 formatter = file.formatter
179 terminator = file.terminator
181 file.formatter = clean_formatter
184 kwargs[
'extra'] = {
'_duplicated_from_file':
True }
185 logger_call( msg, args, kwargs )
187 file.formatter = formatter
188 file.terminator = terminator
191 logger.exception(
"Could not write to the file: %s(%s)", file, logger )
200 def _sys_stdout_write(*args, **kwargs):
202 Hides the actual function pointer. This allow the external function pointer to 203 be cached while the internal written can be exchanged between the standard 204 `sys.stdout.write` and our custom wrapper around it. 206 _sys_stdout_write_hidden( *args, **kwargs )
219 class stdout_replament_hidden(_stdout_default_class_type):
221 Which special methods bypasses __getattribute__ in Python? 222 https://stackoverflow.com/questions/12872695/which-special-methods-bypasses-getattribute-in-python 225 if hasattr( _stdout_default,
"__abstractmethods__" ):
226 __abstractmethods__ = _stdout_default.__abstractmethods__
228 if hasattr( _stdout_default,
"__base__" ):
229 __base__ = _stdout_default.__base__
231 if hasattr( _stdout_default,
"__bases__" ):
232 __bases__ = _stdout_default.__bases__
234 if hasattr( _stdout_default,
"__basicsize__" ):
235 __basicsize__ = _stdout_default.__basicsize__
237 if hasattr( _stdout_default,
"__call__" ):
238 __call__ = _stdout_default.__call__
240 if hasattr( _stdout_default,
"__class__" ):
241 __class__ = _stdout_default.__class__
243 if hasattr( _stdout_default,
"__delattr__" ):
244 __delattr__ = _stdout_default.__delattr__
246 if hasattr( _stdout_default,
"__dict__" ):
247 __dict__ = _stdout_default.__dict__
249 if hasattr( _stdout_default,
"__dictoffset__" ):
250 __dictoffset__ = _stdout_default.__dictoffset__
252 if hasattr( _stdout_default,
"__dir__" ):
253 __dir__ = _stdout_default.__dir__
255 if hasattr( _stdout_default,
"__doc__" ):
256 __doc__ = _stdout_default.__doc__
258 if hasattr( _stdout_default,
"__eq__" ):
259 __eq__ = _stdout_default.__eq__
261 if hasattr( _stdout_default,
"__flags__" ):
262 __flags__ = _stdout_default.__flags__
264 if hasattr( _stdout_default,
"__format__" ):
265 __format__ = _stdout_default.__format__
267 if hasattr( _stdout_default,
"__ge__" ):
268 __ge__ = _stdout_default.__ge__
270 if hasattr( _stdout_default,
"__getattribute__" ):
271 __getattribute__ = _stdout_default.__getattribute__
273 if hasattr( _stdout_default,
"__gt__" ):
274 __gt__ = _stdout_default.__gt__
276 if hasattr( _stdout_default,
"__hash__" ):
277 __hash__ = _stdout_default.__hash__
279 if hasattr( _stdout_default,
"__init__" ):
280 __init__ = _stdout_default.__init__
282 if hasattr( _stdout_default,
"__init_subclass__" ):
283 __init_subclass__ = _stdout_default.__init_subclass__
285 if hasattr( _stdout_default,
"__instancecheck__" ):
286 __instancecheck__ = _stdout_default.__instancecheck__
288 if hasattr( _stdout_default,
"__itemsize__" ):
289 __itemsize__ = _stdout_default.__itemsize__
291 if hasattr( _stdout_default,
"__le__" ):
292 __le__ = _stdout_default.__le__
294 if hasattr( _stdout_default,
"__lt__" ):
295 __lt__ = _stdout_default.__lt__
297 if hasattr( _stdout_default,
"__module__" ):
298 __module__ = _stdout_default.__module__
300 if hasattr( _stdout_default,
"__mro__" ):
301 __mro__ = _stdout_default.__mro__
303 if hasattr( _stdout_default,
"__name__" ):
304 __name__ = _stdout_default.__name__
306 if hasattr( _stdout_default,
"__ne__" ):
307 __ne__ = _stdout_default.__ne__
309 if hasattr( _stdout_default,
"__new__" ):
310 __new__ = _stdout_default.__new__
312 if hasattr( _stdout_default,
"__prepare__" ):
313 __prepare__ = _stdout_default.__prepare__
315 if hasattr( _stdout_default,
"__qualname__" ):
316 __qualname__ = _stdout_default.__qualname__
318 if hasattr( _stdout_default,
"__reduce__" ):
319 __reduce__ = _stdout_default.__reduce__
321 if hasattr( _stdout_default,
"__reduce_ex__" ):
322 __reduce_ex__ = _stdout_default.__reduce_ex__
324 if hasattr( _stdout_default,
"__repr__" ):
325 __repr__ = _stdout_default.__repr__
327 if hasattr( _stdout_default,
"__setattr__" ):
328 __setattr__ = _stdout_default.__setattr__
330 if hasattr( _stdout_default,
"__sizeof__" ):
331 __sizeof__ = _stdout_default.__sizeof__
333 if hasattr( _stdout_default,
"__str__" ):
334 __str__ = _stdout_default.__str__
336 if hasattr( _stdout_default,
"__subclasscheck__" ):
337 __subclasscheck__ = _stdout_default.__subclasscheck__
339 if hasattr( _stdout_default,
"__subclasses__" ):
340 __subclasses__ = _stdout_default.__subclasses__
342 if hasattr( _stdout_default,
"__subclasshook__" ):
343 __subclasshook__ = _stdout_default.__subclasshook__
345 if hasattr( _stdout_default,
"__text_signature__" ):
346 __text_signature__ = _stdout_default.__text_signature__
348 if hasattr( _stdout_default,
"__weakrefoffset__" ):
349 __weakrefoffset__ = _stdout_default.__weakrefoffset__
351 if hasattr( _stdout_default,
"mro" ):
352 mro = _stdout_default.mro
356 Override any super class `type( _stdout_default )` constructor, so we can 357 instantiate any kind of `sys.stdout` replacement object, in case it was 358 already replaced by something else like on Sublime Text with `_LogWriter()`. 360 Assures all attributes were statically replaced just above. This should happen in case 361 some new attribute is added to the python language. 363 This also ignores the only two methods which are not equal, `__init__()` and `__getattribute__()`. 365 different_methods = (
"__init__",
"__class__",
"__getattribute__")
366 attributes_to_check = set( dir( object ) + dir( type ) )
368 for attribute
in attributes_to_check:
370 if attribute
not in different_methods \
371 and hasattr( _stdout_default, attribute ):
373 base_class_attribute = super( _stdout_default_class_type, self ).__getattribute__( attribute )
374 target_class_attribute = _stdout_default.__getattribute__( attribute )
376 if base_class_attribute != target_class_attribute:
377 sys.stdout.write(
" The base class attribute `%s` is different from the target class:\n%s\n%s\n\n" % ( attribute, base_class_attribute, target_class_attribute ) )
379 def __getattribute__(self, item):
383 return _sys_stdout_write
386 return _stdout_default.__getattribute__( item )
388 except AttributeError:
389 return super( _stdout_default_class_type, _stdout_default ).__getattribute__( item )
395 _stdout_singleton = stdout_replament_hidden()
399 sys.stdout = _stdout_singleton
411 Detach this `stdout` writer from `sys.stdout` and allow the next call to `lock()` create 412 a new writer for the stdout. 416 global _sys_stdout_write_hidden
420 _sys_stdout_write_hidden = _stdout_default.write