def search(self): # Begins a search of either Github or the database. # Searching github can take a long time and multithreading could be useful here. # But I haven't implemented it as there is nothing the user would want to do # during a search anyway. self.mainUi.statusbar.showMessage("Searching") startTime = time.time() packageID = self.searchUi.textPackageID.text() if packageID == '': packageID = None packageName = self.searchUi.textPackageName.text() if packageName == '': packageName = None language = self.searchUi.textLanguage.text() if language == '': language = None size = self.searchUi.textSize.text() if size == '': size = None elif not size.strip('<>').isnumeric(): QtGui.QMessageBox.warning(self.mainWindow, 'Warning', 'The size criteria can\'t contains letters. ' 'The application will remove the letters and attempt the search.') logging.error('The user attempted to search using letters in the size criteria.') size = ''.join([x for x in self.searchUi.textSize.text() if x in '1234567890<>']) if self.searchUi.checkBoxGithub.checkState() == 2 and packageName == None: self.mainUi.statusbar.showMessage("Search Failed") QtGui.QMessageBox.warning(self.mainWindow, "Warning", "You can't search Github without a package name.") logging.error("The user attempted to search Github without a package name.") return elif self.searchUi.checkBoxDatabase.checkState() == 2: self.app.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) # Made results a member variable as I am going to only use parts of the result # to display in the table. Other parts of the results are vital but would end with # this function if it weren't for making this a member variable. self.results = utils.search(True, [packageID, packageName, False, language, size], self.configuration.databaseFile) elif self.searchUi.checkBoxGithub.checkState() == 2: self.app.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor)) # Perform a search of Github. self.results = utils.search(False, [packageID, packageName, True, language, size], None) else: self.mainUi.statusbar.showMessage("Search Failed") QtGui.QMessageBox.warning(self.mainWindow, "Warning", "No search target entered.") logging.error("The user attempted to search without a target.") return duration = time.time() - startTime self.mainUi.statusbar.showMessage("Search completed in {0:.3f} seconds".format(duration)) logging.info("The search completed in {0:.3f} seconds".format(duration)) self.populateTable(self.mainUi.tableWidget, self.results) self.app.restoreOverrideCursor()
def refreshMainTable(self): # Refresh the values in the table. This can be slightly buggy # and I have therefore added a button in the UI for the user # to force a refresh. logging.info("Refreshing the main window.") self.populateTable(self.mainUi.tableWidget, utils.search(True, [None, None, False, None, None], self.configuration.databaseFile))
def search_monster(name, monster_list, rank=None): # if name is empty if name == '' or name == None: return ['Missing name or ID'] name_list = [] results = [] # retreive monster names for key in monster_list.keys(): name_list.append(key) args = name.split() last_arg = args.pop().upper() rank = None # check if there is a rank suffix inside the name if last_arg in rank_suffix.keys(): rank = rank_suffix[last_arg] print('found rank ' + rank) else: args.append(last_arg) name = ' '.join(args) log.debug('now searching for ' + name) # if name is the ID - check and return the monster try: name_id = int(name) except ValueError: log.debug(name + ' is not an ID') else: # if the ID does exist try: results += ['[' + str(name_id) + '] ' + name_list[name_id]] results += monster_list[name_list[name_id]].show(rank=rank) return results except IndexError: return ['Incorrect Monster ID'] # search if the name matches with any item matches = utils.search(name, name_list) matches_s = len(matches) # if nothing match if matches_s == 0: return ['Nothing found'] # if exaclty 1 match is found if matches_s == 1: results += ['[' + str(name_list.index(matches[0])) + '] ' + matches[0]] results += monster_list[matches[0]].show(rank=rank) return results # if multiples match are found if matches_s > 1: r = '' for match in matches: r += '[' + str(name_list.index(match)) + '] ' + match + '\n' return [r]
def search_item(name, monster_list): # find all the possible items first item_list = find_items(monster_list) results = [] # if name is the ID - check and return the item try: item_id = int(name) except ValueError: log.debug(name + " is not an ID") else: # if the ID does exist try: results += ['[' + str(item_id) + '] ' + item_list[item_id]] result = find_item(monster_list, item_list[item_id]) # if the message will be too long - split it if len(result) > 1800: results += find_item(monster_list, item_list[item_id], as_list=True) else: results += [result] return results except IndexError: return ["Incorrect Item ID"] # search if the name matches with any item matches = utils.search(name, item_list) matches_s = len(matches) # if nothing match if matches_s == 0: return ["Nothing found"] # if exaclty 1 match is found if matches_s == 1: results += ['[' + str(item_list.index(matches[0])) + '] ' + matches[0]] result = find_item(monster_list, matches[0]) # if the message will be too long - split it if len(result) > 1800: results += find_item(monster_list, matches[0], as_list=True) else: results += [result] return results # if multiples match are found if matches_s > 1: r = "" for match in matches: r += '[' + str(item_list.index(match)) + '] ' + match + '\n' return [r]
def deleteReportPack(args): # Downloads the specified RP reportpacks = w4n.listReportPacks() # Resolve the report name from the id report_id = args.id report_name = '' try: report_name = utils.search('id', args.id, reportpacks)[0]['name'] except: logging.error("ReportPack ID '%s' not found!", report_id) exit(1) # Delete ReportPack result = w4n.deleteReportPack(report_id, report_name) logging.info("ReportPack '%s' ID '%s' deleted.", report_name, report_id)
def delete(self): # This function iterates through the values in the member variable # deleteTableData. It then checks if the check box for removing downloaded # is checked. If so, it deletes the extract folder (if it exists), then the # tar.gz file and finally removes it from the database. deletedPackages = 0 numberOfPackages = len(self.deleteTableData) for item in self.deleteTableData: # Item[1] refers to the package ID. if item[1] != '': # Query the database to find out where the package is downloaded to. # The return value is a one element list with a tuple. # Use [0] to get the first element (the tuple) and then use # [6] to get the install path. downloadPath = utils.search(True, [item[1], None, False, None, None], self.configuration.databaseFile)[0][6] tgz = targz.TarGZ(downloadPath) # If the tar file has a setup.py, it must be a python file. if tgz.getSetup(): # Extract from the setup.py the name with which the package # was installed using. Then run a command to uninstall it. name = tgz.getPipValue("name") command = ["xterm", "-T", "Uninstalling {0}".format(name), "-e", "sudo pip uninstall {0} --log={1}; sleep {2}".format(name, self.configuration.pipLogFile, self.configuration.terminalWaitTime)] try: subprocess.call(command) except subprocess.CalledProcessError as e: logging.error(e) if self.deleteUi.boxRemoveDownloadedContent.checkState() == 2: folderPath = os.sep.join(downloadPath.split(os.sep)[:-1] + [tgz.getFolderName()]) if os.path.exists(folderPath): shutil.rmtree(folderPath) os.remove(downloadPath) logging.debug("Deleted the file {0}".format(downloadPath)) logging.info("Deleting package with ID {0}".format(item[1])) self.db.deletePackage(item[1]) deletedPackages += 1 self.mainUi.statusbar.showMessage("Deleted package {0} of {1}".format(deletedPackages, numberOfPackages)) else: QtGui.QMessageBox.warning(self.mainWindow, "Warning", "You can't delete a package that isn't installed.") logging.error("User tried to delete a package that isn't installed.") return self.refreshMainTable()
def getReportPack(args): # Downloads the specified RP reportpacks = w4n.listReportPacks() # Resolve the report name from the id report_id = args.id report_name = '' try: report_name = utils.search('id', args.id, reportpacks)[0]['name'] except: logging.error("ReportPack ID '%s' not found!", report_id) exit(1) # Download a ReportPack report_file = w4n.getReportPack(report_id, report_name) if args.x: w4n.unzipReportPack(report_file)
def setFavouritesToFile(self): # This function queries the database for all the packages and looks for those # that are favourited. It then adds the URL, language and size of the package # to the favourites file. # Query the database for all installed packages so that they can be # iterated through in order to check if the are favourites. installedPackages = utils.search(True, [None, None, False, None, None], self.configuration.databaseFile) favourites = [] for package in installedPackages: # If the favourite field of the package is set to 1, it is a favourite # and can be later written to the favourites file. if package[9] == 1: # The URL, then language and finally size of the package is added to the favourites. # The 3 values are seperated by a tab so they can easily be split later. # Using a config parser style class would be too restrictive. favourites.append(str(package[4]) + '\t' + str(package[3]) + '\t' + str(package[2]) + '\n') f = open(self.configuration.favouritesFile, "w") for item in favourites: f.write(item) f.close() logging.debug("Updated the favourites file.")
def getFavourites(self): # This function reads from the favourites file the packages that are to be installed. # It then queries the database for all of the already installed packages and compares. # If the URL of a favourite package matches one that is already installed, then the # favourites is already there, otherwise it needs to be installed. # The URL is the only unique data about a package that can be compared with a # package that isn't installed. packagesToBeInstalled = [] if os.path.exists(self.configuration.favouritesFile): # The favourites file contains the URLs of the favourited packages. with open(self.configuration.favouritesFile, "r") as file: favourites = file.readlines() logging.debug("Read the favourites file.") # Grab all of the installed packages. installedPackages = utils.search(True, [None, None, False, None, None], self.configuration.databaseFile) for favourite in favourites: # A flag that determines whether a package is installed or not. # It is set to false until proven true. installed = False # Split the line into 3 variables in order to pass them to the download function. details = {} url, details['language'], details['size'] = favourite.split() # The name of the package can be extracted from the URL and will need # to be passed to the download function. details['name'] = url.split('/')[-3] for package in installedPackages: # If the URLs match, it is installed. if url in package: installed = True if not installed: logging.warning("The favourite package {0} is not installed".format(details['name'])) # Show a message box to let the user decide if they want to install it. reply = QtGui.QMessageBox.question(self.mainWindow, 'Message', "The package {0} is not installed but is marked as a favourite. " \ "Do you wish to install it now?".format(details['name']), QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, QtGui.QMessageBox.No) if reply == QtGui.QMessageBox.Yes: packagesToBeInstalled.append([details, url]) self.install(packagesToBeInstalled)
def showEdit(self): # Displays the edit screen and populates all of the fields with # the values that are stored in the database. row = self.getSelectedRows() if len(row) > 1: QtGui.QMessageBox.warning(self.mainWindow, "Warning", "You can't edit more than one package at a time.") return elif len(row) == 0: QtGui.QMessageBox.warning(self.mainWindow, "Warning", "You can't edit a package without selecting one.") return # After checking the length of the set returned by the function, # we can be sure it is only one element long and so remove the set. row = row.pop() # Grab the packageId from the table in order to later query # the database. # I am making it a member variable as it will need to be accessed by the # edit function later. self.editPackageId = self.mainUi.tableWidget.item(row, 1).text() if self.editPackageId == None: QtGui.QMessageBox.warning(self.mainWindow, "Warning", "You can't edit a package that isn't installed.") return packageData = utils.search(True, [self.editPackageId, None, False, None, None], self.configuration.databaseFile) # Package data is a one element list, so get rid of the list. packageData = packageData[0] # Now set each text box to the value from the database. if packageData[9] == 1: self.editUi.checkBoxFavourite.setChecked(True) else: self.editUi.checkBoxFavourite.setChecked(False) self.editUi.textPackageName.setText(packageData[1]) self.editUi.textLanguage.setText(packageData[3]) self.editUi.textVersion.setText(packageData[8]) self.editUi.textSize.setText(str(packageData[2])) self.editUi.textDownloadPath.setText(packageData[6]) self.editUi.textInstallPath.setText(packageData[5]) self.editUi.textURL.setText(packageData[4]) self.editUi.textInstalledDate.setText(packageData[7]) logging.info("Editing dialog being displayed.") self.editDialog.show()
def testSearchDatabase(self): for item in self.validSearchTerms: result = search(True, item, self.configuration.databaseFile) self.assertIsNotNone(result)
def testSearchGithub(self): # Only send one request, to stop my IP from being banned :( term = random.choice(self.validSearchTerms) result = search(False, term, self.configuration.databaseFile) self.assertIsNotNone(result)