root/branch/QuickScan/umit/plugin/Engine.py @ 4946

Revision 4946, 8.9 kB (checked in by cassiano, 4 years ago)

Merged revisions 4909,4930-4932,4934-4935 via svnmerge from
http://svn.umitproject.org/svnroot/umit/trunk

................

r4909 | nopper | 2009-06-22 11:55:24 -0300 (Mon, 22 Jun 2009) | 21 lines


Merged revisions 4781-4783,4908 via svnmerge from
http://svn.umitproject.org/svnroot/umit/branch/UmitPlugins


........

r4781 | nopper | 2009-05-08 21:26:32 +0200 (ven, 08 mag 2009) | 1 line


Switching to new schema see UmitPlugins.xsd in PM branch. Switched also from xml.minidom to sax to speed up things.

........

r4782 | nopper | 2009-05-09 16:11:38 +0200 (sab, 09 mag 2009) | 1 line


Switched update process to new xml schema file.

........

r4783 | nopper | 2009-05-09 17:02:06 +0200 (sab, 09 mag 2009) | 1 line


Updating documentation to the new schema

........

r4908 | nopper | 2009-06-22 16:43:59 +0200 (lun, 22 giu 2009) | 1 line


Fixing a typo

........

................

r4930 | luis | 2009-06-27 11:33:59 -0300 (Sat, 27 Jun 2009) | 1 line


Fixing #334 - import error when umit is installed from package

................

r4931 | luis | 2009-06-27 22:38:54 -0300 (Sat, 27 Jun 2009) | 1 line


Fixed #331 - Permission denied writing umit config file

................

r4932 | luis | 2009-06-27 23:09:05 -0300 (Sat, 27 Jun 2009) | 1 line


Typo in Flow Analyzer plugin

................

r4934 | luis | 2009-06-27 23:30:31 -0300 (Sat, 27 Jun 2009) | 3 lines


Initialized merge tracking via "svnmerge" with revisions "1-4699" from
http://svn.umitproject.org/svnroot/umit/branch/radialnet

................

r4935 | ignotus | 2009-06-27 23:54:28 -0300 (Sat, 27 Jun 2009) | 3 lines


Fix accents problem in header.

