119
# FIXME note always emits utf-8, regardless of the terminal encoding
121
113
# FIXME: clearing the ui and then going through the abstract logging
122
114
# framework is whack; we should probably have a logging Handler that
123
115
# deals with terminal output if needed.
130
122
_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
125
def show_error(*args, **kwargs):
152
126
"""Show an error message to the user.
309
283
start_time = osutils.format_local_date(_bzr_log_start_time,
310
284
timezone='local')
311
# create encoded wrapper around stderr
312
285
bzr_log_file = _open_bzr_log()
313
286
if bzr_log_file is not None:
314
287
bzr_log_file.write(start_time.encode('utf-8') + '\n')
317
290
r'%Y-%m-%d %H:%M:%S')
318
291
# after hooking output into bzr_log, we also need to attach a stderr
319
292
# 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)
293
stderr_handler = EncodedStreamHandler(sys.stderr,
294
osutils.get_terminal_encoding(), 'replace', level=logging.INFO)
325
295
logging.getLogger('bzr').addHandler(stderr_handler)
337
307
global _trace_file
338
308
# make a new handler
339
new_handler = logging.StreamHandler(to_file)
340
new_handler.setLevel(logging.DEBUG)
309
new_handler = EncodedStreamHandler(to_file, "utf-8", level=logging.DEBUG)
341
310
if log_format is None:
342
311
log_format = '%(levelname)8s %(message)s'
343
312
new_handler.setFormatter(logging.Formatter(log_format, date_format))
514
483
print_exception(exc_info, err_file)
515
484
return errors.EXIT_ERROR
516
485
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):
486
if isinstance(exc_object, KeyboardInterrupt):
522
487
err_file.write("bzr: interrupted\n")
523
488
return errors.EXIT_ERROR
524
489
elif isinstance(exc_object, MemoryError):
536
501
elif not getattr(exc_object, 'internal_error', True):
537
502
report_user_error(exc_info, err_file)
538
503
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"):
504
elif osutils.is_environment_error(exc_object):
505
if getattr(exc_object, 'errno', None) == errno.EPIPE:
506
err_file.write("bzr: broken pipe\n")
507
return errors.EXIT_ERROR
542
508
# Might be nice to catch all of these and show them as something more
543
509
# specific, but there are too many cases at the moment.
544
510
report_user_error(exc_info, err_file)
597
567
_trace_file.flush()
570
class EncodedStreamHandler(logging.Handler):
571
"""Robustly write logging events to a stream using the specified encoding
573
Messages are expected to be formatted to unicode, but UTF-8 byte strings
574
are also accepted. An error during formatting or a str message in another
575
encoding will be quitely noted as an error in the Bazaar log file.
577
The stream is not closed so sys.stdout or sys.stderr may be passed.
580
def __init__(self, stream, encoding=None, errors='strict', level=0):
581
logging.Handler.__init__(self, level)
584
encoding = getattr(stream, "encoding", "ascii")
585
self.encoding = encoding
589
flush = getattr(self.stream, "flush", None)
590
if flush is not None:
593
def emit(self, record):
595
line = self.format(record)
596
if not isinstance(line, unicode):
597
line = line.decode("utf-8")
598
self.stream.write(line.encode(self.encoding, self.errors) + "\n")
600
log_exception_quietly()
601
# Try saving the details that would have been logged in some form
602
msg = args = "<Unformattable>"
604
msg = repr(record.msg).encode("ascii")
605
args = repr(record.args).encode("ascii")
608
# Using mutter() bypasses the logging module and writes directly
609
# to the file so there's no danger of getting into a loop here.
610
mutter("Logging record unformattable: %s %% %s", msg, args)
600
613
class Config(object):
601
614
"""Configuration of message tracing in bzrlib.