ProjectPyramid/Project.py

branch
eric7
changeset 159
d4e7f5a389e6
parent 156
62170c2682a3
child 160
41b23683d5a1
equal deleted inserted replaced
158:24582cac737e 159:d4e7f5a389e6
10 import configparser 10 import configparser
11 import contextlib 11 import contextlib
12 import glob 12 import glob
13 import os 13 import os
14 import re 14 import re
15 import subprocess # secok 15 import subprocess # secok
16 import sys 16 import sys
17 17
18 from PyQt6.QtCore import ( 18 from PyQt6.QtCore import pyqtSlot, QObject, QFileInfo, QTimer, QUrl, QIODeviceBase
19 pyqtSlot, QObject, QFileInfo, QTimer, QUrl, QIODeviceBase
20 )
21 from PyQt6.QtGui import QDesktopServices 19 from PyQt6.QtGui import QDesktopServices
22 from PyQt6.QtWidgets import QMenu, QDialog, QInputDialog, QLineEdit 20 from PyQt6.QtWidgets import QMenu, QDialog, QInputDialog, QLineEdit
23 from PyQt6.QtCore import QProcess as QProcessPyQt 21 from PyQt6.QtCore import QProcess as QProcessPyQt
24 22
25 from EricWidgets.EricApplication import ericApp 23 from EricWidgets.EricApplication import ericApp
32 import Utilities 30 import Utilities
33 from Globals import isWindowsPlatform 31 from Globals import isWindowsPlatform
34 import UI.PixmapCache 32 import UI.PixmapCache
35 33
36 34
37 class PyramidNoProjectSelectedException(Exception): 35 class PyramidNoProjectSelectedError(Exception):
38 """ 36 """
39 Exception thrown to signal, that there is no current Pyramid project. 37 Exception thrown to signal, that there is no current Pyramid project.
40 """ 38 """
39
41 pass 40 pass
42 41
43 42
44 class QProcess(QProcessPyQt): 43 class QProcess(QProcessPyQt):
45 """ 44 """
46 Class transforming the call arguments in case of gnome-terminal. 45 Class transforming the call arguments in case of gnome-terminal.
47 """ 46 """
47
48 def start(self, cmd, args=None, mode=QIODeviceBase.OpenModeFlag.ReadWrite): 48 def start(self, cmd, args=None, mode=QIODeviceBase.OpenModeFlag.ReadWrite):
49 """ 49 """
50 Public method to start the given program (cmd) in a new process, if 50 Public method to start the given program (cmd) in a new process, if
51 none is already running, passing the command line arguments in args. 51 none is already running, passing the command line arguments in args.
52 52
53 @param cmd start the given program cmd 53 @param cmd start the given program cmd
54 @type str 54 @type str
55 @param args list of parameters 55 @param args list of parameters
56 @type list of str 56 @type list of str
57 @param mode access mode 57 @param mode access mode
58 @type QIODeviceBase.OpenMode 58 @type QIODeviceBase.OpenMode
59 """ 59 """
60 if args is None: 60 if args is None:
61 args = [] 61 args = []
62 62
63 if ( 63 if (
64 cmd.endswith(('gnome-terminal', 'konsole', 'xfce4-terminal', 64 cmd.endswith(
65 'mate-terminal')) and 65 ("gnome-terminal", "konsole", "xfce4-terminal", "mate-terminal")
66 '-e' in args 66 )
67 and "-e" in args
67 ): 68 ):
68 index = args.index('-e') + 1 69 index = args.index("-e") + 1
69 cargs = ' '.join(args[index:]) 70 cargs = " ".join(args[index:])
70 args[index:] = [cargs] 71 args[index:] = [cargs]
71 72
72 super().start(cmd, args, mode) 73 super().start(cmd, args, mode)
73 74
74 @staticmethod 75 @staticmethod
75 def startDetached(cmd, args=None, path=''): 76 def startDetached(cmd, args=None, path=""):
76 """ 77 """
77 Public static method to start the given program (cmd) in a new process, 78 Public static method to start the given program (cmd) in a new process,
78 if none is already running, passing the command line arguments in args. 79 if none is already running, passing the command line arguments in args.
79 80
80 @param cmd start the given program cmd 81 @param cmd start the given program cmd
81 @type str 82 @type str
82 @param args list of parameters 83 @param args list of parameters
83 @type list of str 84 @type list of str
84 @param path new working directory 85 @param path new working directory
86 @return tuple of successful start and process id 87 @return tuple of successful start and process id
87 @rtype tuple of (bool, int) 88 @rtype tuple of (bool, int)
88 """ 89 """
89 if args is None: 90 if args is None:
90 args = [] 91 args = []
91 92
92 if ( 93 if (
93 cmd.endswith(('gnome-terminal', 'konsole', 'xfce4-terminal', 94 cmd.endswith(
94 'mate-terminal')) and 95 ("gnome-terminal", "konsole", "xfce4-terminal", "mate-terminal")
95 '-e' in args 96 )
97 and "-e" in args
96 ): 98 ):
97 index = args.index('-e') + 1 99 index = args.index("-e") + 1
98 cargs = ' '.join(args[index:]) 100 cargs = " ".join(args[index:])
99 args[index:] = [cargs] 101 args[index:] = [cargs]
100 102
101 return QProcessPyQt.startDetached(cmd, args, path) 103 return QProcessPyQt.startDetached(cmd, args, path)
102 104
103 105
104 class Project(QObject): 106 class Project(QObject):
105 """ 107 """
106 Class implementing the Pyramid project support. 108 Class implementing the Pyramid project support.
107 """ 109 """
110
108 def __init__(self, plugin, iconSuffix, parent=None): 111 def __init__(self, plugin, iconSuffix, parent=None):
109 """ 112 """
110 Constructor 113 Constructor
111 114
112 @param plugin reference to the plugin object 115 @param plugin reference to the plugin object
113 @type ProjectPyramidPlugin 116 @type ProjectPyramidPlugin
114 @param iconSuffix suffix for the icons 117 @param iconSuffix suffix for the icons
115 @type str 118 @type str
116 @param parent parent 119 @param parent parent
117 @type QObject 120 @type QObject
118 """ 121 """
119 super().__init__(parent) 122 super().__init__(parent)
120 123
121 self.__plugin = plugin 124 self.__plugin = plugin
122 self.__iconSuffix = iconSuffix 125 self.__iconSuffix = iconSuffix
123 self.__ui = parent 126 self.__ui = parent
124 self.__ericProject = ericApp().getObject("Project") 127 self.__ericProject = ericApp().getObject("Project")
125 self.__virtualEnvManager = ericApp().getObject("VirtualEnvManager") 128 self.__virtualEnvManager = ericApp().getObject("VirtualEnvManager")
126 self.__hooksInstalled = False 129 self.__hooksInstalled = False
127 130
128 self.__menus = {} # dictionary with references to menus 131 self.__menus = {} # dictionary with references to menus
129 132
130 self.__serverProc = None 133 self.__serverProc = None
131 134
132 self.__pyramidVersion = "" 135 self.__pyramidVersion = ""
133 136
134 self.__migrationSummaryDialog = None 137 self.__migrationSummaryDialog = None
135 138
136 def initActions(self): 139 def initActions(self):
137 """ 140 """
138 Public method to define the Pyramid actions. 141 Public method to define the Pyramid actions.
139 """ 142 """
140 self.actions = [] 143 self.actions = []
141 144
142 self.selectProjectAct = EricAction( 145 self.selectProjectAct = EricAction(
143 self.tr('Current Pyramid Project'), 146 self.tr("Current Pyramid Project"),
144 "", 147 "",
145 0, 0, 148 0,
146 self, 'pyramid_current_project') 149 0,
147 self.selectProjectAct.setStatusTip(self.tr( 150 self,
148 'Selects the current Pyramid project')) 151 "pyramid_current_project",
149 self.selectProjectAct.setWhatsThis(self.tr( 152 )
150 """<b>Current Pyramid Project</b>""" 153 self.selectProjectAct.setStatusTip(
151 """<p>Selects the Pyramid project. Used for multi-project """ 154 self.tr("Selects the current Pyramid project")
152 """Pyramid projects to switch between the projects.</p>""" 155 )
153 )) 156 self.selectProjectAct.setWhatsThis(
157 self.tr(
158 """<b>Current Pyramid Project</b>"""
159 """<p>Selects the Pyramid project. Used for multi-project """
160 """Pyramid projects to switch between the projects.</p>"""
161 )
162 )
154 self.selectProjectAct.triggered.connect(self.__selectProject) 163 self.selectProjectAct.triggered.connect(self.__selectProject)
155 self.actions.append(self.selectProjectAct) 164 self.actions.append(self.selectProjectAct)
156 165
157 ############################### 166 ###############################
158 ## create actions below ## 167 ## create actions below ##
159 ############################### 168 ###############################
160 169
161 self.createProjectAct = EricAction( 170 self.createProjectAct = EricAction(
162 self.tr('Create Pyramid Project'), 171 self.tr("Create Pyramid Project"),
163 self.tr('Create Pyramid &Project'), 172 self.tr("Create Pyramid &Project"),
164 0, 0, 173 0,
165 self, 'pyramid_create_project') 174 0,
166 self.createProjectAct.setStatusTip(self.tr( 175 self,
167 'Creates a new Pyramid project')) 176 "pyramid_create_project",
168 self.createProjectAct.setWhatsThis(self.tr( 177 )
169 """<b>Create Pyramid Project</b>""" 178 self.createProjectAct.setStatusTip(self.tr("Creates a new Pyramid project"))
170 """<p>Creates a new Pyramid project using "pcreate".</p>""" 179 self.createProjectAct.setWhatsThis(
171 )) 180 self.tr(
181 """<b>Create Pyramid Project</b>"""
182 """<p>Creates a new Pyramid project using "pcreate".</p>"""
183 )
184 )
172 self.createProjectAct.triggered.connect(self.__createProject) 185 self.createProjectAct.triggered.connect(self.__createProject)
173 self.actions.append(self.createProjectAct) 186 self.actions.append(self.createProjectAct)
174 187
175 ############################## 188 ##############################
176 ## run actions below ## 189 ## run actions below ##
177 ############################## 190 ##############################
178 191
179 self.runServerAct = EricAction( 192 self.runServerAct = EricAction(
180 self.tr('Run Server'), 193 self.tr("Run Server"),
181 self.tr('Run &Server'), 194 self.tr("Run &Server"),
182 0, 0, 195 0,
183 self, 'pyramid_run_server') 196 0,
184 self.runServerAct.setStatusTip(self.tr( 197 self,
185 'Starts the Pyramid Web server')) 198 "pyramid_run_server",
186 self.runServerAct.setWhatsThis(self.tr( 199 )
187 """<b>Run Server</b>""" 200 self.runServerAct.setStatusTip(self.tr("Starts the Pyramid Web server"))
188 """<p>Starts the Pyramid Web server using""" 201 self.runServerAct.setWhatsThis(
189 """ "pserve --reload development.ini".</p>""" 202 self.tr(
190 )) 203 """<b>Run Server</b>"""
204 """<p>Starts the Pyramid Web server using"""
205 """ "pserve --reload development.ini".</p>"""
206 )
207 )
191 self.runServerAct.triggered.connect(self.__runServer) 208 self.runServerAct.triggered.connect(self.__runServer)
192 self.actions.append(self.runServerAct) 209 self.actions.append(self.runServerAct)
193 210
194 self.runBrowserAct = EricAction( 211 self.runBrowserAct = EricAction(
195 self.tr('Run Web-Browser'), 212 self.tr("Run Web-Browser"),
196 self.tr('Run &Web-Browser'), 213 self.tr("Run &Web-Browser"),
197 0, 0, 214 0,
198 self, 'pyramid_run_browser') 215 0,
199 self.runBrowserAct.setStatusTip(self.tr( 216 self,
200 'Starts the default Web-Browser with the URL of the Pyramid Web' 217 "pyramid_run_browser",
201 ' server')) 218 )
202 self.runBrowserAct.setWhatsThis(self.tr( 219 self.runBrowserAct.setStatusTip(
203 """<b>Run Web-Browser</b>""" 220 self.tr(
204 """<p>Starts the default Web-Browser with the URL of the """ 221 "Starts the default Web-Browser with the URL of the Pyramid Web"
205 """Pyramid Web server.</p>""" 222 " server"
206 )) 223 )
224 )
225 self.runBrowserAct.setWhatsThis(
226 self.tr(
227 """<b>Run Web-Browser</b>"""
228 """<p>Starts the default Web-Browser with the URL of the """
229 """Pyramid Web server.</p>"""
230 )
231 )
207 self.runBrowserAct.triggered.connect(self.__runBrowser) 232 self.runBrowserAct.triggered.connect(self.__runBrowser)
208 self.actions.append(self.runBrowserAct) 233 self.actions.append(self.runBrowserAct)
209 234
210 self.runPythonShellAct = EricAction( 235 self.runPythonShellAct = EricAction(
211 self.tr('Start Pyramid Python Console'), 236 self.tr("Start Pyramid Python Console"),
212 self.tr('Start Pyramid &Python Console'), 237 self.tr("Start Pyramid &Python Console"),
213 0, 0, 238 0,
214 self, 'pyramid_python_console') 239 0,
215 self.runPythonShellAct.setStatusTip(self.tr( 240 self,
216 'Starts an interactive Python interpreter')) 241 "pyramid_python_console",
217 self.runPythonShellAct.setWhatsThis(self.tr( 242 )
218 """<b>Start Pyramid Python Console</b>""" 243 self.runPythonShellAct.setStatusTip(
219 """<p>Starts an interactive Python interpreter.</p>""" 244 self.tr("Starts an interactive Python interpreter")
220 )) 245 )
246 self.runPythonShellAct.setWhatsThis(
247 self.tr(
248 """<b>Start Pyramid Python Console</b>"""
249 """<p>Starts an interactive Python interpreter.</p>"""
250 )
251 )
221 self.runPythonShellAct.triggered.connect(self.__runPythonShell) 252 self.runPythonShellAct.triggered.connect(self.__runPythonShell)
222 self.actions.append(self.runPythonShellAct) 253 self.actions.append(self.runPythonShellAct)
223 254
224 ############################### 255 ###############################
225 ## show actions below ## 256 ## show actions below ##
226 ############################### 257 ###############################
227 258
228 self.showViewsAct = EricAction( 259 self.showViewsAct = EricAction(
229 self.tr('Show Matching Views'), 260 self.tr("Show Matching Views"),
230 self.tr('Show Matching &Views'), 261 self.tr("Show Matching &Views"),
231 0, 0, 262 0,
232 self, 'pyramid_show_views') 263 0,
233 self.showViewsAct.setStatusTip(self.tr( 264 self,
234 'Show views matching a given URL')) 265 "pyramid_show_views",
235 self.showViewsAct.setWhatsThis(self.tr( 266 )
236 """<b>Show Matching Views</b>""" 267 self.showViewsAct.setStatusTip(self.tr("Show views matching a given URL"))
237 """<p>Show views matching a given URL.</p>""" 268 self.showViewsAct.setWhatsThis(
238 )) 269 self.tr(
270 """<b>Show Matching Views</b>"""
271 """<p>Show views matching a given URL.</p>"""
272 )
273 )
239 self.showViewsAct.triggered.connect(self.__showMatchingViews) 274 self.showViewsAct.triggered.connect(self.__showMatchingViews)
240 self.actions.append(self.showViewsAct) 275 self.actions.append(self.showViewsAct)
241 276
242 self.showRoutesAct = EricAction( 277 self.showRoutesAct = EricAction(
243 self.tr('Show Routes'), 278 self.tr("Show Routes"),
244 self.tr('Show &Routes'), 279 self.tr("Show &Routes"),
245 0, 0, 280 0,
246 self, 'pyramid_show_routes') 281 0,
247 self.showRoutesAct.setStatusTip(self.tr( 282 self,
248 'Show all URL dispatch routes used by a Pyramid application')) 283 "pyramid_show_routes",
249 self.showRoutesAct.setWhatsThis(self.tr( 284 )
250 """<b>Show Routes</b>""" 285 self.showRoutesAct.setStatusTip(
251 """<p>Show all URL dispatch routes used by a Pyramid application""" 286 self.tr("Show all URL dispatch routes used by a Pyramid application")
252 """ in the order in which they are evaluated.</p>""" 287 )
253 )) 288 self.showRoutesAct.setWhatsThis(
289 self.tr(
290 """<b>Show Routes</b>"""
291 """<p>Show all URL dispatch routes used by a Pyramid application"""
292 """ in the order in which they are evaluated.</p>"""
293 )
294 )
254 self.showRoutesAct.triggered.connect(self.__showRoutes) 295 self.showRoutesAct.triggered.connect(self.__showRoutes)
255 self.actions.append(self.showRoutesAct) 296 self.actions.append(self.showRoutesAct)
256 297
257 self.showTweensAct = EricAction( 298 self.showTweensAct = EricAction(
258 self.tr('Show Tween Objects'), 299 self.tr("Show Tween Objects"),
259 self.tr('Show &Tween Objects'), 300 self.tr("Show &Tween Objects"),
260 0, 0, 301 0,
261 self, 'pyramid_show_routes') 302 0,
262 self.showTweensAct.setStatusTip(self.tr( 303 self,
263 'Show all implicit and explicit tween objects used by a Pyramid' 304 "pyramid_show_routes",
264 ' application')) 305 )
265 self.showTweensAct.setWhatsThis(self.tr( 306 self.showTweensAct.setStatusTip(
266 """<b>Show Tween Objects</b>""" 307 self.tr(
267 """<p>Show all implicit and explicit tween objects used by a""" 308 "Show all implicit and explicit tween objects used by a Pyramid"
268 """ Pyramid application.</p>""" 309 " application"
269 )) 310 )
311 )
312 self.showTweensAct.setWhatsThis(
313 self.tr(
314 """<b>Show Tween Objects</b>"""
315 """<p>Show all implicit and explicit tween objects used by a"""
316 """ Pyramid application.</p>"""
317 )
318 )
270 self.showTweensAct.triggered.connect(self.__showTweens) 319 self.showTweensAct.triggered.connect(self.__showTweens)
271 self.actions.append(self.showTweensAct) 320 self.actions.append(self.showTweensAct)
272 321
273 ################################## 322 ##################################
274 ## distribution actions below ## 323 ## distribution actions below ##
275 ################################## 324 ##################################
276 325
277 self.buildDistroAct = EricAction( 326 self.buildDistroAct = EricAction(
278 self.tr('Build Distribution'), 327 self.tr("Build Distribution"),
279 self.tr('Build &Distribution'), 328 self.tr("Build &Distribution"),
280 0, 0, 329 0,
281 self, 'pyramid_build_distribution') 330 0,
282 self.buildDistroAct.setStatusTip(self.tr( 331 self,
283 'Builds a distribution file for the Pyramid project')) 332 "pyramid_build_distribution",
284 self.buildDistroAct.setWhatsThis(self.tr( 333 )
285 """<b>Build Distribution</b>""" 334 self.buildDistroAct.setStatusTip(
286 """<p>Builds a distribution file for the Pyramid project using""" 335 self.tr("Builds a distribution file for the Pyramid project")
287 """ "python setup.py sdist".</p>""" 336 )
288 )) 337 self.buildDistroAct.setWhatsThis(
338 self.tr(
339 """<b>Build Distribution</b>"""
340 """<p>Builds a distribution file for the Pyramid project using"""
341 """ "python setup.py sdist".</p>"""
342 )
343 )
289 self.buildDistroAct.triggered.connect(self.__buildDistribution) 344 self.buildDistroAct.triggered.connect(self.__buildDistribution)
290 self.actions.append(self.buildDistroAct) 345 self.actions.append(self.buildDistroAct)
291 346
292 ################################## 347 ##################################
293 ## documentation action below ## 348 ## documentation action below ##
294 ################################## 349 ##################################
295 350
296 self.documentationAct = EricAction( 351 self.documentationAct = EricAction(
297 self.tr('Documentation'), 352 self.tr("Documentation"),
298 self.tr('D&ocumentation'), 353 self.tr("D&ocumentation"),
299 0, 0, 354 0,
300 self, 'pyramid_documentation') 355 0,
301 self.documentationAct.setStatusTip(self.tr( 356 self,
302 'Shows the help viewer with the Pyramid documentation')) 357 "pyramid_documentation",
303 self.documentationAct.setWhatsThis(self.tr( 358 )
304 """<b>Documentation</b>""" 359 self.documentationAct.setStatusTip(
305 """<p>Shows the help viewer with the Pyramid documentation.</p>""" 360 self.tr("Shows the help viewer with the Pyramid documentation")
306 )) 361 )
362 self.documentationAct.setWhatsThis(
363 self.tr(
364 """<b>Documentation</b>"""
365 """<p>Shows the help viewer with the Pyramid documentation.</p>"""
366 )
367 )
307 self.documentationAct.triggered.connect(self.__showDocumentation) 368 self.documentationAct.triggered.connect(self.__showDocumentation)
308 self.actions.append(self.documentationAct) 369 self.actions.append(self.documentationAct)
309 370
310 ############################## 371 ##############################
311 ## about action below ## 372 ## about action below ##
312 ############################## 373 ##############################
313 374
314 self.aboutPyramidAct = EricAction( 375 self.aboutPyramidAct = EricAction(
315 self.tr('About Pyramid'), 376 self.tr("About Pyramid"),
316 self.tr('About P&yramid'), 377 self.tr("About P&yramid"),
317 0, 0, 378 0,
318 self, 'pyramid_about') 379 0,
319 self.aboutPyramidAct.setStatusTip(self.tr( 380 self,
320 'Shows some information about Pyramid')) 381 "pyramid_about",
321 self.aboutPyramidAct.setWhatsThis(self.tr( 382 )
322 """<b>About Pyramid</b>""" 383 self.aboutPyramidAct.setStatusTip(
323 """<p>Shows some information about Pyramid.</p>""" 384 self.tr("Shows some information about Pyramid")
324 )) 385 )
386 self.aboutPyramidAct.setWhatsThis(
387 self.tr(
388 """<b>About Pyramid</b>"""
389 """<p>Shows some information about Pyramid.</p>"""
390 )
391 )
325 self.aboutPyramidAct.triggered.connect(self.__pyramidInfo) 392 self.aboutPyramidAct.triggered.connect(self.__pyramidInfo)
326 self.actions.append(self.aboutPyramidAct) 393 self.actions.append(self.aboutPyramidAct)
327 394
328 self.__initDatabaseActions() 395 self.__initDatabaseActions()
329 396
330 self.__setCurrentProject(None) 397 self.__setCurrentProject(None)
331 398
332 def __initDatabaseActions(self): 399 def __initDatabaseActions(self):
333 """ 400 """
334 Private method to initialize the database related actions. 401 Private method to initialize the database related actions.
335 """ 402 """
336 self.initializeDbAct = EricAction( 403 self.initializeDbAct = EricAction(
337 self.tr('Initialize Database'), 404 self.tr("Initialize Database"),
338 self.tr('Initialize &Database'), 405 self.tr("Initialize &Database"),
339 0, 0, 406 0,
340 self, 'pyramid_initialize_database') 407 0,
341 self.initializeDbAct.setStatusTip(self.tr( 408 self,
342 'Initializes (or re-initializes) the database of the current' 409 "pyramid_initialize_database",
343 ' Pyramid project')) 410 )
344 self.initializeDbAct.setWhatsThis(self.tr( 411 self.initializeDbAct.setStatusTip(
345 """<b>Initialize Database</b>""" 412 self.tr(
346 """<p>Initializes (or re-initializes) the database of the""" 413 "Initializes (or re-initializes) the database of the current"
347 """ current Pyramid project.</p>""" 414 " Pyramid project"
348 )) 415 )
416 )
417 self.initializeDbAct.setWhatsThis(
418 self.tr(
419 """<b>Initialize Database</b>"""
420 """<p>Initializes (or re-initializes) the database of the"""
421 """ current Pyramid project.</p>"""
422 )
423 )
349 self.initializeDbAct.triggered.connect(self.__initializeDatabase) 424 self.initializeDbAct.triggered.connect(self.__initializeDatabase)
350 self.actions.append(self.initializeDbAct) 425 self.actions.append(self.initializeDbAct)
351 426
352 ######################################################### 427 #########################################################
353 ## action to create a new database migration 428 ## action to create a new database migration
354 ######################################################### 429 #########################################################
355 430
356 self.migrateCreateAct = EricAction( 431 self.migrateCreateAct = EricAction(
357 self.tr('Create Migration'), 432 self.tr("Create Migration"),
358 self.tr('&Create Migration'), 433 self.tr("&Create Migration"),
359 0, 0, 434 0,
360 self, 'flask_create_migration') 435 0,
361 self.migrateCreateAct.setStatusTip(self.tr( 436 self,
362 'Create a new migration for the current database')) 437 "flask_create_migration",
363 self.migrateCreateAct.setWhatsThis(self.tr( 438 )
364 """<b>Create Migration</b>""" 439 self.migrateCreateAct.setStatusTip(
365 """<p>Creates a new migration for the current database""" 440 self.tr("Create a new migration for the current database")
366 """ and stores it in the configured migrations directory.</p>""" 441 )
367 )) 442 self.migrateCreateAct.setWhatsThis(
368 self.migrateCreateAct.triggered.connect( 443 self.tr(
369 self.__createMigration) 444 """<b>Create Migration</b>"""
445 """<p>Creates a new migration for the current database"""
446 """ and stores it in the configured migrations directory.</p>"""
447 )
448 )
449 self.migrateCreateAct.triggered.connect(self.__createMigration)
370 self.actions.append(self.migrateCreateAct) 450 self.actions.append(self.migrateCreateAct)
371 451
372 ######################################################### 452 #########################################################
373 ## action to up- and downgrade a databse 453 ## action to up- and downgrade a databse
374 ######################################################### 454 #########################################################
375 455
376 self.upgradeDatabaseAct = EricAction( 456 self.upgradeDatabaseAct = EricAction(
377 self.tr('Upgrade Database'), 457 self.tr("Upgrade Database"),
378 self.tr('&Upgrade Database'), 458 self.tr("&Upgrade Database"),
379 0, 0, 459 0,
380 self, 'flask_upgrade_database') 460 0,
381 self.upgradeDatabaseAct.setStatusTip(self.tr( 461 self,
382 'Upgrade the database to the current migration')) 462 "flask_upgrade_database",
383 self.upgradeDatabaseAct.setWhatsThis(self.tr( 463 )
384 """<b>Upgrade Database</b>""" 464 self.upgradeDatabaseAct.setStatusTip(
385 """<p>Upgrades the database to the current migration.</p>""" 465 self.tr("Upgrade the database to the current migration")
386 )) 466 )
387 self.upgradeDatabaseAct.triggered.connect( 467 self.upgradeDatabaseAct.setWhatsThis(
388 self.upgradeDatabase) 468 self.tr(
469 """<b>Upgrade Database</b>"""
470 """<p>Upgrades the database to the current migration.</p>"""
471 )
472 )
473 self.upgradeDatabaseAct.triggered.connect(self.upgradeDatabase)
389 self.actions.append(self.upgradeDatabaseAct) 474 self.actions.append(self.upgradeDatabaseAct)
390 475
391 self.downgradeDatabaseAct = EricAction( 476 self.downgradeDatabaseAct = EricAction(
392 self.tr('Downgrade Database'), 477 self.tr("Downgrade Database"),
393 self.tr('&Downgrade Database'), 478 self.tr("&Downgrade Database"),
394 0, 0, 479 0,
395 self, 'flask_downgrade_database') 480 0,
396 self.downgradeDatabaseAct.setStatusTip(self.tr( 481 self,
397 'Downgrade the database to the previous version')) 482 "flask_downgrade_database",
398 self.downgradeDatabaseAct.setWhatsThis(self.tr( 483 )
399 """<b>Downgrade Database</b>""" 484 self.downgradeDatabaseAct.setStatusTip(
400 """<p>Downgrades the database to the previous version.</p>""" 485 self.tr("Downgrade the database to the previous version")
401 )) 486 )
402 self.downgradeDatabaseAct.triggered.connect( 487 self.downgradeDatabaseAct.setWhatsThis(
403 self.downgradeDatabase) 488 self.tr(
489 """<b>Downgrade Database</b>"""
490 """<p>Downgrades the database to the previous version.</p>"""
491 )
492 )
493 self.downgradeDatabaseAct.triggered.connect(self.downgradeDatabase)
404 self.actions.append(self.downgradeDatabaseAct) 494 self.actions.append(self.downgradeDatabaseAct)
405 495
406 ######################################################### 496 #########################################################
407 ## actions to show migrations history information 497 ## actions to show migrations history information
408 ######################################################### 498 #########################################################
409 499
410 self.migrationSummaryAct = EricAction( 500 self.migrationSummaryAct = EricAction(
411 self.tr('Show Migrations Summary'), 501 self.tr("Show Migrations Summary"),
412 self.tr('Show Migrations &Summary'), 502 self.tr("Show Migrations &Summary"),
413 0, 0, 503 0,
414 self, 'flask_show_migrations_summary') 504 0,
415 self.migrationSummaryAct.setStatusTip(self.tr( 505 self,
416 'Show a summary of the created database migrations')) 506 "flask_show_migrations_summary",
417 self.migrationSummaryAct.setWhatsThis(self.tr( 507 )
418 """<b>Show Migrations Summary</b>""" 508 self.migrationSummaryAct.setStatusTip(
419 """<p>Shows a summary list of the created database""" 509 self.tr("Show a summary of the created database migrations")
420 """ migrations.</p>""" 510 )
421 )) 511 self.migrationSummaryAct.setWhatsThis(
422 self.migrationSummaryAct.triggered.connect( 512 self.tr(
423 self.__showMigrationsSummary) 513 """<b>Show Migrations Summary</b>"""
514 """<p>Shows a summary list of the created database"""
515 """ migrations.</p>"""
516 )
517 )
518 self.migrationSummaryAct.triggered.connect(self.__showMigrationsSummary)
424 self.actions.append(self.migrationSummaryAct) 519 self.actions.append(self.migrationSummaryAct)
425 520
426 self.migrationHistoryAct = EricAction( 521 self.migrationHistoryAct = EricAction(
427 self.tr('Show Migrations History'), 522 self.tr("Show Migrations History"),
428 self.tr('Show Migrations &History'), 523 self.tr("Show Migrations &History"),
429 0, 0, 524 0,
430 self, 'flask_show_migrations_history') 525 0,
431 self.migrationHistoryAct.setStatusTip(self.tr( 526 self,
432 'Show the full history of the created database migrations')) 527 "flask_show_migrations_history",
433 self.migrationHistoryAct.setWhatsThis(self.tr( 528 )
434 """<b>Show Migrations History</b>""" 529 self.migrationHistoryAct.setStatusTip(
435 """<p>Shows the full history of the created database""" 530 self.tr("Show the full history of the created database migrations")
436 """ migrations.</p>""" 531 )
437 )) 532 self.migrationHistoryAct.setWhatsThis(
438 self.migrationHistoryAct.triggered.connect( 533 self.tr(
439 self.__showMigrationsHistory) 534 """<b>Show Migrations History</b>"""
535 """<p>Shows the full history of the created database"""
536 """ migrations.</p>"""
537 )
538 )
539 self.migrationHistoryAct.triggered.connect(self.__showMigrationsHistory)
440 self.actions.append(self.migrationHistoryAct) 540 self.actions.append(self.migrationHistoryAct)
441 541
442 def initMenu(self): 542 def initMenu(self):
443 """ 543 """
444 Public slot to initialize the Pyramid menu. 544 Public slot to initialize the Pyramid menu.
445 545
446 @return the menu generated 546 @return the menu generated
447 @rtype QMenu 547 @rtype QMenu
448 """ 548 """
449 self.__menus = {} # clear menus references 549 self.__menus = {} # clear menus references
450 550
451 # Database menu 551 # Database menu
452 dbMenu = QMenu(self.tr("Database")) 552 dbMenu = QMenu(self.tr("Database"))
453 dbMenu.setTearOffEnabled(True) 553 dbMenu.setTearOffEnabled(True)
454 554
455 dbMenu.addAction(self.initializeDbAct) 555 dbMenu.addAction(self.initializeDbAct)
456 dbMenu.addSeparator() 556 dbMenu.addSeparator()
457 dbMenu.addAction(self.migrateCreateAct) 557 dbMenu.addAction(self.migrateCreateAct)
458 dbMenu.addSeparator() 558 dbMenu.addSeparator()
459 dbMenu.addAction(self.upgradeDatabaseAct) 559 dbMenu.addAction(self.upgradeDatabaseAct)
460 dbMenu.addAction(self.downgradeDatabaseAct) 560 dbMenu.addAction(self.downgradeDatabaseAct)
461 dbMenu.addSeparator() 561 dbMenu.addSeparator()
462 dbMenu.addAction(self.migrationSummaryAct) 562 dbMenu.addAction(self.migrationSummaryAct)
463 dbMenu.addAction(self.migrationHistoryAct) 563 dbMenu.addAction(self.migrationHistoryAct)
464 564
465 # main Pyramid menu 565 # main Pyramid menu
466 menu = QMenu(self.tr('P&yramid'), self.__ui) 566 menu = QMenu(self.tr("P&yramid"), self.__ui)
467 menu.setTearOffEnabled(True) 567 menu.setTearOffEnabled(True)
468 568
469 menu.addAction(self.selectProjectAct) 569 menu.addAction(self.selectProjectAct)
470 menu.addSeparator() 570 menu.addSeparator()
471 menu.addAction(self.runServerAct) 571 menu.addAction(self.runServerAct)
472 menu.addAction(self.runBrowserAct) 572 menu.addAction(self.runBrowserAct)
473 menu.addSeparator() 573 menu.addSeparator()
484 menu.addAction(self.buildDistroAct) 584 menu.addAction(self.buildDistroAct)
485 menu.addSeparator() 585 menu.addSeparator()
486 menu.addAction(self.documentationAct) 586 menu.addAction(self.documentationAct)
487 menu.addSeparator() 587 menu.addSeparator()
488 menu.addAction(self.aboutPyramidAct) 588 menu.addAction(self.aboutPyramidAct)
489 589
490 self.__menus["main"] = menu 590 self.__menus["main"] = menu
491 self.__menus["database"] = dbMenu 591 self.__menus["database"] = dbMenu
492 592
493 self.__setCurrentProject(None) 593 self.__setCurrentProject(None)
494 594
495 return menu 595 return menu
496 596
497 def getMenu(self, name): 597 def getMenu(self, name):
498 """ 598 """
499 Public method to get a reference to the requested menu. 599 Public method to get a reference to the requested menu.
500 600
501 @param name name of the menu 601 @param name name of the menu
502 @type str 602 @type str
503 @return reference to the menu or None, if no menu with the given 603 @return reference to the menu or None, if no menu with the given
504 name exists 604 name exists
505 @rtype QMenu 605 @rtype QMenu
506 """ 606 """
507 if name in self.__menus: 607 if name in self.__menus:
508 return self.__menus[name] 608 return self.__menus[name]
509 else: 609 else:
510 return None 610 return None
511 611
512 def getMenuNames(self): 612 def getMenuNames(self):
513 """ 613 """
514 Public method to get the names of all menus. 614 Public method to get the names of all menus.
515 615
516 @return menu names 616 @return menu names
517 @rtype list of str 617 @rtype list of str
518 """ 618 """
519 return list(self.__menus.keys()) 619 return list(self.__menus.keys())
520 620
521 def registerOpenHook(self): 621 def registerOpenHook(self):
522 """ 622 """
523 Public method to register the open hook to open a translations file 623 Public method to register the open hook to open a translations file
524 in a translations editor. 624 in a translations editor.
525 """ 625 """
526 if self.__hooksInstalled: 626 if self.__hooksInstalled:
527 editor = self.__plugin.getPreferences("TranslationsEditor") 627 editor = self.__plugin.getPreferences("TranslationsEditor")
528 if editor: 628 if editor:
529 self.__translationsBrowser.addHookMethodAndMenuEntry( 629 self.__translationsBrowser.addHookMethodAndMenuEntry(
530 "open", self.openPOEditor, 630 "open",
531 self.tr("Open with {0}").format( 631 self.openPOEditor,
532 os.path.basename(editor))) 632 self.tr("Open with {0}").format(os.path.basename(editor)),
633 )
533 else: 634 else:
534 self.__translationsBrowser.removeHookMethod("open") 635 self.__translationsBrowser.removeHookMethod("open")
535 636
536 def projectOpenedHooks(self): 637 def projectOpenedHooks(self):
537 """ 638 """
538 Public method to add our hook methods. 639 Public method to add our hook methods.
539 """ 640 """
540 if self.__ericProject.getProjectType() == "Pyramid": 641 if self.__ericProject.getProjectType() == "Pyramid":
541 self.__formsBrowser = ( 642 self.__formsBrowser = (
542 ericApp().getObject("ProjectBrowser") 643 ericApp().getObject("ProjectBrowser").getProjectBrowser("forms")
543 .getProjectBrowser("forms")) 644 )
544 self.__formsBrowser.addHookMethodAndMenuEntry( 645 self.__formsBrowser.addHookMethodAndMenuEntry(
545 "newForm", self.newForm, self.tr("New template...")) 646 "newForm", self.newForm, self.tr("New template...")
546 647 )
648
547 self.__ericProject.projectLanguageAddedByCode.connect( 649 self.__ericProject.projectLanguageAddedByCode.connect(
548 self.__projectLanguageAdded) 650 self.__projectLanguageAdded
651 )
549 self.__translationsBrowser = ( 652 self.__translationsBrowser = (
550 ericApp().getObject("ProjectBrowser") 653 ericApp().getObject("ProjectBrowser").getProjectBrowser("translations")
551 .getProjectBrowser("translations")) 654 )
552 self.__translationsBrowser.addHookMethodAndMenuEntry( 655 self.__translationsBrowser.addHookMethodAndMenuEntry(
553 "extractMessages", self.extractMessages, 656 "extractMessages", self.extractMessages, self.tr("Extract Messages")
554 self.tr("Extract Messages")) 657 )
555 self.__translationsBrowser.addHookMethodAndMenuEntry( 658 self.__translationsBrowser.addHookMethodAndMenuEntry(
556 "releaseAll", self.compileCatalogs, 659 "releaseAll", self.compileCatalogs, self.tr("Compile All Catalogs")
557 self.tr("Compile All Catalogs")) 660 )
558 self.__translationsBrowser.addHookMethodAndMenuEntry( 661 self.__translationsBrowser.addHookMethodAndMenuEntry(
559 "releaseSelected", self.compileSelectedCatalogs, 662 "releaseSelected",
560 self.tr("Compile Selected Catalogs")) 663 self.compileSelectedCatalogs,
664 self.tr("Compile Selected Catalogs"),
665 )
561 self.__translationsBrowser.addHookMethodAndMenuEntry( 666 self.__translationsBrowser.addHookMethodAndMenuEntry(
562 "generateAll", self.updateCatalogs, 667 "generateAll", self.updateCatalogs, self.tr("Update All Catalogs")
563 self.tr("Update All Catalogs")) 668 )
564 self.__translationsBrowser.addHookMethodAndMenuEntry( 669 self.__translationsBrowser.addHookMethodAndMenuEntry(
565 "generateSelected", self.updateSelectedCatalogs, 670 "generateSelected",
566 self.tr("Update Selected Catalogs")) 671 self.updateSelectedCatalogs,
567 672 self.tr("Update Selected Catalogs"),
673 )
674
568 self.__hooksInstalled = True 675 self.__hooksInstalled = True
569 676
570 self.registerOpenHook() 677 self.registerOpenHook()
571 678
572 def projectClosedHooks(self): 679 def projectClosedHooks(self):
573 """ 680 """
574 Public method to remove our hook methods. 681 Public method to remove our hook methods.
575 """ 682 """
576 if self.__hooksInstalled: 683 if self.__hooksInstalled:
577 self.__formsBrowser.removeHookMethod("newForm") 684 self.__formsBrowser.removeHookMethod("newForm")
578 self.__formsBrowser = None 685 self.__formsBrowser = None
579 686
580 self.__ericProject.projectLanguageAddedByCode.disconnect( 687 self.__ericProject.projectLanguageAddedByCode.disconnect(
581 self.__projectLanguageAdded) 688 self.__projectLanguageAdded
689 )
582 self.__translationsBrowser.removeHookMethod("extractMessages") 690 self.__translationsBrowser.removeHookMethod("extractMessages")
583 self.__translationsBrowser.removeHookMethod("releaseAll") 691 self.__translationsBrowser.removeHookMethod("releaseAll")
584 self.__translationsBrowser.removeHookMethod("releaseSelected") 692 self.__translationsBrowser.removeHookMethod("releaseSelected")
585 self.__translationsBrowser.removeHookMethod("generateAll") 693 self.__translationsBrowser.removeHookMethod("generateAll")
586 self.__translationsBrowser.removeHookMethod("generateSelected") 694 self.__translationsBrowser.removeHookMethod("generateSelected")
587 self.__translationsBrowser.removeHookMethod("open") 695 self.__translationsBrowser.removeHookMethod("open")
588 self.__translationsBrowser = None 696 self.__translationsBrowser = None
589 697
590 self.__hooksInstalled = False 698 self.__hooksInstalled = False
591 699
592 def newForm(self, path): 700 def newForm(self, path):
593 """ 701 """
594 Public method to create a new form. 702 Public method to create a new form.
595 703
596 @param path full directory path for the new form file 704 @param path full directory path for the new form file
597 @type str 705 @type str
598 """ 706 """
599 from .FormSelectionDialog import FormSelectionDialog 707 from .FormSelectionDialog import FormSelectionDialog
600 708
601 dlg = FormSelectionDialog() 709 dlg = FormSelectionDialog()
602 if dlg.exec() == QDialog.DialogCode.Accepted: 710 if dlg.exec() == QDialog.DialogCode.Accepted:
603 template = dlg.getTemplateText() 711 template = dlg.getTemplateText()
604 712
605 fileFilters = self.tr( 713 fileFilters = self.tr(
606 "Chameleon Templates (*.pt);;" 714 "Chameleon Templates (*.pt);;"
607 "Chameleon Text Templates (*.txt);;" 715 "Chameleon Text Templates (*.txt);;"
608 "Mako Templates (*.mako);;" 716 "Mako Templates (*.mako);;"
609 "Mako Templates (*.mak);;" 717 "Mako Templates (*.mak);;"
610 "HTML Files (*.html);;" 718 "HTML Files (*.html);;"
611 "HTML Files (*.htm);;" 719 "HTML Files (*.htm);;"
612 "All Files (*)") 720 "All Files (*)"
721 )
613 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( 722 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter(
614 self.__ui, 723 self.__ui,
615 self.tr("New Form"), 724 self.tr("New Form"),
616 path, 725 path,
617 fileFilters, 726 fileFilters,
618 None, 727 None,
619 EricFileDialog.DontConfirmOverwrite) 728 EricFileDialog.DontConfirmOverwrite,
729 )
620 if fname: 730 if fname:
621 ext = QFileInfo(fname).suffix() 731 ext = QFileInfo(fname).suffix()
622 if not ext: 732 if not ext:
623 ex = selectedFilter.split("(*")[1].split(")")[0] 733 ex = selectedFilter.split("(*")[1].split(")")[0]
624 if ex: 734 if ex:
625 fname += ex 735 fname += ex
626 736
627 if os.path.exists(fname): 737 if os.path.exists(fname):
628 res = EricMessageBox.yesNo( 738 res = EricMessageBox.yesNo(
629 self.__ui, 739 self.__ui,
630 self.tr("New Form"), 740 self.tr("New Form"),
631 self.tr("""The file already exists! Overwrite""" 741 self.tr("""The file already exists! Overwrite""" """ it?"""),
632 """ it?"""), 742 icon=EricMessageBox.Warning,
633 icon=EricMessageBox.Warning) 743 )
634 if not res: 744 if not res:
635 # user selected to not overwrite 745 # user selected to not overwrite
636 return 746 return
637 747
638 try: 748 try:
639 with open(fname, "w", encoding="utf-8") as f: 749 with open(fname, "w", encoding="utf-8") as f:
640 f.write(template) 750 f.write(template)
641 except OSError as e: 751 except OSError as e:
642 EricMessageBox.critical( 752 EricMessageBox.critical(
643 self.__ui, 753 self.__ui,
644 self.tr("New Form"), 754 self.tr("New Form"),
645 self.tr("<p>The new form file <b>{0}</b> could" 755 self.tr(
646 " not be created.<br/> Problem: {1}</p>") 756 "<p>The new form file <b>{0}</b> could"
647 .format(fname, e)) 757 " not be created.<br/> Problem: {1}</p>"
758 ).format(fname, e),
759 )
648 return 760 return
649 761
650 self.__ericProject.appendFile(fname) 762 self.__ericProject.appendFile(fname)
651 self.__formsBrowser.sourceFile.emit(fname) 763 self.__formsBrowser.sourceFile.emit(fname)
652 764
653 ################################################################## 765 ##################################################################
654 ## methods below implement general functionality 766 ## methods below implement general functionality
655 ################################################################## 767 ##################################################################
656 768
657 def projectClosed(self): 769 def projectClosed(self):
658 """ 770 """
659 Public method to handle the closing of a project. 771 Public method to handle the closing of a project.
660 """ 772 """
661 if self.__serverProc is not None: 773 if self.__serverProc is not None:
662 self.__serverProcFinished() 774 self.__serverProcFinished()
663 self.__setCurrentProject(None) 775 self.__setCurrentProject(None)
664 776
665 for dlg in (self.__migrationSummaryDialog,): 777 for dlg in (self.__migrationSummaryDialog,):
666 if dlg is not None: 778 if dlg is not None:
667 dlg.close() 779 dlg.close()
668 780
669 def __getExecutablePaths(self, file): 781 def __getExecutablePaths(self, file):
670 """ 782 """
671 Private method to build all full paths of an executable file from 783 Private method to build all full paths of an executable file from
672 the environment. 784 the environment.
673 785
674 @param file filename of the executable 786 @param file filename of the executable
675 @type str 787 @type str
676 @return list of full executable names, if the executable file is 788 @return list of full executable names, if the executable file is
677 accessible via the searchpath defined by the PATH environment 789 accessible via the searchpath defined by the PATH environment
678 variable, or an empty list otherwise. 790 variable, or an empty list otherwise.
679 @rtype list of str 791 @rtype list of str
680 """ 792 """
681 paths = [] 793 paths = []
682 794
683 if os.path.isabs(file): 795 if os.path.isabs(file):
684 if os.access(file, os.X_OK): 796 if os.access(file, os.X_OK):
685 return [file] 797 return [file]
686 else: 798 else:
687 return [] 799 return []
688 800
689 cur_path = os.path.join(os.curdir, file) 801 cur_path = os.path.join(os.curdir, file)
690 if os.path.exists(cur_path) and os.access(cur_path, os.X_OK): 802 if os.path.exists(cur_path) and os.access(cur_path, os.X_OK):
691 paths.append(cur_path) 803 paths.append(cur_path)
692 804
693 path = os.getenv('PATH') 805 path = os.getenv("PATH")
694 806
695 # environment variable not defined 807 # environment variable not defined
696 if path is not None: 808 if path is not None:
697 dirs = path.split(os.pathsep) 809 dirs = path.split(os.pathsep)
698 for directory in dirs: 810 for directory in dirs:
699 exe = os.path.join(directory, file) 811 exe = os.path.join(directory, file)
700 if os.access(exe, os.X_OK) and exe not in paths: 812 if os.access(exe, os.X_OK) and exe not in paths:
701 paths.append(exe) 813 paths.append(exe)
702 814
703 return paths 815 return paths
704 816
705 def supportedPythonVariants(self): 817 def supportedPythonVariants(self):
706 """ 818 """
707 Public method to get the supported Python variants. 819 Public method to get the supported Python variants.
708 820
709 @return list of supported Python variants 821 @return list of supported Python variants
710 @rtype list of str 822 @rtype list of str
711 """ 823 """
712 variants = [] 824 variants = []
713 cmd = "cookiecutter" 825 cmd = "cookiecutter"
714 826
715 for variant in ['Python3']: 827 for variant in ["Python3"]:
716 virtEnv = self.__getVirtualEnvironment(variant) 828 virtEnv = self.__getVirtualEnvironment(variant)
717 if virtEnv: 829 if virtEnv:
718 fullCmd = self.getPyramidCommand(cmd, variant) 830 fullCmd = self.getPyramidCommand(cmd, variant)
719 if fullCmd != cmd: 831 if fullCmd != cmd:
720 variants.append(variant) 832 variants.append(variant)
729 fullCmds = Utilities.getExecutablePaths(cmd) 841 fullCmds = Utilities.getExecutablePaths(cmd)
730 except AttributeError: 842 except AttributeError:
731 fullCmds = self.__getExecutablePaths(cmd) 843 fullCmds = self.__getExecutablePaths(cmd)
732 for fullCmd in fullCmds: 844 for fullCmd in fullCmds:
733 try: 845 try:
734 with open(fullCmd, 'r', encoding='utf-8') as f: 846 with open(fullCmd, "r", encoding="utf-8") as f:
735 l0 = f.readline() 847 l0 = f.readline()
736 except OSError: 848 except OSError:
737 l0 = "" 849 l0 = ""
738 if self.__isSuitableForVariant(variant, l0): 850 if self.__isSuitableForVariant(variant, l0):
739 variants.append(variant) 851 variants.append(variant)
740 break 852 break
741 853
742 return variants 854 return variants
743 855
744 def __isSuitableForVariant(self, variant, line0): 856 def __isSuitableForVariant(self, variant, line0):
745 """ 857 """
746 Private method to test, if a detected command file is suitable for the 858 Private method to test, if a detected command file is suitable for the
747 given Python variant. 859 given Python variant.
748 860
749 @param variant Python variant to test for 861 @param variant Python variant to test for
750 @type str 862 @type str
751 @param line0 first line of the executable 863 @param line0 first line of the executable
752 @type str 864 @type str
753 @return flag indicating a suitable command 865 @return flag indicating a suitable command
754 @rtype bool 866 @rtype bool
755 """ 867 """
756 l0 = line0.lower() 868 l0 = line0.lower()
757 ok = (variant.lower() in l0 or 869 ok = variant.lower() in l0 or "{0}.".format(variant[-1]) in l0
758 "{0}.".format(variant[-1]) in l0)
759 ok |= "pypy3" in l0 870 ok |= "pypy3" in l0
760 871
761 return ok 872 return ok
762 873
763 def __getVirtualEnvironment(self, language=""): 874 def __getVirtualEnvironment(self, language=""):
764 """ 875 """
765 Private method to get the path of the virtual environment. 876 Private method to get the path of the virtual environment.
766 877
767 @param language Python variant to get the virtual environment 878 @param language Python variant to get the virtual environment
768 for (one of '' or 'Python3') 879 for (one of '' or 'Python3')
769 @type str 880 @type str
770 @return path of the virtual environment 881 @return path of the virtual environment
771 @rtype str 882 @rtype str
772 """ 883 """
773 if not language: 884 if not language:
774 language = self.__ericProject.getProjectLanguage() 885 language = self.__ericProject.getProjectLanguage()
775 if self.__virtualEnvManager: 886 if self.__virtualEnvManager:
776 if language == "Python3": 887 if language == "Python3":
777 venvName = self.__plugin.getPreferences( 888 venvName = self.__plugin.getPreferences("VirtualEnvironmentNamePy3")
778 "VirtualEnvironmentNamePy3")
779 else: 889 else:
780 venvName = "" 890 venvName = ""
781 if venvName: 891 if venvName:
782 virtEnv = self.__virtualEnvManager.getVirtualenvDirectory( 892 virtEnv = self.__virtualEnvManager.getVirtualenvDirectory(venvName)
783 venvName)
784 if not virtEnv: 893 if not virtEnv:
785 virtEnv = os.path.dirname( 894 virtEnv = os.path.dirname(
786 self.__virtualEnvManager.getVirtualenvInterpreter( 895 self.__virtualEnvManager.getVirtualenvInterpreter(venvName)
787 venvName)) 896 )
788 if virtEnv.endswith(("Scripts", "bin")): 897 if virtEnv.endswith(("Scripts", "bin")):
789 virtEnv = os.path.dirname(virtEnv) 898 virtEnv = os.path.dirname(virtEnv)
790 else: 899 else:
791 virtEnv = "" 900 virtEnv = ""
792 901
793 if virtEnv and not os.path.exists(virtEnv): 902 if virtEnv and not os.path.exists(virtEnv):
794 virtEnv = "" 903 virtEnv = ""
795 return virtEnv # __IGNORE_WARNING_M834__ 904 return virtEnv # __IGNORE_WARNING_M834__
796 905
797 def __getDebugEnvironment(self, language=""): 906 def __getDebugEnvironment(self, language=""):
798 """ 907 """
799 Private method to get the path of the debugger environment. 908 Private method to get the path of the debugger environment.
800 909
801 @param language Python variant to get the debugger environment 910 @param language Python variant to get the debugger environment
802 for (one of '' or 'Python3') 911 for (one of '' or 'Python3')
803 @type str 912 @type str
804 @return path of the debugger environment 913 @return path of the debugger environment
805 @rtype str 914 @rtype str
811 if not debugEnv: 920 if not debugEnv:
812 if language == "Python3": 921 if language == "Python3":
813 venvName = Preferences.getDebugger("Python3VirtualEnv") 922 venvName = Preferences.getDebugger("Python3VirtualEnv")
814 else: 923 else:
815 venvName = "" 924 venvName = ""
816 925
817 if venvName: 926 if venvName:
818 return self.__virtualEnvManager.getVirtualenvDirectory( 927 return self.__virtualEnvManager.getVirtualenvDirectory(venvName)
819 venvName) 928
820
821 return "" 929 return ""
822 930
823 def getProjectVirtualEnvironment(self): 931 def getProjectVirtualEnvironment(self):
824 """ 932 """
825 Public method to generate the path of the project virtual environment. 933 Public method to generate the path of the project virtual environment.
826 934
827 @return path of the Pyramid project virtual environment 935 @return path of the Pyramid project virtual environment
828 @rtype str 936 @rtype str
829 """ 937 """
830 return os.path.join(self.projectPath(), "env") 938 return os.path.join(self.projectPath(), "env")
831 939
832 def getPyramidCommand(self, cmd, language="", virtualEnv=""): 940 def getPyramidCommand(self, cmd, language="", virtualEnv=""):
833 """ 941 """
834 Public method to build a Pyramid command. 942 Public method to build a Pyramid command.
835 943
836 @param cmd command 944 @param cmd command
837 @type str 945 @type str
838 @param language Python variant to get the virtual environment 946 @param language Python variant to get the virtual environment
839 for (one of '' or 'Python3') 947 for (one of '' or 'Python3')
840 @type str 948 @type str
843 @return full pyramid command 951 @return full pyramid command
844 @rtype str 952 @rtype str
845 """ 953 """
846 if not language: 954 if not language:
847 language = self.__ericProject.getProjectLanguage() 955 language = self.__ericProject.getProjectLanguage()
848 956
849 if not virtualEnv: 957 if not virtualEnv:
850 virtualEnv = self.__getVirtualEnvironment(language) 958 virtualEnv = self.__getVirtualEnvironment(language)
851 if not virtualEnv: 959 if not virtualEnv:
852 virtualEnv = self.__getDebugEnvironment(language) 960 virtualEnv = self.__getDebugEnvironment(language)
853 if isWindowsPlatform(): 961 if isWindowsPlatform():
854 fullCmds = [ 962 fullCmds = [
855 os.path.join(virtualEnv, "Scripts", cmd + '.exe'), 963 os.path.join(virtualEnv, "Scripts", cmd + ".exe"),
856 os.path.join(virtualEnv, "bin", cmd + '.exe'), 964 os.path.join(virtualEnv, "bin", cmd + ".exe"),
857 cmd # fall back to just cmd 965 cmd, # fall back to just cmd
858 ] 966 ]
859 for cmd in fullCmds: 967 for cmd in fullCmds:
860 if os.path.exists(cmd): 968 if os.path.exists(cmd):
861 break 969 break
862 else: 970 else:
863 fullCmds = [ 971 fullCmds = [
864 os.path.join(virtualEnv, "bin", cmd), 972 os.path.join(virtualEnv, "bin", cmd),
865 os.path.join(virtualEnv, "local", "bin", cmd), 973 os.path.join(virtualEnv, "local", "bin", cmd),
866 Utilities.getExecutablePath(cmd), 974 Utilities.getExecutablePath(cmd),
867 cmd # fall back to just cmd 975 cmd, # fall back to just cmd
868 ] 976 ]
869 for cmd in fullCmds: 977 for cmd in fullCmds:
870 if os.path.exists(cmd): 978 if os.path.exists(cmd):
871 break 979 break
872 return cmd 980 return cmd
873 981
874 def __assemblePyramidCommand(self, cmd, virtualEnv): 982 def __assemblePyramidCommand(self, cmd, virtualEnv):
875 """ 983 """
876 Private method to assemble the full pyramid command for a given virtual 984 Private method to assemble the full pyramid command for a given virtual
877 environment. 985 environment.
878 986
879 @param cmd command 987 @param cmd command
880 @type str 988 @type str
881 @param virtualEnv path of the project's Python virtual environment 989 @param virtualEnv path of the project's Python virtual environment
882 @type str 990 @type str
883 @return assembled pyramid command 991 @return assembled pyramid command
884 @rtype str 992 @rtype str
885 """ 993 """
886 return ( 994 return (
887 os.path.join(virtualEnv, "Scripts", cmd + '.exe') 995 os.path.join(virtualEnv, "Scripts", cmd + ".exe")
888 if isWindowsPlatform() else 996 if isWindowsPlatform()
889 os.path.join(virtualEnv, "bin", cmd) 997 else os.path.join(virtualEnv, "bin", cmd)
890 ) 998 )
891 999
892 def getPythonCommand(self): 1000 def getPythonCommand(self):
893 """ 1001 """
894 Public method to build the Python command. 1002 Public method to build the Python command.
895 1003
896 @return python command 1004 @return python command
897 @rtype str 1005 @rtype str
898 """ 1006 """
899 language = self.__ericProject.getProjectLanguage() 1007 language = self.__ericProject.getProjectLanguage()
900 if self.__virtualEnvManager: 1008 if self.__virtualEnvManager:
901 if language == "Python3": 1009 if language == "Python3":
902 venvName = self.__plugin.getPreferences( 1010 venvName = self.__plugin.getPreferences("VirtualEnvironmentNamePy3")
903 "VirtualEnvironmentNamePy3")
904 if not venvName: 1011 if not venvName:
905 # if none configured, use the global one 1012 # if none configured, use the global one
906 venvName = Preferences.getDebugger("Python3VirtualEnv") 1013 venvName = Preferences.getDebugger("Python3VirtualEnv")
907 else: 1014 else:
908 venvName = "" 1015 venvName = ""
909 if venvName: 1016 if venvName:
910 return self.__virtualEnvManager.getVirtualenvInterpreter( 1017 return self.__virtualEnvManager.getVirtualenvInterpreter(venvName)
911 venvName) 1018
912
913 return "" 1019 return ""
914 1020
915 def __pyramidInfo(self): 1021 def __pyramidInfo(self):
916 """ 1022 """
917 Private slot to show some info about Pyramid. 1023 Private slot to show some info about Pyramid.
918 """ 1024 """
919 try: 1025 try:
920 version = self.getPyramidVersionString() 1026 version = self.getPyramidVersionString()
921 except PyramidNoProjectSelectedException: 1027 except PyramidNoProjectSelectedError:
922 version = self.tr("not available") 1028 version = self.tr("not available")
923 url = "http://www.pylonsproject.org/projects/pyramid/about" 1029 url = "http://www.pylonsproject.org/projects/pyramid/about"
924 1030
925 msgBox = EricMessageBox.EricMessageBox( 1031 msgBox = EricMessageBox.EricMessageBox(
926 EricMessageBox.Question, 1032 EricMessageBox.Question,
927 self.tr("About Pyramid"), 1033 self.tr("About Pyramid"),
928 self.tr( 1034 self.tr(
929 "<p>Pyramid is a high-level Python Web framework that" 1035 "<p>Pyramid is a high-level Python Web framework that"
930 " encourages rapid development and clean, pragmatic" 1036 " encourages rapid development and clean, pragmatic"
931 " design.</p>" 1037 " design.</p>"
932 "<p><table>" 1038 "<p><table>"
933 "<tr><td>Version:</td><td>{0}</td></tr>" 1039 "<tr><td>Version:</td><td>{0}</td></tr>"
934 "<tr><td>URL:</td><td><a href=\"{1}\">" 1040 '<tr><td>URL:</td><td><a href="{1}">'
935 "{1}</a></td></tr>" 1041 "{1}</a></td></tr>"
936 "</table></p>" 1042 "</table></p>"
937 ).format(version, url), 1043 ).format(version, url),
938 modal=True, 1044 modal=True,
939 buttons=EricMessageBox.Ok) 1045 buttons=EricMessageBox.Ok,
940 msgBox.setIconPixmap(UI.PixmapCache.getPixmap( 1046 )
941 os.path.join("ProjectPyramid", "icons", 1047 msgBox.setIconPixmap(
942 "pyramid64-{0}".format(self.__iconSuffix)) 1048 UI.PixmapCache.getPixmap(
943 )) 1049 os.path.join(
1050 "ProjectPyramid", "icons", "pyramid64-{0}".format(self.__iconSuffix)
1051 )
1052 )
1053 )
944 msgBox.exec() 1054 msgBox.exec()
945 1055
946 def getPyramidVersionString(self): 1056 def getPyramidVersionString(self):
947 """ 1057 """
948 Public method to get the Pyramid version as a string. 1058 Public method to get the Pyramid version as a string.
949 1059
950 @return Pyramid version 1060 @return Pyramid version
951 @rtype str 1061 @rtype str
952 """ 1062 """
953 if not self.__pyramidVersion: 1063 if not self.__pyramidVersion:
954 cmd = self.getPyramidCommand( 1064 cmd = self.getPyramidCommand(
955 "pdistreport", 1065 "pdistreport", virtualEnv=self.getProjectVirtualEnvironment()
956 virtualEnv=self.getProjectVirtualEnvironment()
957 ) 1066 )
958 try: 1067 try:
959 output = subprocess.check_output([cmd]) # secok 1068 output = subprocess.check_output([cmd]) # secok
960 outputLines = output.decode().splitlines() 1069 outputLines = output.decode().splitlines()
961 for line in outputLines: 1070 for line in outputLines:
962 if line.startswith("Pyramid version:"): 1071 if line.startswith("Pyramid version:"):
963 self.__pyramidVersion = line.rsplit(None, 1)[1] 1072 self.__pyramidVersion = line.rsplit(None, 1)[1]
964 break 1073 break
965 except (OSError, subprocess.CalledProcessError): 1074 except (OSError, subprocess.CalledProcessError):
966 self.__pyramidVersion = "" 1075 self.__pyramidVersion = ""
967 1076
968 return self.__pyramidVersion 1077 return self.__pyramidVersion
969 1078
970 def getPyramidVersion(self): 1079 def getPyramidVersion(self):
971 """ 1080 """
972 Public method to get the Pyramid version as a tuple. 1081 Public method to get the Pyramid version as a tuple.
973 1082
974 @return Pyramid version 1083 @return Pyramid version
975 @rtype tuple of int 1084 @rtype tuple of int
976 """ 1085 """
977 pyramidVersionStr = self.getPyramidVersionString() 1086 pyramidVersionStr = self.getPyramidVersionString()
978 pyramidVersionList = [] 1087 pyramidVersionList = []
980 for part in pyramidVersionStr.split("."): 1089 for part in pyramidVersionStr.split("."):
981 try: 1090 try:
982 pyramidVersionList.append(int(part)) 1091 pyramidVersionList.append(int(part))
983 except ValueError: 1092 except ValueError:
984 pyramidVersionList.append(part) 1093 pyramidVersionList.append(part)
985 1094
986 return tuple(pyramidVersionList) 1095 return tuple(pyramidVersionList)
987 1096
988 def isSpawningConsole(self, consoleCmd): 1097 def isSpawningConsole(self, consoleCmd):
989 """ 1098 """
990 Public method to check, if the given console is a spawning console. 1099 Public method to check, if the given console is a spawning console.
991 1100
992 @param consoleCmd console command 1101 @param consoleCmd console command
993 @type str 1102 @type str
994 @return tuple of two entries giving an indication, if the console 1103 @return tuple of two entries giving an indication, if the console
995 is spawning (boolean) and the (possibly) cleaned console command 1104 is spawning (boolean) and the (possibly) cleaned console command
996 @rtype str 1105 @rtype str
997 """ 1106 """
998 if consoleCmd and consoleCmd[0] == '@': 1107 if consoleCmd and consoleCmd[0] == "@":
999 return (True, consoleCmd[1:]) 1108 return (True, consoleCmd[1:])
1000 else: 1109 else:
1001 return (False, consoleCmd) 1110 return (False, consoleCmd)
1002 1111
1003 def __adjustWorkingDirectory(self, args, wd): 1112 def __adjustWorkingDirectory(self, args, wd):
1004 """ 1113 """
1005 Private method to adjust the working directory in the arguments list. 1114 Private method to adjust the working directory in the arguments list.
1006 1115
1007 @param args list of arguments to be modified 1116 @param args list of arguments to be modified
1008 @type list of str 1117 @type list of str
1009 @param wd working directory 1118 @param wd working directory
1010 @type str 1119 @type str
1011 """ 1120 """
1015 elif args[0].endswith(("gnome-terminal", "mate-terminal")): 1124 elif args[0].endswith(("gnome-terminal", "mate-terminal")):
1016 for index in range(len(args)): 1125 for index in range(len(args)):
1017 if args[index].startswith("--working-directory="): 1126 if args[index].startswith("--working-directory="):
1018 args[index] = "--working-directory={0}".format(wd) 1127 args[index] = "--working-directory={0}".format(wd)
1019 break 1128 break
1020 1129
1021 ################################################################## 1130 ##################################################################
1022 ## slots below implement creation functions 1131 ## slots below implement creation functions
1023 ################################################################## 1132 ##################################################################
1024 1133
1025 def __createProject(self): 1134 def __createProject(self):
1026 """ 1135 """
1027 Private slot to create a new Pyramid project. 1136 Private slot to create a new Pyramid project.
1028 """ 1137 """
1029 from .CreateParametersDialog import CreateParametersDialog 1138 from .CreateParametersDialog import CreateParametersDialog
1030 1139
1031 dlg = CreateParametersDialog(self.__ui) 1140 dlg = CreateParametersDialog(self.__ui)
1032 if dlg.exec() == QDialog.DialogCode.Accepted: 1141 if dlg.exec() == QDialog.DialogCode.Accepted:
1033 template, version, overwrite, contextData = dlg.getData() 1142 template, version, overwrite, contextData = dlg.getData()
1034 1143
1035 cmd = self.getPyramidCommand("cookiecutter") 1144 cmd = self.getPyramidCommand("cookiecutter")
1036 args = ["--no-input"] 1145 args = ["--no-input"]
1037 if overwrite: 1146 if overwrite:
1038 args.append("--overwrite-if-exists") 1147 args.append("--overwrite-if-exists")
1039 if version: 1148 if version:
1040 args += ["--checkout", version] 1149 args += ["--checkout", version]
1041 args.append(template) 1150 args.append(template)
1042 for context, data in contextData.items(): 1151 for context, data in contextData.items():
1043 args.append("{0}={1}".format(context, data)) 1152 args.append("{0}={1}".format(context, data))
1044 dlg = PyramidDialog(self.tr("Create Pyramid Project"), 1153 dlg = PyramidDialog(self.tr("Create Pyramid Project"), parent=self.__ui)
1045 parent=self.__ui) 1154 if dlg.startProcess(cmd, args, self.__ericProject.getProjectPath()):
1046 if dlg.startProcess(
1047 cmd, args, self.__ericProject.getProjectPath()
1048 ):
1049 dlg.exec() 1155 dlg.exec()
1050 if dlg.normalExit() and "repo_name" in contextData: 1156 if dlg.normalExit() and "repo_name" in contextData:
1051 # search for files created by cookiecutter and add them 1157 # search for files created by cookiecutter and add them
1052 # to the project 1158 # to the project
1053 projectPath = os.path.join( 1159 projectPath = os.path.join(
1054 self.__ericProject.getProjectPath(), 1160 self.__ericProject.getProjectPath(), contextData["repo_name"]
1055 contextData["repo_name"]) 1161 )
1056 for entry in os.walk(projectPath): 1162 for entry in os.walk(projectPath):
1057 for fileName in entry[2]: 1163 for fileName in entry[2]:
1058 fullName = os.path.join(entry[0], fileName) 1164 fullName = os.path.join(entry[0], fileName)
1059 self.__ericProject.appendFile(fullName) 1165 self.__ericProject.appendFile(fullName)
1060 1166
1061 # create the base directory for translations 1167 # create the base directory for translations
1062 i18nPath = os.path.join( 1168 i18nPath = os.path.join(
1063 projectPath, contextData["repo_name"].lower(), 1169 projectPath, contextData["repo_name"].lower(), "i18n"
1064 "i18n") 1170 )
1065 if not os.path.exists(i18nPath): 1171 if not os.path.exists(i18nPath):
1066 os.makedirs(i18nPath) 1172 os.makedirs(i18nPath)
1067 self.__ericProject.setDirty(True) 1173 self.__ericProject.setDirty(True)
1068 1174
1069 combinedOutput = False 1175 combinedOutput = False
1070 argsLists = [] 1176 argsLists = []
1071 1177
1072 # 1. create a Python virtual environment for the project 1178 # 1. create a Python virtual environment for the project
1073 argsLists.append([sys.executable, "-m", "venv", "env"]) 1179 argsLists.append([sys.executable, "-m", "venv", "env"])
1074 # 2. upgrade packaging tools 1180 # 2. upgrade packaging tools
1075 python = self.__assemblePyramidCommand( 1181 python = self.__assemblePyramidCommand(
1076 "python", os.path.join(projectPath, "env")) 1182 "python", os.path.join(projectPath, "env")
1077 argsLists.append([python, "-m", "pip", "install", 1183 )
1078 "--upgrade", "pip", "setuptools"]) 1184 argsLists.append(
1185 [
1186 python,
1187 "-m",
1188 "pip",
1189 "install",
1190 "--upgrade",
1191 "pip",
1192 "setuptools",
1193 ]
1194 )
1079 # 3. install project in editable mode with testing 1195 # 3. install project in editable mode with testing
1080 argsLists.append([python, "-m", "pip", "install", "-e", 1196 argsLists.append(
1081 ".[testing]"]) 1197 [python, "-m", "pip", "install", "-e", ".[testing]"]
1082 1198 )
1199
1083 if ( 1200 if (
1084 "backend" in contextData and 1201 "backend" in contextData
1085 contextData["backend"] == "sqlalchemy" 1202 and contextData["backend"] == "sqlalchemy"
1086 ): 1203 ):
1087 # only SQLAlchemy needs initialization of alembic 1204 # only SQLAlchemy needs initialization of alembic
1088 combinedOutput = True 1205 combinedOutput = True
1089 1206
1090 # 4. initialize database 1207 # 4. initialize database
1091 alembic = self.__assemblePyramidCommand( 1208 alembic = self.__assemblePyramidCommand(
1092 "alembic", os.path.join(projectPath, "env")) 1209 "alembic", os.path.join(projectPath, "env")
1093 argsLists.append([alembic, "-c", "development.ini", 1210 )
1094 "revision", "--autogenerate", 1211 argsLists.append(
1095 "--message", "initialized database"]) 1212 [
1213 alembic,
1214 "-c",
1215 "development.ini",
1216 "revision",
1217 "--autogenerate",
1218 "--message",
1219 "initialized database",
1220 ]
1221 )
1096 # 5. upgrade database to initial version 1222 # 5. upgrade database to initial version
1097 argsLists.append([alembic, "-c", "development.ini", 1223 argsLists.append(
1098 "upgrade", "head"]) 1224 [alembic, "-c", "development.ini", "upgrade", "head"]
1099 1225 )
1226
1100 dlg = PyramidDialog( 1227 dlg = PyramidDialog(
1101 self.tr("Initializing Pyramid Project"), 1228 self.tr("Initializing Pyramid Project"),
1102 combinedOutput=combinedOutput, 1229 combinedOutput=combinedOutput,
1103 parent=self.__ui) 1230 parent=self.__ui,
1104 if dlg.startBatchProcesses(argsLists, 1231 )
1105 workingDir=projectPath): 1232 if dlg.startBatchProcesses(argsLists, workingDir=projectPath):
1106 dlg.exec() 1233 dlg.exec()
1107 1234
1108 self.__setCurrentProject(contextData["repo_name"]) 1235 self.__setCurrentProject(contextData["repo_name"])
1109 1236
1110 if ( 1237 if (
1111 "backend" in contextData and 1238 "backend" in contextData
1112 contextData["backend"] == "sqlalchemy" 1239 and contextData["backend"] == "sqlalchemy"
1113 ): 1240 ):
1114 # add the alembic files created above to the project 1241 # add the alembic files created above to the project
1115 migrationsPath = self.migrationsPath() 1242 migrationsPath = self.migrationsPath()
1116 for entry in os.walk(migrationsPath): 1243 for entry in os.walk(migrationsPath):
1117 for fileName in entry[2]: 1244 for fileName in entry[2]:
1118 fullName = os.path.join(entry[0], fileName) 1245 fullName = os.path.join(entry[0], fileName)
1119 self.__ericProject.appendFile(fullName) 1246 self.__ericProject.appendFile(fullName)
1120 1247
1121 ################################################################## 1248 ##################################################################
1122 ## methods below implement site related functions 1249 ## methods below implement site related functions
1123 ################################################################## 1250 ##################################################################
1124 1251
1125 def __findProjects(self): 1252 def __findProjects(self):
1126 """ 1253 """
1127 Private method to determine the relative path of all Pyramid 1254 Private method to determine the relative path of all Pyramid
1128 projects (= top level dirs). 1255 projects (= top level dirs).
1129 1256
1130 @return list of projects 1257 @return list of projects
1131 @rtype list of str 1258 @rtype list of str
1132 """ 1259 """
1133 projects = [] 1260 projects = []
1134 ppath = self.__ericProject.getProjectPath() 1261 ppath = self.__ericProject.getProjectPath()
1135 for entry in os.listdir(ppath): 1262 for entry in os.listdir(ppath):
1136 if ( 1263 if entry[0] not in "._" and os.path.isdir(os.path.join(ppath, entry)):
1137 entry[0] not in "._" and
1138 os.path.isdir(os.path.join(ppath, entry))
1139 ):
1140 projects.append(entry) 1264 projects.append(entry)
1141 return sorted(projects) 1265 return sorted(projects)
1142 1266
1143 def __selectProject(self): 1267 def __selectProject(self):
1144 """ 1268 """
1145 Private method to select a Pyramid project to work with. 1269 Private method to select a Pyramid project to work with.
1146 """ 1270 """
1147 projects = self.__findProjects() 1271 projects = self.__findProjects()
1160 project, ok = QInputDialog.getItem( 1284 project, ok = QInputDialog.getItem(
1161 self.__ui, 1285 self.__ui,
1162 self.tr("Select Pyramid Project"), 1286 self.tr("Select Pyramid Project"),
1163 self.tr("Select the Pyramid project to work with."), 1287 self.tr("Select the Pyramid project to work with."),
1164 projects, 1288 projects,
1165 cur, False) 1289 cur,
1290 False,
1291 )
1166 if not ok: 1292 if not ok:
1167 projects = None 1293 projects = None
1168 self.__setCurrentProject(project) 1294 self.__setCurrentProject(project)
1169 1295
1170 def projectPath(self): 1296 def projectPath(self):
1171 """ 1297 """
1172 Public method to calculate the full path of the Pyramid project. 1298 Public method to calculate the full path of the Pyramid project.
1173 1299
1174 @return path of the project 1300 @return path of the project
1175 @rtype str 1301 @rtype str
1176 @exception PyramidNoProjectSelectedException raised, if no project is 1302 @exception PyramidNoProjectSelectedError raised, if no project is
1177 selected 1303 selected
1178 """ 1304 """
1179 if self.__currentProject is None: 1305 if self.__currentProject is None:
1180 self.__selectProject() 1306 self.__selectProject()
1181 1307
1182 if self.__currentProject is None: 1308 if self.__currentProject is None:
1183 raise PyramidNoProjectSelectedException 1309 raise PyramidNoProjectSelectedError
1184 else: 1310 else:
1185 return os.path.join(self.__ericProject.getProjectPath(), 1311 return os.path.join(
1186 self.__currentProject) 1312 self.__ericProject.getProjectPath(), self.__currentProject
1187 1313 )
1314
1188 def __setCurrentProject(self, project): 1315 def __setCurrentProject(self, project):
1189 """ 1316 """
1190 Private slot to set the current project. 1317 Private slot to set the current project.
1191 1318
1192 @param project name of the project 1319 @param project name of the project
1193 @type str 1320 @type str
1194 """ 1321 """
1195 if project is not None and len(project) == 0: 1322 if project is not None and len(project) == 0:
1196 self.__currentProject = None 1323 self.__currentProject = None
1197 else: 1324 else:
1198 self.__currentProject = project 1325 self.__currentProject = project
1199 1326
1200 curProject = ( 1327 curProject = (
1201 self.tr("None") 1328 self.tr("None") if self.__currentProject is None else self.__currentProject
1202 if self.__currentProject is None else
1203 self.__currentProject
1204 ) 1329 )
1205 self.selectProjectAct.setText( 1330 self.selectProjectAct.setText(
1206 self.tr('&Current Pyramid Project ({0})').format(curProject)) 1331 self.tr("&Current Pyramid Project ({0})").format(curProject)
1207 1332 )
1333
1208 if self.__currentProject is None: 1334 if self.__currentProject is None:
1209 self.__ericProject.setTranslationPattern("") 1335 self.__ericProject.setTranslationPattern("")
1210 else: 1336 else:
1211 lowerProject = self.__project().lower() 1337 lowerProject = self.__project().lower()
1212 config = configparser.ConfigParser() 1338 config = configparser.ConfigParser()
1213 config.read(os.path.join(self.projectPath(), "setup.cfg")) 1339 config.read(os.path.join(self.projectPath(), "setup.cfg"))
1214 try: 1340 try:
1215 outputDir = config.get("init_catalog", "output_dir") 1341 outputDir = config.get("init_catalog", "output_dir")
1216 except (configparser.NoOptionError, configparser.NoSectionError): 1342 except (configparser.NoOptionError, configparser.NoSectionError):
1217 outputDir = '{0}/locale'.format(lowerProject) 1343 outputDir = "{0}/locale".format(lowerProject)
1218 try: 1344 try:
1219 domain = config.get("init_catalog", "domain") 1345 domain = config.get("init_catalog", "domain")
1220 except (configparser.NoOptionError, configparser.NoSectionError): 1346 except (configparser.NoOptionError, configparser.NoSectionError):
1221 domain = lowerProject 1347 domain = lowerProject
1222 self.__ericProject.setTranslationPattern( 1348 self.__ericProject.setTranslationPattern(
1223 os.path.join(project, outputDir, "%language%", 1349 os.path.join(
1224 "LC_MESSAGES", "{0}.po".format(domain)) 1350 project,
1225 ) 1351 outputDir,
1226 1352 "%language%",
1353 "LC_MESSAGES",
1354 "{0}.po".format(domain),
1355 )
1356 )
1357
1227 if self.__currentProject is None: 1358 if self.__currentProject is None:
1228 self.initializeDbAct.setEnabled(False) 1359 self.initializeDbAct.setEnabled(False)
1229 with contextlib.suppress(KeyError): 1360 with contextlib.suppress(KeyError):
1230 self.__menus["database"].setEnabled(False) 1361 self.__menus["database"].setEnabled(False)
1231 else: 1362 else:
1232 initCmd = self.__getInitDbCommand() 1363 initCmd = self.__getInitDbCommand()
1233 self.initializeDbAct.setEnabled(os.path.exists(initCmd)) 1364 self.initializeDbAct.setEnabled(os.path.exists(initCmd))
1234 1365
1235 alembicDir = os.path.join( 1366 alembicDir = os.path.join(
1236 self.projectPath(), self.__currentProject, 1367 self.projectPath(), self.__currentProject, "alembic", "versions"
1237 "alembic", "versions") 1368 )
1238 self.__menus["database"].setEnabled(os.path.exists(alembicDir)) 1369 self.__menus["database"].setEnabled(os.path.exists(alembicDir))
1239 1370
1240 self.runServerAct.setEnabled(project is not None) 1371 self.runServerAct.setEnabled(project is not None)
1241 self.runBrowserAct.setEnabled(project is not None) 1372 self.runBrowserAct.setEnabled(project is not None)
1242 self.runPythonShellAct.setEnabled(project is not None) 1373 self.runPythonShellAct.setEnabled(project is not None)
1243 self.showViewsAct.setEnabled(project is not None) 1374 self.showViewsAct.setEnabled(project is not None)
1244 self.showRoutesAct.setEnabled(project is not None) 1375 self.showRoutesAct.setEnabled(project is not None)
1245 self.showTweensAct.setEnabled(project is not None) 1376 self.showTweensAct.setEnabled(project is not None)
1246 self.buildDistroAct.setEnabled(project is not None) 1377 self.buildDistroAct.setEnabled(project is not None)
1247 1378
1248 def __project(self): 1379 def __project(self):
1249 """ 1380 """
1250 Private method to get the name of the current Pyramid project. 1381 Private method to get the name of the current Pyramid project.
1251 1382
1252 @return name of the project 1383 @return name of the project
1253 @rtype str 1384 @rtype str
1254 @exception PyramidNoProjectSelectedException raised, if no project is 1385 @exception PyramidNoProjectSelectedError raised, if no project is
1255 selected 1386 selected
1256 """ 1387 """
1257 if self.__currentProject is None: 1388 if self.__currentProject is None:
1258 self.__selectProject() 1389 self.__selectProject()
1259 1390
1260 if self.__currentProject is None: 1391 if self.__currentProject is None:
1261 raise PyramidNoProjectSelectedException 1392 raise PyramidNoProjectSelectedError
1262 else: 1393 else:
1263 return self.__currentProject 1394 return self.__currentProject
1264 1395
1265 ################################################################## 1396 ##################################################################
1266 ## slots below implement run functions 1397 ## slots below implement run functions
1267 ################################################################## 1398 ##################################################################
1268 1399
1269 def __runServer(self): 1400 def __runServer(self):
1270 """ 1401 """
1271 Private slot to start the Pyramid Web server. 1402 Private slot to start the Pyramid Web server.
1272 """ 1403 """
1273 consoleCmd = self.isSpawningConsole( 1404 consoleCmd = self.isSpawningConsole(
1274 self.__plugin.getPreferences("ConsoleCommand"))[1] 1405 self.__plugin.getPreferences("ConsoleCommand")
1406 )[1]
1275 if consoleCmd: 1407 if consoleCmd:
1276 try: 1408 try:
1277 projectPath = self.projectPath() 1409 projectPath = self.projectPath()
1278 except PyramidNoProjectSelectedException: 1410 except PyramidNoProjectSelectedError:
1279 EricMessageBox.warning( 1411 EricMessageBox.warning(
1280 self.__ui, 1412 self.__ui,
1281 self.tr('Run Server'), 1413 self.tr("Run Server"),
1282 self.tr('No current Pyramid project selected or no' 1414 self.tr(
1283 ' Pyramid project created yet. Aborting...')) 1415 "No current Pyramid project selected or no"
1416 " Pyramid project created yet. Aborting..."
1417 ),
1418 )
1284 return 1419 return
1285 1420
1286 args = Utilities.parseOptionString(consoleCmd) 1421 args = Utilities.parseOptionString(consoleCmd)
1287 args[0] = Utilities.getExecutablePath(args[0]) 1422 args[0] = Utilities.getExecutablePath(args[0])
1288 args.append(self.getPyramidCommand( 1423 args.append(
1289 "pserve", 1424 self.getPyramidCommand(
1290 virtualEnv=self.getProjectVirtualEnvironment() 1425 "pserve", virtualEnv=self.getProjectVirtualEnvironment()
1291 )) 1426 )
1427 )
1292 args.append("--reload") 1428 args.append("--reload")
1293 args.append(os.path.join(projectPath, "development.ini")) 1429 args.append(os.path.join(projectPath, "development.ini"))
1294 1430
1295 if isWindowsPlatform(): 1431 if isWindowsPlatform():
1296 serverProcStarted, pid = QProcess.startDetached( 1432 serverProcStarted, pid = QProcess.startDetached(
1297 args[0], args[1:], projectPath) 1433 args[0], args[1:], projectPath
1434 )
1298 else: 1435 else:
1299 if self.__serverProc is not None: 1436 if self.__serverProc is not None:
1300 self.__serverProcFinished() 1437 self.__serverProcFinished()
1301 1438
1302 self.__serverProc = QProcess() 1439 self.__serverProc = QProcess()
1303 self.__serverProc.finished.connect(self.__serverProcFinished) 1440 self.__serverProc.finished.connect(self.__serverProcFinished)
1304 self.__serverProc.setWorkingDirectory(projectPath) 1441 self.__serverProc.setWorkingDirectory(projectPath)
1305 self.__serverProc.start(args[0], args[1:]) 1442 self.__serverProc.start(args[0], args[1:])
1306 serverProcStarted = self.__serverProc.waitForStarted() 1443 serverProcStarted = self.__serverProc.waitForStarted()
1307 if not serverProcStarted: 1444 if not serverProcStarted:
1308 EricMessageBox.critical( 1445 EricMessageBox.critical(
1309 self.__ui, 1446 self.__ui,
1310 self.tr('Process Generation Error'), 1447 self.tr("Process Generation Error"),
1311 self.tr('The Pyramid server could not be started.')) 1448 self.tr("The Pyramid server could not be started."),
1312 1449 )
1450
1313 def __serverProcFinished(self): 1451 def __serverProcFinished(self):
1314 """ 1452 """
1315 Private slot connected to the finished signal. 1453 Private slot connected to the finished signal.
1316 """ 1454 """
1317 if ( 1455 if (
1318 self.__serverProc is not None and 1456 self.__serverProc is not None
1319 self.__serverProc.state() != QProcess.ProcessState.NotRunning 1457 and self.__serverProc.state() != QProcess.ProcessState.NotRunning
1320 ): 1458 ):
1321 self.__serverProc.terminate() 1459 self.__serverProc.terminate()
1322 QTimer.singleShot(2000, self.__serverProc.kill) 1460 QTimer.singleShot(2000, self.__serverProc.kill)
1323 self.__serverProc.waitForFinished(3000) 1461 self.__serverProc.waitForFinished(3000)
1324 self.__serverProc = None 1462 self.__serverProc = None
1325 1463
1326 def __runBrowser(self): 1464 def __runBrowser(self):
1327 """ 1465 """
1328 Private slot to start the default web browser with the server URL. 1466 Private slot to start the default web browser with the server URL.
1329 """ 1467 """
1330 try: 1468 try:
1331 projectPath = self.projectPath() 1469 projectPath = self.projectPath()
1332 except PyramidNoProjectSelectedException: 1470 except PyramidNoProjectSelectedError:
1333 EricMessageBox.warning( 1471 EricMessageBox.warning(
1334 self.__ui, 1472 self.__ui,
1335 self.tr('Run Web-Browser'), 1473 self.tr("Run Web-Browser"),
1336 self.tr('No current Pyramid project selected or no Pyramid' 1474 self.tr(
1337 ' project created yet. Aborting...')) 1475 "No current Pyramid project selected or no Pyramid"
1476 " project created yet. Aborting..."
1477 ),
1478 )
1338 return 1479 return
1339 1480
1340 config = configparser.ConfigParser() 1481 config = configparser.ConfigParser()
1341 config.read(os.path.join(projectPath, "development.ini")) 1482 config.read(os.path.join(projectPath, "development.ini"))
1342 try: 1483 try:
1343 listen = config.get("server:main", "listen") 1484 listen = config.get("server:main", "listen")
1344 except (configparser.NoOptionError, configparser.NoSectionError): 1485 except (configparser.NoOptionError, configparser.NoSectionError):
1347 if self.__plugin.getPreferences("UseExternalBrowser"): 1488 if self.__plugin.getPreferences("UseExternalBrowser"):
1348 res = QDesktopServices.openUrl(QUrl(url)) 1489 res = QDesktopServices.openUrl(QUrl(url))
1349 if not res: 1490 if not res:
1350 EricMessageBox.critical( 1491 EricMessageBox.critical(
1351 self.__ui, 1492 self.__ui,
1352 self.tr('Run Web-Browser'), 1493 self.tr("Run Web-Browser"),
1353 self.tr('Could not start the web-browser for the URL' 1494 self.tr(
1354 ' "{0}".').format(url.toString())) 1495 "Could not start the web-browser for the URL" ' "{0}".'
1496 ).format(url.toString()),
1497 )
1355 else: 1498 else:
1356 self.__ui.launchHelpViewer(url) 1499 self.__ui.launchHelpViewer(url)
1357 1500
1358 def __runPythonShell(self): 1501 def __runPythonShell(self):
1359 """ 1502 """
1360 Private slot to start a Python console for a Pyramid project. 1503 Private slot to start a Python console for a Pyramid project.
1361 """ 1504 """
1362 consoleCmd = self.isSpawningConsole( 1505 consoleCmd = self.isSpawningConsole(
1363 self.__plugin.getPreferences("ConsoleCommand"))[1] 1506 self.__plugin.getPreferences("ConsoleCommand")
1507 )[1]
1364 if consoleCmd: 1508 if consoleCmd:
1365 try: 1509 try:
1366 projectPath = self.projectPath() 1510 projectPath = self.projectPath()
1367 except PyramidNoProjectSelectedException: 1511 except PyramidNoProjectSelectedError:
1368 EricMessageBox.warning( 1512 EricMessageBox.warning(
1369 self.__ui, 1513 self.__ui,
1370 self.tr('Start Pyramid Python Console'), 1514 self.tr("Start Pyramid Python Console"),
1371 self.tr('No current Pyramid project selected or no' 1515 self.tr(
1372 ' Pyramid project created yet. Aborting...')) 1516 "No current Pyramid project selected or no"
1517 " Pyramid project created yet. Aborting..."
1518 ),
1519 )
1373 return 1520 return
1374 1521
1375 args = Utilities.parseOptionString(consoleCmd) 1522 args = Utilities.parseOptionString(consoleCmd)
1376 args[0] = Utilities.getExecutablePath(args[0]) 1523 args[0] = Utilities.getExecutablePath(args[0])
1377 args.append(self.getPyramidCommand( 1524 args.append(
1378 "pshell", 1525 self.getPyramidCommand(
1379 virtualEnv=self.getProjectVirtualEnvironment() 1526 "pshell", virtualEnv=self.getProjectVirtualEnvironment()
1380 )) 1527 )
1528 )
1381 consoleType = self.__plugin.getPreferences("Python3ConsoleType") 1529 consoleType = self.__plugin.getPreferences("Python3ConsoleType")
1382 args.append("--python-shell={0}".format(consoleType)) 1530 args.append("--python-shell={0}".format(consoleType))
1383 args.append(os.path.join(projectPath, "development.ini")) 1531 args.append(os.path.join(projectPath, "development.ini"))
1384 1532
1385 self.__adjustWorkingDirectory(args, projectPath) 1533 self.__adjustWorkingDirectory(args, projectPath)
1386 started, pid = QProcess.startDetached( 1534 started, pid = QProcess.startDetached(args[0], args[1:], projectPath)
1387 args[0], args[1:], projectPath)
1388 if not started: 1535 if not started:
1389 EricMessageBox.critical( 1536 EricMessageBox.critical(
1390 self.__ui, 1537 self.__ui,
1391 self.tr('Process Generation Error'), 1538 self.tr("Process Generation Error"),
1392 self.tr('The Pyramid Shell process could not be' 1539 self.tr("The Pyramid Shell process could not be" " started."),
1393 ' started.')) 1540 )
1394 1541
1395 ################################################################## 1542 ##################################################################
1396 ## slots below implement distribution functions 1543 ## slots below implement distribution functions
1397 ################################################################## 1544 ##################################################################
1398 1545
1399 def __buildDistribution(self): 1546 def __buildDistribution(self):
1400 """ 1547 """
1401 Private slot to build a distribution file for the current Pyramid 1548 Private slot to build a distribution file for the current Pyramid
1402 project. 1549 project.
1403 """ 1550 """
1404 title = self.tr("Build Distribution File") 1551 title = self.tr("Build Distribution File")
1405 try: 1552 try:
1406 projectPath = self.projectPath() 1553 projectPath = self.projectPath()
1407 except PyramidNoProjectSelectedException: 1554 except PyramidNoProjectSelectedError:
1408 EricMessageBox.warning( 1555 EricMessageBox.warning(
1409 self.__ui, 1556 self.__ui,
1410 title, 1557 title,
1411 self.tr('No current Pyramid project selected or no Pyramid' 1558 self.tr(
1412 ' project created yet. Aborting...')) 1559 "No current Pyramid project selected or no Pyramid"
1560 " project created yet. Aborting..."
1561 ),
1562 )
1413 return 1563 return
1414 1564
1415 from .DistributionTypeSelectionDialog import ( 1565 from .DistributionTypeSelectionDialog import DistributionTypeSelectionDialog
1416 DistributionTypeSelectionDialog 1566
1417 )
1418
1419 dlg = DistributionTypeSelectionDialog(self, projectPath, self.__ui) 1567 dlg = DistributionTypeSelectionDialog(self, projectPath, self.__ui)
1420 if dlg.exec() == QDialog.DialogCode.Accepted: 1568 if dlg.exec() == QDialog.DialogCode.Accepted:
1421 formats = dlg.getFormats() 1569 formats = dlg.getFormats()
1422 cmd = self.getPyramidCommand( 1570 cmd = self.getPyramidCommand(
1423 "python", 1571 "python", virtualEnv=self.getProjectVirtualEnvironment()
1424 virtualEnv=self.getProjectVirtualEnvironment()
1425 ) 1572 )
1426 args = [] 1573 args = []
1427 args.append("setup.py") 1574 args.append("setup.py")
1428 args.append("sdist") 1575 args.append("sdist")
1429 if formats: 1576 if formats:
1430 args.append("--formats={0}".format(','.join(formats))) 1577 args.append("--formats={0}".format(",".join(formats)))
1431 1578
1432 dia = PyramidDialog( 1579 dia = PyramidDialog(
1433 title, 1580 title,
1434 msgSuccess=self.tr("Python distribution file built" 1581 msgSuccess=self.tr("Python distribution file built" " successfully."),
1435 " successfully.")) 1582 )
1436 res = dia.startProcess(cmd, args, projectPath) 1583 res = dia.startProcess(cmd, args, projectPath)
1437 if res: 1584 if res:
1438 dia.exec() 1585 dia.exec()
1439 1586
1440 ################################################################## 1587 ##################################################################
1441 ## slots below implement various debugging functions 1588 ## slots below implement various debugging functions
1442 ################################################################## 1589 ##################################################################
1443 1590
1444 def __showMatchingViews(self): 1591 def __showMatchingViews(self):
1445 """ 1592 """
1446 Private slot showing all views that would match a given URL. 1593 Private slot showing all views that would match a given URL.
1447 """ 1594 """
1448 title = self.tr("Show Matching Views") 1595 title = self.tr("Show Matching Views")
1449 try: 1596 try:
1450 projectPath = self.projectPath() 1597 projectPath = self.projectPath()
1451 except PyramidNoProjectSelectedException: 1598 except PyramidNoProjectSelectedError:
1452 EricMessageBox.warning( 1599 EricMessageBox.warning(
1453 self.__ui, 1600 self.__ui,
1454 title, 1601 title,
1455 self.tr('No current Pyramid project selected or no Pyramid' 1602 self.tr(
1456 ' project created yet. Aborting...')) 1603 "No current Pyramid project selected or no Pyramid"
1604 " project created yet. Aborting..."
1605 ),
1606 )
1457 return 1607 return
1458 1608
1459 url, ok = QInputDialog.getText( 1609 url, ok = QInputDialog.getText(
1460 self.__ui, 1610 self.__ui,
1461 self.tr("Show Matching Views"), 1611 self.tr("Show Matching Views"),
1462 self.tr("Enter the URL to be matched:"), 1612 self.tr("Enter the URL to be matched:"),
1463 QLineEdit.EchoMode.Normal, 1613 QLineEdit.EchoMode.Normal,
1464 "/") 1614 "/",
1615 )
1465 if not ok or url == "": 1616 if not ok or url == "":
1466 return 1617 return
1467 1618
1468 cmd = self.getPyramidCommand( 1619 cmd = self.getPyramidCommand(
1469 "pviews", 1620 "pviews", virtualEnv=self.getProjectVirtualEnvironment()
1470 virtualEnv=self.getProjectVirtualEnvironment()
1471 ) 1621 )
1472 args = [] 1622 args = []
1473 args.append("development.ini") 1623 args.append("development.ini")
1474 args.append(url) 1624 args.append(url)
1475 1625
1476 dia = PyramidDialog(title, fixed=True, linewrap=False) 1626 dia = PyramidDialog(title, fixed=True, linewrap=False)
1477 res = dia.startProcess(cmd, args, projectPath) 1627 res = dia.startProcess(cmd, args, projectPath)
1478 if res: 1628 if res:
1479 dia.exec() 1629 dia.exec()
1480 1630
1481 def __showRoutes(self): 1631 def __showRoutes(self):
1482 """ 1632 """
1483 Private slot showing all URL dispatch routes. 1633 Private slot showing all URL dispatch routes.
1484 """ 1634 """
1485 title = self.tr("Show Routes") 1635 title = self.tr("Show Routes")
1486 try: 1636 try:
1487 projectPath = self.projectPath() 1637 projectPath = self.projectPath()
1488 except PyramidNoProjectSelectedException: 1638 except PyramidNoProjectSelectedError:
1489 EricMessageBox.warning( 1639 EricMessageBox.warning(
1490 self.__ui, 1640 self.__ui,
1491 title, 1641 title,
1492 self.tr('No current Pyramid project selected or no Pyramid' 1642 self.tr(
1493 ' project created yet. Aborting...')) 1643 "No current Pyramid project selected or no Pyramid"
1644 " project created yet. Aborting..."
1645 ),
1646 )
1494 return 1647 return
1495 1648
1496 from .PyramidRoutesDialog import PyramidRoutesDialog 1649 from .PyramidRoutesDialog import PyramidRoutesDialog
1497 1650
1498 dia = PyramidRoutesDialog(self) 1651 dia = PyramidRoutesDialog(self)
1499 res = dia.start(projectPath) 1652 res = dia.start(projectPath)
1500 if res: 1653 if res:
1501 dia.exec() 1654 dia.exec()
1502 1655
1503 def __showTweens(self): 1656 def __showTweens(self):
1504 """ 1657 """
1505 Private slot showing all implicit and explicit tween objects. 1658 Private slot showing all implicit and explicit tween objects.
1506 """ 1659 """
1507 title = self.tr("Show Tween Objects") 1660 title = self.tr("Show Tween Objects")
1508 try: 1661 try:
1509 projectPath = self.projectPath() 1662 projectPath = self.projectPath()
1510 except PyramidNoProjectSelectedException: 1663 except PyramidNoProjectSelectedError:
1511 EricMessageBox.warning( 1664 EricMessageBox.warning(
1512 self.__ui, 1665 self.__ui,
1513 title, 1666 title,
1514 self.tr('No current Pyramid project selected or no Pyramid' 1667 self.tr(
1515 ' project created yet. Aborting...')) 1668 "No current Pyramid project selected or no Pyramid"
1669 " project created yet. Aborting..."
1670 ),
1671 )
1516 return 1672 return
1517 1673
1518 cmd = self.getPyramidCommand( 1674 cmd = self.getPyramidCommand(
1519 "ptweens", 1675 "ptweens", virtualEnv=self.getProjectVirtualEnvironment()
1520 virtualEnv=self.getProjectVirtualEnvironment()
1521 ) 1676 )
1522 args = [] 1677 args = []
1523 args.append("development.ini") 1678 args.append("development.ini")
1524 1679
1525 dia = PyramidDialog(title, fixed=True, linewrap=False) 1680 dia = PyramidDialog(title, fixed=True, linewrap=False)
1526 res = dia.startProcess(cmd, args, projectPath) 1681 res = dia.startProcess(cmd, args, projectPath)
1527 if res: 1682 if res:
1528 dia.exec() 1683 dia.exec()
1529 1684
1530 ################################################################## 1685 ##################################################################
1531 ## slots below implement documentation functions 1686 ## slots below implement documentation functions
1532 ################################################################## 1687 ##################################################################
1533 1688
1534 def __showDocumentation(self): 1689 def __showDocumentation(self):
1535 """ 1690 """
1536 Private slot to show the helpviewer with the Pyramid documentation. 1691 Private slot to show the helpviewer with the Pyramid documentation.
1537 """ 1692 """
1538 page = self.__plugin.getPreferences("PyramidDocUrl") 1693 page = self.__plugin.getPreferences("PyramidDocUrl")
1539 self.__ui.launchHelpViewer(page) 1694 self.__ui.launchHelpViewer(page)
1540 1695
1541 ################################################################## 1696 ##################################################################
1542 ## slots below implement translation functions 1697 ## slots below implement translation functions
1543 ################################################################## 1698 ##################################################################
1544 1699
1545 def __getLocale(self, filename): 1700 def __getLocale(self, filename):
1546 """ 1701 """
1547 Private method to extract the locale out of a file name. 1702 Private method to extract the locale out of a file name.
1548 1703
1549 @param filename name of the file used for extraction 1704 @param filename name of the file used for extraction
1550 @type str 1705 @type str
1551 @return extracted locale or None 1706 @return extracted locale or None
1552 @rtype str 1707 @rtype str
1553 """ 1708 """
1556 # to an invalid search pattern '...\(' because the opening bracket 1711 # to an invalid search pattern '...\(' because the opening bracket
1557 # will be escaped. 1712 # will be escaped.
1558 pattern = self.__ericProject.getTranslationPattern() 1713 pattern = self.__ericProject.getTranslationPattern()
1559 pattern = os.path.normpath(pattern) 1714 pattern = os.path.normpath(pattern)
1560 pattern = pattern.replace("%language%", "(.*?)") 1715 pattern = pattern.replace("%language%", "(.*?)")
1561 pattern = pattern.replace('\\', '\\\\') 1716 pattern = pattern.replace("\\", "\\\\")
1562 match = re.search(pattern, filename) 1717 match = re.search(pattern, filename)
1563 if match is not None: 1718 if match is not None:
1564 return match.group(1) 1719 return match.group(1)
1565 1720
1566 return None 1721 return None
1567 1722
1568 def __normalizeList(self, filenames): 1723 def __normalizeList(self, filenames):
1569 """ 1724 """
1570 Private method to normalize a list of file names. 1725 Private method to normalize a list of file names.
1571 1726
1572 @param filenames list of file names to normalize 1727 @param filenames list of file names to normalize
1573 @type list of str 1728 @type list of str
1574 @return normalized file names 1729 @return normalized file names
1575 @rtype list of str 1730 @rtype list of str
1576 """ 1731 """
1578 for filename in filenames: 1733 for filename in filenames:
1579 if filename.endswith(".mo"): 1734 if filename.endswith(".mo"):
1580 filename = filename.replace(".mo", ".po") 1735 filename = filename.replace(".mo", ".po")
1581 if filename not in nfilenames: 1736 if filename not in nfilenames:
1582 nfilenames.append(filename) 1737 nfilenames.append(filename)
1583 1738
1584 return nfilenames 1739 return nfilenames
1585 1740
1586 def __projectFilteredList(self, filenames): 1741 def __projectFilteredList(self, filenames):
1587 """ 1742 """
1588 Private method to filter a list of file names by Pyramid project. 1743 Private method to filter a list of file names by Pyramid project.
1589 1744
1590 @param filenames list of file names to be filtered 1745 @param filenames list of file names to be filtered
1591 @type list of str 1746 @type list of str
1592 @return file names belonging to the current site 1747 @return file names belonging to the current site
1593 @rtype list of str 1748 @rtype list of str
1594 """ 1749 """
1595 project = self.__project() 1750 project = self.__project()
1596 nfilenames = [] 1751 nfilenames = []
1597 for filename in filenames: 1752 for filename in filenames:
1598 if filename.startswith(project + os.sep): 1753 if filename.startswith(project + os.sep):
1599 nfilenames.append(filename) 1754 nfilenames.append(filename)
1600 1755
1601 return nfilenames 1756 return nfilenames
1602 1757
1603 def extractMessages(self): 1758 def extractMessages(self):
1604 """ 1759 """
1605 Public method to extract the messages catalog template file. 1760 Public method to extract the messages catalog template file.
1606 """ 1761 """
1607 title = self.tr("Extract messages") 1762 title = self.tr("Extract messages")
1608 try: 1763 try:
1609 projectPath = self.projectPath() 1764 projectPath = self.projectPath()
1610 except PyramidNoProjectSelectedException: 1765 except PyramidNoProjectSelectedError:
1611 EricMessageBox.warning( 1766 EricMessageBox.warning(
1612 self.__ui, 1767 self.__ui,
1613 title, 1768 title,
1614 self.tr('No current Pyramid project selected or no Pyramid' 1769 self.tr(
1615 ' project created yet. Aborting...')) 1770 "No current Pyramid project selected or no Pyramid"
1771 " project created yet. Aborting..."
1772 ),
1773 )
1616 return 1774 return
1617 1775
1618 config = configparser.ConfigParser() 1776 config = configparser.ConfigParser()
1619 config.read(os.path.join(projectPath, "setup.cfg")) 1777 config.read(os.path.join(projectPath, "setup.cfg"))
1620 try: 1778 try:
1621 potFile = config.get("extract_messages", "output_file") 1779 potFile = config.get("extract_messages", "output_file")
1622 except configparser.NoSectionError: 1780 except configparser.NoSectionError:
1623 EricMessageBox.warning( 1781 EricMessageBox.warning(
1624 self.__ui, 1782 self.__ui,
1625 title, 1783 title,
1626 self.tr('No setup.cfg found or no "extract_messages"' 1784 self.tr(
1627 ' section found in setup.cfg.')) 1785 'No setup.cfg found or no "extract_messages"'
1786 " section found in setup.cfg."
1787 ),
1788 )
1628 return 1789 return
1629 except configparser.NoOptionError: 1790 except configparser.NoOptionError:
1630 EricMessageBox.warning( 1791 EricMessageBox.warning(
1631 self.__ui, 1792 self.__ui, title, self.tr('No "output_file" option found in setup.cfg.')
1632 title, 1793 )
1633 self.tr('No "output_file" option found in setup.cfg.'))
1634 return 1794 return
1635 1795
1636 with contextlib.suppress(OSError): 1796 with contextlib.suppress(OSError):
1637 path = os.path.join(projectPath, os.path.dirname(potFile)) 1797 path = os.path.join(projectPath, os.path.dirname(potFile))
1638 os.makedirs(path) 1798 os.makedirs(path)
1639 1799
1640 cmd = self.getPythonCommand() 1800 cmd = self.getPythonCommand()
1641 args = [] 1801 args = []
1642 args.append("setup.py") 1802 args.append("setup.py")
1643 args.append("extract_messages") 1803 args.append("extract_messages")
1644 1804
1645 dia = PyramidDialog( 1805 dia = PyramidDialog(
1646 title, 1806 title, msgSuccess=self.tr("\nMessages extracted successfully.")
1647 msgSuccess=self.tr("\nMessages extracted successfully.")) 1807 )
1648 res = dia.startProcess(cmd, args, projectPath) 1808 res = dia.startProcess(cmd, args, projectPath)
1649 if res: 1809 if res:
1650 dia.exec() 1810 dia.exec()
1651 self.__ericProject.appendFile(os.path.join(projectPath, potFile)) 1811 self.__ericProject.appendFile(os.path.join(projectPath, potFile))
1652 1812
1653 def __projectLanguageAdded(self, code): 1813 def __projectLanguageAdded(self, code):
1654 """ 1814 """
1655 Private slot handling the addition of a new language. 1815 Private slot handling the addition of a new language.
1656 1816
1657 @param code language code of the new language 1817 @param code language code of the new language
1658 @type str 1818 @type str
1659 """ 1819 """
1660 title = self.tr( 1820 title = self.tr("Initializing message catalog for '{0}'").format(code)
1661 "Initializing message catalog for '{0}'").format(code)
1662 try: 1821 try:
1663 projectPath = self.projectPath() 1822 projectPath = self.projectPath()
1664 except PyramidNoProjectSelectedException: 1823 except PyramidNoProjectSelectedError:
1665 EricMessageBox.warning( 1824 EricMessageBox.warning(
1666 self.__ui, 1825 self.__ui,
1667 title, 1826 title,
1668 self.tr('No current Pyramid project selected or no Pyramid' 1827 self.tr(
1669 ' project created yet. Aborting...')) 1828 "No current Pyramid project selected or no Pyramid"
1829 " project created yet. Aborting..."
1830 ),
1831 )
1670 return 1832 return
1671 1833
1672 cmd = self.getPythonCommand() 1834 cmd = self.getPythonCommand()
1673 args = [] 1835 args = []
1674 args.append("setup.py") 1836 args.append("setup.py")
1675 args.append("init_catalog") 1837 args.append("init_catalog")
1676 args.append("-l") 1838 args.append("-l")
1677 args.append(code) 1839 args.append(code)
1678 1840
1679 dia = PyramidDialog( 1841 dia = PyramidDialog(
1680 title, 1842 title, msgSuccess=self.tr("\nMessage catalog initialized" " successfully.")
1681 msgSuccess=self.tr("\nMessage catalog initialized" 1843 )
1682 " successfully."))
1683 res = dia.startProcess(cmd, args, projectPath) 1844 res = dia.startProcess(cmd, args, projectPath)
1684 if res: 1845 if res:
1685 dia.exec() 1846 dia.exec()
1686 1847
1687 langFile = self.__ericProject.getTranslationPattern().replace( 1848 langFile = self.__ericProject.getTranslationPattern().replace(
1688 "%language%", code) 1849 "%language%", code
1850 )
1689 self.__ericProject.appendFile(langFile) 1851 self.__ericProject.appendFile(langFile)
1690 1852
1691 def compileCatalogs(self, filenames): 1853 def compileCatalogs(self, filenames):
1692 """ 1854 """
1693 Public method to compile the message catalogs. 1855 Public method to compile the message catalogs.
1694 1856
1695 @param filenames list of filenames (not used) 1857 @param filenames list of filenames (not used)
1696 @type list of str 1858 @type list of str
1697 """ 1859 """
1698 title = self.tr("Compiling message catalogs") 1860 title = self.tr("Compiling message catalogs")
1699 try: 1861 try:
1700 projectPath = self.projectPath() 1862 projectPath = self.projectPath()
1701 except PyramidNoProjectSelectedException: 1863 except PyramidNoProjectSelectedError:
1702 EricMessageBox.warning( 1864 EricMessageBox.warning(
1703 self.__ui, 1865 self.__ui,
1704 title, 1866 title,
1705 self.tr('No current Pyramid project selected or no Pyramid' 1867 self.tr(
1706 ' project created yet. Aborting...')) 1868 "No current Pyramid project selected or no Pyramid"
1869 " project created yet. Aborting..."
1870 ),
1871 )
1707 return 1872 return
1708 1873
1709 cmd = self.getPythonCommand() 1874 cmd = self.getPythonCommand()
1710 args = [] 1875 args = []
1711 args.append("setup.py") 1876 args.append("setup.py")
1712 args.append("compile_catalog") 1877 args.append("compile_catalog")
1713 1878
1714 dia = PyramidDialog( 1879 dia = PyramidDialog(
1715 title, 1880 title, msgSuccess=self.tr("\nMessage catalogs compiled" " successfully.")
1716 msgSuccess=self.tr("\nMessage catalogs compiled" 1881 )
1717 " successfully."))
1718 res = dia.startProcess(cmd, args, projectPath) 1882 res = dia.startProcess(cmd, args, projectPath)
1719 if res: 1883 if res:
1720 dia.exec() 1884 dia.exec()
1721 1885
1722 for entry in os.walk(projectPath): 1886 for entry in os.walk(projectPath):
1723 for fileName in entry[2]: 1887 for fileName in entry[2]:
1724 fullName = os.path.join(entry[0], fileName) 1888 fullName = os.path.join(entry[0], fileName)
1725 if fullName.endswith('.mo'): 1889 if fullName.endswith(".mo"):
1726 self.__ericProject.appendFile(fullName) 1890 self.__ericProject.appendFile(fullName)
1727 1891
1728 def compileSelectedCatalogs(self, filenames): 1892 def compileSelectedCatalogs(self, filenames):
1729 """ 1893 """
1730 Public method to update the message catalogs. 1894 Public method to update the message catalogs.
1731 1895
1732 @param filenames list of file names 1896 @param filenames list of file names
1733 @type list of str 1897 @type list of str
1734 """ 1898 """
1735 title = self.tr("Compiling message catalogs") 1899 title = self.tr("Compiling message catalogs")
1736 try: 1900 try:
1737 projectPath = self.projectPath() 1901 projectPath = self.projectPath()
1738 except PyramidNoProjectSelectedException: 1902 except PyramidNoProjectSelectedError:
1739 EricMessageBox.warning( 1903 EricMessageBox.warning(
1740 self.__ui, 1904 self.__ui,
1741 title, 1905 title,
1742 self.tr('No current Pyramid project selected or no Pyramid' 1906 self.tr(
1743 ' project created yet. Aborting...')) 1907 "No current Pyramid project selected or no Pyramid"
1908 " project created yet. Aborting..."
1909 ),
1910 )
1744 return 1911 return
1745 1912
1746 argsLists = [] 1913 argsLists = []
1747 1914
1748 for filename in self.__normalizeList( 1915 for filename in self.__normalizeList(self.__projectFilteredList(filenames)):
1749 self.__projectFilteredList(filenames)):
1750 locale = self.__getLocale(filename) 1916 locale = self.__getLocale(filename)
1751 if locale: 1917 if locale:
1752 args = [] 1918 args = []
1753 args.append(self.getPythonCommand()) 1919 args.append(self.getPythonCommand())
1754 args.append("setup.py") 1920 args.append("setup.py")
1755 args.append("compile_catalog") 1921 args.append("compile_catalog")
1756 args.append("-l") 1922 args.append("-l")
1757 args.append(locale) 1923 args.append(locale)
1758 argsLists.append(args) 1924 argsLists.append(args)
1759 1925
1760 if len(argsLists) == 0: 1926 if len(argsLists) == 0:
1927 EricMessageBox.warning(
1928 self.__ui, title, self.tr("No locales detected. Aborting...")
1929 )
1930 return
1931
1932 dia = PyramidDialog(
1933 title, msgSuccess=self.tr("\nMessage catalogs compiled" " successfully.")
1934 )
1935 res = dia.startBatchProcesses(argsLists, projectPath)
1936 if res:
1937 dia.exec()
1938
1939 for entry in os.walk(self.__sitePath()):
1940 for fileName in entry[2]:
1941 fullName = os.path.join(entry[0], fileName)
1942 if fullName.endswith(".mo"):
1943 self.__ericProject.appendFile(fullName)
1944
1945 def updateCatalogs(self, filenames):
1946 """
1947 Public method to update the message catalogs.
1948
1949 @param filenames list of filenames (not used)
1950 @type list of str
1951 """
1952 title = self.tr("Updating message catalogs")
1953 try:
1954 projectPath = self.projectPath()
1955 except PyramidNoProjectSelectedError:
1761 EricMessageBox.warning( 1956 EricMessageBox.warning(
1762 self.__ui, 1957 self.__ui,
1763 title, 1958 title,
1764 self.tr('No locales detected. Aborting...')) 1959 self.tr(
1960 "No current Pyramid project selected or no Pyramid"
1961 " project created yet. Aborting..."
1962 ),
1963 )
1765 return 1964 return
1766 1965
1767 dia = PyramidDialog(
1768 title,
1769 msgSuccess=self.tr("\nMessage catalogs compiled"
1770 " successfully."))
1771 res = dia.startBatchProcesses(argsLists, projectPath)
1772 if res:
1773 dia.exec()
1774
1775 for entry in os.walk(self.__sitePath()):
1776 for fileName in entry[2]:
1777 fullName = os.path.join(entry[0], fileName)
1778 if fullName.endswith('.mo'):
1779 self.__ericProject.appendFile(fullName)
1780
1781 def updateCatalogs(self, filenames):
1782 """
1783 Public method to update the message catalogs.
1784
1785 @param filenames list of filenames (not used)
1786 @type list of str
1787 """
1788 title = self.tr("Updating message catalogs")
1789 try:
1790 projectPath = self.projectPath()
1791 except PyramidNoProjectSelectedException:
1792 EricMessageBox.warning(
1793 self.__ui,
1794 title,
1795 self.tr('No current Pyramid project selected or no Pyramid'
1796 ' project created yet. Aborting...'))
1797 return
1798
1799 cmd = self.getPythonCommand() 1966 cmd = self.getPythonCommand()
1800 args = [] 1967 args = []
1801 args.append("setup.py") 1968 args.append("setup.py")
1802 args.append("update_catalog") 1969 args.append("update_catalog")
1803 1970
1804 dia = PyramidDialog( 1971 dia = PyramidDialog(
1805 title, 1972 title, msgSuccess=self.tr("\nMessage catalogs updated successfully.")
1806 msgSuccess=self.tr("\nMessage catalogs updated successfully.")) 1973 )
1807 res = dia.startProcess(cmd, args, projectPath) 1974 res = dia.startProcess(cmd, args, projectPath)
1808 if res: 1975 if res:
1809 dia.exec() 1976 dia.exec()
1810 1977
1811 def updateSelectedCatalogs(self, filenames): 1978 def updateSelectedCatalogs(self, filenames):
1812 """ 1979 """
1813 Public method to update the message catalogs. 1980 Public method to update the message catalogs.
1814 1981
1815 @param filenames list of filenames 1982 @param filenames list of filenames
1816 @type list of str 1983 @type list of str
1817 """ 1984 """
1818 title = self.tr("Updating message catalogs") 1985 title = self.tr("Updating message catalogs")
1819 try: 1986 try:
1820 projectPath = self.projectPath() 1987 projectPath = self.projectPath()
1821 except PyramidNoProjectSelectedException: 1988 except PyramidNoProjectSelectedError:
1822 EricMessageBox.warning( 1989 EricMessageBox.warning(
1823 self.__ui, 1990 self.__ui,
1824 title, 1991 title,
1825 self.tr('No current Pyramid project selected or no Pyramid' 1992 self.tr(
1826 ' project created yet. Aborting...')) 1993 "No current Pyramid project selected or no Pyramid"
1994 " project created yet. Aborting..."
1995 ),
1996 )
1827 return 1997 return
1828 1998
1829 argsLists = [] 1999 argsLists = []
1830 2000
1831 for filename in self.__normalizeList( 2001 for filename in self.__normalizeList(self.__projectFilteredList(filenames)):
1832 self.__projectFilteredList(filenames)):
1833 locale = self.__getLocale(filename) 2002 locale = self.__getLocale(filename)
1834 if locale: 2003 if locale:
1835 args = [] 2004 args = []
1836 args.append(self.getPythonCommand()) 2005 args.append(self.getPythonCommand())
1837 args.append("setup.py") 2006 args.append("setup.py")
1838 args.append("update_catalog") 2007 args.append("update_catalog")
1839 args.append("-l") 2008 args.append("-l")
1840 args.append(locale) 2009 args.append(locale)
1841 argsLists.append(args) 2010 argsLists.append(args)
1842 2011
1843 if len(argsLists) == 0: 2012 if len(argsLists) == 0:
1844 EricMessageBox.warning( 2013 EricMessageBox.warning(
1845 self.__ui, 2014 self.__ui, title, self.tr("No locales detected. Aborting...")
1846 title, 2015 )
1847 self.tr('No locales detected. Aborting...'))
1848 return 2016 return
1849 2017
1850 dia = PyramidDialog( 2018 dia = PyramidDialog(
1851 title, 2019 title, msgSuccess=self.tr("\nMessage catalogs updated successfully.")
1852 msgSuccess=self.tr("\nMessage catalogs updated successfully.")) 2020 )
1853 res = dia.startBatchProcesses(argsLists, projectPath) 2021 res = dia.startBatchProcesses(argsLists, projectPath)
1854 if res: 2022 if res:
1855 dia.exec() 2023 dia.exec()
1856 2024
1857 def openPOEditor(self, poFile): 2025 def openPOEditor(self, poFile):
1858 """ 2026 """
1859 Public method to edit the given file in an external .po editor. 2027 Public method to edit the given file in an external .po editor.
1860 2028
1861 @param poFile name of the .po file 2029 @param poFile name of the .po file
1862 @type str 2030 @type str
1863 """ 2031 """
1864 editor = self.__plugin.getPreferences("TranslationsEditor") 2032 editor = self.__plugin.getPreferences("TranslationsEditor")
1865 if poFile.endswith(".po") and editor: 2033 if poFile.endswith(".po") and editor:
1866 try: 2034 try:
1867 wd = self.projectPath() 2035 wd = self.projectPath()
1868 except PyramidNoProjectSelectedException: 2036 except PyramidNoProjectSelectedError:
1869 wd = "" 2037 wd = ""
1870 started, pid = QProcess.startDetached(editor, [poFile], wd) 2038 started, pid = QProcess.startDetached(editor, [poFile], wd)
1871 if not started: 2039 if not started:
1872 EricMessageBox.critical( 2040 EricMessageBox.critical(
1873 None, 2041 None,
1874 self.tr('Process Generation Error'), 2042 self.tr("Process Generation Error"),
1875 self.tr('The translations editor process ({0}) could' 2043 self.tr(
1876 ' not be started.').format( 2044 "The translations editor process ({0}) could" " not be started."
1877 os.path.basename(editor))) 2045 ).format(os.path.basename(editor)),
1878 2046 )
2047
1879 ####################################################################### 2048 #######################################################################
1880 ## database related methods and slots below 2049 ## database related methods and slots below
1881 ####################################################################### 2050 #######################################################################
1882 2051
1883 def getAlembicCommand(self): 2052 def getAlembicCommand(self):
1884 """ 2053 """
1885 Public method to get the path to the alembic executable of the current 2054 Public method to get the path to the alembic executable of the current
1886 Pyramid project. 2055 Pyramid project.
1887 2056
1888 @return path to the alembic executable 2057 @return path to the alembic executable
1889 @rtype str 2058 @rtype str
1890 """ 2059 """
1891 return self.getPyramidCommand( 2060 return self.getPyramidCommand(
1892 "alembic", 2061 "alembic", virtualEnv=self.getProjectVirtualEnvironment()
1893 virtualEnv=self.getProjectVirtualEnvironment() 2062 )
1894 ) 2063
1895
1896 def migrationsPath(self): 2064 def migrationsPath(self):
1897 """ 2065 """
1898 Public method to get the path to the migrations directory of the 2066 Public method to get the path to the migrations directory of the
1899 current Pyramid project. 2067 current Pyramid project.
1900 2068
1901 @return pathof the directory containing the migrations 2069 @return pathof the directory containing the migrations
1902 @rtype str 2070 @rtype str
1903 """ 2071 """
1904 return os.path.join(self.projectPath(), self.__currentProject, 2072 return os.path.join(
1905 "alembic", "versions") 2073 self.projectPath(), self.__currentProject, "alembic", "versions"
1906 2074 )
2075
1907 def __getInitDbCommand(self): 2076 def __getInitDbCommand(self):
1908 """ 2077 """
1909 Private method to create the path to the initialization script. 2078 Private method to create the path to the initialization script.
1910 2079
1911 @return path to the initialization script 2080 @return path to the initialization script
1912 @rtype str 2081 @rtype str
1913 """ 2082 """
1914 try: 2083 try:
1915 cmd = "initialize_{0}_db".format(self.__project()) 2084 cmd = "initialize_{0}_db".format(self.__project())
1916 return self.getPyramidCommand( 2085 return self.getPyramidCommand(
1917 cmd, 2086 cmd, virtualEnv=self.getProjectVirtualEnvironment()
1918 virtualEnv=self.getProjectVirtualEnvironment() 2087 )
1919 ) 2088 except PyramidNoProjectSelectedError:
1920 except PyramidNoProjectSelectedException:
1921 EricMessageBox.warning( 2089 EricMessageBox.warning(
1922 self.__ui, 2090 self.__ui,
1923 self.tr("Initialize Database"), 2091 self.tr("Initialize Database"),
1924 self.tr('No current Pyramid project selected or no Pyramid' 2092 self.tr(
1925 ' project created yet. Aborting...')) 2093 "No current Pyramid project selected or no Pyramid"
2094 " project created yet. Aborting..."
2095 ),
2096 )
1926 return "" 2097 return ""
1927 2098
1928 @pyqtSlot() 2099 @pyqtSlot()
1929 def __initializeDatabase(self): 2100 def __initializeDatabase(self):
1930 """ 2101 """
1931 Private slot to initialize the database of the Pyramid project. 2102 Private slot to initialize the database of the Pyramid project.
1932 """ 2103 """
1933 title = self.tr("Initialize Database") 2104 title = self.tr("Initialize Database")
1934 try: 2105 try:
1935 projectPath = self.projectPath() 2106 projectPath = self.projectPath()
1936 except PyramidNoProjectSelectedException: 2107 except PyramidNoProjectSelectedError:
1937 EricMessageBox.warning( 2108 EricMessageBox.warning(
1938 self.__ui, 2109 self.__ui,
1939 title, 2110 title,
1940 self.tr('No current Pyramid project selected or no Pyramid' 2111 self.tr(
1941 ' project created yet. Aborting...')) 2112 "No current Pyramid project selected or no Pyramid"
2113 " project created yet. Aborting..."
2114 ),
2115 )
1942 return 2116 return
1943 2117
1944 cmd = self.__getInitDbCommand() 2118 cmd = self.__getInitDbCommand()
1945 args = [] 2119 args = []
1946 args.append("development.ini") 2120 args.append("development.ini")
1947 2121
1948 dia = PyramidDialog( 2122 dia = PyramidDialog(
1949 title, 2123 title, msgSuccess=self.tr("Database initialized successfully.")
1950 msgSuccess=self.tr("Database initialized successfully.")) 2124 )
1951 res = dia.startProcess(cmd, args, projectPath) 2125 res = dia.startProcess(cmd, args, projectPath)
1952 if res: 2126 if res:
1953 dia.exec() 2127 dia.exec()
1954 2128
1955 @pyqtSlot() 2129 @pyqtSlot()
1956 def __createMigration(self): 2130 def __createMigration(self):
1957 """ 2131 """
1958 Private slot to create a new database migration. 2132 Private slot to create a new database migration.
1959 """ 2133 """
1960 title = self.tr("Create Migration") 2134 title = self.tr("Create Migration")
1961 projectPath = self.projectPath() 2135 projectPath = self.projectPath()
1962 migrations = self.migrationsPath() 2136 migrations = self.migrationsPath()
1963 2137
1964 message, ok = QInputDialog.getText( 2138 message, ok = QInputDialog.getText(
1965 None, 2139 None,
1966 title, 2140 title,
1967 self.tr("Enter a short message for the migration:"), 2141 self.tr("Enter a short message for the migration:"),
1968 QLineEdit.EchoMode.Normal) 2142 QLineEdit.EchoMode.Normal,
2143 )
1969 if ok: 2144 if ok:
1970 args = ["-c", "development.ini", "revision", "--autogenerate"] 2145 args = ["-c", "development.ini", "revision", "--autogenerate"]
1971 if migrations: 2146 if migrations:
1972 args += ["--version-path", migrations] 2147 args += ["--version-path", migrations]
1973 if message: 2148 if message:
1974 args += ["--message", message] 2149 args += ["--message", message]
1975 2150
1976 dlg = PyramidDialog( 2151 dlg = PyramidDialog(
1977 title, 2152 title,
1978 msgSuccess=self.tr("\nMigration created successfully."), 2153 msgSuccess=self.tr("\nMigration created successfully."),
1979 linewrap=False, combinedOutput=True, 2154 linewrap=False,
1980 parent=self.__ui 2155 combinedOutput=True,
1981 ) 2156 parent=self.__ui,
1982 if dlg.startProcess(self.getAlembicCommand(), args, 2157 )
1983 workingDir=projectPath): 2158 if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath):
1984 dlg.exec() 2159 dlg.exec()
1985 if dlg.normalExit(): 2160 if dlg.normalExit():
1986 versionsPattern = os.path.join(migrations, "*.py") 2161 versionsPattern = os.path.join(migrations, "*.py")
1987 for fileName in glob.iglob(versionsPattern): 2162 for fileName in glob.iglob(versionsPattern):
1988 self.__ericProject.appendFile(fileName) 2163 self.__ericProject.appendFile(fileName)
1989 2164
1990 @pyqtSlot() 2165 @pyqtSlot()
1991 def upgradeDatabase(self, revision=None): 2166 def upgradeDatabase(self, revision=None):
1992 """ 2167 """
1993 Public slot to upgrade the database to the head or a given version. 2168 Public slot to upgrade the database to the head or a given version.
1994 2169
1995 @param revision migration revision to upgrade to 2170 @param revision migration revision to upgrade to
1996 @type str 2171 @type str
1997 """ 2172 """
1998 title = self.tr("Upgrade Database") 2173 title = self.tr("Upgrade Database")
1999 projectPath = self.projectPath() 2174 projectPath = self.projectPath()
2000 2175
2001 args = ["-c", "development.ini", "upgrade"] 2176 args = ["-c", "development.ini", "upgrade"]
2002 if revision: 2177 if revision:
2003 args.append(revision) 2178 args.append(revision)
2004 else: 2179 else:
2005 args.append("head") 2180 args.append("head")
2006 2181
2007 dlg = PyramidDialog( 2182 dlg = PyramidDialog(
2008 title, 2183 title,
2009 msgSuccess=self.tr("\nDatabase upgraded successfully."), 2184 msgSuccess=self.tr("\nDatabase upgraded successfully."),
2010 linewrap=False, combinedOutput=True, parent=self.__ui 2185 linewrap=False,
2011 ) 2186 combinedOutput=True,
2012 if dlg.startProcess(self.getAlembicCommand(), args, 2187 parent=self.__ui,
2013 workingDir=projectPath): 2188 )
2189 if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath):
2014 dlg.exec() 2190 dlg.exec()
2015 2191
2016 @pyqtSlot() 2192 @pyqtSlot()
2017 def downgradeDatabase(self, revision=None): 2193 def downgradeDatabase(self, revision=None):
2018 """ 2194 """
2019 Public slot to downgrade the database to the previous or a given 2195 Public slot to downgrade the database to the previous or a given
2020 version. 2196 version.
2021 2197
2022 @param revision migration revision to downgrade to 2198 @param revision migration revision to downgrade to
2023 @type str 2199 @type str
2024 """ 2200 """
2025 title = self.tr("Downgrade Database") 2201 title = self.tr("Downgrade Database")
2026 projectPath = self.projectPath() 2202 projectPath = self.projectPath()
2027 2203
2028 args = ["-c", "development.ini", "downgrade"] 2204 args = ["-c", "development.ini", "downgrade"]
2029 if revision: 2205 if revision:
2030 args.append(revision) 2206 args.append(revision)
2031 else: 2207 else:
2032 args.append("-1") 2208 args.append("-1")
2033 2209
2034 dlg = PyramidDialog( 2210 dlg = PyramidDialog(
2035 title, 2211 title,
2036 msgSuccess=self.tr("\nDatabase downgraded successfully."), 2212 msgSuccess=self.tr("\nDatabase downgraded successfully."),
2037 linewrap=False, combinedOutput=True, parent=self.__ui 2213 linewrap=False,
2038 ) 2214 combinedOutput=True,
2039 if dlg.startProcess(self.getAlembicCommand(), args, 2215 parent=self.__ui,
2040 workingDir=projectPath): 2216 )
2217 if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath):
2041 dlg.exec() 2218 dlg.exec()
2042 2219
2043 @pyqtSlot() 2220 @pyqtSlot()
2044 def __showMigrationsSummary(self): 2221 def __showMigrationsSummary(self):
2045 """ 2222 """
2046 Private slot to show a migrations history summary. 2223 Private slot to show a migrations history summary.
2047 """ 2224 """
2048 from .MigrateSummaryDialog import MigrateSummaryDialog 2225 from .MigrateSummaryDialog import MigrateSummaryDialog
2049 2226
2050 if self.__migrationSummaryDialog is None: 2227 if self.__migrationSummaryDialog is None:
2051 self.__migrationSummaryDialog = MigrateSummaryDialog( 2228 self.__migrationSummaryDialog = MigrateSummaryDialog(self, parent=self.__ui)
2052 self, parent=self.__ui) 2229
2053
2054 self.__migrationSummaryDialog.showSummary() 2230 self.__migrationSummaryDialog.showSummary()
2055 2231
2056 @pyqtSlot() 2232 @pyqtSlot()
2057 def __showMigrationsHistory(self): 2233 def __showMigrationsHistory(self):
2058 """ 2234 """
2059 Private slot to show the full migrations history. 2235 Private slot to show the full migrations history.
2060 """ 2236 """
2061 title = self.tr("Migrations History") 2237 title = self.tr("Migrations History")
2062 projectPath = self.projectPath() 2238 projectPath = self.projectPath()
2063 2239
2064 args = ["-c", "development.ini", "history", "--indicate-current", 2240 args = ["-c", "development.ini", "history", "--indicate-current", "--verbose"]
2065 "--verbose"] 2241
2066
2067 dlg = PyramidDialog( 2242 dlg = PyramidDialog(
2068 title, 2243 title, linewrap=False, combinedOutput=True, parent=self.__ui
2069 linewrap=False, combinedOutput=True, parent=self.__ui 2244 )
2070 ) 2245 if dlg.startProcess(self.getAlembicCommand(), args, workingDir=projectPath):
2071 if dlg.startProcess(self.getAlembicCommand(), args,
2072 workingDir=projectPath):
2073 dlg.exec() 2246 dlg.exec()

eric ide

mercurial