"""
FtpCube
Copyright (C) Michael Gilfix
This file is part of FtpCube.
You should have received a file COPYING containing license terms
along with this program; if not, write to Michael Gilfix
(mgilfix@eecs.tufts.edu) for a copy.
This version of FtpCube is open source; you can redistribute it and/or
modify it under the terms listed in the file COPYING.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
"""
import wx
import events
import messages
import utils
import threading
import time
class Logger:
"""Base logger type.
Provides an interface for all logger implementations."""
LOCAL = 'local'
REMOTE = 'remote'
ERROR = 'error'
def __init__(self):
pass
def log(self, kind, msg):
"""Logs a message of the specified kind.
A message is a printable string and should be converted to its
a translatable unicode string prior to logging."""
raise NotImplementedError
class ConsoleLogger(Logger):
"""Logger for the main window console."""
def __init__(self):
Logger.__init__(self)
def log(self, kind, msg):
"""Logs a message to the main window console.
Accepted kinds are: 'local', 'remote', or 'error'."""
event = events.ConsoleEvent(kind, msg)
registry = events.getEventRegistry()
registry.postEvent(event)
class FileLogger(Logger):
"""File logger.
This logger can be used to log FTP command sessions to a file.
This implementation is thread safe in that multiple threads may
attempt to log messages through this logger simultaneously. As
such, messages written to the logger should be as self-contained
to avoid mixed ordering within the logs."""
def __init__(self, *args):
"""Initializes the file logger to write to the a variable
list of supplied filenames."""
Logger.__init__(self)
self.format = {
'local' : _("LOCAL > %s\n"),
'remote' : _("REMOTE > %s\n"),
'error' : _("! - %s\n"),
}
# Allow for multi-threaded access
self.file_lock = threading.Lock()
self.logs = [ ]
try:
for file in args:
self.logs.append(open(file, 'a'))
except IOError, strerror:
self.closeAll()
raise IOError, strerror
self.printMark()
def __del__(self):
"""Closes all files when this object is being destroyed."""
self.closeAll()
def printMark(self):
"""Writes a mark to indicate that the file log is being opened.
A mark is written each time the log is opened, regardless of
whether new content is written to the log."""
self.file_lock.acquire()
try:
for log in self.logs:
log.write(_("\n---------- MARK %s ----------\n\n") %time.asctime())
log.flush()
finally:
self.file_lock.release()
def log(self, kind, msg):
"""Logs a message to all open log files.
Accepted kinds are: 'local', 'remote', or 'error'."""
if not self.format.has_key(kind):
raise ValueError, _("Attempted to log with invalid kind: %(kind)s") %{ 'kind' : kind }
text = self.format[kind] %msg
self._log(text)
def log(self, msg):
"""Logs a simple text message to all open log files."""
self._log(msg)
def _log(self, text):
"""Performs the actual write to all log files."""
self.file_lock.acquire()
try:
for log in self.logs:
try:
log.write(text)
log.flush()
except IOError, strerror:
main_window = utils.getMainWindow()
messages.displayErrorDialog(main_window,
_("Error writing to file log: %(err)s") %{ 'err' : strerror })
finally:
self.file_lock.release()
def closeAll(self):
"""Closes all open log files."""
for log in self.logs:
try:
log.close()
except:
pass
self.logs = [ ]
class FileAndConsoleLogger(ConsoleLogger, FileLogger):
"""File and main window console logger class.
Each log message is written to both sources."""
def __init__(self, *args):
ConsoleLogger.__init__(self)
FileLogger.__init__(self, *args)
def log(self, kind, msg):
"""Logs a message to the main window console and all open log files.
Accepted kinds are: 'local', 'remote', or 'error'."""
ConsoleLogger.log(self, kind, msg)
FileLogger.log(self, kind, msg)
|