ProjectFlask/FlaskMigrateExtension/MigrateProjectExtension.py

Tue, 24 Nov 2020 19:23:28 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Tue, 24 Nov 2020 19:23:28 +0100
changeset 29
a8817ea36587
child 30
76c86fe13f36
permissions
-rw-r--r--

Started implementing support for the 'flask-migrate' extension.

# -*- 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
    #########################################################

eric ide

mercurial