#!/usr/bin/python
#
# LC
#
# base class for the fingerprint plugin classes
#
import os
import FingerPrint
from FingerPrint.swirl import SwirlFile
"""This is the base class that implement the interface that all the plugins subclasses
should implement
"""
[docs]class PluginMount(type):
"""
this is a singleton object which can return a list of all available
plugins. All plugin available inside the FingerPrint.plugins are loaded
inside the PluginMount when this module is loaded.
Insipired by (or totaly copied from) Marty Alchin:
http://martyalchin.com/2008/jan/10/simple-plugin-framework/
"""
def __init__(cls, name, bases, attrs):
if not hasattr(cls, 'plugins'):
# This branch only executes when processing the mount point itself.
# So, since this is a new plugin type, not an implementation, this
# class shouldn't be registered as a plugin. Instead, it sets up a
# list where plugins can be registered later.
cls.plugins = {}
else:
# This must be a plugin implementation, which should be registered.
# we use a dictionary here for fast lookup during dependecy verification
cls.plugins[cls.pluginName] = cls
[docs] def get_plugins(cls):
"""
return the list of currently registered plugins
:rtype: list
:return: a list of :class:`PluginManager` registered
"""
return cls.plugins
[docs]class PluginManager(object):
"""
Super class of the various plugins. All plugins should inherit from
this class.
To implement a new Plugin you should subclass this class and provide the
following attributes/methods:
- :attr:`pluginName`: this must be a unique string representing the plugin name
- :meth:`getPathToLibrary`: a class method which return a file name pointing to the
file which can provide the given dependency
- :meth:`getSwirl`: a class method that given a path to a file it return None if the
file can not be handled by the given plugin or a SwirlFile
with the dependency set if the plugin can handle the file
"""
__metaclass__ = PluginMount
systemPath = []
"""list of string containing the paths we should look for dependencies"""
@classmethod
[docs] def addSystemPaths(self, paths):
"""
add an additional paths to the search for dependency
:type paths: list
:param paths: a list of string with the extra path to be added
"""
if paths :
self.systemPath += paths
@classmethod
[docs] def getSwirl(self, fileName, swirl, env = None):
"""
helper function given a filename it return a SwirlFile. This should be
re-implemented by the various plugins. If none of the plugins return
a SwirlFile this method will return a 'data' SwirlFile.
ATT: only one plugin should return a SwirlFile for a given file
ATT2: this is a class method
:type fileName: string
:param fileName: a path to the new file we want to add
:type swirl: :class:`FingerPrint.swirl.Swirl`
:param swirl: the current Swirl object. Static dependencies of the new
SwirlFile are resolved first inside the Swirl and if not
found then they are resolved recursively invoking this
function and recursively added to the Swirl
:type env: list
:param env: a list of string with all the environment variable
available to this file when it was executing. This field
is used only when doing dynamic tracing.
:rtype: :class:`FingerPrint.swirl.SwirlFile`
:return: a SwirlFile representing the given fileName. The SwirlFile
should have all the static dependencies resolved (if they
could be find on the system)
"""
# if the file does not exist anymore (possible with temporary file and
# dynamic tracing) just set it to Data
fileName = os.path.normpath(fileName)
if os.path.exists(fileName) and not \
FingerPrint.sergeant.is_special_folder(fileName):
#we call all the getSwirl method of all the plugin
for key, plugin in self.plugins.iteritems():
temp = plugin.getSwirl(fileName, swirl, env)
if temp != None:
return temp
#nobady claimed the file let's make it a Data file
swirlFile = swirl.createSwirlFile(fileName)
if os.path.isfile(fileName) and os.access(fileName, os.X_OK):
# TODO this should be in his own plugin class
f = open(fileName)
if f.read(2) == '#!':
swirlFile.executable = True
f.close()
return swirlFile
@classmethod
[docs] def getPathToLibrary(cls, dependency, useCache = True, rpath = []):
"""
Given a dependency it find the path of the library which provides
that dependency
:type dependency: :class:`FingerPrint.swirl.Dependency`
:param dependency: the Dependency that we need to satisfy with the
returned library
:type useCache: bool
:param useCache: if true it will use a cache that will speed up a
lot searching for libraries
:type rpath: list
:param rpath: a list of string which contains extra paths that
we want to add during the search for the dependency
Generally used to add RPATH to the search path.
:rtype: string
:return: the path to the library which satisfy the given dependency
"""
plugin = cls.plugins[dependency.type]
return plugin.getPathToLibrary(dependency, useCache, rpath)
#
# now let's import all the plugins aka all the .py file which are inside the
# plugins directory
#
import pkgutil
import os
import sys
import logging
logger = logging.getLogger('fingerprint')
if hasattr(pkgutil,'iter_modules'): #line added
for importer, package_name, _ in pkgutil.iter_modules(globals()["__path__"]):
full_package_name = 'FingerPrint.plugins.%s' % package_name
module = importer.find_module(package_name).load_module(full_package_name)
else:
# in python 2.4 pkgutil does not have a iter_modules function :-(
for pth in globals()["__path__"]:
for mod_path in sorted(os.listdir(pth)):
init_py = os.path.join(pth, mod_path)
if mod_path.endswith('.py') and mod_path != '__init__.py' \
and os.path.isfile(init_py):
nm = "FingerPrint.plugins.%s" % mod_path.split('.py')[0]
try:
__import__(nm)
except:
logger.error("Failed to import module %s" % nm)
pass