--- a/ProjectPyramid/Project.py Thu Dec 30 12:17:44 2021 +0100 +++ b/ProjectPyramid/Project.py Wed Sep 21 16:24:54 2022 +0200 @@ -12,12 +12,10 @@ import glob import os import re -import subprocess # secok +import subprocess # secok import sys -from PyQt6.QtCore import ( - pyqtSlot, QObject, QFileInfo, QTimer, QUrl, QIODeviceBase -) +from PyQt6.QtCore import pyqtSlot, QObject, QFileInfo, QTimer, QUrl, QIODeviceBase from PyQt6.QtGui import QDesktopServices from PyQt6.QtWidgets import QMenu, QDialog, QInputDialog, QLineEdit from PyQt6.QtCore import QProcess as QProcessPyQt @@ -34,10 +32,11 @@ import UI.PixmapCache -class PyramidNoProjectSelectedException(Exception): +class PyramidNoProjectSelectedError(Exception): """ Exception thrown to signal, that there is no current Pyramid project. """ + pass @@ -45,11 +44,12 @@ """ Class transforming the call arguments in case of gnome-terminal. """ + def start(self, cmd, args=None, mode=QIODeviceBase.OpenModeFlag.ReadWrite): """ Public method to start the given program (cmd) in a new process, if none is already running, passing the command line arguments in args. - + @param cmd start the given program cmd @type str @param args list of parameters @@ -59,24 +59,25 @@ """ if args is None: args = [] - + if ( - cmd.endswith(('gnome-terminal', 'konsole', 'xfce4-terminal', - 'mate-terminal')) and - '-e' in args + cmd.endswith( + ("gnome-terminal", "konsole", "xfce4-terminal", "mate-terminal") + ) + and "-e" in args ): - index = args.index('-e') + 1 - cargs = ' '.join(args[index:]) + index = args.index("-e") + 1 + cargs = " ".join(args[index:]) args[index:] = [cargs] - + super().start(cmd, args, mode) - + @staticmethod - def startDetached(cmd, args=None, path=''): + def startDetached(cmd, args=None, path=""): """ Public static method to start the given program (cmd) in a new process, if none is already running, passing the command line arguments in args. - + @param cmd start the given program cmd @type str @param args list of parameters @@ -88,16 +89,17 @@ """ if args is None: args = [] - + if ( - cmd.endswith(('gnome-terminal', 'konsole', 'xfce4-terminal', - 'mate-terminal')) and - '-e' in args + cmd.endswith( + ("gnome-terminal", "konsole", "xfce4-terminal", "mate-terminal") + ) + and "-e" in args ): - index = args.index('-e') + 1 - cargs = ' '.join(args[index:]) + index = args.index("-e") + 1 + cargs = " ".join(args[index:]) args[index:] = [cargs] - + return QProcessPyQt.startDetached(cmd, args, path) @@ -105,10 +107,11 @@ """ Class implementing the Pyramid project support. """ + def __init__(self, plugin, iconSuffix, parent=None): """ Constructor - + @param plugin reference to the plugin object @type ProjectPyramidPlugin @param iconSuffix suffix for the icons @@ -117,341 +120,438 @@ @type QObject """ super().__init__(parent) - + self.__plugin = plugin self.__iconSuffix = iconSuffix self.__ui = parent self.__ericProject = ericApp().getObject("Project") self.__virtualEnvManager = ericApp().getObject("VirtualEnvManager") self.__hooksInstalled = False - - self.__menus = {} # dictionary with references to menus - + + self.__menus = {} # dictionary with references to menus + self.__serverProc = None - + self.__pyramidVersion = "" - + self.__migrationSummaryDialog = None - + def initActions(self): """ Public method to define the Pyramid actions. """ self.actions = [] - + self.selectProjectAct = EricAction( - self.tr('Current Pyramid Project'), + self.tr("Current Pyramid Project"), "", - 0, 0, - self, 'pyramid_current_project') - self.selectProjectAct.setStatusTip(self.tr( - 'Selects the current Pyramid project')) - self.selectProjectAct.setWhatsThis(self.tr( - """<b>Current Pyramid Project</b>""" - """<p>Selects the Pyramid project. Used for multi-project """ - """Pyramid projects to switch between the projects.</p>""" - )) + 0, + 0, + self, + "pyramid_current_project", + ) + self.selectProjectAct.setStatusTip( + self.tr("Selects the current Pyramid project") + ) + self.selectProjectAct.setWhatsThis( + self.tr( + """<b>Current Pyramid Project</b>""" + """<p>Selects the Pyramid project. Used for multi-project """ + """Pyramid projects to switch between the projects.</p>""" + ) + ) self.selectProjectAct.triggered.connect(self.__selectProject) self.actions.append(self.selectProjectAct) - + ############################### ## create actions below ## ############################### - + self.createProjectAct = EricAction( - self.tr('Create Pyramid Project'), - self.tr('Create Pyramid &Project'), - 0, 0, - self, 'pyramid_create_project') - self.createProjectAct.setStatusTip(self.tr( - 'Creates a new Pyramid project')) - self.createProjectAct.setWhatsThis(self.tr( - """<b>Create Pyramid Project</b>""" - """<p>Creates a new Pyramid project using "pcreate".</p>""" - )) + self.tr("Create Pyramid Project"), + self.tr("Create Pyramid &Project"), + 0, + 0, + self, + "pyramid_create_project", + ) + self.createProjectAct.setStatusTip(self.tr("Creates a new Pyramid project")) + self.createProjectAct.setWhatsThis( + self.tr( + """<b>Create Pyramid Project</b>""" + """<p>Creates a new Pyramid project using "pcreate".</p>""" + ) + ) self.createProjectAct.triggered.connect(self.__createProject) self.actions.append(self.createProjectAct) - + ############################## ## run actions below ## ############################## - + self.runServerAct = EricAction( - self.tr('Run Server'), - self.tr('Run &Server'), - 0, 0, - self, 'pyramid_run_server') - self.runServerAct.setStatusTip(self.tr( - 'Starts the Pyramid Web server')) - self.runServerAct.setWhatsThis(self.tr( - """<b>Run Server</b>""" - """<p>Starts the Pyramid Web server using""" - """ "pserve --reload development.ini".</p>""" - )) + self.tr("Run Server"), + self.tr("Run &Server"), + 0, + 0, + self, + "pyramid_run_server", + ) + self.runServerAct.setStatusTip(self.tr("Starts the Pyramid Web server")) + self.runServerAct.setWhatsThis( + self.tr( + """<b>Run Server</b>""" + """<p>Starts the Pyramid Web server using""" + """ "pserve --reload development.ini".</p>""" + ) + ) self.runServerAct.triggered.connect(self.__runServer) self.actions.append(self.runServerAct) - + self.runBrowserAct = EricAction( - self.tr('Run Web-Browser'), - self.tr('Run &Web-Browser'), - 0, 0, - self, 'pyramid_run_browser') - self.runBrowserAct.setStatusTip(self.tr( - 'Starts the default Web-Browser with the URL of the Pyramid Web' - ' server')) - self.runBrowserAct.setWhatsThis(self.tr( - """<b>Run Web-Browser</b>""" - """<p>Starts the default Web-Browser with the URL of the """ - """Pyramid Web server.</p>""" - )) + self.tr("Run Web-Browser"), + self.tr("Run &Web-Browser"), + 0, + 0, + self, + "pyramid_run_browser", + ) + self.runBrowserAct.setStatusTip( + self.tr( + "Starts the default Web-Browser with the URL of the Pyramid Web" + " server" + ) + ) + self.runBrowserAct.setWhatsThis( + self.tr( + """<b>Run Web-Browser</b>""" + """<p>Starts the default Web-Browser with the URL of the """ + """Pyramid Web server.</p>""" + ) + ) self.runBrowserAct.triggered.connect(self.__runBrowser) self.actions.append(self.runBrowserAct) - + self.runPythonShellAct = EricAction( - self.tr('Start Pyramid Python Console'), - self.tr('Start Pyramid &Python Console'), - 0, 0, - self, 'pyramid_python_console') - self.runPythonShellAct.setStatusTip(self.tr( - 'Starts an interactive Python interpreter')) - self.runPythonShellAct.setWhatsThis(self.tr( - """<b>Start Pyramid Python Console</b>""" - """<p>Starts an interactive Python interpreter.</p>""" - )) + self.tr("Start Pyramid Python Console"), + self.tr("Start Pyramid &Python Console"), + 0, + 0, + self, + "pyramid_python_console", + ) + self.runPythonShellAct.setStatusTip( + self.tr("Starts an interactive Python interpreter") + ) + self.runPythonShellAct.setWhatsThis( + self.tr( + """<b>Start Pyramid Python Console</b>""" + """<p>Starts an interactive Python interpreter.</p>""" + ) + ) self.runPythonShellAct.triggered.connect(self.__runPythonShell) self.actions.append(self.runPythonShellAct) - + ############################### ## show actions below ## ############################### - + self.showViewsAct = EricAction( - self.tr('Show Matching Views'), - self.tr('Show Matching &Views'), - 0, 0, - self, 'pyramid_show_views') - self.showViewsAct.setStatusTip(self.tr( - 'Show views matching a given URL')) - self.showViewsAct.setWhatsThis(self.tr( - """<b>Show Matching Views</b>""" - """<p>Show views matching a given URL.</p>""" - )) + self.tr("Show Matching Views"), + self.tr("Show Matching &Views"), + 0, + 0, + self, + "pyramid_show_views", + ) + self.showViewsAct.setStatusTip(self.tr("Show views matching a given URL")) + self.showViewsAct.setWhatsThis( + self.tr( + """<b>Show Matching Views</b>""" + """<p>Show views matching a given URL.</p>""" + ) + ) self.showViewsAct.triggered.connect(self.__showMatchingViews) self.actions.append(self.showViewsAct) - + self.showRoutesAct = EricAction( - self.tr('Show Routes'), - self.tr('Show &Routes'), - 0, 0, - self, 'pyramid_show_routes') - self.showRoutesAct.setStatusTip(self.tr( - 'Show all URL dispatch routes used by a Pyramid application')) - self.showRoutesAct.setWhatsThis(self.tr( - """<b>Show Routes</b>""" - """<p>Show all URL dispatch routes used by a Pyramid application""" - """ in the order in which they are evaluated.</p>""" - )) + self.tr("Show Routes"), + self.tr("Show &Routes"), + 0, + 0, + self, + "pyramid_show_routes", + ) + self.showRoutesAct.setStatusTip( + self.tr("Show all URL dispatch routes used by a Pyramid application") + ) + self.showRoutesAct.setWhatsThis( + self.tr( + """<b>Show Routes</b>""" + """<p>Show all URL dispatch routes used by a Pyramid application""" + """ in the order in which they are evaluated.</p>""" + ) + ) self.showRoutesAct.triggered.connect(self.__showRoutes) self.actions.append(self.showRoutesAct) - + self.showTweensAct = EricAction( - self.tr('Show Tween Objects'), - self.tr('Show &Tween Objects'), - 0, 0, - self, 'pyramid_show_routes') - self.showTweensAct.setStatusTip(self.tr( - 'Show all implicit and explicit tween objects used by a Pyramid' - ' application')) - self.showTweensAct.setWhatsThis(self.tr( - """<b>Show Tween Objects</b>""" - """<p>Show all implicit and explicit tween objects used by a""" - """ Pyramid application.</p>""" - )) + self.tr("Show Tween Objects"), + self.tr("Show &Tween Objects"), + 0, + 0, + self, + "pyramid_show_routes", + ) + self.showTweensAct.setStatusTip( + self.tr( + "Show all implicit and explicit tween objects used by a Pyramid" + " application" + ) + ) + self.showTweensAct.setWhatsThis( + self.tr( + """<b>Show Tween Objects</b>""" + """<p>Show all implicit and explicit tween objects used by a""" + """ Pyramid application.</p>""" + ) + ) self.showTweensAct.triggered.connect(self.__showTweens) self.actions.append(self.showTweensAct) - + ################################## ## distribution actions below ## ################################## - + self.buildDistroAct = EricAction( - self.tr('Build Distribution'), - self.tr('Build &Distribution'), - 0, 0, - self, 'pyramid_build_distribution') - self.buildDistroAct.setStatusTip(self.tr( - 'Builds a distribution file for the Pyramid project')) - self.buildDistroAct.setWhatsThis(self.tr( - """<b>Build Distribution</b>""" - """<p>Builds a distribution file for the Pyramid project using""" - """ "python setup.py sdist".</p>""" - )) + self.tr("Build Distribution"), + self.tr("Build &Distribution"), + 0, + 0, + self, + "pyramid_build_distribution", + ) + self.buildDistroAct.setStatusTip( + self.tr("Builds a distribution file for the Pyramid project") + ) + self.buildDistroAct.setWhatsThis( + self.tr( + """<b>Build Distribution</b>""" + """<p>Builds a distribution file for the Pyramid project using""" + """ "python setup.py sdist".</p>""" + ) + ) self.buildDistroAct.triggered.connect(self.__buildDistribution) self.actions.append(self.buildDistroAct) - + ################################## ## documentation action below ## ################################## - + self.documentationAct = EricAction( - self.tr('Documentation'), - self.tr('D&ocumentation'), - 0, 0, - self, 'pyramid_documentation') - self.documentationAct.setStatusTip(self.tr( - 'Shows the help viewer with the Pyramid documentation')) - self.documentationAct.setWhatsThis(self.tr( - """<b>Documentation</b>""" - """<p>Shows the help viewer with the Pyramid documentation.</p>""" - )) + self.tr("Documentation"), + self.tr("D&ocumentation"), + 0, + 0, + self, + "pyramid_documentation", + ) + self.documentationAct.setStatusTip( + self.tr("Shows the help viewer with the Pyramid documentation") + ) + self.documentationAct.setWhatsThis( + self.tr( + """<b>Documentation</b>""" + """<p>Shows the help viewer with the Pyramid documentation.</p>""" + ) + ) self.documentationAct.triggered.connect(self.__showDocumentation) self.actions.append(self.documentationAct) - + ############################## ## about action below ## ############################## - + self.aboutPyramidAct = EricAction( - self.tr('About Pyramid'), - self.tr('About P&yramid'), - 0, 0, - self, 'pyramid_about') - self.aboutPyramidAct.setStatusTip(self.tr( - 'Shows some information about Pyramid')) - self.aboutPyramidAct.setWhatsThis(self.tr( - """<b>About Pyramid</b>""" - """<p>Shows some information about Pyramid.</p>""" - )) + self.tr("About Pyramid"), + self.tr("About P&yramid"), + 0, + 0, + self, + "pyramid_about", + ) + self.aboutPyramidAct.setStatusTip( + self.tr("Shows some information about Pyramid") + ) + self.aboutPyramidAct.setWhatsThis( + self.tr( + """<b>About Pyramid</b>""" + """<p>Shows some information about Pyramid.</p>""" + ) + ) self.aboutPyramidAct.triggered.connect(self.__pyramidInfo) self.actions.append(self.aboutPyramidAct) - + self.__initDatabaseActions() - + self.__setCurrentProject(None) - + def __initDatabaseActions(self): """ Private method to initialize the database related actions. """ self.initializeDbAct = EricAction( - self.tr('Initialize Database'), - self.tr('Initialize &Database'), - 0, 0, - self, 'pyramid_initialize_database') - self.initializeDbAct.setStatusTip(self.tr( - 'Initializes (or re-initializes) the database of the current' - ' Pyramid project')) - self.initializeDbAct.setWhatsThis(self.tr( - """<b>Initialize Database</b>""" - """<p>Initializes (or re-initializes) the database of the""" - """ current Pyramid project.</p>""" - )) + self.tr("Initialize Database"), + self.tr("Initialize &Database"), + 0, + 0, + self, + "pyramid_initialize_database", + ) + self.initializeDbAct.setStatusTip( + self.tr( + "Initializes (or re-initializes) the database of the current" + " Pyramid project" + ) + ) + self.initializeDbAct.setWhatsThis( + self.tr( + """<b>Initialize Database</b>""" + """<p>Initializes (or re-initializes) the database of the""" + """ current Pyramid project.</p>""" + ) + ) self.initializeDbAct.triggered.connect(self.__initializeDatabase) self.actions.append(self.initializeDbAct) - + ######################################################### ## action to create a new database migration ######################################################### - + self.migrateCreateAct = EricAction( - self.tr('Create Migration'), - self.tr('&Create Migration'), - 0, 0, - self, 'flask_create_migration') - self.migrateCreateAct.setStatusTip(self.tr( - 'Create a new migration for the current database')) - self.migrateCreateAct.setWhatsThis(self.tr( - """<b>Create Migration</b>""" - """<p>Creates a new migration for the current database""" - """ and stores it in the configured migrations directory.</p>""" - )) - self.migrateCreateAct.triggered.connect( - self.__createMigration) + self.tr("Create Migration"), + self.tr("&Create Migration"), + 0, + 0, + self, + "flask_create_migration", + ) + self.migrateCreateAct.setStatusTip( + self.tr("Create a new migration for the current database") + ) + self.migrateCreateAct.setWhatsThis( + self.tr( + """<b>Create Migration</b>""" + """<p>Creates a new migration for the current database""" + """ and stores it in the configured migrations directory.</p>""" + ) + ) + self.migrateCreateAct.triggered.connect(self.__createMigration) self.actions.append(self.migrateCreateAct) - + ######################################################### ## action to up- and downgrade a databse ######################################################### - + self.upgradeDatabaseAct = EricAction( - self.tr('Upgrade Database'), - self.tr('&Upgrade Database'), - 0, 0, - self, 'flask_upgrade_database') - self.upgradeDatabaseAct.setStatusTip(self.tr( - 'Upgrade the database to the current migration')) - self.upgradeDatabaseAct.setWhatsThis(self.tr( - """<b>Upgrade Database</b>""" - """<p>Upgrades the database to the current migration.</p>""" - )) - self.upgradeDatabaseAct.triggered.connect( - self.upgradeDatabase) + self.tr("Upgrade Database"), + self.tr("&Upgrade Database"), + 0, + 0, + self, + "flask_upgrade_database", + ) + self.upgradeDatabaseAct.setStatusTip( + self.tr("Upgrade the database to the current migration") + ) + self.upgradeDatabaseAct.setWhatsThis( + self.tr( + """<b>Upgrade Database</b>""" + """<p>Upgrades the database to the current migration.</p>""" + ) + ) + self.upgradeDatabaseAct.triggered.connect(self.upgradeDatabase) self.actions.append(self.upgradeDatabaseAct) - + self.downgradeDatabaseAct = EricAction( - self.tr('Downgrade Database'), - self.tr('&Downgrade Database'), - 0, 0, - self, 'flask_downgrade_database') - self.downgradeDatabaseAct.setStatusTip(self.tr( - 'Downgrade the database to the previous version')) - self.downgradeDatabaseAct.setWhatsThis(self.tr( - """<b>Downgrade Database</b>""" - """<p>Downgrades the database to the previous version.</p>""" - )) - self.downgradeDatabaseAct.triggered.connect( - self.downgradeDatabase) + self.tr("Downgrade Database"), + self.tr("&Downgrade Database"), + 0, + 0, + self, + "flask_downgrade_database", + ) + self.downgradeDatabaseAct.setStatusTip( + self.tr("Downgrade the database to the previous version") + ) + self.downgradeDatabaseAct.setWhatsThis( + self.tr( + """<b>Downgrade Database</b>""" + """<p>Downgrades the database to the previous version.</p>""" + ) + ) + self.downgradeDatabaseAct.triggered.connect(self.downgradeDatabase) self.actions.append(self.downgradeDatabaseAct) - + ######################################################### ## actions to show migrations history information ######################################################### - + self.migrationSummaryAct = EricAction( - self.tr('Show Migrations Summary'), - self.tr('Show Migrations &Summary'), - 0, 0, - self, 'flask_show_migrations_summary') - self.migrationSummaryAct.setStatusTip(self.tr( - 'Show a summary of the created database migrations')) - self.migrationSummaryAct.setWhatsThis(self.tr( - """<b>Show Migrations Summary</b>""" - """<p>Shows a summary list of the created database""" - """ migrations.</p>""" - )) - self.migrationSummaryAct.triggered.connect( - self.__showMigrationsSummary) + self.tr("Show Migrations Summary"), + self.tr("Show Migrations &Summary"), + 0, + 0, + self, + "flask_show_migrations_summary", + ) + self.migrationSummaryAct.setStatusTip( + self.tr("Show a summary of the created database migrations") + ) + self.migrationSummaryAct.setWhatsThis( + self.tr( + """<b>Show Migrations Summary</b>""" + """<p>Shows a summary list of the created database""" + """ migrations.</p>""" + ) + ) + self.migrationSummaryAct.triggered.connect(self.__showMigrationsSummary) self.actions.append(self.migrationSummaryAct) - + self.migrationHistoryAct = EricAction( - self.tr('Show Migrations History'), - self.tr('Show Migrations &History'), - 0, 0, - self, 'flask_show_migrations_history') - self.migrationHistoryAct.setStatusTip(self.tr( - 'Show the full history of the created database migrations')) - self.migrationHistoryAct.setWhatsThis(self.tr( - """<b>Show Migrations History</b>""" - """<p>Shows the full history of the created database""" - """ migrations.</p>""" - )) - self.migrationHistoryAct.triggered.connect( - self.__showMigrationsHistory) + self.tr("Show Migrations History"), + self.tr("Show Migrations &History"), + 0, + 0, + self, + "flask_show_migrations_history", + ) + self.migrationHistoryAct.setStatusTip( + self.tr("Show the full history of the created database migrations") + ) + self.migrationHistoryAct.setWhatsThis( + self.tr( + """<b>Show Migrations History</b>""" + """<p>Shows the full history of the created database""" + """ migrations.</p>""" + ) + ) + self.migrationHistoryAct.triggered.connect(self.__showMigrationsHistory) self.actions.append(self.migrationHistoryAct) - + def initMenu(self): """ Public slot to initialize the Pyramid menu. - + @return the menu generated @rtype QMenu """ - self.__menus = {} # clear menus references - + self.__menus = {} # clear menus references + # Database menu dbMenu = QMenu(self.tr("Database")) dbMenu.setTearOffEnabled(True) - + dbMenu.addAction(self.initializeDbAct) dbMenu.addSeparator() dbMenu.addAction(self.migrateCreateAct) @@ -461,11 +561,11 @@ dbMenu.addSeparator() dbMenu.addAction(self.migrationSummaryAct) dbMenu.addAction(self.migrationHistoryAct) - + # main Pyramid menu - menu = QMenu(self.tr('P&yramid'), self.__ui) + menu = QMenu(self.tr("P&yramid"), self.__ui) menu.setTearOffEnabled(True) - + menu.addAction(self.selectProjectAct) menu.addSeparator() menu.addAction(self.runServerAct) @@ -486,18 +586,18 @@ menu.addAction(self.documentationAct) menu.addSeparator() menu.addAction(self.aboutPyramidAct) - + self.__menus["main"] = menu self.__menus["database"] = dbMenu - + self.__setCurrentProject(None) - + return menu - + def getMenu(self, name): """ Public method to get a reference to the requested menu. - + @param name name of the menu @type str @return reference to the menu or None, if no menu with the given @@ -508,16 +608,16 @@ return self.__menus[name] else: return None - + def getMenuNames(self): """ Public method to get the names of all menus. - + @return menu names @rtype list of str """ return list(self.__menus.keys()) - + def registerOpenHook(self): """ Public method to register the open hook to open a translations file @@ -527,48 +627,55 @@ editor = self.__plugin.getPreferences("TranslationsEditor") if editor: self.__translationsBrowser.addHookMethodAndMenuEntry( - "open", self.openPOEditor, - self.tr("Open with {0}").format( - os.path.basename(editor))) + "open", + self.openPOEditor, + self.tr("Open with {0}").format(os.path.basename(editor)), + ) else: self.__translationsBrowser.removeHookMethod("open") - + def projectOpenedHooks(self): """ Public method to add our hook methods. """ if self.__ericProject.getProjectType() == "Pyramid": self.__formsBrowser = ( - ericApp().getObject("ProjectBrowser") - .getProjectBrowser("forms")) + ericApp().getObject("ProjectBrowser").getProjectBrowser("forms") + ) self.__formsBrowser.addHookMethodAndMenuEntry( - "newForm", self.newForm, self.tr("New template...")) - + "newForm", self.newForm, self.tr("New template...") + ) + self.__ericProject.projectLanguageAddedByCode.connect( - self.__projectLanguageAdded) + self.__projectLanguageAdded + ) self.__translationsBrowser = ( - ericApp().getObject("ProjectBrowser") - .getProjectBrowser("translations")) + ericApp().getObject("ProjectBrowser").getProjectBrowser("translations") + ) self.__translationsBrowser.addHookMethodAndMenuEntry( - "extractMessages", self.extractMessages, - self.tr("Extract Messages")) + "extractMessages", self.extractMessages, self.tr("Extract Messages") + ) self.__translationsBrowser.addHookMethodAndMenuEntry( - "releaseAll", self.compileCatalogs, - self.tr("Compile All Catalogs")) + "releaseAll", self.compileCatalogs, self.tr("Compile All Catalogs") + ) self.__translationsBrowser.addHookMethodAndMenuEntry( - "releaseSelected", self.compileSelectedCatalogs, - self.tr("Compile Selected Catalogs")) + "releaseSelected", + self.compileSelectedCatalogs, + self.tr("Compile Selected Catalogs"), + ) self.__translationsBrowser.addHookMethodAndMenuEntry( - "generateAll", self.updateCatalogs, - self.tr("Update All Catalogs")) + "generateAll", self.updateCatalogs, self.tr("Update All Catalogs") + ) self.__translationsBrowser.addHookMethodAndMenuEntry( - "generateSelected", self.updateSelectedCatalogs, - self.tr("Update Selected Catalogs")) - + "generateSelected", + self.updateSelectedCatalogs, + self.tr("Update Selected Catalogs"), + ) + self.__hooksInstalled = True - + self.registerOpenHook() - + def projectClosedHooks(self): """ Public method to remove our hook methods. @@ -576,9 +683,10 @@ if self.__hooksInstalled: self.__formsBrowser.removeHookMethod("newForm") self.__formsBrowser = None - + self.__ericProject.projectLanguageAddedByCode.disconnect( - self.__projectLanguageAdded) + self.__projectLanguageAdded + ) self.__translationsBrowser.removeHookMethod("extractMessages") self.__translationsBrowser.removeHookMethod("releaseAll") self.__translationsBrowser.removeHookMethod("releaseSelected") @@ -586,22 +694,22 @@ self.__translationsBrowser.removeHookMethod("generateSelected") self.__translationsBrowser.removeHookMethod("open") self.__translationsBrowser = None - + self.__hooksInstalled = False - + def newForm(self, path): """ Public method to create a new form. - + @param path full directory path for the new form file @type str """ from .FormSelectionDialog import FormSelectionDialog - + dlg = FormSelectionDialog() if dlg.exec() == QDialog.DialogCode.Accepted: template = dlg.getTemplateText() - + fileFilters = self.tr( "Chameleon Templates (*.pt);;" "Chameleon Text Templates (*.txt);;" @@ -609,32 +717,34 @@ "Mako Templates (*.mak);;" "HTML Files (*.html);;" "HTML Files (*.htm);;" - "All Files (*)") + "All Files (*)" + ) fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( self.__ui, self.tr("New Form"), path, fileFilters, None, - EricFileDialog.DontConfirmOverwrite) + EricFileDialog.DontConfirmOverwrite, + ) if fname: ext = QFileInfo(fname).suffix() if not ext: ex = selectedFilter.split("(*")[1].split(")")[0] if ex: fname += ex - + if os.path.exists(fname): res = EricMessageBox.yesNo( self.__ui, self.tr("New Form"), - self.tr("""The file already exists! Overwrite""" - """ it?"""), - icon=EricMessageBox.Warning) + self.tr("""The file already exists! Overwrite""" """ it?"""), + icon=EricMessageBox.Warning, + ) if not res: # user selected to not overwrite return - + try: with open(fname, "w", encoding="utf-8") as f: f.write(template) @@ -642,18 +752,20 @@ EricMessageBox.critical( self.__ui, self.tr("New Form"), - self.tr("<p>The new form file <b>{0}</b> could" - " not be created.<br/> Problem: {1}</p>") - .format(fname, e)) + self.tr( + "<p>The new form file <b>{0}</b> could" + " not be created.<br/> Problem: {1}</p>" + ).format(fname, e), + ) return - + self.__ericProject.appendFile(fname) self.__formsBrowser.sourceFile.emit(fname) ################################################################## ## methods below implement general functionality ################################################################## - + def projectClosed(self): """ Public method to handle the closing of a project. @@ -661,16 +773,16 @@ if self.__serverProc is not None: self.__serverProcFinished() self.__setCurrentProject(None) - + for dlg in (self.__migrationSummaryDialog,): if dlg is not None: dlg.close() - + def __getExecutablePaths(self, file): """ Private method to build all full paths of an executable file from the environment. - + @param file filename of the executable @type str @return list of full executable names, if the executable file is @@ -679,19 +791,19 @@ @rtype list of str """ paths = [] - + if os.path.isabs(file): if os.access(file, os.X_OK): return [file] else: return [] - + cur_path = os.path.join(os.curdir, file) if os.path.exists(cur_path) and os.access(cur_path, os.X_OK): paths.append(cur_path) - path = os.getenv('PATH') - + path = os.getenv("PATH") + # environment variable not defined if path is not None: dirs = path.split(os.pathsep) @@ -699,20 +811,20 @@ exe = os.path.join(directory, file) if os.access(exe, os.X_OK) and exe not in paths: paths.append(exe) - + return paths - + def supportedPythonVariants(self): """ Public method to get the supported Python variants. - + @return list of supported Python variants @rtype list of str """ variants = [] cmd = "cookiecutter" - - for variant in ['Python3']: + + for variant in ["Python3"]: virtEnv = self.__getVirtualEnvironment(variant) if virtEnv: fullCmd = self.getPyramidCommand(cmd, variant) @@ -731,21 +843,21 @@ fullCmds = self.__getExecutablePaths(cmd) for fullCmd in fullCmds: try: - with open(fullCmd, 'r', encoding='utf-8') as f: + with open(fullCmd, "r", encoding="utf-8") as f: l0 = f.readline() except OSError: l0 = "" if self.__isSuitableForVariant(variant, l0): variants.append(variant) break - + return variants - + def __isSuitableForVariant(self, variant, line0): """ Private method to test, if a detected command file is suitable for the given Python variant. - + @param variant Python variant to test for @type str @param line0 first line of the executable @@ -754,16 +866,15 @@ @rtype bool """ l0 = line0.lower() - ok = (variant.lower() in l0 or - "{0}.".format(variant[-1]) in l0) + ok = variant.lower() in l0 or "{0}.".format(variant[-1]) in l0 ok |= "pypy3" in l0 - + return ok - + def __getVirtualEnvironment(self, language=""): """ Private method to get the path of the virtual environment. - + @param language Python variant to get the virtual environment for (one of '' or 'Python3') @type str @@ -774,30 +885,28 @@ language = self.__ericProject.getProjectLanguage() if self.__virtualEnvManager: if language == "Python3": - venvName = self.__plugin.getPreferences( - "VirtualEnvironmentNamePy3") + venvName = self.__plugin.getPreferences("VirtualEnvironmentNamePy3") else: venvName = "" if venvName: - virtEnv = self.__virtualEnvManager.getVirtualenvDirectory( - venvName) + virtEnv = self.__virtualEnvManager.getVirtualenvDirectory(venvName) if not virtEnv: virtEnv = os.path.dirname( - self.__virtualEnvManager.getVirtualenvInterpreter( - venvName)) + self.__virtualEnvManager.getVirtualenvInterpreter(venvName) + ) if virtEnv.endswith(("Scripts", "bin")): virtEnv = os.path.dirname(virtEnv) else: virtEnv = "" - + if virtEnv and not os.path.exists(virtEnv): virtEnv = "" - return virtEnv # __IGNORE_WARNING_M834__ + return virtEnv # __IGNORE_WARNING_M834__ def __getDebugEnvironment(self, language=""): """ Private method to get the path of the debugger environment. - + @param language Python variant to get the debugger environment for (one of '' or 'Python3') @type str @@ -813,26 +922,25 @@ venvName = Preferences.getDebugger("Python3VirtualEnv") else: venvName = "" - + if venvName: - return self.__virtualEnvManager.getVirtualenvDirectory( - venvName) - + return self.__virtualEnvManager.getVirtualenvDirectory(venvName) + return "" def getProjectVirtualEnvironment(self): """ Public method to generate the path of the project virtual environment. - + @return path of the Pyramid project virtual environment @rtype str """ return os.path.join(self.projectPath(), "env") - + def getPyramidCommand(self, cmd, language="", virtualEnv=""): """ Public method to build a Pyramid command. - + @param cmd command @type str @param language Python variant to get the virtual environment @@ -845,16 +953,16 @@ """ if not language: language = self.__ericProject.getProjectLanguage() - + if not virtualEnv: virtualEnv = self.__getVirtualEnvironment(language) if not virtualEnv: virtualEnv = self.__getDebugEnvironment(language) if isWindowsPlatform(): fullCmds = [ - os.path.join(virtualEnv, "Scripts", cmd + '.exe'), - os.path.join(virtualEnv, "bin", cmd + '.exe'), - cmd # fall back to just cmd + os.path.join(virtualEnv, "Scripts", cmd + ".exe"), + os.path.join(virtualEnv, "bin", cmd + ".exe"), + cmd, # fall back to just cmd ] for cmd in fullCmds: if os.path.exists(cmd): @@ -864,18 +972,18 @@ os.path.join(virtualEnv, "bin", cmd), os.path.join(virtualEnv, "local", "bin", cmd), Utilities.getExecutablePath(cmd), - cmd # fall back to just cmd + cmd, # fall back to just cmd ] for cmd in fullCmds: if os.path.exists(cmd): break return cmd - + def __assemblePyramidCommand(self, cmd, virtualEnv): """ Private method to assemble the full pyramid command for a given virtual environment. - + @param cmd command @type str @param virtualEnv path of the project's Python virtual environment @@ -884,44 +992,42 @@ @rtype str """ return ( - os.path.join(virtualEnv, "Scripts", cmd + '.exe') - if isWindowsPlatform() else - os.path.join(virtualEnv, "bin", cmd) + os.path.join(virtualEnv, "Scripts", cmd + ".exe") + if isWindowsPlatform() + else os.path.join(virtualEnv, "bin", cmd) ) - + def getPythonCommand(self): """ Public method to build the Python command. - + @return python command @rtype str """ language = self.__ericProject.getProjectLanguage() if self.__virtualEnvManager: if language == "Python3": - venvName = self.__plugin.getPreferences( - "VirtualEnvironmentNamePy3") + venvName = self.__plugin.getPreferences("VirtualEnvironmentNamePy3") if not venvName: # if none configured, use the global one venvName = Preferences.getDebugger("Python3VirtualEnv") else: venvName = "" if venvName: - return self.__virtualEnvManager.getVirtualenvInterpreter( - venvName) - + return self.__virtualEnvManager.getVirtualenvInterpreter(venvName) + return "" - + def __pyramidInfo(self): """ Private slot to show some info about Pyramid. """ try: version = self.getPyramidVersionString() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: version = self.tr("not available") url = "http://www.pylonsproject.org/projects/pyramid/about" - + msgBox = EricMessageBox.EricMessageBox( EricMessageBox.Question, self.tr("About Pyramid"), @@ -931,32 +1037,35 @@ " design.</p>" "<p><table>" "<tr><td>Version:</td><td>{0}</td></tr>" - "<tr><td>URL:</td><td><a href=\"{1}\">" + '<tr><td>URL:</td><td><a href="{1}">' "{1}</a></td></tr>" "</table></p>" ).format(version, url), modal=True, - buttons=EricMessageBox.Ok) - msgBox.setIconPixmap(UI.PixmapCache.getPixmap( - os.path.join("ProjectPyramid", "icons", - "pyramid64-{0}".format(self.__iconSuffix)) - )) + buttons=EricMessageBox.Ok, + ) + msgBox.setIconPixmap( + UI.PixmapCache.getPixmap( + os.path.join( + "ProjectPyramid", "icons", "pyramid64-{0}".format(self.__iconSuffix) + ) + ) + ) msgBox.exec() - + def getPyramidVersionString(self): """ Public method to get the Pyramid version as a string. - + @return Pyramid version @rtype str """ if not self.__pyramidVersion: cmd = self.getPyramidCommand( - "pdistreport", - virtualEnv=self.getProjectVirtualEnvironment() + "pdistreport", virtualEnv=self.getProjectVirtualEnvironment() ) try: - output = subprocess.check_output([cmd]) # secok + output = subprocess.check_output([cmd]) # secok outputLines = output.decode().splitlines() for line in outputLines: if line.startswith("Pyramid version:"): @@ -964,13 +1073,13 @@ break except (OSError, subprocess.CalledProcessError): self.__pyramidVersion = "" - + return self.__pyramidVersion - + def getPyramidVersion(self): """ Public method to get the Pyramid version as a tuple. - + @return Pyramid version @rtype tuple of int """ @@ -982,20 +1091,20 @@ pyramidVersionList.append(int(part)) except ValueError: pyramidVersionList.append(part) - + return tuple(pyramidVersionList) - + def isSpawningConsole(self, consoleCmd): """ Public method to check, if the given console is a spawning console. - + @param consoleCmd console command @type str @return tuple of two entries giving an indication, if the console is spawning (boolean) and the (possibly) cleaned console command @rtype str """ - if consoleCmd and consoleCmd[0] == '@': + if consoleCmd and consoleCmd[0] == "@": return (True, consoleCmd[1:]) else: return (False, consoleCmd) @@ -1003,7 +1112,7 @@ def __adjustWorkingDirectory(self, args, wd): """ Private method to adjust the working directory in the arguments list. - + @param args list of arguments to be modified @type list of str @param wd working directory @@ -1017,21 +1126,21 @@ if args[index].startswith("--working-directory="): args[index] = "--working-directory={0}".format(wd) break - + ################################################################## ## slots below implement creation functions ################################################################## - + def __createProject(self): """ Private slot to create a new Pyramid project. """ from .CreateParametersDialog import CreateParametersDialog - + dlg = CreateParametersDialog(self.__ui) if dlg.exec() == QDialog.DialogCode.Accepted: template, version, overwrite, contextData = dlg.getData() - + cmd = self.getPyramidCommand("cookiecutter") args = ["--no-input"] if overwrite: @@ -1041,75 +1150,93 @@ args.append(template) for context, data in contextData.items(): args.append("{0}={1}".format(context, data)) - dlg = PyramidDialog(self.tr("Create Pyramid Project"), - parent=self.__ui) - if dlg.startProcess( - cmd, args, self.__ericProject.getProjectPath() - ): + dlg = PyramidDialog(self.tr("Create Pyramid Project"), parent=self.__ui) + if dlg.startProcess(cmd, args, self.__ericProject.getProjectPath()): dlg.exec() if dlg.normalExit() and "repo_name" in contextData: # search for files created by cookiecutter and add them # to the project projectPath = os.path.join( - self.__ericProject.getProjectPath(), - contextData["repo_name"]) + self.__ericProject.getProjectPath(), contextData["repo_name"] + ) for entry in os.walk(projectPath): for fileName in entry[2]: fullName = os.path.join(entry[0], fileName) self.__ericProject.appendFile(fullName) - + # create the base directory for translations i18nPath = os.path.join( - projectPath, contextData["repo_name"].lower(), - "i18n") + projectPath, contextData["repo_name"].lower(), "i18n" + ) if not os.path.exists(i18nPath): os.makedirs(i18nPath) self.__ericProject.setDirty(True) - + combinedOutput = False argsLists = [] - + # 1. create a Python virtual environment for the project argsLists.append([sys.executable, "-m", "venv", "env"]) # 2. upgrade packaging tools python = self.__assemblePyramidCommand( - "python", os.path.join(projectPath, "env")) - argsLists.append([python, "-m", "pip", "install", - "--upgrade", "pip", "setuptools"]) + "python", os.path.join(projectPath, "env") + ) + argsLists.append( + [ + python, + "-m", + "pip", + "install", + "--upgrade", + "pip", + "setuptools", + ] + ) # 3. install project in editable mode with testing - argsLists.append([python, "-m", "pip", "install", "-e", - ".[testing]"]) - + argsLists.append( + [python, "-m", "pip", "install", "-e", ".[testing]"] + ) + if ( - "backend" in contextData and - contextData["backend"] == "sqlalchemy" + "backend" in contextData + and contextData["backend"] == "sqlalchemy" ): # only SQLAlchemy needs initialization of alembic combinedOutput = True - + # 4. initialize database alembic = self.__assemblePyramidCommand( - "alembic", os.path.join(projectPath, "env")) - argsLists.append([alembic, "-c", "development.ini", - "revision", "--autogenerate", - "--message", "initialized database"]) + "alembic", os.path.join(projectPath, "env") + ) + argsLists.append( + [ + alembic, + "-c", + "development.ini", + "revision", + "--autogenerate", + "--message", + "initialized database", + ] + ) # 5. upgrade database to initial version - argsLists.append([alembic, "-c", "development.ini", - "upgrade", "head"]) - + argsLists.append( + [alembic, "-c", "development.ini", "upgrade", "head"] + ) + dlg = PyramidDialog( self.tr("Initializing Pyramid Project"), combinedOutput=combinedOutput, - parent=self.__ui) - if dlg.startBatchProcesses(argsLists, - workingDir=projectPath): + parent=self.__ui, + ) + if dlg.startBatchProcesses(argsLists, workingDir=projectPath): dlg.exec() - + self.__setCurrentProject(contextData["repo_name"]) - + if ( - "backend" in contextData and - contextData["backend"] == "sqlalchemy" + "backend" in contextData + and contextData["backend"] == "sqlalchemy" ): # add the alembic files created above to the project migrationsPath = self.migrationsPath() @@ -1117,29 +1244,26 @@ for fileName in entry[2]: fullName = os.path.join(entry[0], fileName) self.__ericProject.appendFile(fullName) - + ################################################################## ## methods below implement site related functions ################################################################## - + def __findProjects(self): """ Private method to determine the relative path of all Pyramid projects (= top level dirs). - + @return list of projects @rtype list of str """ projects = [] ppath = self.__ericProject.getProjectPath() for entry in os.listdir(ppath): - if ( - entry[0] not in "._" and - os.path.isdir(os.path.join(ppath, entry)) - ): + if entry[0] not in "._" and os.path.isdir(os.path.join(ppath, entry)): projects.append(entry) return sorted(projects) - + def __selectProject(self): """ Private method to select a Pyramid project to work with. @@ -1162,33 +1286,36 @@ self.tr("Select Pyramid Project"), self.tr("Select the Pyramid project to work with."), projects, - cur, False) + cur, + False, + ) if not ok: projects = None self.__setCurrentProject(project) - + def projectPath(self): """ Public method to calculate the full path of the Pyramid project. - + @return path of the project @rtype str - @exception PyramidNoProjectSelectedException raised, if no project is + @exception PyramidNoProjectSelectedError raised, if no project is selected """ if self.__currentProject is None: self.__selectProject() - + if self.__currentProject is None: - raise PyramidNoProjectSelectedException + raise PyramidNoProjectSelectedError else: - return os.path.join(self.__ericProject.getProjectPath(), - self.__currentProject) - + return os.path.join( + self.__ericProject.getProjectPath(), self.__currentProject + ) + def __setCurrentProject(self, project): """ Private slot to set the current project. - + @param project name of the project @type str """ @@ -1196,15 +1323,14 @@ self.__currentProject = None else: self.__currentProject = project - + curProject = ( - self.tr("None") - if self.__currentProject is None else - self.__currentProject + self.tr("None") if self.__currentProject is None else self.__currentProject ) self.selectProjectAct.setText( - self.tr('&Current Pyramid Project ({0})').format(curProject)) - + self.tr("&Current Pyramid Project ({0})").format(curProject) + ) + if self.__currentProject is None: self.__ericProject.setTranslationPattern("") else: @@ -1214,16 +1340,21 @@ try: outputDir = config.get("init_catalog", "output_dir") except (configparser.NoOptionError, configparser.NoSectionError): - outputDir = '{0}/locale'.format(lowerProject) + outputDir = "{0}/locale".format(lowerProject) try: domain = config.get("init_catalog", "domain") except (configparser.NoOptionError, configparser.NoSectionError): domain = lowerProject self.__ericProject.setTranslationPattern( - os.path.join(project, outputDir, "%language%", - "LC_MESSAGES", "{0}.po".format(domain)) + os.path.join( + project, + outputDir, + "%language%", + "LC_MESSAGES", + "{0}.po".format(domain), + ) ) - + if self.__currentProject is None: self.initializeDbAct.setEnabled(False) with contextlib.suppress(KeyError): @@ -1231,12 +1362,12 @@ else: initCmd = self.__getInitDbCommand() self.initializeDbAct.setEnabled(os.path.exists(initCmd)) - + alembicDir = os.path.join( - self.projectPath(), self.__currentProject, - "alembic", "versions") + self.projectPath(), self.__currentProject, "alembic", "versions" + ) self.__menus["database"].setEnabled(os.path.exists(alembicDir)) - + self.runServerAct.setEnabled(project is not None) self.runBrowserAct.setEnabled(project is not None) self.runPythonShellAct.setEnabled(project is not None) @@ -1244,61 +1375,67 @@ self.showRoutesAct.setEnabled(project is not None) self.showTweensAct.setEnabled(project is not None) self.buildDistroAct.setEnabled(project is not None) - + def __project(self): """ Private method to get the name of the current Pyramid project. - + @return name of the project @rtype str - @exception PyramidNoProjectSelectedException raised, if no project is + @exception PyramidNoProjectSelectedError raised, if no project is selected """ if self.__currentProject is None: self.__selectProject() - + if self.__currentProject is None: - raise PyramidNoProjectSelectedException + raise PyramidNoProjectSelectedError else: return self.__currentProject - + ################################################################## ## slots below implement run functions ################################################################## - + def __runServer(self): """ Private slot to start the Pyramid Web server. """ consoleCmd = self.isSpawningConsole( - self.__plugin.getPreferences("ConsoleCommand"))[1] + self.__plugin.getPreferences("ConsoleCommand") + )[1] if consoleCmd: try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, - self.tr('Run Server'), - self.tr('No current Pyramid project selected or no' - ' Pyramid project created yet. Aborting...')) + self.tr("Run Server"), + self.tr( + "No current Pyramid project selected or no" + " Pyramid project created yet. Aborting..." + ), + ) return - + args = Utilities.parseOptionString(consoleCmd) args[0] = Utilities.getExecutablePath(args[0]) - args.append(self.getPyramidCommand( - "pserve", - virtualEnv=self.getProjectVirtualEnvironment() - )) + args.append( + self.getPyramidCommand( + "pserve", virtualEnv=self.getProjectVirtualEnvironment() + ) + ) args.append("--reload") args.append(os.path.join(projectPath, "development.ini")) - + if isWindowsPlatform(): serverProcStarted, pid = QProcess.startDetached( - args[0], args[1:], projectPath) + args[0], args[1:], projectPath + ) else: if self.__serverProc is not None: self.__serverProcFinished() - + self.__serverProc = QProcess() self.__serverProc.finished.connect(self.__serverProcFinished) self.__serverProc.setWorkingDirectory(projectPath) @@ -1307,36 +1444,40 @@ if not serverProcStarted: EricMessageBox.critical( self.__ui, - self.tr('Process Generation Error'), - self.tr('The Pyramid server could not be started.')) - + self.tr("Process Generation Error"), + self.tr("The Pyramid server could not be started."), + ) + def __serverProcFinished(self): """ Private slot connected to the finished signal. """ if ( - self.__serverProc is not None and - self.__serverProc.state() != QProcess.ProcessState.NotRunning + self.__serverProc is not None + and self.__serverProc.state() != QProcess.ProcessState.NotRunning ): self.__serverProc.terminate() QTimer.singleShot(2000, self.__serverProc.kill) self.__serverProc.waitForFinished(3000) self.__serverProc = None - + def __runBrowser(self): """ Private slot to start the default web browser with the server URL. """ try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, - self.tr('Run Web-Browser'), - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr("Run Web-Browser"), + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + config = configparser.ConfigParser() config.read(os.path.join(projectPath, "development.ini")) try: @@ -1349,53 +1490,59 @@ if not res: EricMessageBox.critical( self.__ui, - self.tr('Run Web-Browser'), - self.tr('Could not start the web-browser for the URL' - ' "{0}".').format(url.toString())) + self.tr("Run Web-Browser"), + self.tr( + "Could not start the web-browser for the URL" ' "{0}".' + ).format(url.toString()), + ) else: self.__ui.launchHelpViewer(url) - + def __runPythonShell(self): """ Private slot to start a Python console for a Pyramid project. """ consoleCmd = self.isSpawningConsole( - self.__plugin.getPreferences("ConsoleCommand"))[1] + self.__plugin.getPreferences("ConsoleCommand") + )[1] if consoleCmd: try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, - self.tr('Start Pyramid Python Console'), - self.tr('No current Pyramid project selected or no' - ' Pyramid project created yet. Aborting...')) + self.tr("Start Pyramid Python Console"), + self.tr( + "No current Pyramid project selected or no" + " Pyramid project created yet. Aborting..." + ), + ) return - + args = Utilities.parseOptionString(consoleCmd) args[0] = Utilities.getExecutablePath(args[0]) - args.append(self.getPyramidCommand( - "pshell", - virtualEnv=self.getProjectVirtualEnvironment() - )) + args.append( + self.getPyramidCommand( + "pshell", virtualEnv=self.getProjectVirtualEnvironment() + ) + ) consoleType = self.__plugin.getPreferences("Python3ConsoleType") args.append("--python-shell={0}".format(consoleType)) args.append(os.path.join(projectPath, "development.ini")) - + self.__adjustWorkingDirectory(args, projectPath) - started, pid = QProcess.startDetached( - args[0], args[1:], projectPath) + started, pid = QProcess.startDetached(args[0], args[1:], projectPath) if not started: EricMessageBox.critical( self.__ui, - self.tr('Process Generation Error'), - self.tr('The Pyramid Shell process could not be' - ' started.')) + self.tr("Process Generation Error"), + self.tr("The Pyramid Shell process could not be" " started."), + ) ################################################################## ## slots below implement distribution functions ################################################################## - + def __buildDistribution(self): """ Private slot to build a distribution file for the current Pyramid @@ -1404,43 +1551,43 @@ title = self.tr("Build Distribution File") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - - from .DistributionTypeSelectionDialog import ( - DistributionTypeSelectionDialog - ) - + + from .DistributionTypeSelectionDialog import DistributionTypeSelectionDialog + dlg = DistributionTypeSelectionDialog(self, projectPath, self.__ui) if dlg.exec() == QDialog.DialogCode.Accepted: formats = dlg.getFormats() cmd = self.getPyramidCommand( - "python", - virtualEnv=self.getProjectVirtualEnvironment() + "python", virtualEnv=self.getProjectVirtualEnvironment() ) args = [] args.append("setup.py") args.append("sdist") if formats: - args.append("--formats={0}".format(','.join(formats))) - + args.append("--formats={0}".format(",".join(formats))) + dia = PyramidDialog( title, - msgSuccess=self.tr("Python distribution file built" - " successfully.")) + msgSuccess=self.tr("Python distribution file built" " successfully."), + ) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + ################################################################## ## slots below implement various debugging functions ################################################################## - + def __showMatchingViews(self): """ Private slot showing all views that would match a given URL. @@ -1448,36 +1595,39 @@ title = self.tr("Show Matching Views") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + url, ok = QInputDialog.getText( self.__ui, self.tr("Show Matching Views"), self.tr("Enter the URL to be matched:"), QLineEdit.EchoMode.Normal, - "/") + "/", + ) if not ok or url == "": return - + cmd = self.getPyramidCommand( - "pviews", - virtualEnv=self.getProjectVirtualEnvironment() + "pviews", virtualEnv=self.getProjectVirtualEnvironment() ) args = [] args.append("development.ini") args.append(url) - + dia = PyramidDialog(title, fixed=True, linewrap=False) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + def __showRoutes(self): """ Private slot showing all URL dispatch routes. @@ -1485,21 +1635,24 @@ title = self.tr("Show Routes") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + from .PyramidRoutesDialog import PyramidRoutesDialog - + dia = PyramidRoutesDialog(self) res = dia.start(projectPath) if res: dia.exec() - + def __showTweens(self): """ Private slot showing all implicit and explicit tween objects. @@ -1507,17 +1660,19 @@ title = self.tr("Show Tween Objects") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + cmd = self.getPyramidCommand( - "ptweens", - virtualEnv=self.getProjectVirtualEnvironment() + "ptweens", virtualEnv=self.getProjectVirtualEnvironment() ) args = [] args.append("development.ini") @@ -1526,26 +1681,26 @@ res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + ################################################################## ## slots below implement documentation functions ################################################################## - + def __showDocumentation(self): """ Private slot to show the helpviewer with the Pyramid documentation. """ page = self.__plugin.getPreferences("PyramidDocUrl") self.__ui.launchHelpViewer(page) - + ################################################################## ## slots below implement translation functions ################################################################## - + def __getLocale(self, filename): """ Private method to extract the locale out of a file name. - + @param filename name of the file used for extraction @type str @return extracted locale or None @@ -1558,17 +1713,17 @@ pattern = self.__ericProject.getTranslationPattern() pattern = os.path.normpath(pattern) pattern = pattern.replace("%language%", "(.*?)") - pattern = pattern.replace('\\', '\\\\') + pattern = pattern.replace("\\", "\\\\") match = re.search(pattern, filename) if match is not None: return match.group(1) - + return None - + def __normalizeList(self, filenames): """ Private method to normalize a list of file names. - + @param filenames list of file names to normalize @type list of str @return normalized file names @@ -1580,13 +1735,13 @@ filename = filename.replace(".mo", ".po") if filename not in nfilenames: nfilenames.append(filename) - + return nfilenames - + def __projectFilteredList(self, filenames): """ Private method to filter a list of file names by Pyramid project. - + @param filenames list of file names to be filtered @type list of str @return file names belonging to the current site @@ -1597,9 +1752,9 @@ for filename in filenames: if filename.startswith(project + os.sep): nfilenames.append(filename) - + return nfilenames - + def extractMessages(self): """ Public method to extract the messages catalog template file. @@ -1607,12 +1762,15 @@ title = self.tr("Extract messages") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return config = configparser.ConfigParser() @@ -1623,130 +1781,138 @@ EricMessageBox.warning( self.__ui, title, - self.tr('No setup.cfg found or no "extract_messages"' - ' section found in setup.cfg.')) + self.tr( + 'No setup.cfg found or no "extract_messages"' + " section found in setup.cfg." + ), + ) return except configparser.NoOptionError: EricMessageBox.warning( - self.__ui, - title, - self.tr('No "output_file" option found in setup.cfg.')) + self.__ui, title, self.tr('No "output_file" option found in setup.cfg.') + ) return - + with contextlib.suppress(OSError): path = os.path.join(projectPath, os.path.dirname(potFile)) os.makedirs(path) - + cmd = self.getPythonCommand() args = [] args.append("setup.py") args.append("extract_messages") - + dia = PyramidDialog( - title, - msgSuccess=self.tr("\nMessages extracted successfully.")) + title, msgSuccess=self.tr("\nMessages extracted successfully.") + ) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() self.__ericProject.appendFile(os.path.join(projectPath, potFile)) - + def __projectLanguageAdded(self, code): """ Private slot handling the addition of a new language. - + @param code language code of the new language @type str """ - title = self.tr( - "Initializing message catalog for '{0}'").format(code) + title = self.tr("Initializing message catalog for '{0}'").format(code) try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + cmd = self.getPythonCommand() args = [] args.append("setup.py") args.append("init_catalog") args.append("-l") args.append(code) - + dia = PyramidDialog( - title, - msgSuccess=self.tr("\nMessage catalog initialized" - " successfully.")) + title, msgSuccess=self.tr("\nMessage catalog initialized" " successfully.") + ) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + langFile = self.__ericProject.getTranslationPattern().replace( - "%language%", code) + "%language%", code + ) self.__ericProject.appendFile(langFile) - + def compileCatalogs(self, filenames): """ Public method to compile the message catalogs. - + @param filenames list of filenames (not used) @type list of str """ title = self.tr("Compiling message catalogs") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + cmd = self.getPythonCommand() args = [] args.append("setup.py") args.append("compile_catalog") - + dia = PyramidDialog( - title, - msgSuccess=self.tr("\nMessage catalogs compiled" - " successfully.")) + title, msgSuccess=self.tr("\nMessage catalogs compiled" " successfully.") + ) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + for entry in os.walk(projectPath): for fileName in entry[2]: fullName = os.path.join(entry[0], fileName) - if fullName.endswith('.mo'): + if fullName.endswith(".mo"): self.__ericProject.appendFile(fullName) - + def compileSelectedCatalogs(self, filenames): """ Public method to update the message catalogs. - + @param filenames list of file names @type list of str """ title = self.tr("Compiling message catalogs") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + argsLists = [] - - for filename in self.__normalizeList( - self.__projectFilteredList(filenames)): + + for filename in self.__normalizeList(self.__projectFilteredList(filenames)): locale = self.__getLocale(filename) if locale: args = [] @@ -1756,80 +1922,83 @@ args.append("-l") args.append(locale) argsLists.append(args) - + if len(argsLists) == 0: EricMessageBox.warning( - self.__ui, - title, - self.tr('No locales detected. Aborting...')) + self.__ui, title, self.tr("No locales detected. Aborting...") + ) return - + dia = PyramidDialog( - title, - msgSuccess=self.tr("\nMessage catalogs compiled" - " successfully.")) + title, msgSuccess=self.tr("\nMessage catalogs compiled" " successfully.") + ) res = dia.startBatchProcesses(argsLists, projectPath) if res: dia.exec() - + for entry in os.walk(self.__sitePath()): for fileName in entry[2]: fullName = os.path.join(entry[0], fileName) - if fullName.endswith('.mo'): + if fullName.endswith(".mo"): self.__ericProject.appendFile(fullName) - + def updateCatalogs(self, filenames): """ Public method to update the message catalogs. - + @param filenames list of filenames (not used) @type list of str """ title = self.tr("Updating message catalogs") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + cmd = self.getPythonCommand() args = [] args.append("setup.py") args.append("update_catalog") - + dia = PyramidDialog( - title, - msgSuccess=self.tr("\nMessage catalogs updated successfully.")) + title, msgSuccess=self.tr("\nMessage catalogs updated successfully.") + ) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + def updateSelectedCatalogs(self, filenames): """ Public method to update the message catalogs. - + @param filenames list of filenames @type list of str """ title = self.tr("Updating message catalogs") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + argsLists = [] - - for filename in self.__normalizeList( - self.__projectFilteredList(filenames)): + + for filename in self.__normalizeList(self.__projectFilteredList(filenames)): locale = self.__getLocale(filename) if locale: args = [] @@ -1839,25 +2008,24 @@ args.append("-l") args.append(locale) argsLists.append(args) - + if len(argsLists) == 0: EricMessageBox.warning( - self.__ui, - title, - self.tr('No locales detected. Aborting...')) + self.__ui, title, self.tr("No locales detected. Aborting...") + ) return - + dia = PyramidDialog( - title, - msgSuccess=self.tr("\nMessage catalogs updated successfully.")) + title, msgSuccess=self.tr("\nMessage catalogs updated successfully.") + ) res = dia.startBatchProcesses(argsLists, projectPath) if res: dia.exec() - + def openPOEditor(self, poFile): """ Public method to edit the given file in an external .po editor. - + @param poFile name of the .po file @type str """ @@ -1865,66 +2033,69 @@ if poFile.endswith(".po") and editor: try: wd = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: wd = "" started, pid = QProcess.startDetached(editor, [poFile], wd) if not started: EricMessageBox.critical( None, - self.tr('Process Generation Error'), - self.tr('The translations editor process ({0}) could' - ' not be started.').format( - os.path.basename(editor))) - + self.tr("Process Generation Error"), + self.tr( + "The translations editor process ({0}) could" " not be started." + ).format(os.path.basename(editor)), + ) + ####################################################################### ## database related methods and slots below ####################################################################### - + def getAlembicCommand(self): """ Public method to get the path to the alembic executable of the current Pyramid project. - + @return path to the alembic executable @rtype str """ return self.getPyramidCommand( - "alembic", - virtualEnv=self.getProjectVirtualEnvironment() + "alembic", virtualEnv=self.getProjectVirtualEnvironment() ) - + def migrationsPath(self): """ Public method to get the path to the migrations directory of the current Pyramid project. - + @return pathof the directory containing the migrations @rtype str """ - return os.path.join(self.projectPath(), self.__currentProject, - "alembic", "versions") - + return os.path.join( + self.projectPath(), self.__currentProject, "alembic", "versions" + ) + def __getInitDbCommand(self): """ Private method to create the path to the initialization script. - + @return path to the initialization script @rtype str """ try: cmd = "initialize_{0}_db".format(self.__project()) return self.getPyramidCommand( - cmd, - virtualEnv=self.getProjectVirtualEnvironment() + cmd, virtualEnv=self.getProjectVirtualEnvironment() ) - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, self.tr("Initialize Database"), - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return "" - + @pyqtSlot() def __initializeDatabase(self): """ @@ -1933,25 +2104,28 @@ title = self.tr("Initialize Database") try: projectPath = self.projectPath() - except PyramidNoProjectSelectedException: + except PyramidNoProjectSelectedError: EricMessageBox.warning( self.__ui, title, - self.tr('No current Pyramid project selected or no Pyramid' - ' project created yet. Aborting...')) + self.tr( + "No current Pyramid project selected or no Pyramid" + " project created yet. Aborting..." + ), + ) return - + cmd = self.__getInitDbCommand() args = [] args.append("development.ini") - + dia = PyramidDialog( - title, - msgSuccess=self.tr("Database initialized successfully.")) + title, msgSuccess=self.tr("Database initialized successfully.") + ) res = dia.startProcess(cmd, args, projectPath) if res: dia.exec() - + @pyqtSlot() def __createMigration(self): """ @@ -1960,99 +2134,101 @@ title = self.tr("Create Migration") projectPath = self.projectPath() migrations = self.migrationsPath() - + message, ok = QInputDialog.getText( None, title, self.tr("Enter a short message for the migration:"), - QLineEdit.EchoMode.Normal) + QLineEdit.EchoMode.Normal, + ) if ok: args = ["-c", "development.ini", "revision", "--autogenerate"] if migrations: args += ["--version-path", migrations] if message: args += ["--message", message] - + dlg = PyramidDialog( title, msgSuccess=self.tr("\nMigration created successfully."), - linewrap=False, combinedOutput=True, - parent=self.__ui + linewrap=False, + combinedOutput=True, + parent=self.__ui, ) - if dlg.startProcess(self.getAlembicCommand(), args, - workingDir=projectPath): + if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath): dlg.exec() if dlg.normalExit(): versionsPattern = os.path.join(migrations, "*.py") for fileName in glob.iglob(versionsPattern): self.__ericProject.appendFile(fileName) - + @pyqtSlot() def upgradeDatabase(self, revision=None): """ Public slot to upgrade the database to the head or a given version. - + @param revision migration revision to upgrade to @type str """ title = self.tr("Upgrade Database") projectPath = self.projectPath() - + args = ["-c", "development.ini", "upgrade"] if revision: args.append(revision) else: args.append("head") - + dlg = PyramidDialog( title, msgSuccess=self.tr("\nDatabase upgraded successfully."), - linewrap=False, combinedOutput=True, parent=self.__ui + linewrap=False, + combinedOutput=True, + parent=self.__ui, ) - if dlg.startProcess(self.getAlembicCommand(), args, - workingDir=projectPath): + if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath): dlg.exec() - + @pyqtSlot() def downgradeDatabase(self, revision=None): """ Public slot to downgrade the database to the previous or a given version. - + @param revision migration revision to downgrade to @type str """ title = self.tr("Downgrade Database") projectPath = self.projectPath() - + args = ["-c", "development.ini", "downgrade"] if revision: args.append(revision) else: args.append("-1") - + dlg = PyramidDialog( title, msgSuccess=self.tr("\nDatabase downgraded successfully."), - linewrap=False, combinedOutput=True, parent=self.__ui + linewrap=False, + combinedOutput=True, + parent=self.__ui, ) - if dlg.startProcess(self.getAlembicCommand(), args, - workingDir=projectPath): + if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath): dlg.exec() - + @pyqtSlot() def __showMigrationsSummary(self): """ Private slot to show a migrations history summary. """ from .MigrateSummaryDialog import MigrateSummaryDialog - + if self.__migrationSummaryDialog is None: - self.__migrationSummaryDialog = MigrateSummaryDialog( - self, parent=self.__ui) - + self.__migrationSummaryDialog = MigrateSummaryDialog(self, parent=self.__ui) + self.__migrationSummaryDialog.showSummary() - + @pyqtSlot() def __showMigrationsHistory(self): """ @@ -2060,14 +2236,11 @@ """ title = self.tr("Migrations History") projectPath = self.projectPath() - - args = ["-c", "development.ini", "history", "--indicate-current", - "--verbose"] - + + args = ["-c", "development.ini", "history", "--indicate-current", "--verbose"] + dlg = PyramidDialog( - title, - linewrap=False, combinedOutput=True, parent=self.__ui + title, linewrap=False, combinedOutput=True, parent=self.__ui ) - if dlg.startProcess(self.getAlembicCommand(), args, - workingDir=projectPath): + if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath): dlg.exec()