ProjectPyramid/Project.py

changeset 2
e691c51ab655
child 3
76c45d31d462
equal deleted inserted replaced
1:012c492a9bd6 2:e691c51ab655
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the Pyramid project support.
8 """
9
10 import os
11 import configparser
12
13 from PyQt4.QtCore import QObject, QFileInfo, QProcess, QTimer, QUrl
14 from PyQt4.QtGui import QMenu, QDialog, QInputDialog, QDesktopServices
15
16 from E5Gui.E5Application import e5App
17 from E5Gui import E5MessageBox, E5FileDialog
18 from E5Gui.E5Action import E5Action
19
20 from .FormSelectionDialog import FormSelectionDialog
21 from .CreateParametersDialog import CreateParametersDialog
22 from .PyramidDialog import PyramidDialog
23 from .DistributionTypeSelectionDialog import DistributionTypeSelectionDialog
24
25 import Utilities
26 from Globals import isWindowsPlatform
27 import UI.PixmapCache
28
29
30 class PyramidNoProjectSelectedException(Exception):
31 """
32 Exception thrown to signal, that there is no current Pyramid project.
33 """
34 pass
35
36
37 class Project(QObject):
38 """
39 Class implementing the Pyramid project support.
40 """
41 def __init__(self, plugin, parent = None):
42 """
43 Constructor
44
45 @param plugin reference to the plugin object
46 @param parent parent (QObject)
47 """
48 super().__init__(parent)
49
50 self.__plugin = plugin
51 self.__ui = parent
52 self.__e5project = e5App().getObject("Project")
53 self.__hooksInstalled = False
54
55 self.__mainMenu = None
56
57 self.__serverProc = None
58
59 def initActions(self):
60 """
61 Public method to define the Pyramid actions.
62 """
63 self.actions = []
64
65 self.selectProjectAct = E5Action(self.trUtf8('Current Pyramid Project'),
66 "",
67 0, 0,
68 self,'pyramid_current_project')
69 self.selectProjectAct.setStatusTip(self.trUtf8(
70 'Selects the current Pyramid project'))
71 self.selectProjectAct.setWhatsThis(self.trUtf8(
72 """<b>Current Pyramid Project</b>"""
73 """<p>Selects the Pyramid project. Used for multi-project """
74 """Pyramid projects to switch between the projects.</p>"""
75 ))
76 self.selectProjectAct.triggered[()].connect(self.__selectProject)
77 self.actions.append(self.selectProjectAct)
78 self.__setCurrentProject(None)
79
80 ###############################
81 ## create actions below ##
82 ###############################
83
84 self.createProjectAct = E5Action(self.trUtf8('Create Pyramid Project'),
85 self.trUtf8('Create Pyramid &Project'),
86 0, 0,
87 self,'pyramid_create_project')
88 self.createProjectAct.setStatusTip(self.trUtf8(
89 'Creates a new Pyramid project'))
90 self.createProjectAct.setWhatsThis(self.trUtf8(
91 """<b>Create Pyramid Project</b>"""
92 """<p>Creates a new Pyramid project using "pcreate".</p>"""
93 ))
94 self.createProjectAct.triggered[()].connect(self.__createProject)
95 self.actions.append(self.createProjectAct)
96
97 ##############################
98 ## run actions below ##
99 ##############################
100
101 self.runServerAct = E5Action(self.trUtf8('Run Server'),
102 self.trUtf8('Run &Server'),
103 0, 0,
104 self,'pyramid_run_server')
105 self.runServerAct.setStatusTip(self.trUtf8(
106 'Starts the Pyramid Web server'))
107 self.runServerAct.setWhatsThis(self.trUtf8(
108 """<b>Run Server</b>"""
109 """<p>Starts the Pyramid Web server using"""
110 """ "pserve --reload development.ini".</p>"""
111 ))
112 self.runServerAct.triggered[()].connect(self.__runServer)
113 self.actions.append(self.runServerAct)
114
115 self.runLoggingServerAct = E5Action(self.trUtf8('Run Server with Logging'),
116 self.trUtf8('Run Server with &Logging'),
117 0, 0,
118 self,'pyramid_run_logging_server')
119 self.runLoggingServerAct.setStatusTip(self.trUtf8(
120 'Starts the Pyramid Web server with logging'))
121 self.runLoggingServerAct.setWhatsThis(self.trUtf8(
122 """<b>Run Server with Logging</b>"""
123 """<p>Starts the Pyramid Web server with logging using"""
124 """ "pserve --log-file=server.log --reload development.ini".</p>"""
125 ))
126 self.runLoggingServerAct.triggered[()].connect(self.__runLoggingServer)
127 self.actions.append(self.runLoggingServerAct)
128
129 self.runBrowserAct = E5Action(self.trUtf8('Run Web-Browser'),
130 self.trUtf8('Run &Web-Browser'),
131 0, 0,
132 self,'pyramid_run_browser')
133 self.runBrowserAct.setStatusTip(self.trUtf8(
134 'Starts the default Web-Browser with the URL of the Pyramid Web server'))
135 self.runBrowserAct.setWhatsThis(self.trUtf8(
136 """<b>Run Web-Browser</b>"""
137 """<p>Starts the default Web-Browser with the URL of the """
138 """Pyramid Web server.</p>"""
139 ))
140 self.runBrowserAct.triggered[()].connect(self.__runBrowser)
141 self.actions.append(self.runBrowserAct)
142
143 self.runPythonShellAct = E5Action(self.trUtf8('Start Pyramid Python Console'),
144 self.trUtf8('Start Pyramid &Python Console'),
145 0, 0,
146 self,'pyramid_python_console')
147 self.runPythonShellAct.setStatusTip(self.trUtf8(
148 'Starts an interactive Python interpreter'))
149 self.runPythonShellAct.setWhatsThis(self.trUtf8(
150 """<b>Start Pyramid Python Console</b>"""
151 """<p>Starts an interactive Python interpreter.</p>"""
152 ))
153 self.runPythonShellAct.triggered[()].connect(self.__runPythonShell)
154 self.actions.append(self.runPythonShellAct)
155
156 ##############################
157 ## setup actions below ##
158 ##############################
159
160 self.setupDevelopAct = E5Action(self.trUtf8('Setup Development Environment'),
161 self.trUtf8('Setup &Development Environment'),
162 0, 0,
163 self,'pyramid_setup_development')
164 self.setupDevelopAct.setStatusTip(self.trUtf8(
165 'Setup the Pyramid project in development mode'))
166 self.setupDevelopAct.setWhatsThis(self.trUtf8(
167 """<b>Setup Development Environment</b>"""
168 """<p>Setup the Pyramid project in development mode using"""
169 """ "python setup.py develop".</p>"""
170 ))
171 self.setupDevelopAct.triggered[()].connect(self.__setupDevelop)
172 self.actions.append(self.setupDevelopAct)
173
174 ##################################
175 ## distribution actions below ##
176 ##################################
177
178 self.buildDistroAct = E5Action(self.trUtf8('Build Distribution'),
179 self.trUtf8('Build &Distribution'),
180 0, 0,
181 self,'pyramid_build_distribution')
182 self.buildDistroAct.setStatusTip(self.trUtf8(
183 'Builds a distribution file for the Pyramid project'))
184 self.buildDistroAct.setWhatsThis(self.trUtf8(
185 """<b>Build Distribution</b>"""
186 """<p>Builds a distribution file for the Pyramid project using"""
187 """ "python setup.py sdist".</p>"""
188 ))
189 self.buildDistroAct.triggered[()].connect(self.__buildDistribution)
190 self.actions.append(self.buildDistroAct)
191
192 ##################################
193 ## documentation action below ##
194 ##################################
195
196 self.documentationAct = E5Action(self.trUtf8('Documentation'),
197 self.trUtf8('D&ocumentation'),
198 0, 0,
199 self,'pyramid_documentation')
200 self.documentationAct.setStatusTip(self.trUtf8(
201 'Shows the help viewer with the Pyramid documentation'))
202 self.documentationAct.setWhatsThis(self.trUtf8(
203 """<b>Documentation</b>"""
204 """<p>Shows the help viewer with the Pyramid documentation.</p>"""
205 ))
206 self.documentationAct.triggered[()].connect(self.__showDocumentation)
207 self.actions.append(self.documentationAct)
208
209 ##############################
210 ## about action below ##
211 ##############################
212
213 self.aboutPyramidAct = E5Action(self.trUtf8('About Pyramid'),
214 self.trUtf8('About P&yramid'),
215 0, 0,
216 self,'pyramid_about')
217 self.aboutPyramidAct.setStatusTip(self.trUtf8(
218 'Shows some information about Pyramid'))
219 self.aboutPyramidAct.setWhatsThis(self.trUtf8(
220 """<b>About Pyramid</b>"""
221 """<p>Shows some information about Pyramid.</p>"""
222 ))
223 self.aboutPyramidAct.triggered[()].connect(self.__pyramidInfo)
224 self.actions.append(self.aboutPyramidAct)
225
226 def initMenu(self):
227 """
228 Public slot to initialize the Pyramid menu.
229
230 @return the menu generated (QMenu)
231 """
232 menu = QMenu(self.trUtf8('P&yramid'), self.__ui)
233 menu.setTearOffEnabled(True)
234
235 menu.addAction(self.selectProjectAct)
236 menu.addSeparator()
237 menu.addAction(self.runServerAct)
238 menu.addAction(self.runLoggingServerAct)
239 menu.addAction(self.runBrowserAct)
240 menu.addSeparator()
241 menu.addAction(self.createProjectAct)
242 menu.addSeparator()
243 menu.addAction(self.setupDevelopAct)
244 menu.addSeparator()
245 menu.addAction(self.runPythonShellAct)
246 menu.addSeparator()
247 menu.addAction(self.buildDistroAct)
248 menu.addSeparator()
249 menu.addAction(self.documentationAct)
250 menu.addSeparator()
251 menu.addAction(self.aboutPyramidAct)
252
253 self.__mainMenu = menu
254 return menu
255
256 def projectOpenedHooks(self):
257 """
258 Public method to add our hook methods.
259 """
260 if self.__e5project.getProjectType() == "Pyramid":
261 self.__formsBrowser = \
262 e5App().getObject("ProjectBrowser").getProjectBrowser("forms")
263 self.__formsBrowser.addHookMethodAndMenuEntry("newForm",
264 self.newForm, self.trUtf8("New template..."))
265
266 ## self.__e5project.projectLanguageAddedByCode.connect(
267 ## self.__projectLanguageAdded)
268 ## self.__translationsBrowser = \
269 ## e5App().getObject("ProjectBrowser").getProjectBrowser("translations")
270 ## self.__translationsBrowser.addHookMethodAndMenuEntry("extractMessages",
271 ## self.extractMessages, self.trUtf8("Extract messages"))
272 ## self.__translationsBrowser.addHookMethodAndMenuEntry("releaseAll",
273 ## self.compileCatalogs, self.trUtf8("Compile all catalogs"))
274 ## self.__translationsBrowser.addHookMethodAndMenuEntry("releaseSelected",
275 ## self.compileSelectedCatalogs,
276 ## self.trUtf8("Compile selected catalogs"))
277 ## self.__translationsBrowser.addHookMethodAndMenuEntry("generateAll",
278 ## self.updateCatalogs, self.trUtf8("Update all catalogs"))
279 ## self.__translationsBrowser.addHookMethodAndMenuEntry("generateSelected",
280 ## self.updateSelectedCatalogs, self.trUtf8("Update selected catalogs"))
281
282 self.__hooksInstalled = True
283
284 def projectClosedHooks(self):
285 """
286 Public method to remove our hook methods.
287 """
288 if self.__hooksInstalled:
289 self.__formsBrowser.removeHookMethod("newForm")
290 self.__formsBrowser = None
291
292 ## self.__e5project.projectLanguageAddedByCode.disconnect(
293 ## self.__projectLanguageAdded)
294 ## self.__translationsBrowser.removeHookMethod("extractMessages")
295 ## self.__translationsBrowser.removeHookMethod("releaseAll")
296 ## self.__translationsBrowser.removeHookMethod("releaseSelected")
297 ## self.__translationsBrowser.removeHookMethod("generateAll")
298 ## self.__translationsBrowser.removeHookMethod("generateSelected")
299 ## self.__translationsBrowser = None
300
301 self.__hooksInstalled = False
302
303 def newForm(self, path):
304 """
305 Public method to create a new form.
306
307 @param path full directory path for the new form file (string)
308 """
309 dlg = FormSelectionDialog()
310 if dlg.exec_() == QDialog.Accepted:
311 template = dlg.getTemplateText()
312
313 filter = self.trUtf8(
314 "Chameleon Templates (*.pt);;"
315 "Chameleon Text Templates (*.txt);;"
316 "Mako Templates (*.mako);;"
317 "Mako Templates (*.mak);;"
318 "HTML Files (*.html);;"
319 "HTML Files (*.htm);;"
320 "All Files (*)")
321 fname, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
322 self.__ui,
323 self.trUtf8("New Form"),
324 path,
325 filter,
326 None,
327 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite))
328 if fname:
329 ext = QFileInfo(fname).suffix()
330 if not ext:
331 ex = selectedFilter.split("(*")[1].split(")")[0]
332 if ex:
333 fname += ex
334
335 if os.path.exists(fname):
336 res = E5MessageBox.yesNo(self.__ui,
337 self.trUtf8("New Form"),
338 self.trUtf8("""The file already exists! Overwrite it?"""),
339 icon = E5MessageBox.Warning)
340 if not res:
341 # user selected to not overwrite
342 return
343
344 try:
345 f = open(fname, "w", encoding="utf-8")
346 f.write(template)
347 f.close()
348 except IOError as e:
349 E5MessageBox.critical(self,
350 self.trUtf8("New Form"),
351 self.trUtf8("<p>The new form file <b>{0}</b> could not be"
352 " created.<br/>"
353 "Problem: {1}</p>").format(fname, e))
354 return
355
356 self.__e5project.appendFile(fname)
357 self.__formsBrowser.sourceFile.emit(fname)
358
359 ##################################################################
360 ## methods below implement general functionality
361 ##################################################################
362
363 def projectClosed(self):
364 """
365 Public method to handle the closing of a project.
366 """
367 if self.__serverProc is not None:
368 self.__serverProcFinished()
369 self.__setCurrentProject(None)
370
371 def __getVirtualEnvironment(self):
372 """
373 Private method to get the path of the virtual environment.
374
375 @return path of the virtual environment (string)
376 """
377 language = self.__e5project.getProjectLanguage()
378 if language == "Python3":
379 virtEnv = self.__plugin.getPreferences("VirtualEnvironmentPy3")
380 elif language == "Python2":
381 virtEnv = self.__plugin.getPreferences("VirtualEnvironmentPy2")
382 else:
383 virtEnv = ""
384 if virtEnv and not os.path.exists(virtEnv):
385 virtEnv = ""
386 return virtEnv
387
388 def getPyramidCommand(self, cmd):
389 """
390 Public method to build a Pyramid command.
391
392 @param cmd command (string)
393 @return full pyramid command (string)
394 """
395 virtualEnv = self.__getVirtualEnvironment()
396 if virtualEnv:
397 if isWindowsPlatform():
398 cmd = os.path.join(virtualEnv, "Scripts", cmd)
399 else:
400 cmd = os.path.join(virtualEnv, "bin", cmd)
401 return cmd
402
403 def getPythonCommand(self):
404 """
405 Public method to build the Python command.
406
407 @return python command (string)
408 """
409 python = "python"
410 if isWindowsPlatform():
411 python += ".exe"
412 virtualEnv = self.__getVirtualEnvironment()
413 if virtualEnv:
414 if isWindowsPlatform():
415 python = os.path.join(virtualEnv, "Scripts", python)
416 else:
417 python = os.path.join(virtualEnv, "bin", python)
418 return python
419
420 def __pyramidInfo(self):
421 """
422 Private slot to show some info about Pyramid.
423 """
424 url = "http://www.pylonsproject.org/projects/pyramid/about"
425 msgBox = E5MessageBox.E5MessageBox(E5MessageBox.Question,
426 self.trUtf8("About Pyramid"),
427 self.trUtf8(
428 "<p>Pyramid is a high-level Python Web framework that encourages rapid "
429 "development and clean, pragmatic design.</p>"
430 "<p>URL: <a href=\"{0}\">{0}</a></p>"
431 ).format(url),
432 modal=True,
433 buttons=E5MessageBox.Ok)
434 msgBox.setIconPixmap(UI.PixmapCache.getPixmap(
435 os.path.join("ProjectPyramid", "icons", "pyramid64.png")))
436 msgBox.exec_()
437
438 def isSpawningConsole(self, consoleCmd):
439 """
440 Public method to check, if the given console is a spawning console.
441
442 @param consoleCmd console command (string)
443 @return tuple of two entries giving an indication, if the console
444 is spawning (boolean) and the (possibly) cleaned console command
445 (string)
446 """
447 if consoleCmd and consoleCmd[0] == '@':
448 return (True, consoleCmd[1:])
449 else:
450 return (False, consoleCmd)
451
452 ##################################################################
453 ## slots below implement creation functions
454 ##################################################################
455
456 def __createProject(self):
457 """
458 Private slot to create a new Pyramid project.
459 """
460 dlg = CreateParametersDialog(self)
461 if dlg.exec_() == QDialog.Accepted:
462 scaffold, project, overwrite, simulate = dlg.getData()
463
464 cmd = self.getPyramidCommand("pcreate")
465 args = []
466 if overwrite:
467 args.append("--overwrite")
468 else:
469 args.append("--interactive")
470 if simulate:
471 args.append("--simulate")
472 args.append("--scaffold={0}".format(scaffold))
473 args.append(project)
474 dlg = PyramidDialog(self.trUtf8("Create Pyramid Project"),
475 linewrap=False, parent=self.__ui)
476 if dlg.startProcess(cmd, args, self.__e5project.getProjectPath()):
477 dlg.exec_()
478 if dlg.normalExit() and not simulate:
479 # search for files created by pcreate and add them to the project
480 projectPath = os.path.join(self.__e5project.getProjectPath(), project)
481 for entry in os.walk(projectPath):
482 for fileName in entry[2]:
483 fullName = os.path.join(entry[0], fileName)
484 self.__e5project.appendFile(fullName)
485
486 # create the base directory for translations
487 i18nPath = os.path.join(projectPath, project.lower(), "i18n")
488 if not os.path.exists(i18nPath):
489 os.makedirs(i18nPath)
490 self.__e5project.setDirty(True)
491
492 self.__setCurrentProject(project)
493
494 ##################################################################
495 ## methods below implement site related functions
496 ##################################################################
497
498 def __findProjects(self):
499 """
500 Private method to determine the relative path of all Pyramid
501 projects (= top level dirs).
502
503 @return list of projects (list of string)
504 """
505 projects = []
506 ppath = self.__e5project.getProjectPath()
507 for entry in os.listdir(ppath):
508 if entry[0] not in "._" and \
509 os.path.isdir(os.path.join(ppath, entry)):
510 projects.append(entry)
511 return projects
512
513 def __selectProject(self):
514 """
515 Private method to select a Pyramid project to work with.
516
517 @return selected project (string)
518 """
519 projects = self.__findProjects()
520 if len(projects) == 0:
521 project = None
522 elif len(projects) == 1:
523 project = projects[0]
524 else:
525 if self.__currentProject is not None:
526 try:
527 cur = projects.index(self.__currentProject)
528 except ValueError:
529 cur = 0
530 else:
531 cur = 0
532 project, ok = QInputDialog.getItem(
533 self.__ui,
534 self.trUtf8("Select Pyramid Project"),
535 self.trUtf8("Select the Pyramid project to work with."),
536 projects,
537 cur, False)
538 if not ok:
539 projects = None
540 self.__setCurrentProject(project)
541
542 def __projectPath(self):
543 """
544 Private method to calculate the full path of the Pyramid project.
545
546 @exception PyramidNoProjectSelectedException raised, if no project is selected
547 @return path of the project (string)
548 """
549 if self.__currentProject is None:
550 self.__selectProject()
551
552 if self.__currentProject is None:
553 raise PyramidNoProjectSelectedException
554 else:
555 return os.path.join(self.__e5project.getProjectPath(),
556 self.__currentProject)
557
558 def __setCurrentProject(self, project):
559 """
560 Private slot to set the current project.
561
562 @param project name of the project (string)
563 """
564 if project is not None and len(project) == 0:
565 self.__currentProject = None
566 else:
567 self.__currentProject = project
568
569 if self.__currentProject is None:
570 curProject = self.trUtf8("None")
571 else:
572 curProject = self.__currentProject
573 self.selectProjectAct.setText(
574 self.trUtf8('&Current Pyramid Project ({0})').format(curProject))
575
576 if self.__currentProject is None:
577 self.__e5project.pdata["TRANSLATIONPATTERN"] = []
578 else:
579 # TODO: adjust this to the Pyramid docu
580 self.__e5project.pdata["TRANSLATIONPATTERN"] = [
581 os.path.join(project, project.lower(), "i18n", "%language%",
582 "LC_MESSAGES", "%s.po" % project.lower())
583 ]
584
585 def __project(self):
586 """
587 Private method to get the name of the current Pyramid project.
588
589 @exception PyramidNoProjectSelectedException raised, if no project is selected
590 @return name of the project (string)
591 """
592 if self.__currentProject is None:
593 self.__selectProject()
594
595 if self.__currentProject is None:
596 raise PyramidNoProjectSelectedException
597 else:
598 return self.__currentProject
599
600 ##################################################################
601 ## slots below implement run functions
602 ##################################################################
603
604 def __runServer(self, logging = False):
605 """
606 Private slot to start the Pyramid Web server.
607
608 @param logging flag indicating to enable logging (boolean)
609 """
610 consoleCmd = self.isSpawningConsole(
611 self.__plugin.getPreferences("ConsoleCommand"))[1]
612 if consoleCmd:
613 try:
614 projectPath = self.__projectPath()
615 except PyramidNoProjectSelectedException:
616 E5MessageBox.warning(self.__ui,
617 self.trUtf8('Run Server'),
618 self.trUtf8('No current Pyramid project selected or no Pyramid '
619 'project created yet. Aborting...'))
620 return
621
622 args = Utilities.parseOptionString(consoleCmd)
623 args[0] = Utilities.getExecutablePath(args[0])
624 args.append(self.getPyramidCommand("pserve"))
625 if logging:
626 args.append("--log-file=server.log")
627 args.append("--reload")
628 args.append(os.path.join(projectPath, "development.ini"))
629
630 if isWindowsPlatform():
631 serverProcStarted, pid = \
632 QProcess.startDetached(args[0], args[1:], projectPath)
633 else:
634 if self.__serverProc is not None:
635 self.__serverProcFinished()
636
637 self.__serverProc = QProcess()
638 self.__serverProc.finished.connect(self.__serverProcFinished)
639 self.__serverProc.setWorkingDirectory(projectPath)
640 self.__serverProc.start(args[0], args[1:])
641 serverProcStarted = self.__serverProc.waitForStarted()
642 if not serverProcStarted:
643 E5MessageBox.critical(self.__ui,
644 self.trUtf8('Process Generation Error'),
645 self.trUtf8('The Pyramid server could not be started.'))
646
647 def __runLoggingServer(self):
648 """
649 Private slot to start the Pyramid Web server with logging.
650 """
651 self.__runServer(True)
652
653 def __serverProcFinished(self):
654 """
655 Private slot connected to the finished signal.
656 """
657 if self.__serverProc is not None and \
658 self.__serverProc.state() != QProcess.NotRunning:
659 self.__serverProc.terminate()
660 QTimer.singleShot(2000, self.__serverProc.kill)
661 self.__serverProc.waitForFinished(3000)
662 self.__serverProc = None
663
664 def __runBrowser(self):
665 """
666 Private slot to start the default web browser with the server URL.
667 """
668 try:
669 projectPath = self.__projectPath()
670 except PyramidNoProjectSelectedException:
671 E5MessageBox.warning(self.__ui,
672 self.trUtf8('Run Web-Browser'),
673 self.trUtf8('No current Pyramid project selected or no Pyramid project'
674 ' created yet. Aborting...'))
675 return
676
677 config = configparser.ConfigParser()
678 config.read(os.path.join(projectPath, "development.ini"))
679 port = config.get("server:main", "port", fallback="6543")
680 url = QUrl("http://localhost:{0}".format(port))
681 res = QDesktopServices.openUrl(url)
682 if not res:
683 E5MessageBox.critical(self.__ui,
684 self.trUtf8('Run Web-Browser'),
685 self.trUtf8('Could not start the web-browser for the URL "{0}".')\
686 .format(url.toString()))
687
688 def __runPythonShell(self):
689 """
690 Private slot to start a Python console for a Pyramid project.
691 """
692 consoleCmd = self.isSpawningConsole(
693 self.__plugin.getPreferences("ConsoleCommand"))[1]
694 if consoleCmd:
695 try:
696 projectPath = self.__projectPath()
697 except PyramidNoProjectSelectedException:
698 E5MessageBox.warning(self.__ui,
699 self.trUtf8('Start Pyramid Python Console'),
700 self.trUtf8('No current Pyramid project selected or no Pyramid '
701 'project created yet. Aborting...'))
702 return
703
704 args = Utilities.parseOptionString(consoleCmd)
705 args[0] = Utilities.getExecutablePath(args[0])
706 args.append(self.getPyramidCommand("pshell"))
707 language = self.__e5project.getProjectLanguage()
708 if language == "Python2":
709 consoleType = self.__plugin.getPreferences("Python2ConsoleType")
710 else:
711 consoleType = self.__plugin.getPreferences("Python3ConsoleType")
712 args.append("--python-shell={0}".format(consoleType))
713 args.append(os.path.join(projectPath, "development.ini"))
714
715 started, pid = QProcess.startDetached(args[0], args[1:], projectPath)
716 if not started:
717 E5MessageBox.critical(self.__ui,
718 self.trUtf8('Process Generation Error'),
719 self.trUtf8('The Pyramid Shell process could not be started.'))
720
721 ##################################################################
722 ## slots below implement setup functions
723 ##################################################################
724
725 def __setupDevelop(self):
726 """
727 Private slot to set up the development environment for the current project.
728 """
729 title = self.trUtf8("Setup Development Environment")
730
731 cmd = self.getPythonCommand()
732 args = []
733 args.append("setup.py")
734 args.append("develop")
735
736 try:
737 wd = self.__projectPath()
738 except PyramidNoProjectSelectedException:
739 E5MessageBox.warning(self.__ui,
740 title,
741 self.trUtf8('No current Pyramid project selected or no Pyramid project'
742 ' created yet. Aborting...'))
743 return
744
745 dia = PyramidDialog(title,
746 msgSuccess = \
747 self.trUtf8("Pyramid development environment setup successfully."))
748 res = dia.startProcess(cmd, args, wd)
749 if res:
750 dia.exec_()
751
752 ##################################################################
753 ## slots below implement distribution functions
754 ##################################################################
755
756 def __buildDistribution(self):
757 """
758 Private slot to build a distribution file for the current Pyramid project.
759 """
760 title = self.trUtf8("Build Distribution File")
761 try:
762 projectPath = self.__projectPath()
763 except PyramidNoProjectSelectedException:
764 E5MessageBox.warning(self.__ui,
765 title,
766 self.trUtf8('No current Pyramid project selected or no Pyramid project'
767 ' created yet. Aborting...'))
768 return
769
770 dlg = DistributionTypeSelectionDialog(self, projectPath, self.__ui)
771 if dlg.exec_() == QDialog.Accepted:
772 formats = dlg.getFormats()
773 cmd = self.getPythonCommand()
774 args = []
775 args.append("setup.py")
776 args.append("sdist")
777 if formats:
778 args.append("--formats={0}".format(','.join(formats)))
779
780 dia = PyramidDialog(title,
781 msgSuccess = \
782 self.trUtf8("Python distribution file built successfully."))
783 res = dia.startProcess(cmd, args, projectPath)
784 if res:
785 dia.exec_()
786
787 ##################################################################
788 ## slots below implement documentation functions
789 ##################################################################
790
791 def __showDocumentation(self):
792 """
793 Private slot to show the helpviewer with the Pylons documentation.
794 """
795 page = self.__plugin.getPreferences("PyramidDocUrl")
796 self.__ui.launchHelpViewer(page)

eric ide

mercurial