root/tags/release-0.6.2/lib/newplugin.py

Revision 1, 11.0 kB (checked in by mjoc, 2 years ago)

Initial import.

Line 
1 #
2 # OpenDict
3 # Copyright (c) 2005 Martynas Jocius <mjoc@akl.lt>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your opinion) any later version.
9 #
10 # This program is distributed in the hope that will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MECHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more detals.
14 #
15 # You shoud have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 # 02111-1307 USA
19 #
20
21 # TODO: rename to "dictplugin.py"
22
23 """
24 New plugin module
25 """
26
27 import os
28 import sys
29 import traceback
30 import xml.dom.minidom
31
32 from lib import info
33 from lib import meta
34 from lib.logger import systemLog, debugLog, DEBUG, INFO, WARNING, ERROR
35 from lib import util
36
37
38 class PluginInfo:
39     """Plugin information"""
40
41
42     def __init__(self, xmlData):
43         """Parse XML data and store it into class attributes"""
44
45         self.name = None
46         self.version = None
47         self.authors = []
48         self.module = {}
49         self.encoding = None
50         self.usesWordList = None
51         self.opendictVersion = None
52         self.pythonVersion = None
53         self.platforms = []
54         self.description = None
55         self.licenceFile = None
56
57         self.xmlData = xmlData
58         self._parse()
59
60    
61     def _parse(self):
62         """Parse plugin information XML data"""
63        
64         doc = xml.dom.minidom.parseString(self.xmlData)
65
66         pluginElement = doc.getElementsByTagName('plugin')[0]
67         pluginType = pluginElement.getAttribute('type')
68
69         if pluginType != 'dictionary':
70             raise Exception, "Plugin is not dictionary plugin"
71
72         # Get name
73         for nameElement in doc.getElementsByTagName('name'):
74             for node in nameElement.childNodes:
75                 if node.nodeType == node.TEXT_NODE:
76                     self.name = node.data
77
78         # Get version
79         for versionElement in doc.getElementsByTagName('version'):
80             for node in versionElement.childNodes:
81                 if node.nodeType == node.TEXT_NODE:
82                     self.version = node.data
83
84         # Get authors
85         for authorElement in doc.getElementsByTagName('author'):
86             authorName = authorElement.getAttribute('name')
87             authorEMail = authorElement.getAttribute('email')
88             self.authors.append({'name': authorName, 'email': authorEMail})
89
90         # Get module
91         for moduleElement in doc.getElementsByTagName('module'):
92             moduleName = None
93             for node in moduleElement.childNodes:
94                 if node.nodeType == node.TEXT_NODE:
95                     moduleName = node.data
96             moduleLang = moduleElement.getAttribute('lang')
97             self.module = {'name': moduleName, 'lang': moduleLang}
98
99         # Get encoding
100         for encodingElement in doc.getElementsByTagName('encoding'):
101             for node in encodingElement.childNodes:
102                 if node.nodeType == node.TEXT_NODE:
103                     self.encoding = node.data
104
105         # Get info about word list usage
106         for wordListElement in doc.getElementsByTagName('uses-word-list'):
107             for node in wordListElement.childNodes:
108                 if node.nodeType == node.TEXT_NODE:
109                     self.usesWordList = node.data.lower() == 'true'
110
111         # Get required OpenDict version
112         for odVersionElement in doc.getElementsByTagName('opendict-version'):
113             for node in odVersionElement.childNodes:
114                 if node.nodeType == node.TEXT_NODE:
115                     self.opendictVersion = node.data
116
117         # Get required Python version
118         for pyVersionElement in doc.getElementsByTagName('python-version'):
119             for node in pyVersionElement.childNodes:
120                 if node.nodeType == node.TEXT_NODE:
121                     self.pythonVersion = node.data
122
123         # Get supported platforms
124         for platformElement in doc.getElementsByTagName('platform'):
125             platformName = platformElement.getAttribute('name')
126             self.platforms.append({'name': platformName})
127         self.platforms.sort()
128
129         # Get description
130         for descElement in doc.getElementsByTagName('description'):
131             for node in descElement.childNodes:
132                 if node.nodeType == node.TEXT_NODE:
133                     self.description = node.data
134
135         # Get licence file
136         for licenceElement in doc.getElementsByTagName('licence'):
137             for node in licenceElement.childNodes:
138                 if node.nodeType == node.TEXT_NODE:
139                     self.licenceFile = node.data
140
141
142
143 class DictionaryPlugin(meta.Dictionary):
144     """Dictionary plugin handler"""
145
146     def __init__(self, path):
147         """Prepare plugin and plugin information objects"""
148
149         self.path = path
150
151         try:
152             self.info = self._loadInfo(path)
153         except Exception, e:
154             raise InvalidPluginException, e
155
156         try:
157             self.dictionary = self._loadPlugin(path)
158         except Exception, e:
159             raise InvalidPluginException, e
160
161
162     def getType(self):
163         """Return dictionary type"""
164
165         from lib import dicttype
166         return dicttype.PLUGIN
167
168
169     def getName(self):
170         """Return plugin name"""
171
172         return self.info.name
173
174
175     def setName(self, newName):
176         """Set plugin name"""
177
178         self.info.name = newName
179
180
181     def getPath(self):
182         """Return plugin location"""
183
184         return self.path
185
186
187     def getVersion(self):
188         """Return version"""
189
190         return self.info.version
191
192
193     def getAuthors(self):
194         """Return list of authors"""
195
196         return self.info.authors
197
198
199     def getModule(self):
200         """Return module info"""
201
202         return self.info.module
203
204
205     def getEncoding(self):
206         """Return encoding used by dictionary"""
207
208         return self.info.encoding
209    
210
211     def getUsesWordList(self):
212         """Return boolean value of word list usage"""
213
214         return self.info.usesWordList
215
216
217     def getOpendictVersion(self):
218         """Return required min OpenDict version"""
219
220         return self.info.opendictVersion
221
222
223     def getPythonVersion(self):
224         """Return required min Python version"""
225
226         return self.info.pythonVersion
227
228
229     def getPlatforms(self):
230         """Return supported platforms"""
231        
232         return self.info.platforms
233
234
235     def getDescription(self):
236         """Returns description text"""
237        
238         return self.info.description
239
240
241     def getLicence(self):
242         """Return licence text (HTML format required)"""
243
244         if self.info.licenceFile:
245             try:
246                 fd = open(os.path.join(self.getPath(), self.info.licenceFile))
247                 data = fd.read()
248                 fd.close()
249             except Exception, e:
250                 systemLog(ERROR, "Unable to read licence file: %s" % e)
251                 data = 'Error: <i>Licence file not found</i>'
252         else:
253             data = ''
254
255         return data
256        
257
258     def search(self, word):
259         """Lookup word"""
260
261         return self.dictionary.search(word)
262        
263
264     def _loadInfo(self, path):
265         """Load plugin information"""
266
267         try:
268             fd = open(os.path.join(path, "plugin.xml"))
269             xmlData = fd.read()
270             fd.close()
271
272             info = PluginInfo(xmlData)
273             return info
274         except Exception, e:
275             raise InvalidPluginException, \
276                   "Unable to load plugin info (%s)" % e
277    
278
279     def _loadPlugin(self, path):
280         """Load plugin"""
281
282         moduleName = os.path.splitext(self.info.module.get('name'))[0]
283         fullPath = os.path.join(path, moduleName)
284
285         try:
286            del sys.modules[moduleName]
287         except:
288            pass
289         sys.path.insert(0, path)
290         module =  __import__(moduleName)
291         sys.path.remove(path)
292
293         instance = module.init(info.GLOBAL_HOME)
294
295         return instance
296
297
298     # Usable?
299     def isValid(self):
300         """Validate plugin. Validates both plugin and plugin info objects"""
301
302         try:
303             assert hasattr(self.info, "name")
304             assert hasattr(self.info, "version")
305             assert hasattr(self.info, "authors")
306             assert hasattr(self.info, "module")
307             assert hasattr(self.info, "encoding")
308             assert hasattr(self.info, "usesWordList")
309             assert hasattr(self.info, "opendictVersion")
310             assert hasattr(self.info, "pythonVersion")
311             assert hasattr(self.info, "platforms")
312             assert hasattr(self.info, "description")
313            
314             assert hasattr(self.dictionary, "search")
315             assert callable(self.dictionary.search)
316            
317             return True
318         except:
319             return False
320
321
322 def _loadDictionaryPlugin(directory):
323     """Load dictionary plugin"""
324
325     plugin = None
326
327     try:
328         plugin = DictionaryPlugin(directory)
329         util.correctDictName(plugin)
330     except InvalidPluginException, e:
331         systemLog(ERROR, "Unable to load plugin from %s (%s)" % (directory, e))
332
333     return plugin
334
335
336 def loadDictionaryPlugins(dictionaries, invalidDictionaries):
337     """Load plugins. Returns list of PluginHandler objects"""
338
339     pluginDirs = []
340     globalPluginPath = os.path.join(info.GLOBAL_HOME,
341                                     info.__DICT_DIR,
342                                     info.__PLUGIN_DICT_DIR)
343     localPluginPath = os.path.join(info.LOCAL_HOME,
344                                    info.__DICT_DIR,
345                                    info.__PLUGIN_DICT_DIR)
346
347     if os.path.exists(localPluginPath):
348         pluginDirs = [os.path.join(localPluginPath, fileName) \
349                       for fileName in os.listdir(localPluginPath) \
350                       if os.path.isdir(os.path.join(localPluginPath,
351                                                     fileName))]
352
353     if os.path.exists(globalPluginPath):
354         for fileName in os.listdir(globalPluginPath):
355             if os.path.isdir(os.path.join(globalPluginPath, fileName)) \
356                and not fileName in pluginDirs:
357                 pluginDirs.append(os.path.join(globalPluginPath, fileName))
358
359     plugins = []
360
361     for dirName in pluginDirs:
362         #print dirName,
363         plugin = _loadDictionaryPlugin(dirName)
364         #print plugin
365         if plugin:
366             #nameList = _pluginNames(plugins)
367             #if plugin.getName() in nameList:
368             #    plugin.setName("%s (%d)" % (plugin.getName(),
369             #                                _nameMatches(plugin.getName(),
370             #                                             nameList)))
371             plugins.append(plugin)
372             dictionaries[plugin.getName()] = plugin
373         else:
374             invalidDictionaries.append(dirName)
375
376     return plugins
377
378
379
380 class InvalidPluginException(Exception):
381     """This exception should be raised if plugin has some errors"""
382    
383
384 if __name__ == "__main__":
385     loadPlugins()
386    
Note: See TracBrowser for help on using the browser.