AssistantEric/APIsManager.py

changeset 143
468560828f55
parent 142
eac390ad0c2e
child 147
0b2e8ddacad7
equal deleted inserted replaced
142:eac390ad0c2e 143:468560828f55
75 SELECT id FROM file WHERE file = :file 75 SELECT id FROM file WHERE file = :file
76 """ 76 """
77 file_delete_id_stmt = """ 77 file_delete_id_stmt = """
78 DELETE FROM file WHERE id = :id 78 DELETE FROM file WHERE id = :id
79 """ 79 """
80 80
81 def __init__(self, proxy, language, apiFiles, projectPath="", 81 api_files_stmt = """
82 SELECT file FROM file
83 """
84
85 def __init__(self, proxy, language, apiFiles, dbName, projectPath="",
82 refresh=False, projectType=""): 86 refresh=False, projectType=""):
83 """ 87 """
84 Constructor 88 Constructor
85 89
86 @param proxy reference to the object that is proxied 90 @param proxy reference to the object that is proxied
87 @type DbAPIs 91 @type DbAPIs
88 @param language language of the APIs object 92 @param language language of the APIs object
89 @type str 93 @type str
90 @param apiFiles list of API files to process 94 @param apiFiles list of API files to process
91 @type list of str 95 @type list of str
96 @param dbName path name of the database file
97 @type str
92 @param projectPath path of the project. Only needed, if the APIs 98 @param projectPath path of the project. Only needed, if the APIs
93 are extracted out of the sources of a project. 99 are extracted out of the sources of a project.
94 @type str 100 @type str
95 @param refresh flag indicating a refresh of the APIs of one file 101 @param refresh flag indicating a refresh of the APIs of one file
96 @type bool 102 @type bool
116 self.__apiFiles = apiFiles[:] 122 self.__apiFiles = apiFiles[:]
117 self.__aborted = False 123 self.__aborted = False
118 self.__projectPath = projectPath 124 self.__projectPath = projectPath
119 self.__refresh = refresh 125 self.__refresh = refresh
120 126
127 self.__databaseName = dbName
128
121 if self.__projectType: 129 if self.__projectType:
130 self.__connectionName = "{0}_{1}_{2}".format(
131 self.__language, self.__projectType, id(self))
132 else:
122 self.__connectionName = "{0}_{1}".format( 133 self.__connectionName = "{0}_{1}".format(
123 self.__language, self.__projectType) 134 self.__language, id(self))
124 else:
125 self.__connectionName = self.__language
126 135
127 def __autoCompletionWordSeparators(self, language): 136 def __autoCompletionWordSeparators(self, language):
128 """ 137 """
129 Private method to get the word separator characters for a language. 138 Private method to get the word separator characters for a language.
130 139
131 @param language language of the APIs object (string) 140 @param language language of the APIs object (string)
132 @return word separator characters (list of strings) 141 @return word separator characters (list of strings)
133 """ 142 """
134 return self.__wseps.get(language, None) 143 if language:
144 return self.__wseps.get(language, None)
145 else:
146 return self.__proxy.autoCompletionWordSeparators()
135 147
136 def abort(self): 148 def abort(self):
137 """ 149 """
138 Public method to ask the thread to stop. 150 Public method to ask the thread to stop.
139 """ 151 """
155 query.exec_() 167 query.exec_()
156 if query.next() and query.isValid(): # __IGNORE_WARNING_M513__ 168 if query.next() and query.isValid(): # __IGNORE_WARNING_M513__
157 loadTime = QDateTime.fromString(query.value(0), Qt.ISODate) 169 loadTime = QDateTime.fromString(query.value(0), Qt.ISODate)
158 else: 170 else:
159 loadTime = QDateTime(1970, 1, 1, 0, 0) 171 loadTime = QDateTime(1970, 1, 1, 0, 0)
172 query.finish()
160 del query 173 del query
161 finally: 174 finally:
162 db.commit() 175 db.commit()
163 if self.__projectPath: 176 if self.__projectPath:
164 modTime = QFileInfo(os.path.join(self.__projectPath, apiFile))\ 177 modTime = QFileInfo(os.path.join(self.__projectPath, apiFile))\
276 query.prepare(self.update_file_stmt) 289 query.prepare(self.update_file_stmt)
277 query.bindValue(":lastRead", QDateTime.currentDateTime()) 290 query.bindValue(":lastRead", QDateTime.currentDateTime())
278 query.bindValue(":file", apiFile) 291 query.bindValue(":file", apiFile)
279 query.exec_() 292 query.exec_()
280 finally: 293 finally:
294 query.finish()
281 del query 295 del query
282 if self.__aborted: 296 if self.__aborted:
283 db.rollback() 297 db.rollback()
284 else: 298 else:
285 db.commit() 299 db.commit()
291 @param apis list of api entries (list of strings) 305 @param apis list of api entries (list of strings)
292 @param bases list of base class entries (list of strings) 306 @param bases list of base class entries (list of strings)
293 @param apiFile filename of the file read to get the APIs (string) 307 @param apiFile filename of the file read to get the APIs (string)
294 @param language programming language of the file of the APIs (string) 308 @param language programming language of the file of the APIs (string)
295 """ 309 """
296 if language: 310 wseps = self.__autoCompletionWordSeparators(language)
297 wseps = self.__autoCompletionWordSeparators(language)
298 else:
299 wseps = self.__proxy.autoCompletionWordSeparators()
300 if wseps is None: 311 if wseps is None:
301 return 312 return
302 313
303 db = QSqlDatabase.database(self.__connectionName) 314 db = QSqlDatabase.database(self.__connectionName)
304 db.transaction() 315 db.transaction()
410 query.prepare(self.update_file_stmt) 421 query.prepare(self.update_file_stmt)
411 query.bindValue(":lastRead", QDateTime.currentDateTime()) 422 query.bindValue(":lastRead", QDateTime.currentDateTime())
412 query.bindValue(":file", apiFile) 423 query.bindValue(":file", apiFile)
413 query.exec_() 424 query.exec_()
414 finally: 425 finally:
426 query.finish()
415 del query 427 del query
416 if self.__aborted: 428 if self.__aborted:
417 db.rollback() 429 db.rollback()
418 else: 430 else:
419 db.commit() 431 db.commit()
449 # step 4: delete the file entry 461 # step 4: delete the file entry
450 query.prepare(self.file_delete_id_stmt) 462 query.prepare(self.file_delete_id_stmt)
451 query.bindValue(":id", fileId) 463 query.bindValue(":id", fileId)
452 query.exec_() 464 query.exec_()
453 finally: 465 finally:
466 query.finish()
454 del query 467 del query
455 db.commit() 468 db.commit()
469
470 def __getApiFiles(self):
471 """
472 Private method to get a list of API files loaded into the database.
473
474 @return list of API filenames
475 @rtype list of str
476 """
477 apiFiles = []
478
479 db = QSqlDatabase.database(self.__connectionName)
480 db.transaction()
481 try:
482 query = QSqlQuery(db)
483 query.exec_(self.api_files_stmt)
484 while query.next(): # __IGNORE_WARNING_M513__
485 apiFiles.append(query.value(0))
486 finally:
487 query.finish()
488 del query
489 db.commit()
490
491 return apiFiles
456 492
457 def run(self): 493 def run(self):
458 """ 494 """
459 Public method to perform the threads work. 495 Public method to perform the threads work.
460 """ 496 """
461 self.processing.emit(WorkerStatusStarted, "") 497 self.processing.emit(WorkerStatusStarted, "")
462 498
463 db = QSqlDatabase.database(self.__connectionName) 499 db = QSqlDatabase.addDatabase("QSQLITE", self.__connectionName)
500 db.setDatabaseName(self.__databaseName)
501 db.open()
502
464 if db.isValid() and db.isOpen(): 503 if db.isValid() and db.isOpen():
465 # step 1: remove API files not wanted any longer 504 # step 1: remove API files not wanted any longer
466 if not self.__refresh: 505 if not self.__refresh:
467 loadedApiFiles = self.__proxy.getApiFiles() 506 loadedApiFiles = self.__getApiFiles()
468 for apiFile in loadedApiFiles: 507 for apiFile in loadedApiFiles:
469 if not self.__aborted and apiFile not in self.__apiFiles: 508 if not self.__aborted and apiFile not in self.__apiFiles:
470 self.__deleteApiFile(apiFile) 509 self.__deleteApiFile(apiFile)
471 510
472 # step 2: (re-)load api files 511 # step 2: (re-)load api files
473 for apiFile in self.__apiFiles: 512 for apiFile in self.__apiFiles:
474 if not self.__aborted: 513 if not self.__aborted:
475 self.__loadApiFileIfNewer(apiFile) 514 self.__loadApiFileIfNewer(apiFile)
515
516 db.close()
476 517
477 if self.__aborted: 518 if self.__aborted:
478 self.processing.emit(WorkerStatusAborted, "") 519 self.processing.emit(WorkerStatusAborted, "")
479 else: 520 else:
480 self.processing.emit(WorkerStatusFinished, "") 521 self.processing.emit(WorkerStatusFinished, "")
695 self.__worker.wait(5000) 736 self.__worker.wait(5000)
696 737
697 if QSqlDatabase and QSqlDatabase.database( 738 if QSqlDatabase and QSqlDatabase.database(
698 self.__connectionName).isOpen(): 739 self.__connectionName).isOpen():
699 QSqlDatabase.database(self.__connectionName).close() 740 QSqlDatabase.database(self.__connectionName).close()
700 QSqlDatabase.removeDatabase(self.__language) 741
742 for connectionName in QSqlDatabase.connectionNames():
743 QSqlDatabase.removeDatabase(connectionName)
701 744
702 self.__opened = False 745 self.__opened = False
703 746
704 def __openApiDb(self): 747 def __openApiDb(self):
705 """ 748 """
755 query.exec_(self.create_context_idx) 798 query.exec_(self.create_context_idx)
756 query.exec_(self.create_fullContext_idx) 799 query.exec_(self.create_fullContext_idx)
757 query.exec_(self.create_bases_idx) 800 query.exec_(self.create_bases_idx)
758 query.exec_(self.create_file_idx) 801 query.exec_(self.create_file_idx)
759 finally: 802 finally:
803 query.finish()
760 del query 804 del query
761 db.commit() 805 db.commit()
762 806
763 def getApiFiles(self): 807 def getApiFiles(self):
764 """ 808 """
774 query = QSqlQuery(db) 818 query = QSqlQuery(db)
775 query.exec_(self.api_files_stmt) 819 query.exec_(self.api_files_stmt)
776 while query.next(): # __IGNORE_WARNING_M513__ 820 while query.next(): # __IGNORE_WARNING_M513__
777 apiFiles.append(query.value(0)) 821 apiFiles.append(query.value(0))
778 finally: 822 finally:
823 query.finish()
779 del query 824 del query
780 db.commit() 825 db.commit()
781 826
782 return apiFiles 827 return apiFiles
783 828
799 query.next() # __IGNORE_WARNING_M513__ 844 query.next() # __IGNORE_WARNING_M513__
800 formatVersion = int(query.value(0)) 845 formatVersion = int(query.value(0))
801 if formatVersion >= self.DB_VERSION: 846 if formatVersion >= self.DB_VERSION:
802 prepared = True 847 prepared = True
803 finally: 848 finally:
849 query.finish()
804 del query 850 del query
805 db.commit() 851 db.commit()
806 return prepared 852 return prepared
807 853
808 def getCompletions(self, start=None, context=None, followHierarchy=False): 854 def getCompletions(self, start=None, context=None, followHierarchy=False):
846 query.exec_() 892 query.exec_()
847 while query.next(): # __IGNORE_WARNING_M513__ 893 while query.next(): # __IGNORE_WARNING_M513__
848 completions.append({"completion": query.value(0), 894 completions.append({"completion": query.value(0),
849 "context": query.value(1), 895 "context": query.value(1),
850 "pictureId": query.value(2)}) 896 "pictureId": query.value(2)})
897 query.finish()
851 del query 898 del query
852 finally: 899 finally:
853 db.commit() 900 db.commit()
854 901
855 if followHierarchy: 902 if followHierarchy:
862 else: 909 else:
863 bases = [] 910 bases = []
864 for base in bases: 911 for base in bases:
865 completions.extend(self.getCompletions(start, base, 912 completions.extend(self.getCompletions(start, base,
866 followHierarchy=True)) 913 followHierarchy=True))
914 query.finish()
915 del query
867 916
868 return completions 917 return completions
869 918
870 def getCalltips(self, acWord, commas, context=None, fullContext=None, 919 def getCalltips(self, acWord, commas, context=None, fullContext=None,
871 showContext=True, followHierarchy=False): 920 showContext=True, followHierarchy=False):
920 fullCtx, 969 fullCtx,
921 contextSeparator if fullCtx else "", 970 contextSeparator if fullCtx else "",
922 word, sig)) 971 word, sig))
923 else: 972 else:
924 calltips.append("{0}{1}".format(word, sig)) 973 calltips.append("{0}{1}".format(word, sig))
974 query.finish()
925 del query 975 del query
926 finally: 976 finally:
927 db.commit() 977 db.commit()
928 978
929 if followHierarchy: 979 if followHierarchy:
937 bases = [] 987 bases = []
938 for base in bases: 988 for base in bases:
939 calltips.extend(self.getCalltips( 989 calltips.extend(self.getCalltips(
940 acWord, commas, context=base, showContext=showContext, 990 acWord, commas, context=base, showContext=showContext,
941 followHierarchy=True)) 991 followHierarchy=True))
992 query.finish()
993 del query
942 994
943 if context and len(calltips) == 0 and not followHierarchy: 995 if context and len(calltips) == 0 and not followHierarchy:
944 # nothing found, try without a context 996 # nothing found, try without a context
945 calltips = self.getCalltips( 997 calltips = self.getCalltips(
946 acWord, commas, showContext=showContext) 998 acWord, commas, showContext=showContext)
1034 except TypeError: 1086 except TypeError:
1035 # older interface 1087 # older interface
1036 apiFiles = Preferences.getEditorAPI(self.__language) 1088 apiFiles = Preferences.getEditorAPI(self.__language)
1037 projectType = self.__projectType 1089 projectType = self.__projectType
1038 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, 1090 self.__worker = DbAPIsWorker(self, self.__language, apiFiles,
1039 projectPath, projectType=projectType) 1091 self._apiDbName(), projectPath,
1092 projectType=projectType)
1040 self.__worker.processing.connect( 1093 self.__worker.processing.connect(
1041 self.__processingStatus, Qt.QueuedConnection) 1094 self.__processingStatus, Qt.QueuedConnection)
1042 self.__worker.start() 1095 self.__worker.start()
1043 1096
1044 def __processQueue(self): 1097 def __processQueue(self):
1057 projectType = "" 1110 projectType = ""
1058 else: 1111 else:
1059 projectPath = "" 1112 projectPath = ""
1060 projectType = self.__projectType 1113 projectType = self.__projectType
1061 self.__worker = DbAPIsWorker(self, self.__language, apiFiles, 1114 self.__worker = DbAPIsWorker(self, self.__language, apiFiles,
1062 projectPath, projectType=projectType, 1115 self._apiDbName(), projectPath,
1063 refresh=True) 1116 projectType=projectType, refresh=True)
1064 self.__worker.processing.connect( 1117 self.__worker.processing.connect(
1065 self.__processingStatus, Qt.QueuedConnection) 1118 self.__processingStatus, Qt.QueuedConnection)
1066 self.__worker.start() 1119 self.__worker.start()
1067 1120
1068 def getLexer(self): 1121 def getLexer(self):

eric ide

mercurial