+#
+# Backupninja python reimplementation, based on original backupninja program
+# by riseup.net.
+# Copyright (C) 2010 Matthijs Kooijman <matthijs@stdin.nl>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+""" Action superclass with common functionality """
+
+import sys
+import logging as log
+
+from backupninja import config
+
+class Action(object):
+ """
+ Subclasses of Action represent handlers for various action types.
+ This class is called Action instead of Handler, since even though the
+ classes could be referred to as handlers, the instances of this
+ class are really actions (i.e., it represents a specific action,
+ which is a combination of a action type and a specific action
+ configuration).
+ """
+ def __init__(self):
+ # Subclasses should overwrite this with their default config
+ # See backupninja.config.load_config for the structure of this
+ # value.
+ self.default_config = {}
+
+ def run(self, **kwargs):
+ """
+ Run this action for a single target. Override this method
+ in a subclass
+ """
+ pass
+
+ def finish(self, **kwargs):
+ """
+ Called when all targets have been processed. Can be overridden
+ in a subclass.
+ """
+ pass
+
+ def load_config(self, filename):
+ """
+ Load the configuration for this action from the given filename.
+ """
+ self.conf = config.load_config(filename, self.default_config)
+
+
+
+def create_action(ty):
+ """
+ Create a new (subclass of) Action object for an action with the
+ given type.
+
+ If the handler class for this type cannot be loaded, an exception is
+ thrown.
+ """
+ modname = 'backupninja.handlers.%s' % ty
+ # Load the handler if it is not loaded yet
+ if not modname in sys.modules:
+ log.debug('Loading handler for type "%s"', ty)
+ try:
+ __import__(modname, globals(), locals(), [])
+ except ImportError, e:
+ # Add some extra info, since the default exception does not
+ # show the full module name.
+ raise ImportError('Cannot load module %s: %s' % (modname, e))
+ log.debug('Loaded handler for type "%s" from "%s"', ty, sys.modules[modname].__file__)
+ # Get the module from the module table
+ module = sys.modules[modname]
+
+ # Check that the module has a "handler" top level function, which
+ # should create a new Action object.
+ if not hasattr(module, 'handler'):
+ raise ImportError('%s is not valid: it '
+ 'does not have a "handler" top level function.'
+ % (module.__file__))
+
+ # Call the "handler" function to create the actual action
+ action = module.handler()
+
+ # Check if the handler returned is really a subclass of Action
+ if not isinstance(action, Action):
+ raise TypeError('%s is not valid, %s.handler did not return a '
+ 'subclass of backupninja.handlers.Handler.'
+ % (module.__file__, modname))
+ return action