aboutsummaryrefslogtreecommitdiffstats
path: root/lvc/windows/exelogging.py
diff options
context:
space:
mode:
Diffstat (limited to 'lvc/windows/exelogging.py')
-rw-r--r--lvc/windows/exelogging.py91
1 files changed, 91 insertions, 0 deletions
diff --git a/lvc/windows/exelogging.py b/lvc/windows/exelogging.py
new file mode 100644
index 0000000..a63c836
--- /dev/null
+++ b/lvc/windows/exelogging.py
@@ -0,0 +1,91 @@
+"""lvc.windows.exelogging -- handle logging inside an exe file
+
+Most of this is copied from the Miro code.
+"""
+
+import logging
+import os
+import sys
+import tempfile
+from StringIO import StringIO
+from logging.handlers import RotatingFileHandler
+
+class ApatheticRotatingFileHandler(RotatingFileHandler):
+ """The whole purpose of this class is to prevent rotation errors
+ from percolating up into stdout/stderr and popping up a dialog
+ that's not particularly useful to users or us.
+ """
+ def doRollover(self):
+ # If you shut down LibreVideoConverter then start it up again immediately
+ # afterwards, then we get in this squirrely situation where
+ # the log is opened by another process. We ignore the
+ # exception, but make sure we have an open file. (bug #11228)
+ try:
+ RotatingFileHandler.doRollover(self)
+ except WindowsError:
+ if not self.stream or self.stream.closed:
+ self.stream = open(self.baseFilename, "a")
+ try:
+ RotatingFileHandler.doRollover(self)
+ except WindowsError:
+ pass
+
+ def shouldRollover(self, record):
+ # if doRollover doesn't work, then we don't want to find
+ # ourselves in a situation where we're trying to do things on
+ # a closed stream.
+ if self.stream.closed:
+ self.stream = open(self.baseFilename, "a")
+ return RotatingFileHandler.shouldRollover(self, record)
+
+ def handleError(self, record):
+ # ignore logging errors that occur rather than printing them to
+ # stdout/stderr which isn't helpful to us
+
+ pass
+class AutoLoggingStream(StringIO):
+ """Create a stream that intercepts write calls and sends them to
+ the log.
+ """
+ def __init__(self, logging_callback, prefix):
+ StringIO.__init__(self)
+ # We init from StringIO to give us a bunch of stream-related
+ # methods, like closed() and read() automatically.
+ self.logging_callback = logging_callback
+ self.prefix = prefix
+
+ def write(self, data):
+ if isinstance(data, unicode):
+ data = data.encode('ascii', 'backslashreplace')
+ if data.endswith("\n"):
+ data = data[:-1]
+ if data:
+ self.logging_callback(self.prefix + data)
+
+FORMAT = "%(asctime)s %(levelname)-8s %(name)s: %(message)s"
+def setup_logging():
+ """Setup logging for when we're running inside a windows exe.
+
+ The object here is to avoid logging anything to stderr since
+ windows will consider that an error.
+
+ We also catch things written to sys.stdout and forward that to the logging
+ system.
+
+ Finally we also copy the log output to stdout so that when MVC is run in
+ console mode we see the logs
+ """
+
+ log_path = os.path.join(tempfile.gettempdir(), "MVC.log")
+ rotater = ApatheticRotatingFileHandler(
+ log_path, mode="a", maxBytes=100000, backupCount=5)
+
+ formatter = logging.Formatter(FORMAT)
+ rotater.setFormatter(formatter)
+ logger = logging.getLogger('')
+ logger.addHandler(rotater)
+ logger.addHandler(logging.StreamHandler(sys.stdout))
+ logger.setLevel(logging.INFO)
+ rotater.doRollover()
+ sys.stdout = AutoLoggingStream(logging.warn, '(from stdout) ')
+ sys.stderr = AutoLoggingStream(logging.error, '(from stderr) ')