AssistantEric/APIsManager.py

branch
eric7
changeset 180
89ff060ef0d9
parent 177
25cb41783971
child 186
c228779ea15d
equal deleted inserted replaced
179:62d9dc4eedd5 180:89ff060ef0d9
8 """ 8 """
9 9
10 import contextlib 10 import contextlib
11 import os 11 import os
12 12
13 from PyQt5.QtCore import ( 13 from PyQt6.QtCore import (
14 QTimer, QThread, QFileInfo, pyqtSignal, QDateTime, QObject, Qt 14 QTimer, QThread, QFileInfo, pyqtSignal, QDateTime, QObject, Qt
15 ) 15 )
16 with contextlib.suppress(ImportError): 16 with contextlib.suppress(ImportError):
17 from PyQt5.QtSql import QSqlDatabase, QSqlQuery 17 from PyQt6.QtSql import QSqlDatabase, QSqlQuery
18 18
19 from E5Gui.E5Application import e5App 19 from EricWidgets.EricApplication import ericApp
20 20
21 import QScintilla.Lexers 21 import QScintilla.Lexers
22 22
23 import Globals 23 import Globals
24 import Utilities.ModuleParser 24 import Utilities.ModuleParser
132 132
133 def __autoCompletionWordSeparators(self, language): 133 def __autoCompletionWordSeparators(self, language):
134 """ 134 """
135 Private method to get the word separator characters for a language. 135 Private method to get the word separator characters for a language.
136 136
137 @param language language of the APIs object (string) 137 @param language language of the APIs object
138 @return word separator characters (list of strings) 138 @type str
139 @return word separator characters
140 @rtype list of str
139 """ 141 """
140 if language: 142 if language:
141 return self.__wseps.get(language, None) 143 return self.__wseps.get(language, None)
142 else: 144 else:
143 return self.__proxy.autoCompletionWordSeparators() 145 return self.__proxy.autoCompletionWordSeparators()
151 def __loadApiFileIfNewer(self, apiFile): 153 def __loadApiFileIfNewer(self, apiFile):
152 """ 154 """
153 Private method to load an API file, if it is newer than the one read 155 Private method to load an API file, if it is newer than the one read
154 into the database. 156 into the database.
155 157
156 @param apiFile filename of the raw API file (string) 158 @param apiFile filename of the raw API file
159 @type str
157 """ 160 """
158 db = QSqlDatabase.database(self.__connectionName) 161 db = QSqlDatabase.database(self.__connectionName)
159 db.transaction() 162 db.transaction()
160 try: 163 try:
161 query = QSqlQuery(db) 164 query = QSqlQuery(db)
190 193
191 def __classesAttributesApi(self, module): 194 def __classesAttributesApi(self, module):
192 """ 195 """
193 Private method to generate class api section for class attributes. 196 Private method to generate class api section for class attributes.
194 197
195 @param module module object to get the info from (Module) 198 @param module module object to get the info from
196 @return API information (list of strings) 199 @type Module
200 @return API information
201 @rtype list of str
197 """ 202 """
198 api = [] 203 api = []
199 modulePath = module.name.split('.') 204 modulePath = module.name.split('.')
200 moduleName = "{0}.".format('.'.join(modulePath)) 205 moduleName = "{0}.".format('.'.join(modulePath))
201 206
217 222
218 def __loadApiFile(self, apiFile): 223 def __loadApiFile(self, apiFile):
219 """ 224 """
220 Private method to read a raw API file into the database. 225 Private method to read a raw API file into the database.
221 226
222 @param apiFile filename of the raw API file (string) 227 @param apiFile filename of the raw API file
228 @type str
223 """ 229 """
224 apis = [] 230 apis = []
225 bases = [] 231 bases = []
226 232
227 if self.__language == ApisNameProject: 233 if self.__language == ApisNameProject:
269 Private method to store file info only. 275 Private method to store file info only.
270 276
271 Doing this avoids rereading the file whenever the API is initialized 277 Doing this avoids rereading the file whenever the API is initialized
272 in case the given file doesn't contain API data. 278 in case the given file doesn't contain API data.
273 279
274 @param apiFile file name of the API file (string) 280 @param apiFile file name of the API file
281 @type str
275 """ 282 """
276 db = QSqlDatabase.database(self.__connectionName) 283 db = QSqlDatabase.database(self.__connectionName)
277 db.transaction() 284 db.transaction()
278 try: 285 try:
279 query = QSqlQuery(db) 286 query = QSqlQuery(db)
297 304
298 def __storeApis(self, apis, bases, apiFile, language): 305 def __storeApis(self, apis, bases, apiFile, language):
299 """ 306 """
300 Private method to put the API entries into the database. 307 Private method to put the API entries into the database.
301 308
302 @param apis list of api entries (list of strings) 309 @param apis list of api entries
303 @param bases list of base class entries (list of strings) 310 @type list of str
304 @param apiFile filename of the file read to get the APIs (string) 311 @param bases list of base class entries
305 @param language programming language of the file of the APIs (string) 312 @type list of str
313 @param apiFile filename of the file read to get the APIs
314 @type str
315 @param language programming language of the file of the APIs
316 @type str
306 """ 317 """
307 wseps = self.__autoCompletionWordSeparators(language) 318 wseps = self.__autoCompletionWordSeparators(language)
308 if wseps is None: 319 if wseps is None:
309 return 320 return
310 321
427 438
428 def __deleteApiFile(self, apiFile): 439 def __deleteApiFile(self, apiFile):
429 """ 440 """
430 Private method to delete all references to an api file. 441 Private method to delete all references to an api file.
431 442
432 @param apiFile filename of the raw API file (string) 443 @param apiFile filename of the raw API file
444 @type str
433 """ 445 """
434 db = QSqlDatabase.database(self.__connectionName) 446 db = QSqlDatabase.database(self.__connectionName)
435 db.transaction() 447 db.transaction()
436 try: 448 try:
437 query = QSqlQuery(db) 449 query = QSqlQuery(db)
668 """ 680 """
669 Private method to initialize as a project API object. 681 Private method to initialize as a project API object.
670 """ 682 """
671 self.__lexer = None 683 self.__lexer = None
672 684
673 self.__project = e5App().getObject("Project") 685 self.__project = ericApp().getObject("Project")
674 self.__project.projectOpened.connect(self.__projectOpened) 686 self.__project.projectOpened.connect(self.__projectOpened)
675 self.__project.newProject.connect(self.__projectOpened) 687 self.__project.newProject.connect(self.__projectOpened)
676 self.__project.projectClosed.connect(self.__projectClosed) 688 self.__project.projectClosed.connect(self.__projectClosed)
677 self.__project.projectFormCompiled.connect(self.__projectFormCompiled) 689 self.__project.projectFormCompiled.connect(self.__projectFormCompiled)
678 self.__project.projectChanged.connect(self.__projectChanged) 690 self.__project.projectChanged.connect(self.__projectChanged)
701 713
702 def _apiDbName(self): 714 def _apiDbName(self):
703 """ 715 """
704 Protected method to determine the name of the database file. 716 Protected method to determine the name of the database file.
705 717
706 @return name of the database file (string) 718 @return name of the database file
719 @rtype str
707 """ 720 """
708 if self.__language == ApisNameProject: 721 if self.__language == ApisNameProject:
709 return os.path.join(self.__project.getProjectManagementDir(), 722 return os.path.join(self.__project.getProjectManagementDir(),
710 "project-apis.db") 723 "project-apis.db")
711 else: 724 else:
745 758
746 def __openApiDb(self): 759 def __openApiDb(self):
747 """ 760 """
748 Private method to open the API database. 761 Private method to open the API database.
749 762
750 @return flag indicating the database status (boolean) 763 @return flag indicating the database status
764 @rtype bool
751 """ 765 """
752 db = QSqlDatabase.database(self.__connectionName, False) 766 db = QSqlDatabase.database(self.__connectionName, False)
753 if not db.isValid(): 767 if not db.isValid():
754 # the database connection is a new one 768 # the database connection is a new one
755 db = QSqlDatabase.addDatabase("QSQLITE", self.__connectionName) 769 db = QSqlDatabase.addDatabase("QSQLITE", self.__connectionName)
806 820
807 def getApiFiles(self): 821 def getApiFiles(self):
808 """ 822 """
809 Public method to get a list of API files loaded into the database. 823 Public method to get a list of API files loaded into the database.
810 824
811 @return list of API filenames (list of strings) 825 @return list of API filenames
826 @rtype list of str
812 """ 827 """
813 apiFiles = [] 828 apiFiles = []
814 829
815 db = QSqlDatabase.database(self.__connectionName) 830 db = QSqlDatabase.database(self.__connectionName)
816 db.transaction() 831 db.transaction()
828 843
829 def __isPrepared(self): 844 def __isPrepared(self):
830 """ 845 """
831 Private method to check, if the database has been prepared. 846 Private method to check, if the database has been prepared.
832 847
833 @return flag indicating the prepared status (boolean) 848 @return flag indicating the prepared status
849 @rtype bool
834 """ 850 """
835 db = QSqlDatabase.database(self.__connectionName) 851 db = QSqlDatabase.database(self.__connectionName)
836 prepared = len(db.tables()) > 0 852 prepared = len(db.tables()) > 0
837 if prepared: 853 if prepared:
838 db.transaction() 854 db.transaction()
853 869
854 def getCompletions(self, start=None, context=None, followHierarchy=False): 870 def getCompletions(self, start=None, context=None, followHierarchy=False):
855 """ 871 """
856 Public method to determine the possible completions. 872 Public method to determine the possible completions.
857 873
858 @keyparam start string giving the start of the word to be 874 @param start string giving the start of the word to be
859 completed (string) 875 completed
860 @keyparam context string giving the context (e.g. classname) 876 @type str
861 to be completed (string) 877 @param context string giving the context (e.g. classname)
862 @keyparam followHierarchy flag indicating to follow the hierarchy of 878 to be completed
863 base classes (boolean) 879 @type str
880 @param followHierarchy flag indicating to follow the hierarchy of
881 base classes
882 @type bool
864 @return list of dictionaries with possible completions 883 @return list of dictionaries with possible completions
865 (key 'completion' contains the completion (string), 884 (key 'completion' contains the completion,
866 key 'context' contains the context (string) and 885 key 'context' contains the context and
867 key 'pictureId' contains the ID of the icon to be shown (string)) 886 key 'pictureId' contains the ID of the icon to be shown)
887 @rtype list of dict
868 """ 888 """
869 completions = [] 889 completions = []
870 890
871 db = QSqlDatabase.database(self.__connectionName) 891 db = QSqlDatabase.database(self.__connectionName)
872 if db.isOpen() and not self.__inPreparation: 892 if db.isOpen() and not self.__inPreparation:
919 def getCalltips(self, acWord, commas, context=None, fullContext=None, 939 def getCalltips(self, acWord, commas, context=None, fullContext=None,
920 showContext=True, followHierarchy=False): 940 showContext=True, followHierarchy=False):
921 """ 941 """
922 Public method to determine the calltips. 942 Public method to determine the calltips.
923 943
924 @param acWord function to get calltips for (string) 944 @param acWord function to get calltips for
945 @type str
925 @param commas minimum number of commas contained in the calltip 946 @param commas minimum number of commas contained in the calltip
926 (integer) 947 @type int
927 @param context string giving the context (e.g. classname) (string) 948 @param context string giving the context (e.g. classname)
928 @param fullContext string giving the full context (string) 949 @type str
950 @param fullContext string giving the full context
951 @type str
929 @param showContext flag indicating to show the calltip context 952 @param showContext flag indicating to show the calltip context
930 (boolean) 953 @type bool
931 @keyparam followHierarchy flag indicating to follow the hierarchy of 954 @param followHierarchy flag indicating to follow the hierarchy of
932 base classes (boolean) 955 base classes
933 @return list of calltips (list of string) 956 @type bool
957 @return list of calltips
958 @rtype list of str
934 """ 959 """
935 calltips = [] 960 calltips = []
936 961
937 db = QSqlDatabase.database(self.__connectionName) 962 db = QSqlDatabase.database(self.__connectionName)
938 if db.isOpen() and not self.__inPreparation: 963 if db.isOpen() and not self.__inPreparation:
1002 def __enoughCommas(self, s, commas): 1027 def __enoughCommas(self, s, commas):
1003 """ 1028 """
1004 Private method to determine, if the given string contains enough 1029 Private method to determine, if the given string contains enough
1005 commas. 1030 commas.
1006 1031
1007 @param s string to check (string) 1032 @param s string to check
1008 @param commas number of commas to check for (integer) 1033 @type str
1009 @return flag indicating, that there are enough commas (boolean) 1034 @param commas number of commas to check for
1035 @type int
1036 @return flag indicating, that there are enough commas
1037 @rtype bool
1010 """ 1038 """
1011 end = s.find(')') 1039 end = s.find(')')
1012 1040
1013 if end < 0: 1041 if end < 0:
1014 return False 1042 return False
1030 1058
1031 def __getProjectFormSources(self, normalized=False): 1059 def __getProjectFormSources(self, normalized=False):
1032 """ 1060 """
1033 Private method to get the source files for the project forms. 1061 Private method to get the source files for the project forms.
1034 1062
1035 @keyparam normalized flag indicating a normalized filename is wanted 1063 @param normalized flag indicating a normalized filename is wanted
1036 (boolean) 1064 @type bool
1037 @return list of project form sources (list of strings) 1065 @return list of project form sources
1038 """ 1066 @rtype list of str
1039 if self.__project.getProjectLanguage() == "Python3": 1067 """
1068 if self.__project.getProjectLanguage() in (
1069 "Python3", "MicroPython", "Cython"
1070 ):
1040 sourceExt = ".py" 1071 sourceExt = ".py"
1041 elif self.__project.getProjectLanguage() == "Ruby": 1072 elif self.__project.getProjectLanguage() == "Ruby":
1042 sourceExt = ".rb" 1073 sourceExt = ".rb"
1043 else: 1074 else:
1044 return [] 1075 return []
1057 1088
1058 def prepareAPIs(self, rawList=None): 1089 def prepareAPIs(self, rawList=None):
1059 """ 1090 """
1060 Public method to prepare the APIs if neccessary. 1091 Public method to prepare the APIs if neccessary.
1061 1092
1062 @keyparam rawList list of raw API files (list of strings) 1093 @param rawList list of raw API files
1094 @type list of str
1063 """ 1095 """
1064 if self.__inPreparation: 1096 if self.__inPreparation:
1065 return 1097 return
1066 1098
1067 projectPath = "" 1099 projectPath = ""
1073 [f for f in self.__getProjectFormSources() if 1105 [f for f in self.__getProjectFormSources() if
1074 f not in apiFiles]) 1106 f not in apiFiles])
1075 projectPath = self.__project.getProjectPath() 1107 projectPath = self.__project.getProjectPath()
1076 projectType = "" 1108 projectType = ""
1077 else: 1109 else:
1078 try: 1110 apiFiles = Preferences.getEditorAPI(
1079 apiFiles = Preferences.getEditorAPI( 1111 self.__language, projectType=self.__projectType)
1080 self.__language, projectType=self.__projectType)
1081 except TypeError:
1082 # older interface
1083 apiFiles = Preferences.getEditorAPI(self.__language)
1084 projectType = self.__projectType 1112 projectType = self.__projectType
1085 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, 1113 self.__worker = DbAPIsWorker(self, self.__language, apiFiles,
1086 self._apiDbName(), projectPath, 1114 self._apiDbName(), projectPath,
1087 projectType=projectType) 1115 projectType=projectType)
1088 self.__worker.processing.connect( 1116 self.__worker.processing.connect(
1115 1143
1116 def getLexer(self): 1144 def getLexer(self):
1117 """ 1145 """
1118 Public method to return a reference to our lexer object. 1146 Public method to return a reference to our lexer object.
1119 1147
1120 @return reference to the lexer object (QScintilla.Lexers.Lexer) 1148 @return reference to the lexer object
1149 @rtype Lexer
1121 """ 1150 """
1122 return self.__lexer 1151 return self.__lexer
1123 1152
1124 def autoCompletionWordSeparators(self): 1153 def autoCompletionWordSeparators(self):
1125 """ 1154 """
1126 Public method to get the word separator characters. 1155 Public method to get the word separator characters.
1127 1156
1128 @return word separator characters (list of strings) 1157 @return word separator characters
1158 @rtype list of str
1129 """ 1159 """
1130 if self.__lexer: 1160 if self.__lexer:
1131 return self.__lexer.autoCompletionWordSeparators() 1161 return self.__lexer.autoCompletionWordSeparators()
1132 return None 1162 return None
1133 1163
1134 def __processingStatus(self, status, filename): 1164 def __processingStatus(self, status, filename):
1135 """ 1165 """
1136 Private slot handling the processing signal of the API preparation 1166 Private slot handling the processing signal of the API preparation
1137 thread. 1167 thread.
1138 1168
1139 @param status preparation status (integer, one of WorkerStatus...) 1169 @param status preparation status (one of WorkerStatus...)
1140 @param filename name of the file being processed (string) 1170 @type int
1171 @param filename name of the file being processed
1172 @type str
1141 """ 1173 """
1142 if status == WorkerStatusStarted: 1174 if status == WorkerStatusStarted:
1143 self.__inPreparation = True 1175 self.__inPreparation = True
1144 self.apiPreparationStatus.emit( 1176 self.apiPreparationStatus.emit(
1145 self.__language, WorkerStatusStarted, "") 1177 self.__language, WorkerStatusStarted, "")
1163 1195
1164 def __projectOpened(self): 1196 def __projectOpened(self):
1165 """ 1197 """
1166 Private slot to perform actions after a project has been opened. 1198 Private slot to perform actions after a project has been opened.
1167 """ 1199 """
1168 if self.__project.getProjectLanguage() == "Python3": 1200 if self.__project.getProjectLanguage() in (
1201 "Python3", "MicroPython", "Cython"
1202 ):
1169 self.__discardFirst = ["self", "cls"] 1203 self.__discardFirst = ["self", "cls"]
1170 else: 1204 else:
1171 self.__discardFirst = [] 1205 self.__discardFirst = []
1172 self.__lexer = QScintilla.Lexers.getLexer( 1206 self.__lexer = QScintilla.Lexers.getLexer(
1173 self.__project.getProjectLanguage()) 1207 self.__project.getProjectLanguage())
1181 1215
1182 def __projectFormCompiled(self, filename): 1216 def __projectFormCompiled(self, filename):
1183 """ 1217 """
1184 Private slot to handle the projectFormCompiled signal. 1218 Private slot to handle the projectFormCompiled signal.
1185 1219
1186 @param filename name of the form file that was compiled (string) 1220 @param filename name of the form file that was compiled
1221 @type str
1187 """ 1222 """
1188 self.__workerQueue.append(filename) 1223 self.__workerQueue.append(filename)
1189 self.__processQueue() 1224 self.__processQueue()
1190 1225
1191 def __projectChanged(self): 1226 def __projectChanged(self):
1198 1233
1199 def editorSaved(self, filename): 1234 def editorSaved(self, filename):
1200 """ 1235 """
1201 Public slot to handle the editorSaved signal. 1236 Public slot to handle the editorSaved signal.
1202 1237
1203 @param filename name of the file that was saved (string) 1238 @param filename name of the file that was saved
1239 @type str
1204 """ 1240 """
1205 if self.__project.isProjectSource(filename): 1241 if self.__project.isProjectSource(filename):
1206 self.__workerQueue.append(filename) 1242 self.__workerQueue.append(filename)
1207 self.__processQueue() 1243 self.__processQueue()
1208 1244
1214 """ 1250 """
1215 def __init__(self, mainWindow, parent=None): 1251 def __init__(self, mainWindow, parent=None):
1216 """ 1252 """
1217 Constructor 1253 Constructor
1218 1254
1219 @param mainWindow reference to the main eric6 window (QMainWindow) 1255 @param mainWindow reference to the main eric7 window
1220 @param parent reference to the parent object (QObject) 1256 @type QMainWindow
1257 @param parent reference to the parent object
1258 @type QObject
1221 """ 1259 """
1222 QObject.__init__(self, parent) 1260 QObject.__init__(self, parent)
1223 self.setObjectName("Assistant_APIsManager") 1261 self.setObjectName("Assistant_APIsManager")
1224 1262
1225 self.__mw = mainWindow 1263 self.__mw = mainWindow
1275 1313
1276 def __showMessage(self, msg): 1314 def __showMessage(self, msg):
1277 """ 1315 """
1278 Private message to show a message in the main windows status bar. 1316 Private message to show a message in the main windows status bar.
1279 1317
1280 @param msg message to be shown (string) 1318 @param msg message to be shown
1319 @type str
1281 """ 1320 """
1282 if msg: 1321 if msg:
1283 self.__mw.statusBar().showMessage(msg, 2000) 1322 self.__mw.statusBar().showMessage(msg, 2000)
1284 1323
1285 def __apiPreparationStatus(self, language, status, filename): 1324 def __apiPreparationStatus(self, language, status, filename):
1286 """ 1325 """
1287 Private slot handling the preparation status signal of an API object. 1326 Private slot handling the preparation status signal of an API object.
1288 1327
1289 @param language language of the API (string) 1328 @param language language of the API
1290 @param status preparation status (integer, one of WorkerStatus...) 1329 @type str
1291 @param filename name of the file being processed (string) 1330 @param status preparation status (one of WorkerStatus...)
1331 @type int
1332 @param filename name of the file being processed
1333 @type str
1292 """ 1334 """
1293 if language == ApisNameProject: 1335 if language == ApisNameProject:
1294 language = self.tr("Project") 1336 language = self.tr("Project")
1295 1337
1296 if status == WorkerStatusStarted: 1338 if status == WorkerStatusStarted:

eric ide

mercurial