48
from __future__ import absolute_import
48
50
# FIXME: Unfortunately it turns out that python's logging module
49
51
# is quite expensive, even when the message is not printed by any handlers.
50
52
# We should perhaps change back to just simply doing it here.
119
# FIXME note always emits utf-8, regardless of the terminal encoding
121
115
# FIXME: clearing the ui and then going through the abstract logging
122
116
# framework is whack; we should probably have a logging Handler that
123
117
# deals with terminal output if needed.
130
124
_bzr_logger.warning(*args, **kwargs)
133
@deprecated_function(deprecated_in((2, 1, 0)))
134
def info(*args, **kwargs):
135
"""Deprecated: use trace.note instead."""
136
note(*args, **kwargs)
139
@deprecated_function(deprecated_in((2, 1, 0)))
140
def log_error(*args, **kwargs):
141
"""Deprecated: use bzrlib.trace.show_error instead"""
142
_bzr_logger.error(*args, **kwargs)
145
@deprecated_function(deprecated_in((2, 1, 0)))
146
def error(*args, **kwargs):
147
"""Deprecated: use bzrlib.trace.show_error instead"""
148
_bzr_logger.error(*args, **kwargs)
151
127
def show_error(*args, **kwargs):
152
128
"""Show an error message to the user.
309
285
start_time = osutils.format_local_date(_bzr_log_start_time,
310
286
timezone='local')
311
# create encoded wrapper around stderr
312
287
bzr_log_file = _open_bzr_log()
313
288
if bzr_log_file is not None:
314
289
bzr_log_file.write(start_time.encode('utf-8') + '\n')
317
292
r'%Y-%m-%d %H:%M:%S')
318
293
# after hooking output into bzr_log, we also need to attach a stderr
319
294
# handler, writing only at level info and with encoding
320
term_encoding = osutils.get_terminal_encoding()
321
writer_factory = codecs.getwriter(term_encoding)
322
encoded_stderr = writer_factory(sys.stderr, errors='replace')
323
stderr_handler = logging.StreamHandler(encoded_stderr)
324
stderr_handler.setLevel(logging.INFO)
295
stderr_handler = EncodedStreamHandler(sys.stderr,
296
osutils.get_terminal_encoding(), 'replace', level=logging.INFO)
325
297
logging.getLogger('bzr').addHandler(stderr_handler)
337
309
global _trace_file
338
310
# make a new handler
339
new_handler = logging.StreamHandler(to_file)
340
new_handler.setLevel(logging.DEBUG)
311
new_handler = EncodedStreamHandler(to_file, "utf-8", level=logging.DEBUG)
341
312
if log_format is None:
342
313
log_format = '%(levelname)8s %(message)s'
343
314
new_handler.setFormatter(logging.Formatter(log_format, date_format))
514
485
print_exception(exc_info, err_file)
515
486
return errors.EXIT_ERROR
516
487
exc_type, exc_object, exc_tb = exc_info
517
if (isinstance(exc_object, IOError)
518
and getattr(exc_object, 'errno', None) == errno.EPIPE):
519
err_file.write("bzr: broken pipe\n")
520
return errors.EXIT_ERROR
521
elif isinstance(exc_object, KeyboardInterrupt):
488
if isinstance(exc_object, KeyboardInterrupt):
522
489
err_file.write("bzr: interrupted\n")
523
490
return errors.EXIT_ERROR
524
491
elif isinstance(exc_object, MemoryError):
536
503
elif not getattr(exc_object, 'internal_error', True):
537
504
report_user_error(exc_info, err_file)
538
505
return errors.EXIT_ERROR
539
elif isinstance(exc_object, (OSError, IOError)) or (
540
# GZ 2010-05-20: Like (exc_type is pywintypes.error) but avoid import
541
exc_type.__name__ == "error" and exc_type.__module__ == "pywintypes"):
506
elif osutils.is_environment_error(exc_object):
507
if getattr(exc_object, 'errno', None) == errno.EPIPE:
508
err_file.write("bzr: broken pipe\n")
509
return errors.EXIT_ERROR
542
510
# Might be nice to catch all of these and show them as something more
543
511
# specific, but there are too many cases at the moment.
544
512
report_user_error(exc_info, err_file)
597
569
_trace_file.flush()
572
class EncodedStreamHandler(logging.Handler):
573
"""Robustly write logging events to a stream using the specified encoding
575
Messages are expected to be formatted to unicode, but UTF-8 byte strings
576
are also accepted. An error during formatting or a str message in another
577
encoding will be quitely noted as an error in the Bazaar log file.
579
The stream is not closed so sys.stdout or sys.stderr may be passed.
582
def __init__(self, stream, encoding=None, errors='strict', level=0):
583
logging.Handler.__init__(self, level)
586
encoding = getattr(stream, "encoding", "ascii")
587
self.encoding = encoding
591
flush = getattr(self.stream, "flush", None)
592
if flush is not None:
595
def emit(self, record):
597
line = self.format(record)
598
if not isinstance(line, unicode):
599
line = line.decode("utf-8")
600
self.stream.write(line.encode(self.encoding, self.errors) + "\n")
602
log_exception_quietly()
603
# Try saving the details that would have been logged in some form
604
msg = args = "<Unformattable>"
606
msg = repr(record.msg).encode("ascii")
607
args = repr(record.args).encode("ascii")
610
# Using mutter() bypasses the logging module and writes directly
611
# to the file so there's no danger of getting into a loop here.
612
mutter("Logging record unformattable: %s %% %s", msg, args)
600
615
class Config(object):
601
616
"""Configuration of message tracing in bzrlib.