diff -r 265c3c2914e2 -r e164b9ad3819 ProjectFlask/Project.py --- a/ProjectFlask/Project.py Sun Nov 08 17:59:31 2020 +0100 +++ b/ProjectFlask/Project.py Mon Nov 09 20:00:56 2020 +0100 @@ -9,7 +9,9 @@ import os -from PyQt5.QtCore import pyqtSlot, QObject, QProcess, QTimer +from PyQt5.QtCore import ( + pyqtSlot, QObject, QProcess, QProcessEnvironment, QTimer +) from PyQt5.QtWidgets import QMenu from E5Gui import E5MessageBox @@ -21,6 +23,8 @@ import UI.PixmapCache import Utilities +from .RunServerDialog import RunServerDialog + class Project(QObject): """ @@ -48,7 +52,8 @@ self.__menus = {} # dictionary with references to menus - self.__serverProc = None +## self.__serverProc = None + self.__serverDialog = None self.__flaskVersions = { "python": "", @@ -61,6 +66,42 @@ Public method to define the Flask actions. """ self.actions = [] + + ############################## + ## run actions below ## + ############################## + + self.runServerAct = E5Action( + self.tr('Run Server'), + self.tr('Run &Server'), + 0, 0, + self, 'flask_run_server') + self.runServerAct.setStatusTip(self.tr( + 'Starts the Flask Web server')) + self.runServerAct.setWhatsThis(self.tr( + """<b>Run Server</b>""" + """<p>Starts the Flask Web server.</p>""" + )) + self.runServerAct.triggered.connect(self.__runServer) + self.actions.append(self.runServerAct) + + ################################## + ## documentation action below ## + ################################## + + self.documentationAct = E5Action( + self.tr('Documentation'), + self.tr('D&ocumentation'), + 0, 0, + self, 'flask_documentation') + self.documentationAct.setStatusTip(self.tr( + 'Shows the help viewer with the Flask documentation')) + self.documentationAct.setWhatsThis(self.tr( + """<b>Documentation</b>""" + """<p>Shows the help viewer with the Flask documentation.</p>""" + )) + self.documentationAct.triggered.connect(self.__showDocumentation) + self.actions.append(self.documentationAct) ############################## ## about action below ## @@ -92,6 +133,10 @@ menu = QMenu(self.tr('&Flask'), self.__ui) menu.setTearOffEnabled(True) + menu.addAction(self.runServerAct) + menu.addSeparator() + menu.addAction(self.documentationAct) + menu.addSeparator() menu.addAction(self.aboutFlaskAct) self.__menus["main"] = menu @@ -130,8 +175,8 @@ """ Public method to handle the closing of a project. """ - if self.__serverProc is not None: - self.__serverProcFinished() +## if self.__serverProc is not None: +## self.__serverProcFinished() def supportedPythonVariants(self): """ @@ -246,7 +291,7 @@ Private slot to show some info about Flask. """ versions = self.getFlaskVersionStrings() - url = "https://flask.palletsprojects.com" + url = "https://palletsprojects.com/p/flask/" msgBox = E5MessageBox.E5MessageBox( E5MessageBox.Question, @@ -260,7 +305,7 @@ "<tr><td>Werkzeug Version:</td><td>{1}</td></tr>" "<tr><td>Python Version:</td><td>{2}</td></tr>" "<tr><td>Flask URL:</td><td><a href=\"{3}\">" - "{3}</a></td></tr>" + "The Pallets Projects - Flask</a></td></tr>" "</table></p>" ).format(versions["flask"], versions["werkzeug"], versions["python"], url), @@ -291,31 +336,93 @@ return self.__flaskVersions + def prepareRuntimeEnvironment(self, development=False): + """ + Public method to prepare a QProcessEnvironment object and determine + the appropriate working directory. + + @param development flag indicating development mode + @type bool + @return tuple containing the working directory and a prepared + environment object to be used with QProcess + @rtype tuple of (str, QProcessEnvironment) + """ + mainScript = self.__e5project.getMainScript(normalized=True) + if not mainScript: + E5MessageBox.critical( + self.__ui, + self.tr("Prepare Environment"), + self.tr("""The project has no configured main script""" + """ (= Flask application). Aborting...""")) + return "", None + + scriptPath, scriptName = os.path.split(mainScript) + if scriptName == "__init__.py": + workdir, app = os.path.split(scriptPath) + else: + workdir, app = scriptPath, scriptName + + env = QProcessEnvironment.systemEnvironment() + env.insert("FLASK_APP", app) + if development: + env.insert("FLASK_ENV", "development") + + return workdir, env + + ################################################################## + ## slots below implement documentation functions + ################################################################## + + def __showDocumentation(self): + """ + Private slot to show the helpviewer with the Flask documentation. + """ + page = self.__plugin.getPreferences("FlaskDocUrl") + self.__ui.launchHelpViewer(page) + ################################################################## ## slots below implement run functions ################################################################## + # TODO: does the flask server support logging? def __runServer(self, logging=False): """ - Private slot to start the Pyramid Web server. + Private slot to start the Flask Web server. @param logging flag indicating to enable logging @type bool """ # TODO: implement this (flask run) + workdir, env = self.prepareRuntimeEnvironment() + if env is not None: + cmd = self.getFlaskCommand() + + dlg = RunServerDialog() + if dlg.startServer(cmd, workdir, env): + dlg.show() + self.__serverDialog = dlg - def __serverProcFinished(self): - """ - Private slot connected to the finished signal. + def __runDevelopmentServer(self, logging=False): """ - if ( - self.__serverProc is not None and - self.__serverProc.state() != QProcess.NotRunning - ): - self.__serverProc.terminate() - QTimer.singleShot(2000, self.__serverProc.kill) - self.__serverProc.waitForFinished(3000) - self.__serverProc = None + Private slot to start the Flask Web server in development mode. + + @param logging flag indicating to enable logging + @type bool + """ + # TODO: implement this (flask run with FLASK_ENV=development) + +## def __serverProcFinished(self): +## """ +## Private slot connected to the finished signal. +## """ +## if ( +## self.__serverProc is not None and +## self.__serverProc.state() != QProcess.NotRunning +## ): +## self.__serverProc.terminate() +## QTimer.singleShot(2000, self.__serverProc.kill) +## self.__serverProc.waitForFinished(3000) +## self.__serverProc = None def __runPythonShell(self): """