................

Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# Copyright (C) 2008 Adriano Monteiro Marques
4#
5# Author: Francesco Piccinno <stack.box@gmail.com>
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
21import os
22import os.path
23
24from umit.plugin.Core import Core
25from umit.plugin.Atoms import Singleton
26from umit.plugin.Tree import PluginsTree, PluginException
27from umit.plugin.Containers import PluginReader, BadPlugin
28
29from umit.core.Paths import Path
30from umit.core.UmitConf import Plugins
31from umit.core.UmitLogging import log
32
33class Plugin(object):
34    """
35    Plugin base class
36    """
37    def start(self, reader):
38        "This is the main for your plugin (reader could be None if testing)"
39        pass
40
41    def stop(self):
42        "This is the exit point of you plugin"
43        pass
44
45class PluginPath(object):
46    """
47    a PluginPath object mantains a dict of Plugins contained in a dir
48
49    >>> p = PluginPath("/blah")
50    >>> p.get_plugins()
51    {}
52    """
53
54    def __init__(self, path):
55        """
56        The default constructor
57
58        @param path the path to search in for plugin
59        """
60        self.path = path
61        self.scanned = False
62        self._plugins = {} # a dict should be great ;)
63
64    def scan_path(self):
65        """
66        Walk the path passed in the constructor for .ump files,
67        then save the found plugins on a dict that could be accesed with get_plugins()
68
69        No recursive scan, only top-level directory is considerated.
70        """
71
72        if self.scanned or not os.path.exists(self.path):
73            return
74
75        for file in os.listdir(self.path):
76            path = os.path.join(self.path, file)
77
78            if file.endswith(".ump") and \
79               os.path.isfile(path):
80
81                try:
82                    reader = PluginReader(path)
83                except BadPlugin, exp:
84                    log.info("%s" % exp)
85                    continue
86
87                self._plugins[file] = reader
88
89        self.scanned = True
90
91    def reset(self):
92        "Reset the PluginPath object"
93
94        self.scanned = False
95        self._plugins = {}
96
97    def get_plugins(self):
98        """
99        Start the scan_path if it's not already started and then return a dict
100        containing the usable plugins.
101
102        @return a dict like
103            key   => file.ump
104            value => PluginReader()
105        """
106        self.scan_path()
107        return self._plugins
108
109    def __repr__(self):
110        return "Path: %s" % self.path
111
112    plugins = property(get_plugins)
113
114class PluginEngine(Singleton):
115    """
116    Plugin Engine class
117    """
118
119    def __init__(self):
120        """
121        Initialize the engine with the paths were plugins are located
122
123        @type paths tuple
124        @param paths a tuple containing various directory where the plugins are located
125        """
126
127        log.debug(">>> Initializing Plugin Engine")
128
129        # Initialize our objects
130        self.plugins = Plugins()
131        self.tree = PluginsTree()
132        self.core = Core()
133
134        self.avaiable_plugins = None
135        self.paths = None
136
137        self.apply_updates()
138        self.recache()
139
140    def apply_updates(self):
141        """
142        Check the downloaded plugins and move to the proper location
143        """
144
145        log.debug("Path.config_dir placed under %s" % Path.config_dir)
146
147        dest_dir = os.path.join(Path.config_dir, 'plugins')
148        temp_dir = os.path.join(Path.config_dir, 'plugins-temp')
149        down_dir = os.path.join(Path.config_dir, 'plugins-download')
150
151        for file in os.listdir(temp_dir):
152            try:
153                os.remove(file)
154            except Exception:
155                continue
156
157        for file in os.listdir(down_dir):
158            path = os.path.join(down_dir, file)
159
160            try:
161                if not '.ump' in file:
162                    os.remove(path)
163                    continue
164
165                fullname = file[:file.index('.ump') + 4]
166                dst_name = os.path.join(dest_dir, fullname)
167
168                if os.path.exists(dst_name):
169                    os.remove(dst_name)
170
171                log.debug("Installing new plugin from update: %s" % dst_name)
172
173                os.rename(path, dst_name)
174
175            except Exception, err:
176                log.debug("Error in appply_updates(): %s" % err)
177                continue
178
179    def recache(self):
180        """
181        Reinit the avaiable_plugins and paths fields
182        """
183
184        self.avaiable_plugins = []
185        self.paths = {}
186
187        idx = 0
188        for path in self.plugins.paths:
189            plug_path = PluginPath(path)
190            self.paths[path] = (idx, plug_path)
191
192            self.avaiable_plugins.extend(
193                [v for k, v in plug_path.plugins.items()]
194            )
195
196            idx += 1
197
198    def load_selected_plugins(self):
199        """
200        Load the selected plugins specified in config file
201        """
202
203        # Load the plugins in order (specified in conf file)
204        for plugin in self.plugins.plugins:
205
206            if not plugin or plugin == "":
207                continue
208
209            loaded, errmsg = self.load_plugin_from_path(plugin)
210
211            if not loaded:
212                log.warning(errmsg)
213
214        if os.environ.get('UMIT_DEVELOPMENT', False):
215            plugins = os.getenv('UMIT_PLUGINS', '')
216
217            if not plugins:
218                return
219
220            for plugin in plugins.split(os.pathsep):
221                self.load_from_directory(plugin)
222
223    def load_from_directory(self, path):
224        log.debug("Loading source files from plugin directory: %s" % path)
225        self.tree.load_directory(path)
226
227    def load_plugin_from_path(self, plugin, force=False):
228        """
229        Load a plugin from a full path
230
231        @param force True to not check plugin deps
232
233        @return (True, None) if is ok OR
234                (False, errmsg) if something went wrong
235        """
236
237        try:
238            log.debug("Loading plugin %s" % plugin)
239
240            path = os.path.dirname(plugin)
241            file = os.path.basename(plugin)
242
243            if not path in self.paths:
244                # Not in path so we could remove from the list
245
246                if plugin in self.plugins.plugins:
247                    tmp = self.plugins.plugins
248                    tmp.remove(plugin)
249                    self.plugins.plugins = tmp
250
251                return (False, "Plugin not in path (%s)" % plugin)
252
253            d = self.paths[path][1].get_plugins()
254
255            if file not in d:
256                return (False, "Plugin does not exists anymore (%s)" % plugin)
257
258            self.tree.load_plugin(d[file], force)
259
260            # Setting enabled field for PluginReader to
261            # mark a clean startup
262            d[file].enabled = True
263
264            # Save the changes
265            path = d[file].get_path()
266            lst = self.plugins.plugins
267
268            if not path in lst:
269                log.debug(">>> Appending plugin to conf file")
270                lst.append(path)
271
272                self.plugins.plugins = lst
273
274            return (True, None)
275
276        # return the exception class
277        except PluginException, err:
278            return (False, err)
279
280    #
281    # Used by PluginWindow
282    #
283
284    def load_plugin(self, reader, force=False):
285        """
286        Load a plugin
287
288        @param reader a PluginReader
289        @param force True to not check depends
290        """
291        return self.load_plugin_from_path(reader.get_path(), force)
292
293    def unload_plugin(self, reader, force=False):
294        """
295        Unload a plugin
296
297        @param reader a PluginReader
298        @param force True to force unload phase
299        """
300        try:
301            self.tree.unload_plugin(reader, force)
302
303            path = reader.get_path()
304            lst  = self.plugins.plugins
305
306            if path in lst:
307                log.debug(">>> Removing plugin from autoload")
308                lst.remove(path)
309
310                self.plugins.plugins = lst
311
312            return (True, None)
313        except PluginException, err:
314            return (False, err)
315
316    def uninstall_plugin(self, reader):
317        """
318        Low level uninstall procedure
319
320        @param reader a PluginReader
321        @return True if ok or False
322        """
323
324        try:
325            os.remove(reader.get_path())
326            self.recache()
327            return True
328        except Exception, err:
329            log.warning("Error in uninstall_plugin(): %s" % err)
330            return False
Note: See TracBrowser for help on using the browser.