PluginManager/PluginManager.py

changeset 3113
2780e230f129
parent 3112
9485059ea9fa
child 3114
7942a890a4fc
equal deleted inserted replaced
3112:9485059ea9fa 3113:2780e230f129
10 import os 10 import os
11 import sys 11 import sys
12 import imp 12 import imp
13 import zipfile 13 import zipfile
14 14
15 from PyQt4.QtCore import pyqtSignal, QObject, QDate, QFile, QUrl, QIODevice 15 from PyQt4.QtCore import pyqtSignal, QObject, QDate, QFile, QFileInfo, QUrl, \
16 QIODevice
16 from PyQt4.QtGui import QPixmap 17 from PyQt4.QtGui import QPixmap
17 from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, \ 18 from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest, \
18 QNetworkReply 19 QNetworkReply
19 20
20 from E5Gui import E5MessageBox 21 from E5Gui import E5MessageBox
188 189
189 if Preferences.getPluginManager("ActivateExternal"): 190 if Preferences.getPluginManager("ActivateExternal"):
190 fname = os.path.join(self.pluginDirs["user"], "__init__.py") 191 fname = os.path.join(self.pluginDirs["user"], "__init__.py")
191 if not os.path.exists(fname): 192 if not os.path.exists(fname):
192 if not os.path.exists(self.pluginDirs["user"]): 193 if not os.path.exists(self.pluginDirs["user"]):
193 os.mkdir(self.pluginDirs["user"], 0o755) 194 os.mkdir(self.pluginDirs["user"], 0o755)
194 try: 195 try:
195 f = open(fname, "w") 196 f = open(fname, "w")
196 f.close() 197 f.close()
197 except IOError: 198 except IOError:
198 del self.pluginDirs["user"] 199 del self.pluginDirs["user"]
361 except Exception as err: 362 except Exception as err:
362 module = imp.new_module(name) 363 module = imp.new_module(name)
363 module.error = self.trUtf8( 364 module.error = self.trUtf8(
364 "Module failed to load. Error: {0}").format(str(err)) 365 "Module failed to load. Error: {0}").format(str(err))
365 self.__failedModules[name] = module 366 self.__failedModules[name] = module
366 print("Error loading plugin module:", name) 367 print("Error loading plugin module:", name)
367 print(str(err)) 368 print(str(err))
368 369
369 def unloadPlugin(self, name): 370 def unloadPlugin(self, name):
370 """ 371 """
371 Public method to unload a plugin module. 372 Public method to unload a plugin module.
680 (boolean), short description (string), error flag (boolean) 681 (boolean), short description (string), error flag (boolean)
681 """ 682 """
682 infos = [] 683 infos = []
683 684
684 for name in list(self.__activeModules.keys()): 685 for name in list(self.__activeModules.keys()):
685 pname, shortDesc, error, version = \ 686 pname, shortDesc, error, version = \
686 self.__getShortInfo(self.__activeModules[name]) 687 self.__getShortInfo(self.__activeModules[name])
687 infos.append((name, pname, version, True, True, shortDesc, error)) 688 infos.append((name, pname, version, True, True, shortDesc, error))
688 for name in list(self.__inactiveModules.keys()): 689 for name in list(self.__inactiveModules.keys()):
689 pname, shortDesc, error, version = \ 690 pname, shortDesc, error, version = \
690 self.__getShortInfo(self.__inactiveModules[name]) 691 self.__getShortInfo(self.__inactiveModules[name])
691 infos.append( 692 infos.append(
692 (name, pname, version, True, False, shortDesc, error)) 693 (name, pname, version, True, False, shortDesc, error))
693 for name in list(self.__onDemandActiveModules.keys()): 694 for name in list(self.__onDemandActiveModules.keys()):
694 pname, shortDesc, error, version = \ 695 pname, shortDesc, error, version = \
695 self.__getShortInfo(self.__onDemandActiveModules[name]) 696 self.__getShortInfo(self.__onDemandActiveModules[name])
696 infos.append( 697 infos.append(
697 (name, pname, version, False, True, shortDesc, error)) 698 (name, pname, version, False, True, shortDesc, error))
698 for name in list(self.__onDemandInactiveModules.keys()): 699 for name in list(self.__onDemandInactiveModules.keys()):
699 pname, shortDesc, error, version = \ 700 pname, shortDesc, error, version = \
700 self.__getShortInfo(self.__onDemandInactiveModules[name]) 701 self.__getShortInfo(self.__onDemandInactiveModules[name])
701 infos.append( 702 infos.append(
702 (name, pname, version, False, False, shortDesc, error)) 703 (name, pname, version, False, False, shortDesc, error))
703 for name in list(self.__failedModules.keys()): 704 for name in list(self.__failedModules.keys()):
704 pname, shortDesc, error, version = \ 705 pname, shortDesc, error, version = \
705 self.__getShortInfo(self.__failedModules[name]) 706 self.__getShortInfo(self.__failedModules[name])
706 infos.append( 707 infos.append(
707 (name, pname, version, False, False, shortDesc, error)) 708 (name, pname, version, False, False, shortDesc, error))
708 return infos 709 return infos
709 710
710 def __getShortInfo(self, module): 711 def __getShortInfo(self, module):
711 """ 712 """
712 Private method to extract the short info from a module. 713 Private method to extract the short info from a module.
1048 """ 1049 """
1049 period = Preferences.getPluginManager("UpdatesCheckInterval") 1050 period = Preferences.getPluginManager("UpdatesCheckInterval")
1050 if period == 0: 1051 if period == 0:
1051 return 1052 return
1052 elif period in [2, 3, 4]: 1053 elif period in [2, 3, 4]:
1053 lastCheck = Preferences.Prefs.settings.value( 1054 lastModified = QFileInfo(self.pluginRepositoryFile).lastModified()
1054 "PluginUpdates/LastCheckDate", QDate(1970, 1, 1)) 1055 if lastModified.isValid() and lastModified.date().isValid():
1055 if lastCheck.isValid(): 1056 lastModifiedDate = lastModified.date()
1056 now = QDate.currentDate() 1057 now = QDate.currentDate()
1057 if period == 2 and lastCheck.day() == now.day(): 1058 if period == 2 and lastModifiedDate.day() == now.day():
1058 # daily 1059 # daily
1059 return 1060 return
1060 elif period == 3 and lastCheck.daysTo(now) < 7: 1061 elif period == 3 and lastModifiedDate.daysTo(now) < 7:
1061 # weekly 1062 # weekly
1062 return 1063 return
1063 elif period == 4 and lastCheck.month() == now.month(): 1064 elif period == 4 and lastModifiedDate.month() == now.month():
1064 # monthly 1065 # monthly
1065 return 1066 return
1066 1067
1067 self.__updateAvailable = False 1068 self.__updateAvailable = False
1068 1069
1069 request = QNetworkRequest( 1070 request = QNetworkRequest(
1070 QUrl(Preferences.getUI("PluginRepositoryUrl5"))) 1071 QUrl(Preferences.getUI("PluginRepositoryUrl5")))
1071 request.setAttribute(QNetworkRequest.CacheLoadControlAttribute, 1072 request.setAttribute(QNetworkRequest.CacheLoadControlAttribute,
1072 QNetworkRequest.AlwaysNetwork) 1073 QNetworkRequest.AlwaysNetwork)
1073 reply = self.__networkManager.get(request) 1074 reply = self.__networkManager.get(request)
1074 reply.finished[()].connect(self.__downloadFileDone) 1075 reply.finished[()].connect(self.__downloadRepositoryFileDone)
1075 reply.downloadProgress.connect(self.__downloadRepositoryFileDone)
1076 self.__replies.append(reply) 1076 self.__replies.append(reply)
1077 1077
1078 def __downloadRepositoryFileDone(self): 1078 def __downloadRepositoryFileDone(self):
1079 """ 1079 """
1080 Private method called after the repository file was downloaded. 1080 Private method called after the repository file was downloaded.
1103 ioDevice.rename(self.pluginRepositoryFile) 1103 ioDevice.rename(self.pluginRepositoryFile)
1104 1104
1105 if os.path.exists(self.pluginRepositoryFile): 1105 if os.path.exists(self.pluginRepositoryFile):
1106 f = QFile(self.pluginRepositoryFile) 1106 f = QFile(self.pluginRepositoryFile)
1107 if f.open(QIODevice.ReadOnly): 1107 if f.open(QIODevice.ReadOnly):
1108 # save current URL
1109 url = Preferences.getUI("PluginRepositoryUrl5")
1110
1111 # read the repository file
1108 from E5XML.PluginRepositoryReader import PluginRepositoryReader 1112 from E5XML.PluginRepositoryReader import PluginRepositoryReader
1109 reader = PluginRepositoryReader(f, self) 1113 reader = PluginRepositoryReader(f, self.checkPluginEntry)
1110 reader.readXML() 1114 reader.readXML()
1111 url = Preferences.getUI("PluginRepositoryUrl5") 1115 if url != Preferences.getUI("PluginRepositoryUrl5"):
1112 if url != self.repositoryUrlEdit.text(): 1116 # redo if it is a redirect
1113 self.checkPluginUpdatesAvailable() 1117 self.checkPluginUpdatesAvailable()
1114 return 1118 return
1115 Preferences.Prefs.settings.setValue(
1116 "Updates/LastCheckDate", QDate.currentDate())
1117 1119
1118 if self.__updateAvailable: 1120 if self.__updateAvailable:
1119 E5MessageBox.information( 1121 E5MessageBox.information(
1120 None, 1122 None,
1121 self.trUtf8("New plugin versions available"), 1123 self.trUtf8("New plugin versions available"),
1122 self.trUtf8("<p>There are new plugins or plugin" 1124 self.trUtf8("<p>There are new plug-ins or plug-in"
1123 " updates available. Use the plugin" 1125 " updates available. Use the plug-in"
1124 " repository dialog to get them.</p>") 1126 " repository dialog to get them.</p>")
1125 ) 1127 )
1126 1128
1127 def addEntry(self, name, short, description, url, author, version, 1129 def checkPluginEntry(self, name, short, description, url, author, version,
1128 filename, status): 1130 filename, status):
1129 """ 1131 """
1130 Public method to add an entry to the list. 1132 Public method to check a plug-in's data for an update.
1131 1133
1132 @param name data for the name field (string) 1134 @param name data for the name field (string)
1133 @param short data for the short field (string) 1135 @param short data for the short field (string)
1134 @param description data for the description field (list of strings) 1136 @param description data for the description field (list of strings)
1135 @param url data for the url field (string) 1137 @param url data for the url field (string)
1138 @param filename data for the filename field (string) 1140 @param filename data for the filename field (string)
1139 @param status status of the plugin (string [stable, unstable, unknown]) 1141 @param status status of the plugin (string [stable, unstable, unknown])
1140 """ 1142 """
1141 archive = os.path.join(Preferences.getPluginManager("DownloadPath"), 1143 archive = os.path.join(Preferences.getPluginManager("DownloadPath"),
1142 filename) 1144 filename)
1143 1145
1146 # TODO: change logic for installed only check to check against loaded plugins
1147
1144 # check, if the archive exists 1148 # check, if the archive exists
1145 if not os.path.exists(archive) and \ 1149 if not os.path.exists(archive):
1146 not Preferences.getPluginManager("CheckInstalledOnly"): 1150 if not Preferences.getPluginManager("CheckInstalledOnly"):
1147 self.__updateAvailable = True 1151 self.__updateAvailable = True
1148 return 1152 return
1149 1153
1150 # check, if the archive is a valid zip file 1154 # check, if the archive is a valid zip file
1151 if not zipfile.is_zipfile(archive) and \ 1155 if not zipfile.is_zipfile(archive):
1152 not Preferences.getPluginManager("CheckInstalledOnly"): 1156 if not Preferences.getPluginManager("CheckInstalledOnly"):
1153 self.__updateAvailable = True 1157 self.__updateAvailable = True
1154 return 1158 return
1155 1159
1156 zip = zipfile.ZipFile(archive, "r") 1160 zip = zipfile.ZipFile(archive, "r")
1157 try: 1161 try:
1158 aversion = zip.read("VERSION").decode("utf-8") 1162 aversion = zip.read("VERSION").decode("utf-8")
1171 @param errors list of SSL errors (list of QSslError) 1175 @param errors list of SSL errors (list of QSslError)
1172 """ 1176 """
1173 ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0] 1177 ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0]
1174 if ignored == E5SslErrorHandler.NotIgnored: 1178 if ignored == E5SslErrorHandler.NotIgnored:
1175 self.__downloadCancelled = True 1179 self.__downloadCancelled = True
1176
1177 # TODO: test this stuff
1178 # TODO: update the config page

eric ide

mercurial