--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ProjectFlask/FlaskMigrateExtension/MigrateProjectExtension.py Tue Nov 24 19:23:28 2020 +0100 @@ -0,0 +1,249 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the project support for flask-migrate. +""" + +import os + +from PyQt5.QtCore import pyqtSlot, QObject, QProcess +from PyQt5.QtWidgets import QMenu, QDialog + +from E5Gui import E5MessageBox +from E5Gui.E5Application import e5App +from E5Gui.E5Action import E5Action + +import Utilities + +from ..FlaskCommandDialog import FlaskCommandDialog + + +class MigrateProject(QObject): + """ + Class implementing the flask-migrate project support. + """ + def __init__(self, plugin, project, parent=None): + """ + Constructor + + @param plugin reference to the plugin object + @type ProjectFlaskPlugin + @param project reference to the project object + @type Project + @param parent parent + @type QObject + """ + super(MigrateProject, self).__init__(parent) + + self.__plugin = plugin + self.__project = project + + # TODO: move virtual env stuff to Project + self.__virtualEnvManager = e5App().getObject("VirtualEnvManager") + + def initActions(self): + """ + Public method to define the flask-migrate actions. + """ + # TODO: implement flask-migrate actions + self.actions = [] + + self.migrateConfigAct = E5Action( + self.tr('Configure Migrate'), + self.tr('&Configure Migrate'), + 0, 0, + self, 'flask_config_migrate') + self.migrateConfigAct.setStatusTip(self.tr( + 'Shows a dialog to edit the configuration for flask-migrate')) + self.migrateConfigAct.setWhatsThis(self.tr( + """<b>Configure Migrate</b>""" + """<p>Shows a dialog to edit the configuration for""" + """ flask-migrate.</p>""" + )) + self.migrateConfigAct.triggered.connect( + self.__configureMigrate) + self.actions.append(self.migrateConfigAct) + + self.migrateInstallAct = E5Action( + self.tr('Install flask-migrate'), + self.tr('&Install flask-migrate'), + 0, 0, + self, 'flask_install_migrate') + self.migrateInstallAct.setStatusTip(self.tr( + 'Installs the flask-migrate extension into the configured' + ' environment')) + self.migrateInstallAct.setWhatsThis(self.tr( + """<b>Install flask-migrate</b>""" + """<p>Installs the flask-migrate extension into the configured""" + """ environment using the pip interface.</p>""" + )) + self.migrateInstallAct.triggered.connect( + self.__installFlaskMigrate) + self.actions.append(self.migrateInstallAct) + + self.migrateAvailabilityAct = E5Action( + self.tr('Check flask-migrate Availability'), + self.tr('Check flask-migrate &Availability'), + 0, 0, + self, 'flask_check_migrate') + self.migrateAvailabilityAct.setStatusTip(self.tr( + 'Check the availability of the flask-migrate extension')) + self.migrateAvailabilityAct.setWhatsThis(self.tr( + """<b>Check flask-migrate Availability</b>""" + """<p>Check the availability of the flask-migrate extension.</p>""" + )) + self.migrateAvailabilityAct.triggered.connect( + self.__checkAvailability) + self.actions.append(self.migrateAvailabilityAct) + + ######################################################### + ## action to initialize the database migration system + ######################################################### + # TODO: add action for flask db init + + ######################################################### + ## action to create a new database migration + ######################################################### + # TODO: add action for flask db migrate + + ######################################################### + ## action to up- and downgrade a databse + ######################################################### + # TODO: add action for flask db upgrade + # TODO: add action for flask db downgrade + + def initMenu(self): + """ + Public method to initialize the flask-migrate menu. + + @return the menu generated + @rtype QMenu + """ + menu = QMenu(self.tr("Database")) + menu.setTearOffEnabled(True) + + menu.addAction(self.migrateConfigAct) + menu.addSeparator() + menu.addAction(self.migrateAvailabilityAct) + menu.addAction(self.migrateInstallAct) + + return menu + + def determineCapability(self): + """ + Public method to determine the availability of flask-migrate. + """ + available = self.__flaskMigrateAvailable() + self.__project.setCapability("migrate", available) + + self.migrateConfigAct.setEnabled(available) + self.migrateInstallAct.setEnabled(not available) + + def __flaskMigrateAvailable(self): + """ + Private method to check, if the 'flask-babel' package is available. + + @return flag indicating the availability of 'flask-babel' + @rtype bool + """ + venvName = self.__plugin.getPreferences("VirtualEnvironmentNamePy3") + interpreter = self.__virtualEnvManager.getVirtualenvInterpreter( + venvName) + if interpreter and Utilities.isinpath(interpreter): + detector = os.path.join( + os.path.dirname(__file__), "FlaskMigrateDetector.py") + proc = QProcess() + proc.setProcessChannelMode(QProcess.MergedChannels) + proc.start(interpreter, [detector]) + finished = proc.waitForFinished(30000) + if finished and proc.exitCode() == 0: + return True + + return False + + ######################################################## + ## Menu related slots below + ######################################################## + + @pyqtSlot() + def __configureMigrate(self): + """ + Private slot to show a dialog to edit the migrate configuration. + """ + # TODO: implement MigrateConfigDialog + from .MigrateConfigDialog import MigrateConfigDialog + + config = self.__project.getData("migrate", "") + dlg = MigrateConfigDialog(config) + if dlg.exec() == QDialog.Accepted: + config = dlg.getConfiguration() + self.__project.setData("migrate", "", config) + + def __ensureMigrateConfigured(self): + """ + Private method to ensure, that flask-migrate has been configured. + + @return flag indicating successful configuration + @rtype bool + """ + config = self.__project.getData("migrate", "") + if not config: + self.__configureMigrate() + return True + + return False + + @pyqtSlot() + def __installFlaskMigrate(self): + """ + Private slot to install the flask-migrate extension into the configured + environment. + """ + language = e5App().getObject("Project").getProjectLanguage() + if language == "Python3": + venvName = self.__plugin.getPreferences( + "VirtualEnvironmentNamePy3") + else: + venvName = "" + if venvName: + interpreter = self.__project.getFullCommand("python") + pip = e5App().getObject("Pip") + pip.installPackages(["flask-migrate"], interpreter=interpreter) + self.determineCapability() + else: + E5MessageBox.critical( + None, + self.tr("Install flask-migrate"), + self.tr("The 'flask-migrate' extension could not be installed" + " because no virtual environment has been" + " configured.")) + + @pyqtSlot() + def __checkAvailability(self): + """ + Private slot to check the availability of the 'flask-babel' extension. + """ + self.determineCapability() + if self.__project.hasCapability("migrate"): + msg = self.tr("The 'flask-migrate' extension is installed.") + else: + msg = self.tr("The 'flask-migrate' extension is not installed.") + E5MessageBox.information( + None, + self.tr("flask-migrate Availability"), + msg) + + ######################################################### + ## slot to initialize the database migration system + ######################################################### + + ######################################################### + ## slot to create a new database migration + ######################################################### + + ######################################################### + ## slots to up- and downgrade a databse + #########################################################