Sat, 09 Jun 2018 17:19:37 +0200
VirtualEnv: started implementing a virtualenv manager.
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvConfigurationDialog.html Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvConfigurationDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvConfigurationDialog</h1> -<p> -Module implementing a dialog to enter the parameters for the -virtual environment. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#VirtualenvConfigurationDialog">VirtualenvConfigurationDialog</a></td> -<td>Class implementing a dialog to enter the parameters for the virtual environment.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="VirtualenvConfigurationDialog" ID="VirtualenvConfigurationDialog"></a> -<h2>VirtualenvConfigurationDialog</h2> -<p> - Class implementing a dialog to enter the parameters for the - virtual environment. -</p> -<h3>Derived from</h3> -QDialog, Ui_VirtualenvConfigurationDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#VirtualenvConfigurationDialog.__init__">VirtualenvConfigurationDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.__generateArguments">__generateArguments</a></td> -<td>Private method to generate the process arguments.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.__generateTargetDir">__generateTargetDir</a></td> -<td>Private method to generate a valid target directory path.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.__setPyvenvVersion">__setPyvenvVersion</a></td> -<td>Private method to determine the pyvenv version and set the respective label.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.__setVirtualenvVersion">__setVirtualenvVersion</a></td> -<td>Private method to determine the virtualenv version and set the respective label.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.__updateOK">__updateOK</a></td> -<td>Private method to update the enabled status of the OK button.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.__updateUi">__updateUi</a></td> -<td>Private method to update the UI depending on the selected virtual environment creator (virtualenv or pyvenv).</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.getData">getData</a></td> -<td>Public method to retrieve the dialog data.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_extraSearchPathButton_clicked">on_extraSearchPathButton_clicked</a></td> -<td>Private slot to select the extra search path via a directory selection dialog.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_pythonExecButton_clicked">on_pythonExecButton_clicked</a></td> -<td>Private slot to select a Python interpreter via a file selection dialog.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_pythonExecEdit_textChanged">on_pythonExecEdit_textChanged</a></td> -<td>Private slot to react to a change of the Python executable.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_pyvenvButton_toggled">on_pyvenvButton_toggled</a></td> -<td>Private slot to react to the selection of 'pyvenv'.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_targetDirectoryButton_clicked">on_targetDirectoryButton_clicked</a></td> -<td>Private slot to select the target directory via a directory selection dialog.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_targetDirectoryEdit_textChanged">on_targetDirectoryEdit_textChanged</a></td> -<td>Private slot handling a change of the target directory.</td> -</tr><tr> -<td><a href="#VirtualenvConfigurationDialog.on_virtualenvButton_toggled">on_virtualenvButton_toggled</a></td> -<td>Private slot to react to the selection of 'virtualenv'.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="VirtualenvConfigurationDialog.__init__" ID="VirtualenvConfigurationDialog.__init__"></a> -<h4>VirtualenvConfigurationDialog (Constructor)</h4> -<b>VirtualenvConfigurationDialog</b>(<i>parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>parent</i></dt> -<dd> -reference to the parent widget (QWidget) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.__generateArguments" ID="VirtualenvConfigurationDialog.__generateArguments"></a> -<h4>VirtualenvConfigurationDialog.__generateArguments</h4> -<b>__generateArguments</b>(<i></i>) -<p> - Private method to generate the process arguments. -</p><dl> -<dt>Returns:</dt> -<dd> -process arguments (list of string) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.__generateTargetDir" ID="VirtualenvConfigurationDialog.__generateTargetDir"></a> -<h4>VirtualenvConfigurationDialog.__generateTargetDir</h4> -<b>__generateTargetDir</b>(<i></i>) -<p> - Private method to generate a valid target directory path. -</p><dl> -<dt>Returns:</dt> -<dd> -target directory path (string) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.__setPyvenvVersion" ID="VirtualenvConfigurationDialog.__setPyvenvVersion"></a> -<h4>VirtualenvConfigurationDialog.__setPyvenvVersion</h4> -<b>__setPyvenvVersion</b>(<i></i>) -<p> - Private method to determine the pyvenv version and set the respective - label. -</p><a NAME="VirtualenvConfigurationDialog.__setVirtualenvVersion" ID="VirtualenvConfigurationDialog.__setVirtualenvVersion"></a> -<h4>VirtualenvConfigurationDialog.__setVirtualenvVersion</h4> -<b>__setVirtualenvVersion</b>(<i></i>) -<p> - Private method to determine the virtualenv version and set the - respective label. -</p><a NAME="VirtualenvConfigurationDialog.__updateOK" ID="VirtualenvConfigurationDialog.__updateOK"></a> -<h4>VirtualenvConfigurationDialog.__updateOK</h4> -<b>__updateOK</b>(<i></i>) -<p> - Private method to update the enabled status of the OK button. -</p><a NAME="VirtualenvConfigurationDialog.__updateUi" ID="VirtualenvConfigurationDialog.__updateUi"></a> -<h4>VirtualenvConfigurationDialog.__updateUi</h4> -<b>__updateUi</b>(<i></i>) -<p> - Private method to update the UI depending on the selected - virtual environment creator (virtualenv or pyvenv). -</p><a NAME="VirtualenvConfigurationDialog.getData" ID="VirtualenvConfigurationDialog.getData"></a> -<h4>VirtualenvConfigurationDialog.getData</h4> -<b>getData</b>(<i></i>) -<p> - Public method to retrieve the dialog data. -</p><dl> -<dt>Returns:</dt> -<dd> -tuple containing a flag indicating the pyvenv selection - (boolean), the process arguments (list of string), a flag - indicating to open the target directory after creation (boolean), - a flag indicating to write a log file (boolean), a flag indicating - to write a script (boolean), the name of the target directory - (string) and the name of the python interpreter to use (string) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.on_extraSearchPathButton_clicked" ID="VirtualenvConfigurationDialog.on_extraSearchPathButton_clicked"></a> -<h4>VirtualenvConfigurationDialog.on_extraSearchPathButton_clicked</h4> -<b>on_extraSearchPathButton_clicked</b>(<i></i>) -<p> - Private slot to select the extra search path via a directory - selection dialog. -</p><a NAME="VirtualenvConfigurationDialog.on_pythonExecButton_clicked" ID="VirtualenvConfigurationDialog.on_pythonExecButton_clicked"></a> -<h4>VirtualenvConfigurationDialog.on_pythonExecButton_clicked</h4> -<b>on_pythonExecButton_clicked</b>(<i></i>) -<p> - Private slot to select a Python interpreter via a file selection - dialog. -</p><a NAME="VirtualenvConfigurationDialog.on_pythonExecEdit_textChanged" ID="VirtualenvConfigurationDialog.on_pythonExecEdit_textChanged"></a> -<h4>VirtualenvConfigurationDialog.on_pythonExecEdit_textChanged</h4> -<b>on_pythonExecEdit_textChanged</b>(<i>txt</i>) -<p> - Private slot to react to a change of the Python executable. -</p><dl> -<dt><i>txt</i></dt> -<dd> -contents of the line edit (string) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.on_pyvenvButton_toggled" ID="VirtualenvConfigurationDialog.on_pyvenvButton_toggled"></a> -<h4>VirtualenvConfigurationDialog.on_pyvenvButton_toggled</h4> -<b>on_pyvenvButton_toggled</b>(<i>checked</i>) -<p> - Private slot to react to the selection of 'pyvenv'. -</p><dl> -<dt><i>checked</i></dt> -<dd> -state of the checkbox (boolean) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.on_targetDirectoryButton_clicked" ID="VirtualenvConfigurationDialog.on_targetDirectoryButton_clicked"></a> -<h4>VirtualenvConfigurationDialog.on_targetDirectoryButton_clicked</h4> -<b>on_targetDirectoryButton_clicked</b>(<i></i>) -<p> - Private slot to select the target directory via a directory - selection dialog. -</p><a NAME="VirtualenvConfigurationDialog.on_targetDirectoryEdit_textChanged" ID="VirtualenvConfigurationDialog.on_targetDirectoryEdit_textChanged"></a> -<h4>VirtualenvConfigurationDialog.on_targetDirectoryEdit_textChanged</h4> -<b>on_targetDirectoryEdit_textChanged</b>(<i>txt</i>) -<p> - Private slot handling a change of the target directory. -</p><dl> -<dt><i>txt</i></dt> -<dd> -target directory (string) -</dd> -</dl><a NAME="VirtualenvConfigurationDialog.on_virtualenvButton_toggled" ID="VirtualenvConfigurationDialog.on_virtualenvButton_toggled"></a> -<h4>VirtualenvConfigurationDialog.on_virtualenvButton_toggled</h4> -<b>on_virtualenvButton_toggled</b>(<i>checked</i>) -<p> - Private slot to react to the selection of 'virtualenv'. -</p><dl> -<dt><i>checked</i></dt> -<dd> -state of the checkbox (boolean) -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvExecDialog.html Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,226 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvExecDialog</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body><a NAME="top" ID="top"></a> -<h1>eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvExecDialog</h1> -<p> -Module implementing the virtualenv execution dialog. -</p> -<h3>Global Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Classes</h3> -<table> -<tr> -<td><a href="#VirtualenvExecDialog">VirtualenvExecDialog</a></td> -<td>Class implementing the virtualenv execution dialog.</td> -</tr> -</table> -<h3>Functions</h3> -<table> -<tr><td>None</td></tr> -</table> -<hr /><hr /> -<a NAME="VirtualenvExecDialog" ID="VirtualenvExecDialog"></a> -<h2>VirtualenvExecDialog</h2> -<p> - Class implementing the virtualenv execution dialog. -</p><p> - This class starts a QProcess and displays a dialog that - shows the output of the virtualenv or pyvenv process. -</p> -<h3>Derived from</h3> -QDialog, Ui_VirtualenvExecDialog -<h3>Class Attributes</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Class Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<h3>Methods</h3> -<table> -<tr> -<td><a href="#VirtualenvExecDialog.__init__">VirtualenvExecDialog</a></td> -<td>Constructor</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__finish">__finish</a></td> -<td>Private slot called when the process finished.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__logError">__logError</a></td> -<td>Private method to log an error.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__logOutput">__logOutput</a></td> -<td>Private method to log some output.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__nextAttempt">__nextAttempt</a></td> -<td>Private method to start another attempt.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__readStderr">__readStderr</a></td> -<td>Private slot to handle the readyReadStandardError signal.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__readStdout">__readStdout</a></td> -<td>Private slot to handle the readyReadStandardOutput signal.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__writeLogFile">__writeLogFile</a></td> -<td>Private method to write a log file to the virtualenv directory.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.__writeScriptFile">__writeScriptFile</a></td> -<td>Private method to write a script file to the virtualenv directory.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.on_buttonBox_clicked">on_buttonBox_clicked</a></td> -<td>Private slot called by a button of the button box clicked.</td> -</tr><tr> -<td><a href="#VirtualenvExecDialog.start">start</a></td> -<td>Public slot to start the virtualenv command.</td> -</tr> -</table> -<h3>Static Methods</h3> -<table> -<tr><td>None</td></tr> -</table> -<a NAME="VirtualenvExecDialog.__init__" ID="VirtualenvExecDialog.__init__"></a> -<h4>VirtualenvExecDialog (Constructor)</h4> -<b>VirtualenvExecDialog</b>(<i>pyvenv, targetDir, openTarget, createLog, createScript, interpreter, parent=None</i>) -<p> - Constructor -</p><dl> -<dt><i>pyvenv</i></dt> -<dd> -flag indicating the use of 'pyvenv' (boolean) -</dd><dt><i>targetDir</i></dt> -<dd> -name of the virtualenv directory (string) -</dd><dt><i>openTarget</i></dt> -<dd> -flag indicating to open the virtualenv directory - in a file manager (boolean) -</dd><dt><i>createLog</i></dt> -<dd> -flag indicating to create a log file of the - creation process (boolean) -</dd><dt><i>createScript</i></dt> -<dd> -flag indicating to create a script to recreate - the virtual environment (boolean) -</dd><dt><i>interpreter</i></dt> -<dd> -name of the python interpreter to use (string) -</dd><dt><i>parent</i></dt> -<dd> -reference to the parent widget (QWidget) -</dd> -</dl><a NAME="VirtualenvExecDialog.__finish" ID="VirtualenvExecDialog.__finish"></a> -<h4>VirtualenvExecDialog.__finish</h4> -<b>__finish</b>(<i>exitCode, exitStatus, giveUp=False</i>) -<p> - Private slot called when the process finished. -</p><p> - It is called when the process finished or - the user pressed the button. -</p><dl> -<dt><i>exitCode</i></dt> -<dd> -exit code of the process (integer) -</dd><dt><i>exitStatus</i></dt> -<dd> -exit status of the process (QProcess.ExitStatus) -</dd><dt><i>giveUp=</i></dt> -<dd> -flag indicating to not start another attempt (boolean) -</dd> -</dl><a NAME="VirtualenvExecDialog.__logError" ID="VirtualenvExecDialog.__logError"></a> -<h4>VirtualenvExecDialog.__logError</h4> -<b>__logError</b>(<i>s</i>) -<p> - Private method to log an error. -</p><dl> -<dt><i>s</i></dt> -<dd> -error string to log (string) -</dd> -</dl><a NAME="VirtualenvExecDialog.__logOutput" ID="VirtualenvExecDialog.__logOutput"></a> -<h4>VirtualenvExecDialog.__logOutput</h4> -<b>__logOutput</b>(<i>s</i>) -<p> - Private method to log some output. -</p><dl> -<dt><i>s</i></dt> -<dd> -output sstring to log (string) -</dd> -</dl><a NAME="VirtualenvExecDialog.__nextAttempt" ID="VirtualenvExecDialog.__nextAttempt"></a> -<h4>VirtualenvExecDialog.__nextAttempt</h4> -<b>__nextAttempt</b>(<i></i>) -<p> - Private method to start another attempt. -</p><a NAME="VirtualenvExecDialog.__readStderr" ID="VirtualenvExecDialog.__readStderr"></a> -<h4>VirtualenvExecDialog.__readStderr</h4> -<b>__readStderr</b>(<i></i>) -<p> - Private slot to handle the readyReadStandardError signal. -</p><p> - It reads the error output of the process and inserts it into the - error pane. -</p><a NAME="VirtualenvExecDialog.__readStdout" ID="VirtualenvExecDialog.__readStdout"></a> -<h4>VirtualenvExecDialog.__readStdout</h4> -<b>__readStdout</b>(<i></i>) -<p> - Private slot to handle the readyReadStandardOutput signal. -</p><p> - It reads the output of the process, formats it and inserts it into - the contents pane. -</p><a NAME="VirtualenvExecDialog.__writeLogFile" ID="VirtualenvExecDialog.__writeLogFile"></a> -<h4>VirtualenvExecDialog.__writeLogFile</h4> -<b>__writeLogFile</b>(<i></i>) -<p> - Private method to write a log file to the virtualenv directory. -</p><a NAME="VirtualenvExecDialog.__writeScriptFile" ID="VirtualenvExecDialog.__writeScriptFile"></a> -<h4>VirtualenvExecDialog.__writeScriptFile</h4> -<b>__writeScriptFile</b>(<i></i>) -<p> - Private method to write a script file to the virtualenv directory. -</p><a NAME="VirtualenvExecDialog.on_buttonBox_clicked" ID="VirtualenvExecDialog.on_buttonBox_clicked"></a> -<h4>VirtualenvExecDialog.on_buttonBox_clicked</h4> -<b>on_buttonBox_clicked</b>(<i>button</i>) -<p> - Private slot called by a button of the button box clicked. -</p><dl> -<dt><i>button</i></dt> -<dd> -button that was clicked (QAbstractButton) -</dd> -</dl><a NAME="VirtualenvExecDialog.start" ID="VirtualenvExecDialog.start"></a> -<h4>VirtualenvExecDialog.start</h4> -<b>start</b>(<i>arguments</i>) -<p> - Public slot to start the virtualenv command. -</p><dl> -<dt><i>arguments</i></dt> -<dd> -commandline arguments for virtualenv/pyvenv program - (list of strings) -</dd> -</dl> -<div align="right"><a href="#top">Up</a></div> -<hr /> -</body></html> \ No newline at end of file
--- a/Documentation/Source/index-eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.html Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -<!DOCTYPE html> -<html><head> -<title>eric6.Plugins.UiExtensionPlugins.VirtualenvInterface</title> -<meta charset="UTF-8"> -<style> -body { - background: #EDECE6; - margin: 0em 1em 10em 1em; - color: black; -} - -h1 { color: white; background: #85774A; } -h2 { color: white; background: #85774A; } -h3 { color: white; background: #9D936E; } -h4 { color: white; background: #9D936E; } - -a { color: #BA6D36; } - -</style> -</head> -<body> -<h1>eric6.Plugins.UiExtensionPlugins.VirtualenvInterface</h1> -<p> -Package implementing the virtualenv wizard dialogs and data. -</p> - - -<h3>Modules</h3> -<table> -<tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvConfigurationDialog.html">VirtualenvConfigurationDialog</a></td> -<td>Module implementing a dialog to enter the parameters for the virtual environment.</td> -</tr><tr> -<td><a href="eric6.Plugins.UiExtensionPlugins.VirtualenvInterface.VirtualenvExecDialog.html">VirtualenvExecDialog</a></td> -<td>Module implementing the virtualenv execution dialog.</td> -</tr> -</table> -</body></html> \ No newline at end of file
--- a/Plugins/PluginVirtualenvInterface.py Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing the virtualenv interface plug-in. -""" - -from __future__ import unicode_literals - -from PyQt5.QtCore import QObject -from PyQt5.QtWidgets import QDialog - -from E5Gui.E5Application import e5App -from E5Gui.E5Action import E5Action - -import UI.Info - -# Start-of-Header -name = "virtualenv Configurator Plug-in" -author = "Detlev Offenbach <detlev@die-offenbachs.de>" -autoactivate = True -deactivateable = True -version = UI.Info.VersionOnly -className = "VirtualenvInterfacePlugin" -packageName = "__core__" -shortDescription = "Configurator for Python virtual environments." -longDescription = \ - """This plug-in implements a configuration interface to create Python""" \ - """ virtual environments using 'virtualenv' or 'pyvenv.""" -needsRestart = False -pyqtApi = 2 -python2Compatible = True -# End-of-Header - -error = "" - - -class VirtualenvInterfacePlugin(QObject): - """ - Class implementing the virtualenv wizard plug-in. - """ - def __init__(self, ui): - """ - Constructor - - @param ui reference to the user interface object (UI.UserInterface) - """ - super(VirtualenvInterfacePlugin, self).__init__(ui) - self.__ui = ui - self.__action = None - - self.__initAction() - - def activate(self): - """ - Public method to activate this plug-in. - - @return tuple of None and activation status (boolean) - """ - e5App().getObject("ToolbarManager").addAction(self.__action, "Tools") - - menu = self.__ui.getMenu("extras") - menu.addAction(self.__action) - - return None, True - - def deactivate(self): - """ - Public method to deactivate this plug-in. - """ - e5App().getObject("ToolbarManager").removeAction(self.__action) - - menu = self.__ui.getMenu("extras") - menu.removeAction(self.__action) - - def __initAction(self): - """ - Private method to initialize the action. - """ - self.__action = E5Action( - self.tr('Virtualenv Configurator'), - self.tr('&Virtualenv Configurator...'), - 0, 0, self, - 'virtualenv_configurator') - self.__action.setStatusTip(self.tr('Virtualenv Configurator')) - self.__action.setWhatsThis(self.tr( - """<b>Virtualenv Configurator</b>""" - """<p>This opens a dialog for entering all the parameters""" - """ needed to create a Python virtual environment using""" - """ virtualenv or pyvenv.</p>""" - )) - self.__action.triggered.connect(self.__handle) - - def __handle(self): - """ - Private method to handle the creation of a virtual environment. - """ - from UiExtensionPlugins.VirtualenvInterface\ - .VirtualenvConfigurationDialog import VirtualenvConfigurationDialog - - dlg = VirtualenvConfigurationDialog() - if dlg.exec_() == QDialog.Accepted: - (pyvenv, args, openTarget, createLog, createScript, targetDir, - interpreter) = dlg.getData() - - # now do the call - from UiExtensionPlugins.VirtualenvInterface.VirtualenvExecDialog \ - import VirtualenvExecDialog - dia = VirtualenvExecDialog(pyvenv, targetDir, openTarget, - createLog, createScript, interpreter) - dia.show() - dia.start(args) - dia.exec_() - -# -# eflag: noqa = M801
--- a/Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvConfigurationDialog.py Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,397 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing a dialog to enter the parameters for the -virtual environment. -""" - -from __future__ import unicode_literals -try: - str = unicode -except NameError: - pass - -import os -import sys -import re - -from PyQt5.QtCore import pyqtSlot, QProcess, QTimer -from PyQt5.QtWidgets import QDialog, QDialogButtonBox - -from E5Gui.E5Completers import E5DirCompleter, E5FileCompleter -from E5Gui import E5FileDialog - -from .Ui_VirtualenvConfigurationDialog import Ui_VirtualenvConfigurationDialog - -import Preferences -import Utilities -import UI.PixmapCache - - -class VirtualenvConfigurationDialog(QDialog, Ui_VirtualenvConfigurationDialog): - """ - Class implementing a dialog to enter the parameters for the - virtual environment. - """ - def __init__(self, parent=None): - """ - Constructor - - @param parent reference to the parent widget (QWidget) - """ - super(VirtualenvConfigurationDialog, self).__init__(parent) - self.setupUi(self) - - self.targetDirectoryButton.setIcon(UI.PixmapCache.getIcon("open.png")) - self.extraSearchPathButton.setIcon(UI.PixmapCache.getIcon("open.png")) - self.pythonExecButton.setIcon(UI.PixmapCache.getIcon("open.png")) - - self.__targetDirectoryCompleter = \ - E5DirCompleter(self.targetDirectoryEdit) - self.__extraSearchPathCompleter = \ - E5DirCompleter(self.extraSearchPathEdit) - self.__pythonExecCompleter = E5FileCompleter(self.pythonExecEdit) - - self.__versionRe = re.compile(r""".*?(\d+\.\d+\.\d+).*""") - - self.__virtualenvFound = False - self.__pyvenvFound = False - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) - - self.__mandatoryStyleSheet = "QLineEdit {border: 2px solid;}" - self.targetDirectoryEdit.setStyleSheet(self.__mandatoryStyleSheet) - - self.__setVirtualenvVersion() - self.__setPyvenvVersion() - if self.__virtualenvFound: - self.virtualenvButton.setChecked(True) - elif self.__pyvenvFound: - self.pyvenvButton.setChecked(True) - - msh = self.minimumSizeHint() - self.resize(max(self.width(), msh.width()), msh.height()) - - def __updateOK(self): - """ - Private method to update the enabled status of the OK button. - """ - self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( - (self.__virtualenvFound or self.__pyvenvFound) and - bool(self.targetDirectoryEdit.text()) - ) - - def __updateUi(self): - """ - Private method to update the UI depending on the selected - virtual environment creator (virtualenv or pyvenv). - """ - enable = self.virtualenvButton.isChecked() - self.extraSearchPathLabel.setEnabled(enable) - self.extraSearchPathEdit.setEnabled(enable) - self.extraSearchPathButton.setEnabled(enable) - self.promptPrefixLabel.setEnabled(enable) - self.promptPrefixEdit.setEnabled(enable) - self.verbosityLabel.setEnabled(enable) - self.verbositySpinBox.setEnabled(enable) - self.versionLabel.setEnabled(enable) - self.versionComboBox.setEnabled(enable) - self.unzipCheckBox.setEnabled(enable) - self.noSetuptoolsCheckBox.setEnabled(enable) - self.symlinkCheckBox.setEnabled(not enable) - self.upgradeCheckBox.setEnabled(not enable) - - @pyqtSlot() - def on_targetDirectoryButton_clicked(self): - """ - Private slot to select the target directory via a directory - selection dialog. - """ - target = self.targetDirectoryEdit.text() - if not target: - target = Utilities.getHomeDir() - target = Utilities.fromNativeSeparators(target) - target = E5FileDialog.getExistingDirectory( - self, - self.tr("Virtualenv Target Directory"), - target, - E5FileDialog.Options(E5FileDialog.ShowDirsOnly)) - if target: - self.targetDirectoryEdit.setText( - Utilities.toNativeSeparators(target)) - - @pyqtSlot(str) - def on_targetDirectoryEdit_textChanged(self, txt): - """ - Private slot handling a change of the target directory. - - @param txt target directory (string) - """ - self.__updateOK() - - @pyqtSlot() - def on_extraSearchPathButton_clicked(self): - """ - Private slot to select the extra search path via a directory - selection dialog. - """ - extraSearchPath = self.extraSearchPathEdit.text() - if not extraSearchPath: - extraSearchPath = Utilities.getHomeDir() - extraSearchPath = Utilities.fromNativeSeparators(extraSearchPath) - extraSearchPath = E5FileDialog.getExistingDirectory( - self, - self.tr("Extra Search Path for setuptools/pip"), - extraSearchPath, - E5FileDialog.Options(E5FileDialog.ShowDirsOnly)) - if extraSearchPath: - self.extraSearchPathEdit.setText( - Utilities.toNativeSeparators(extraSearchPath)) - - @pyqtSlot() - def on_pythonExecButton_clicked(self): - """ - Private slot to select a Python interpreter via a file selection - dialog. - """ - pythonExec = self.pythonExecEdit.text() - if not pythonExec: - pythonExec = sys.executable.replace("w.exe", ".exe") - pythonExec = Utilities.fromNativeSeparators(pythonExec) - pythonExec = E5FileDialog.getOpenFileName( - self, - self.tr("Python Interpreter"), - pythonExec, - "") - if pythonExec: - self.pythonExecEdit.setText( - Utilities.toNativeSeparators(pythonExec)) - - @pyqtSlot(str) - def on_pythonExecEdit_textChanged(self, txt): - """ - Private slot to react to a change of the Python executable. - - @param txt contents of the line edit (string) - """ - self.__setVirtualenvVersion() - self.__setPyvenvVersion() - self.__updateOK() - - @pyqtSlot(bool) - def on_virtualenvButton_toggled(self, checked): - """ - Private slot to react to the selection of 'virtualenv'. - - @param checked state of the checkbox (boolean) - """ - self.__updateUi() - - @pyqtSlot(bool) - def on_pyvenvButton_toggled(self, checked): - """ - Private slot to react to the selection of 'pyvenv'. - - @param checked state of the checkbox (boolean) - """ - self.__updateUi() - - def __setVirtualenvVersion(self): - """ - Private method to determine the virtualenv version and set the - respective label. - """ - calls = [ - (sys.executable.replace("w.exe", ".exe"), - ["-m", "virtualenv", "--version"]), - ("virtualenv", ["--version"]), - ] - if self.pythonExecEdit.text(): - calls.append((self.pythonExecEdit.text(), - ["-m", "virtualenv", "--version"])) - - proc = QProcess() - for prog, args in calls: - proc.start(prog, args) - - if not proc.waitForStarted(5000): - # try next entry - continue - - if not proc.waitForFinished(5000): - # process hangs, kill it - QTimer.singleShot(2000, proc.kill) - proc.waitForFinished(3000) - version = self.tr('<virtualenv did not finish within 5s.>') - self.__virtualenvFound = False - break - - if proc.exitCode() != 0: - # returned with error code, try next - continue - - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace').strip() - match = re.match(self.__versionRe, output) - if match: - self.__virtualenvFound = True - version = match.group(1) - break - else: - self.__virtualenvFound = False - version = self.tr('<No suitable virtualenv found.>') - - self.virtualenvButton.setText(self.tr( - "virtualenv Version: {0}".format(version))) - self.virtualenvButton.setEnabled(self.__virtualenvFound) - if not self.__virtualenvFound: - self.virtualenvButton.setChecked(False) - - def __setPyvenvVersion(self): - """ - Private method to determine the pyvenv version and set the respective - label. - """ - calls = [] - if self.pythonExecEdit.text(): - calls.append((self.pythonExecEdit.text(), - ["-m", "venv"])) - calls.extend([ - (sys.executable.replace("w.exe", ".exe"), - ["-m", "venv"]), - ("python3", ["-m", "venv"]), - ("python", ["-m", "venv"]), - ]) - - proc = QProcess() - for prog, args in calls: - proc.start(prog, args) - - if not proc.waitForStarted(5000): - # try next entry - continue - - if not proc.waitForFinished(5000): - # process hangs, kill it - QTimer.singleShot(2000, proc.kill) - proc.waitForFinished(3000) - version = self.tr('<pyvenv did not finish within 5s.>') - self.__pyvenvFound = False - break - - if proc.exitCode() not in [0, 2]: - # returned with error code, try next - continue - - proc.start(prog, ["--version"]) - proc.waitForFinished(5000) - output = str(proc.readAllStandardOutput(), - Preferences.getSystem("IOEncoding"), - 'replace').strip() - match = re.match(self.__versionRe, output) - if match: - self.__pyvenvFound = True - version = match.group(1) - break - else: - self.__pyvenvFound = False - version = self.tr('<No suitable pyvenv found.>') - - self.pyvenvButton.setText(self.tr( - "pyvenv Version: {0}".format(version))) - self.pyvenvButton.setEnabled(self.__pyvenvFound) - if not self.__pyvenvFound: - self.pyvenvButton.setChecked(False) - - def __generateTargetDir(self): - """ - Private method to generate a valid target directory path. - - @return target directory path (string) - """ - targetDirectory = Utilities.toNativeSeparators( - self.targetDirectoryEdit.text()) - if not os.path.isabs(targetDirectory): - targetDirectory = os.path.join(os.path.expanduser("~"), - targetDirectory) - return targetDirectory - - def __generateArguments(self): - """ - Private method to generate the process arguments. - - @return process arguments (list of string) - """ - args = [] - if self.virtualenvButton.isChecked(): - if self.extraSearchPathEdit.text(): - args.append("--extra-search-dir={0}".format( - Utilities.toNativeSeparators( - self.extraSearchPathEdit.text()))) - if self.promptPrefixEdit.text(): - args.append("--prompt={0}".format( - self.promptPrefixEdit.text().replace(" ", "_"))) - if self.pythonExecEdit.text(): - args.append("--python={0}".format( - Utilities.toNativeSeparators(self.pythonExecEdit.text()))) - elif self.versionComboBox.currentText(): - args.append("--python=python{0}".format( - self.versionComboBox.currentText())) - if self.verbositySpinBox.value() == 1: - args.append("--verbose") - elif self.verbositySpinBox.value() == -1: - args.append("--quiet") - if self.clearCheckBox.isChecked(): - args.append("--clear") - if self.systemCheckBox.isChecked(): - args.append("--system-site-packages") - if self.unzipCheckBox.isChecked(): - args.append("--unzip-setuptools") - if self.noSetuptoolsCheckBox.isChecked(): - args.append("--no-setuptools") - if self.noPipCcheckBox.isChecked(): - args.append("--no-pip") - if self.copyCheckBox.isChecked(): - args.append("--always-copy") - elif self.pyvenvButton.isChecked(): - if self.clearCheckBox.isChecked(): - args.append("--clear") - if self.systemCheckBox.isChecked(): - args.append("--system-site-packages") - if self.noPipCcheckBox.isChecked(): - args.append("--without-pip") - if self.copyCheckBox.isChecked(): - args.append("--copies") - if self.symlinkCheckBox.isChecked(): - args.append("--symlinks") - if self.upgradeCheckBox.isChecked(): - args.append("--upgrade") - targetDirectory = self.__generateTargetDir() - args.append(targetDirectory) - return args - - def getData(self): - """ - Public method to retrieve the dialog data. - - @return tuple containing a flag indicating the pyvenv selection - (boolean), the process arguments (list of string), a flag - indicating to open the target directory after creation (boolean), - a flag indicating to write a log file (boolean), a flag indicating - to write a script (boolean), the name of the target directory - (string) and the name of the python interpreter to use (string) - """ - args = self.__generateArguments() - targetDirectory = self.__generateTargetDir() - return ( - self.pyvenvButton.isChecked(), - args, - self.openCheckBox.isChecked(), - self.logCheckBox.isChecked(), - self.scriptCheckBox.isChecked(), - targetDirectory, - Utilities.toNativeSeparators(self.pythonExecEdit.text()), - )
--- a/Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvConfigurationDialog.ui Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,482 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>VirtualenvConfigurationDialog</class> - <widget class="QDialog" name="VirtualenvConfigurationDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>700</width> - <height>590</height> - </rect> - </property> - <property name="windowTitle"> - <string>Virtualenv Configuration</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="groupBox_3"> - <property name="title"> - <string>Environment Creator</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QRadioButton" name="virtualenvButton"> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="toolTip"> - <string>Select to use 'virtualenv'</string> - </property> - <property name="text"> - <string notr="true">0.0</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <widget class="QRadioButton" name="pyvenvButton"> - <property name="font"> - <font> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="toolTip"> - <string>Select to use 'pyvenv'</string> - </property> - <property name="text"> - <string notr="true">0.0</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Paths</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Target Directory:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="E5ClearableLineEdit" name="targetDirectoryEdit"> - <property name="toolTip"> - <string>Enter the target directory for the virtual environment</string> - </property> - <property name="placeholderText"> - <string>Target directory for the virtual environment</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QToolButton" name="targetDirectoryButton"> - <property name="toolTip"> - <string>Select the target directory via a directory selection dialog</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="extraSearchPathLabel"> - <property name="text"> - <string>Extra Search Path:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="E5ClearableLineEdit" name="extraSearchPathEdit"> - <property name="toolTip"> - <string>Enter the extra search path to look for setuptools/pip</string> - </property> - <property name="placeholderText"> - <string>Extra search path to look for setuptools/pip</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QToolButton" name="extraSearchPathButton"> - <property name="toolTip"> - <string>Select the extra search path to look for setuptools/pip via a directory selection dialog</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="promptPrefixLabel"> - <property name="text"> - <string>Prompt Prefix:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="E5ClearableLineEdit" name="promptPrefixEdit"> - <property name="toolTip"> - <string>Enter the prompt prefix for the virtual environment</string> - </property> - <property name="placeholderText"> - <string>Prompt prefix for the virtual environment</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Python Executable:</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="E5ClearableLineEdit" name="pythonExecEdit"> - <property name="toolTip"> - <string>Enter the Python interpreter for the virtual environment</string> - </property> - <property name="placeholderText"> - <string>Python interpreter for the virtual environment</string> - </property> - </widget> - </item> - <item row="3" column="2"> - <widget class="QToolButton" name="pythonExecButton"> - <property name="toolTip"> - <string>Select the Python interpreter via a file selection dialog</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Options</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QLabel" name="verbosityLabel"> - <property name="text"> - <string>Verbosity:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="verbositySpinBox"> - <property name="toolTip"> - <string>Select the verbosity (-1: quiet, 0: normal, 1: verbose)</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="minimum"> - <number>-1</number> - </property> - <property name="maximum"> - <number>1</number> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="0" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="versionLabel"> - <property name="text"> - <string>Python Version:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="versionComboBox"> - <property name="toolTip"> - <string>Select the Python version (empty for current)</string> - </property> - <item> - <property name="text"> - <string notr="true"/> - </property> - </item> - <item> - <property name="text"> - <string notr="true">2.6</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">2.7</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">3.4</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">3.5</string> - </property> - </item> - <item> - <property name="text"> - <string notr="true">3.6</string> - </property> - </item> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="systemCheckBox"> - <property name="toolTip"> - <string>Select to give the virtualenv access to the global site-packages</string> - </property> - <property name="text"> - <string>System-wide Python Packages</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="unzipCheckBox"> - <property name="toolTip"> - <string>Select to unzip setuptools when installing it</string> - </property> - <property name="text"> - <string>Unzip Setuptool to virtualenv</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="noSetuptoolsCheckBox"> - <property name="toolTip"> - <string>Select to not install setuptools (or pip) in the new virtualenv</string> - </property> - <property name="text"> - <string>Don't install 'setuptool' (or pip) in the virtualenv</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QCheckBox" name="noPipCcheckBox"> - <property name="toolTip"> - <string>Select to not install pip in the new virtualenv</string> - </property> - <property name="text"> - <string>Don't install 'pip' in the virtualenv</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QCheckBox" name="clearCheckBox"> - <property name="toolTip"> - <string>Select to clear the target first</string> - </property> - <property name="text"> - <string>Clear out the target directory</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QCheckBox" name="copyCheckBox"> - <property name="toolTip"> - <string>Select to always copy files rather than symlinking</string> - </property> - <property name="text"> - <string>Always copy files</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QCheckBox" name="symlinkCheckBox"> - <property name="toolTip"> - <string>Select to use symlinks instead of copies</string> - </property> - <property name="text"> - <string>Use Symbolic Links</string> - </property> - </widget> - </item> - <item row="4" column="1"> - <widget class="QCheckBox" name="upgradeCheckBox"> - <property name="toolTip"> - <string>Select to upgrade a virtual environment</string> - </property> - <property name="text"> - <string>Upgrade</string> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QCheckBox" name="logCheckBox"> - <property name="toolTip"> - <string>Select to generate a log file in the target directory</string> - </property> - <property name="text"> - <string>Save a log file in the target directory after creation</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="5" column="1"> - <widget class="QCheckBox" name="scriptCheckBox"> - <property name="toolTip"> - <string>Select to write a shell script/batch file to regenerate the virtualenv</string> - </property> - <property name="text"> - <string>Save virtualenv generation script</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="6" column="0"> - <widget class="QCheckBox" name="openCheckBox"> - <property name="toolTip"> - <string>Open the newly created virtualenv in a file manager window</string> - </property> - <property name="text"> - <string>Open target directory after creation</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>E5ClearableLineEdit</class> - <extends>QLineEdit</extends> - <header>E5Gui/E5LineEdit.h</header> - </customwidget> - </customwidgets> - <tabstops> - <tabstop>virtualenvButton</tabstop> - <tabstop>pyvenvButton</tabstop> - <tabstop>targetDirectoryEdit</tabstop> - <tabstop>targetDirectoryButton</tabstop> - <tabstop>extraSearchPathEdit</tabstop> - <tabstop>extraSearchPathButton</tabstop> - <tabstop>promptPrefixEdit</tabstop> - <tabstop>pythonExecEdit</tabstop> - <tabstop>pythonExecButton</tabstop> - <tabstop>verbositySpinBox</tabstop> - <tabstop>versionComboBox</tabstop> - <tabstop>systemCheckBox</tabstop> - <tabstop>unzipCheckBox</tabstop> - <tabstop>noSetuptoolsCheckBox</tabstop> - <tabstop>noPipCcheckBox</tabstop> - <tabstop>clearCheckBox</tabstop> - <tabstop>copyCheckBox</tabstop> - <tabstop>symlinkCheckBox</tabstop> - <tabstop>upgradeCheckBox</tabstop> - <tabstop>logCheckBox</tabstop> - <tabstop>scriptCheckBox</tabstop> - <tabstop>openCheckBox</tabstop> - </tabstops> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>VirtualenvConfigurationDialog</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>VirtualenvConfigurationDialog</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui>
--- a/Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvExecDialog.py Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,306 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing the virtualenv execution dialog. -""" - -from __future__ import unicode_literals -try: - str = unicode -except NameError: - pass - -import sys -import os - -from PyQt5.QtCore import QProcess, QTimer, QUrl -from PyQt5.QtGui import QDesktopServices -from PyQt5.QtWidgets import QDialog, QDialogButtonBox - -from .Ui_VirtualenvExecDialog import Ui_VirtualenvExecDialog - -import Preferences -from Globals import isWindowsPlatform - - -class VirtualenvExecDialog(QDialog, Ui_VirtualenvExecDialog): - """ - Class implementing the virtualenv execution dialog. - - This class starts a QProcess and displays a dialog that - shows the output of the virtualenv or pyvenv process. - """ - def __init__(self, pyvenv, targetDir, openTarget, createLog, createScript, - interpreter, parent=None): - """ - Constructor - - @param pyvenv flag indicating the use of 'pyvenv' (boolean) - @param targetDir name of the virtualenv directory (string) - @param openTarget flag indicating to open the virtualenv directory - in a file manager (boolean) - @param createLog flag indicating to create a log file of the - creation process (boolean) - @param createScript flag indicating to create a script to recreate - the virtual environment (boolean) - @param interpreter name of the python interpreter to use (string) - @param parent reference to the parent widget (QWidget) - """ - super(VirtualenvExecDialog, self).__init__(parent) - self.setupUi(self) - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) - - self.__pyvenv = pyvenv - self.__targetDir = targetDir - self.__openTarget = openTarget - self.__createLog = createLog - self.__createScript = createScript - - self.process = None - self.__cmd = "" - - if pyvenv: - self.__calls = [] - if interpreter: - self.__calls.append((interpreter, ["-m", "venv"])) - self.__calls.extend([ - (sys.executable.replace("w.exe", ".exe"), - ["-m", "venv"]), - ("python3", ["-m", "venv"]), - ("python", ["-m", "venv"]), - ]) - else: - self.__calls = [ - (sys.executable.replace("w.exe", ".exe"), - ["-m", "virtualenv"]), - ("virtualenv", []), - ] - self.__callIndex = 0 - self.__callArgs = [] - - def start(self, arguments): - """ - Public slot to start the virtualenv command. - - @param arguments commandline arguments for virtualenv/pyvenv program - (list of strings) - """ - if self.__callIndex == 0: - # first attempt, add a given python interpreter and do - # some other setup - self.errorGroup.hide() - self.contents.clear() - self.errors.clear() - - self.process = QProcess() - self.process.readyReadStandardOutput.connect(self.__readStdout) - self.process.readyReadStandardError.connect(self.__readStderr) - self.process.finished.connect(self.__finish) - - if not self.__pyvenv: - for arg in arguments: - if arg.startswith("--python="): - prog = arg.replace("--python=", "") - self.__calls.insert( - 0, (prog, ["-m", "virtualenv"])) - break - self.__callArgs = arguments - - prog, args = self.__calls[self.__callIndex] - args.extend(self.__callArgs) - self.__cmd = "{0} {1}".format(prog, " ".join(args)) - self.__logOutput(self.tr("Executing: {0}\n").format( - self.__cmd)) - self.process.start(prog, args) - procStarted = self.process.waitForStarted(5000) - if not procStarted: - self.__logOutput(self.tr("Failed\n\n")) - self.__nextAttempt() - - def on_buttonBox_clicked(self, button): - """ - Private slot called by a button of the button box clicked. - - @param button button that was clicked (QAbstractButton) - """ - if button == self.buttonBox.button(QDialogButtonBox.Close): - self.accept() - elif button == self.buttonBox.button(QDialogButtonBox.Cancel): - self.__finish() - - def __finish(self, exitCode, exitStatus, giveUp=False): - """ - Private slot called when the process finished. - - It is called when the process finished or - the user pressed the button. - - @param exitCode exit code of the process (integer) - @param exitStatus exit status of the process (QProcess.ExitStatus) - @keyparam giveUp flag indicating to not start another attempt (boolean) - """ - if self.process is not None and \ - self.process.state() != QProcess.NotRunning: - self.process.terminate() - QTimer.singleShot(2000, self.process.kill) - self.process.waitForFinished(3000) - - self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) - self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) - self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) - - if not giveUp: - if exitCode != 0: - self.__logOutput(self.tr("Failed\n\n")) - if len(self.errors.toPlainText().splitlines()) == 1: - self.errors.clear() - self.errorGroup.hide() - self.__nextAttempt() - return - - self.process = None - - if self.__pyvenv: - self.__logOutput(self.tr('\npyvenv finished.\n')) - else: - self.__logOutput(self.tr('\nvirtualenv finished.\n')) - - if os.path.exists(self.__targetDir): - if self.__createScript: - self.__writeScriptFile() - - if self.__createLog: - self.__writeLogFile() - - if self.__openTarget: - QDesktopServices.openUrl(QUrl.fromLocalFile( - self.__targetDir)) - - def __nextAttempt(self): - """ - Private method to start another attempt. - """ - self.__callIndex += 1 - if self.__callIndex < len(self.__calls): - self.start(self.__callArgs) - else: - if self.__pyvenv: - self.__logError( - self.tr('No suitable pyvenv program could be' - ' started.\n')) - else: - self.__logError( - self.tr('No suitable virtualenv program could be' - ' started.\n')) - self.__cmd = "" - self.__finish(0, 0, giveUp=True) - - def __readStdout(self): - """ - Private slot to handle the readyReadStandardOutput signal. - - It reads the output of the process, formats it and inserts it into - the contents pane. - """ - self.process.setReadChannel(QProcess.StandardOutput) - - while self.process.canReadLine(): - s = str(self.process.readLine(), - Preferences.getSystem("IOEncoding"), - 'replace') - self.__logOutput(s) - - def __readStderr(self): - """ - Private slot to handle the readyReadStandardError signal. - - It reads the error output of the process and inserts it into the - error pane. - """ - self.process.setReadChannel(QProcess.StandardError) - - while self.process.canReadLine(): - s = str(self.process.readLine(), - Preferences.getSystem("IOEncoding"), - 'replace') - self.__logError(s) - - def __logOutput(self, s): - """ - Private method to log some output. - - @param s output sstring to log (string) - """ - self.contents.insertPlainText(s) - self.contents.ensureCursorVisible() - - def __logError(self, s): - """ - Private method to log an error. - - @param s error string to log (string) - """ - self.errorGroup.show() - self.errors.insertPlainText(s) - self.errors.ensureCursorVisible() - - def __writeLogFile(self): - """ - Private method to write a log file to the virtualenv directory. - """ - outtxt = self.contents.toPlainText() - if self.__pyvenv: - logFile = os.path.join(self.__targetDir, "pyvenv.log") - else: - logFile = os.path.join(self.__targetDir, "virtualenv.log") - self.__logOutput(self.tr("\nWriting log file '{0}'.\n") - .format(logFile)) - - try: - f = open(logFile, "w", encoding="utf-8") - f.write(self.tr("Output:\n")) - f.write(outtxt) - errtxt = self.errors.toPlainText() - if errtxt: - f.write("\n") - f.write(self.tr("Errors:\n")) - f.write(errtxt) - f.close() - except (IOError, OSError) as err: - self.__logError( - self.tr("""The logfile '{0}' could not be written.\n""" - """Reason: {1}\n""").format(logFile, str(err))) - self.__logOutput(self.tr("Done.\n")) - - def __writeScriptFile(self): - """ - Private method to write a script file to the virtualenv directory. - """ - if self.__pyvenv: - basename = "create_pyvenv" - else: - basename = "create_virtualenv" - if isWindowsPlatform(): - script = os.path.join(self.__targetDir, basename + ".bat") - txt = self.__cmd - else: - script = os.path.join(self.__targetDir, basename + ".sh") - txt = "#!/usr/bin/env sh\n\n" + self.__cmd - - self.__logOutput(self.tr("\nWriting script file '{0}'.\n") - .format(script)) - - try: - f = open(script, "w", encoding="utf-8") - f.write(txt) - f.close() - except (IOError, OSError) as err: - self.__logError( - self.tr("""The script file '{0}' could not be written.\n""" - """Reason: {1}\n""").format(script, str(err))) - self.__logOutput(self.tr("Done.\n"))
--- a/Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvExecDialog.ui Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>VirtualenvExecDialog</class> - <widget class="QDialog" name="VirtualenvExecDialog"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>750</width> - <height>600</height> - </rect> - </property> - <property name="windowTitle"> - <string>Virtualenv Creation</string> - </property> - <property name="sizeGripEnabled"> - <bool>true</bool> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <widget class="QGroupBox" name="messagesGroup"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>3</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Messages</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QTextBrowser" name="contents"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>3</verstretch> - </sizepolicy> - </property> - <property name="whatsThis"> - <string><b>virtualenv Execution</b> -<p>This shows the output of the virtualenv command.</p></string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="errorGroup"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>Errors</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QTextBrowser" name="errors"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="whatsThis"> - <string><b>virtualenv Execution</b> -<p>This shows the errors of the virtualenv command.</p></string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set> - </property> - </widget> - </item> - </layout> - </widget> - <layoutdefault spacing="6" margin="11"/> - <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> - <tabstops> - <tabstop>contents</tabstop> - <tabstop>errors</tabstop> - <tabstop>buttonBox</tabstop> - </tabstops> - <resources/> - <connections/> -</ui>
--- a/Plugins/UiExtensionPlugins/VirtualenvInterface/__init__.py Sat Jun 09 12:09:21 2018 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2014 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Package implementing the virtualenv wizard dialogs and data. -"""
--- a/UI/UserInterface.py Sat Jun 09 12:09:21 2018 +0200 +++ b/UI/UserInterface.py Sat Jun 09 17:19:37 2018 +0200 @@ -546,6 +546,9 @@ QDesktopServices.setUrlHandler("http", self.handleUrl) QDesktopServices.setUrlHandler("https", self.handleUrl) + from VirtualEnv.VirtualenvManager import VirtualenvManager + self.virtualenvManager = VirtualenvManager(self) + # register all relevant objects splash.showMessage(self.tr("Registering Objects...")) e5App().registerObject("UserInterface", self) @@ -568,6 +571,7 @@ e5App().registerObject("Symbols", self.symbolsViewer) e5App().registerObject("Numbers", self.numbersViewer) e5App().registerObject("DocuViewer", self.codeDocumentationViewer) + e5App().registerObject("VirtualEnvManager", self.virtualenvManager) # list of web addresses serving the versions file self.__httpAlternatives = Preferences.getUI("VersionsUrls6") @@ -2414,6 +2418,24 @@ self.pluginRepoAct.triggered.connect(self.showPluginsAvailable) self.actions.append(self.pluginRepoAct) + self.virtualenvConfigAct = E5Action( + self.tr('Virtualenv Configurator'), + UI.PixmapCache.getIcon("virtualenv.png"), + self.tr('&Virtualenv Configurator...'), + 0, 0, self, + 'virtualenv_configurator') + self.virtualenvConfigAct.setStatusTip(self.tr( + 'Virtualenv Configurator')) + self.virtualenvConfigAct.setWhatsThis(self.tr( + """<b>Virtualenv Configurator</b>""" + """<p>This opens a dialog for entering all the parameters""" + """ needed to create a Python virtual environment using""" + """ virtualenv or pyvenv.</p>""" + )) + self.virtualenvConfigAct.triggered.connect( + self.virtualenvManager.createVirtualEnv) + self.actions.append(self.virtualenvConfigAct) + # initialize viewmanager actions self.viewmanager.initActions() @@ -2671,6 +2693,8 @@ self.wizardsMenuAct.setEnabled(False) self.__menus["macros"] = self.viewmanager.initMacroMenu() self.__menus["extras"].addMenu(self.__menus["macros"]) + self.__menus["extras"].addSeparator() + self.__menus["extras"].addAction(self.virtualenvConfigAct) self.toolGroupsMenu = QMenu(self.tr("Select Tool Group"), self) self.toolGroupsMenu.aboutToShow.connect(self.__showToolGroupsMenu) self.toolGroupsMenu.triggered.connect(self.__toolGroupSelected) @@ -2870,6 +2894,8 @@ toolstb.addAction(self.hexEditorAct) toolstb.addAction(self.iconEditorAct) toolstb.addAction(self.snapshotAct) + toolstb.addSeparator() + toolstb.addAction(self.virtualenvConfigAct) if self.webBrowserAct: toolstb.addSeparator() toolstb.addAction(self.webBrowserAct)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvConfigurationDialog.py Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2014 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to enter the parameters for the +virtual environment. +""" + +from __future__ import unicode_literals +try: + str = unicode +except NameError: + pass + +import os +import sys +import re + +from PyQt5.QtCore import pyqtSlot, QProcess, QTimer +from PyQt5.QtWidgets import QDialog, QDialogButtonBox + +from E5Gui.E5PathPicker import E5PathPickerModes + +from .Ui_VirtualenvConfigurationDialog import Ui_VirtualenvConfigurationDialog + +import Preferences +import Utilities + + +class VirtualenvConfigurationDialog(QDialog, Ui_VirtualenvConfigurationDialog): + """ + Class implementing a dialog to enter the parameters for the + virtual environment. + """ + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent widget + @type QWidget + """ + super(VirtualenvConfigurationDialog, self).__init__(parent) + self.setupUi(self) + + self.targetDirectoryPicker.setMode(E5PathPickerModes.DirectoryMode) + self.targetDirectoryPicker.setWindowTitle( + self.tr("Virtualenv Target Directory")) + self.targetDirectoryPicker.setDefaultDirectory(Utilities.getHomeDir()) + + self.extraSearchPathPicker.setMode(E5PathPickerModes.DirectoryMode) + self.extraSearchPathPicker.setWindowTitle( + self.tr("Extra Search Path for setuptools/pip")) + self.extraSearchPathPicker.setDefaultDirectory(Utilities.getHomeDir()) + + self.pythonExecPicker.setMode(E5PathPickerModes.OpenFileMode) + self.pythonExecPicker.setWindowTitle( + self.tr("Python Interpreter")) + self.pythonExecPicker.setDefaultDirectory( + sys.executable.replace("w.exe", ".exe")) + + self.__versionRe = re.compile(r""".*?(\d+\.\d+\.\d+).*""") + + self.__virtualenvFound = False + self.__pyvenvFound = False + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) + + self.__mandatoryStyleSheet = "QLineEdit {border: 2px solid;}" + self.targetDirectoryPicker.setStyleSheet(self.__mandatoryStyleSheet) + self.nameEdit.setStyleSheet(self.__mandatoryStyleSheet) + + self.__setVirtualenvVersion() + self.__setPyvenvVersion() + if self.__virtualenvFound: + self.virtualenvButton.setChecked(True) + elif self.__pyvenvFound: + self.pyvenvButton.setChecked(True) + + msh = self.minimumSizeHint() + self.resize(max(self.width(), msh.width()), msh.height()) + + def __updateOK(self): + """ + Private method to update the enabled status of the OK button. + """ + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( + (self.__virtualenvFound or self.__pyvenvFound) and + bool(self.targetDirectoryPicker.text() and + bool(self.nameEdit.text())) + ) + + def __updateUi(self): + """ + Private method to update the UI depending on the selected + virtual environment creator (virtualenv or pyvenv). + """ + enable = self.virtualenvButton.isChecked() + self.extraSearchPathLabel.setEnabled(enable) + self.extraSearchPathPicker.setEnabled(enable) + self.promptPrefixLabel.setEnabled(enable) + self.promptPrefixEdit.setEnabled(enable) + self.verbosityLabel.setEnabled(enable) + self.verbositySpinBox.setEnabled(enable) + self.versionLabel.setEnabled(enable) + self.versionComboBox.setEnabled(enable) + self.unzipCheckBox.setEnabled(enable) + self.noSetuptoolsCheckBox.setEnabled(enable) + self.symlinkCheckBox.setEnabled(not enable) + self.upgradeCheckBox.setEnabled(not enable) + + @pyqtSlot(str) + def on_targetDirectoryPicker_textChanged(self, txt): + """ + Private slot handling a change of the target directory. + + @param txt target directory + @type str + """ + self.__updateOK() + + @pyqtSlot(str) + def on_pythonExecPicker_textChanged(self, txt): + """ + Private slot to react to a change of the Python executable. + + @param txt contents of the picker's line edit + @type str + """ + self.__setVirtualenvVersion() + self.__setPyvenvVersion() + self.__updateOK() + + @pyqtSlot(bool) + def on_virtualenvButton_toggled(self, checked): + """ + Private slot to react to the selection of 'virtualenv'. + + @param checked state of the checkbox + @type bool + """ + self.__updateUi() + + @pyqtSlot(bool) + def on_pyvenvButton_toggled(self, checked): + """ + Private slot to react to the selection of 'pyvenv'. + + @param checked state of the checkbox + @type bool + """ + self.__updateUi() + + def __setVirtualenvVersion(self): + """ + Private method to determine the virtualenv version and set the + respective label. + """ + calls = [ + (sys.executable.replace("w.exe", ".exe"), + ["-m", "virtualenv", "--version"]), + ("virtualenv", ["--version"]), + ] + if self.pythonExecPicker.text(): + calls.append((self.pythonExecPicker.text(), + ["-m", "virtualenv", "--version"])) + + proc = QProcess() + for prog, args in calls: + proc.start(prog, args) + + if not proc.waitForStarted(5000): + # try next entry + continue + + if not proc.waitForFinished(5000): + # process hangs, kill it + QTimer.singleShot(2000, proc.kill) + proc.waitForFinished(3000) + version = self.tr('<virtualenv did not finish within 5s.>') + self.__virtualenvFound = False + break + + if proc.exitCode() != 0: + # returned with error code, try next + continue + + output = str(proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + 'replace').strip() + match = re.match(self.__versionRe, output) + if match: + self.__virtualenvFound = True + version = match.group(1) + break + else: + self.__virtualenvFound = False + version = self.tr('<No suitable virtualenv found.>') + + self.virtualenvButton.setText(self.tr( + "virtualenv Version: {0}".format(version))) + self.virtualenvButton.setEnabled(self.__virtualenvFound) + if not self.__virtualenvFound: + self.virtualenvButton.setChecked(False) + + def __setPyvenvVersion(self): + """ + Private method to determine the pyvenv version and set the respective + label. + """ + calls = [] + if self.pythonExecPicker.text(): + calls.append((self.pythonExecPicker.text(), + ["-m", "venv"])) + calls.extend([ + (sys.executable.replace("w.exe", ".exe"), + ["-m", "venv"]), + ("python3", ["-m", "venv"]), + ("python", ["-m", "venv"]), + ]) + + proc = QProcess() + for prog, args in calls: + proc.start(prog, args) + + if not proc.waitForStarted(5000): + # try next entry + continue + + if not proc.waitForFinished(5000): + # process hangs, kill it + QTimer.singleShot(2000, proc.kill) + proc.waitForFinished(3000) + version = self.tr('<pyvenv did not finish within 5s.>') + self.__pyvenvFound = False + break + + if proc.exitCode() not in [0, 2]: + # returned with error code, try next + continue + + proc.start(prog, ["--version"]) + proc.waitForFinished(5000) + output = str(proc.readAllStandardOutput(), + Preferences.getSystem("IOEncoding"), + 'replace').strip() + match = re.match(self.__versionRe, output) + if match: + self.__pyvenvFound = True + version = match.group(1) + break + else: + self.__pyvenvFound = False + version = self.tr('<No suitable pyvenv found.>') + + self.pyvenvButton.setText(self.tr( + "pyvenv Version: {0}".format(version))) + self.pyvenvButton.setEnabled(self.__pyvenvFound) + if not self.__pyvenvFound: + self.pyvenvButton.setChecked(False) + + def __generateTargetDir(self): + """ + Private method to generate a valid target directory path. + + @return target directory path + @rtype str + """ + targetDirectory = Utilities.toNativeSeparators( + self.targetDirectoryPicker.text()) + if not os.path.isabs(targetDirectory): + targetDirectory = os.path.join(os.path.expanduser("~"), + targetDirectory) + return targetDirectory + + def __generateArguments(self): + """ + Private method to generate the process arguments. + + @return process arguments + @rtype list of str + """ + args = [] + if self.virtualenvButton.isChecked(): + if self.extraSearchPathPicker.text(): + args.append("--extra-search-dir={0}".format( + Utilities.toNativeSeparators( + self.extraSearchPathPicker.text()))) + if self.promptPrefixEdit.text(): + args.append("--prompt={0}".format( + self.promptPrefixEdit.text().replace(" ", "_"))) + if self.pythonExecPicker.text(): + args.append("--python={0}".format( + Utilities.toNativeSeparators( + self.pythonExecPicker.text()))) + elif self.versionComboBox.currentText(): + args.append("--python=python{0}".format( + self.versionComboBox.currentText())) + if self.verbositySpinBox.value() == 1: + args.append("--verbose") + elif self.verbositySpinBox.value() == -1: + args.append("--quiet") + if self.clearCheckBox.isChecked(): + args.append("--clear") + if self.systemCheckBox.isChecked(): + args.append("--system-site-packages") + if self.unzipCheckBox.isChecked(): + args.append("--unzip-setuptools") + if self.noSetuptoolsCheckBox.isChecked(): + args.append("--no-setuptools") + if self.noPipCcheckBox.isChecked(): + args.append("--no-pip") + if self.copyCheckBox.isChecked(): + args.append("--always-copy") + elif self.pyvenvButton.isChecked(): + if self.clearCheckBox.isChecked(): + args.append("--clear") + if self.systemCheckBox.isChecked(): + args.append("--system-site-packages") + if self.noPipCcheckBox.isChecked(): + args.append("--without-pip") + if self.copyCheckBox.isChecked(): + args.append("--copies") + if self.symlinkCheckBox.isChecked(): + args.append("--symlinks") + if self.upgradeCheckBox.isChecked(): + args.append("--upgrade") + targetDirectory = self.__generateTargetDir() + args.append(targetDirectory) + return args + + def getData(self): + """ + Public method to retrieve the dialog data. + + @return tuple containing a flag indicating the pyvenv selection, the + process arguments, a name for the virtual environment, a flag + indicating to open the target directory after creation, a flag + indicating to write a log file, a flag indicating to write a + script, the name of the target directory and the name of the + Python interpreter to use + @rtype tuple of (bool, list of str, str, bool, bool, bool, str, str) + """ + args = self.__generateArguments() + targetDirectory = self.__generateTargetDir() + return ( + self.pyvenvButton.isChecked(), + args, + self.nameEdit.text(), + self.openCheckBox.isChecked(), + self.logCheckBox.isChecked(), + self.scriptCheckBox.isChecked(), + targetDirectory, + Utilities.toNativeSeparators(self.pythonExecPicker.text()), + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvConfigurationDialog.ui Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,506 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VirtualenvConfigurationDialog</class> + <widget class="QDialog" name="VirtualenvConfigurationDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>700</width> + <height>592</height> + </rect> + </property> + <property name="windowTitle"> + <string>Virtualenv Configuration</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Environment Creator</string> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="0" column="0"> + <widget class="QRadioButton" name="virtualenvButton"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="toolTip"> + <string>Select to use 'virtualenv'</string> + </property> + <property name="text"> + <string notr="true">0.0</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QRadioButton" name="pyvenvButton"> + <property name="font"> + <font> + <weight>75</weight> + <bold>true</bold> + </font> + </property> + <property name="toolTip"> + <string>Select to use 'pyvenv'</string> + </property> + <property name="text"> + <string notr="true">0.0</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Logical Name:</string> + </property> + </widget> + </item> + <item> + <widget class="E5ClearableLineEdit" name="nameEdit"> + <property name="toolTip"> + <string>Enter a name for the virtual environment</string> + </property> + <property name="placeholderText"> + <string>Name for the virtual environment</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="title"> + <string>Paths</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Target Directory:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="E5PathPicker" name="targetDirectoryPicker" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::WheelFocus</enum> + </property> + <property name="toolTip"> + <string>Enter the target directory for the virtual environment</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="extraSearchPathLabel"> + <property name="text"> + <string>Extra Search Path:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="E5PathPicker" name="extraSearchPathPicker" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::WheelFocus</enum> + </property> + <property name="toolTip"> + <string>Enter the extra search path to look for setuptools/pip</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="promptPrefixLabel"> + <property name="text"> + <string>Prompt Prefix:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="E5ClearableLineEdit" name="promptPrefixEdit"> + <property name="toolTip"> + <string>Enter the prompt prefix for the virtual environment</string> + </property> + <property name="placeholderText"> + <string>Prompt prefix for the virtual environment</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_5"> + <property name="text"> + <string>Python Executable:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="E5PathPicker" name="pythonExecPicker" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::WheelFocus</enum> + </property> + <property name="toolTip"> + <string>Enter the Python interpreter for the virtual environment</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Options</string> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_3"> + <item> + <widget class="QLabel" name="verbosityLabel"> + <property name="text"> + <string>Verbosity:</string> + </property> + </widget> + </item> + <item> + <widget class="QSpinBox" name="verbositySpinBox"> + <property name="toolTip"> + <string>Select the verbosity (-1: quiet, 0: normal, 1: verbose)</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="minimum"> + <number>-1</number> + </property> + <property name="maximum"> + <number>1</number> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_3"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="0" column="1"> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="versionLabel"> + <property name="text"> + <string>Python Version:</string> + </property> + </widget> + </item> + <item> + <widget class="QComboBox" name="versionComboBox"> + <property name="toolTip"> + <string>Select the Python version (empty for current)</string> + </property> + <item> + <property name="text"> + <string notr="true"/> + </property> + </item> + <item> + <property name="text"> + <string notr="true">2.6</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">2.7</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">3.4</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">3.5</string> + </property> + </item> + <item> + <property name="text"> + <string notr="true">3.6</string> + </property> + </item> + <item> + <property name="text"> + <string>3.7</string> + </property> + </item> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="0"> + <widget class="QCheckBox" name="systemCheckBox"> + <property name="toolTip"> + <string>Select to give the virtualenv access to the global site-packages</string> + </property> + <property name="text"> + <string>System-wide Python Packages</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QCheckBox" name="unzipCheckBox"> + <property name="toolTip"> + <string>Select to unzip setuptools when installing it</string> + </property> + <property name="text"> + <string>Unzip Setuptool to virtualenv</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="noSetuptoolsCheckBox"> + <property name="toolTip"> + <string>Select to not install setuptools (or pip) in the new virtualenv</string> + </property> + <property name="text"> + <string>Don't install 'setuptool' (or pip) in the virtualenv</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QCheckBox" name="noPipCcheckBox"> + <property name="toolTip"> + <string>Select to not install pip in the new virtualenv</string> + </property> + <property name="text"> + <string>Don't install 'pip' in the virtualenv</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QCheckBox" name="clearCheckBox"> + <property name="toolTip"> + <string>Select to clear the target first</string> + </property> + <property name="text"> + <string>Clear out the target directory</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QCheckBox" name="copyCheckBox"> + <property name="toolTip"> + <string>Select to always copy files rather than symlinking</string> + </property> + <property name="text"> + <string>Always copy files</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QCheckBox" name="symlinkCheckBox"> + <property name="toolTip"> + <string>Select to use symlinks instead of copies</string> + </property> + <property name="text"> + <string>Use Symbolic Links</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QCheckBox" name="upgradeCheckBox"> + <property name="toolTip"> + <string>Select to upgrade a virtual environment</string> + </property> + <property name="text"> + <string>Upgrade</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QCheckBox" name="logCheckBox"> + <property name="toolTip"> + <string>Select to generate a log file in the target directory</string> + </property> + <property name="text"> + <string>Save a log file in the target directory after creation</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QCheckBox" name="scriptCheckBox"> + <property name="toolTip"> + <string>Select to write a shell script/batch file to regenerate the virtualenv</string> + </property> + <property name="text"> + <string>Save virtualenv generation script</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="6" column="0"> + <widget class="QCheckBox" name="openCheckBox"> + <property name="toolTip"> + <string>Open the newly created virtualenv in a file manager window</string> + </property> + <property name="text"> + <string>Open target directory after creation</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5ClearableLineEdit</class> + <extends>QLineEdit</extends> + <header>E5Gui/E5LineEdit.h</header> + </customwidget> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <tabstops> + <tabstop>virtualenvButton</tabstop> + <tabstop>pyvenvButton</tabstop> + <tabstop>nameEdit</tabstop> + <tabstop>targetDirectoryPicker</tabstop> + <tabstop>extraSearchPathPicker</tabstop> + <tabstop>promptPrefixEdit</tabstop> + <tabstop>pythonExecPicker</tabstop> + <tabstop>verbositySpinBox</tabstop> + <tabstop>versionComboBox</tabstop> + <tabstop>systemCheckBox</tabstop> + <tabstop>unzipCheckBox</tabstop> + <tabstop>noSetuptoolsCheckBox</tabstop> + <tabstop>noPipCcheckBox</tabstop> + <tabstop>clearCheckBox</tabstop> + <tabstop>copyCheckBox</tabstop> + <tabstop>symlinkCheckBox</tabstop> + <tabstop>upgradeCheckBox</tabstop> + <tabstop>logCheckBox</tabstop> + <tabstop>scriptCheckBox</tabstop> + <tabstop>openCheckBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>VirtualenvConfigurationDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>VirtualenvConfigurationDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvExecDialog.py Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,322 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2014 - 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the virtualenv execution dialog. +""" + +from __future__ import unicode_literals +try: + str = unicode +except NameError: + pass + +import sys +import os + +from PyQt5.QtCore import QProcess, QTimer, QUrl +from PyQt5.QtGui import QDesktopServices +from PyQt5.QtWidgets import QDialog, QDialogButtonBox + +from .Ui_VirtualenvExecDialog import Ui_VirtualenvExecDialog + +import Preferences +from Globals import isWindowsPlatform + + +class VirtualenvExecDialog(QDialog, Ui_VirtualenvExecDialog): + """ + Class implementing the virtualenv execution dialog. + + This class starts a QProcess and displays a dialog that + shows the output of the virtualenv or pyvenv process. + """ + def __init__(self, pyvenv, targetDir, venvName, openTarget, createLog, + createScript, interpreter, venvManager, parent=None): + """ + Constructor + + @param pyvenv flag indicating the use of 'pyvenv' + @type bool + @param targetDir name of the virtualenv directory + @type str + @param venvName logical name for the virtual environment + @type str + @param openTarget flag indicating to open the virtualenv directory + in a file manager + @type bool + @param createLog flag indicating to create a log file of the + creation process + @type bool + @param createScript flag indicating to create a script to recreate + the virtual environment + @type bool + @param interpreter name of the python interpreter to use + @type str + @param venvManager reference to the virtual environment manager + @type VirtualenvManager + @param parent reference to the parent widget + @type QWidget + """ + super(VirtualenvExecDialog, self).__init__(parent) + self.setupUi(self) + + self.buttonBox.button(QDialogButtonBox.Close).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.Cancel).setDefault(True) + + self.__pyvenv = pyvenv + self.__targetDir = targetDir + self.__openTarget = openTarget + self.__createLog = createLog + self.__createScript = createScript + self.__venvName = venvName + self.__venvManager = venvManager + + self.__process = None + self.__cmd = "" + + if pyvenv: + self.__calls = [] + if interpreter: + self.__calls.append((interpreter, ["-m", "venv"])) + self.__calls.extend([ + (sys.executable.replace("w.exe", ".exe"), + ["-m", "venv"]), + ("python3", ["-m", "venv"]), + ("python", ["-m", "venv"]), + ]) + else: + self.__calls = [ + (sys.executable.replace("w.exe", ".exe"), + ["-m", "virtualenv"]), + ("virtualenv", []), + ] + self.__callIndex = 0 + self.__callArgs = [] + + def start(self, arguments): + """ + Public slot to start the virtualenv command. + + @param arguments commandline arguments for virtualenv/pyvenv program + (list of strings) + """ + if self.__callIndex == 0: + # first attempt, add a given python interpreter and do + # some other setup + self.errorGroup.hide() + self.contents.clear() + self.errors.clear() + + self.__process = QProcess() + self.__process.readyReadStandardOutput.connect(self.__readStdout) + self.__process.readyReadStandardError.connect(self.__readStderr) + self.__process.finished.connect(self.__finish) + + if not self.__pyvenv: + for arg in arguments: + if arg.startswith("--python="): + prog = arg.replace("--python=", "") + self.__calls.insert( + 0, (prog, ["-m", "virtualenv"])) + break + self.__callArgs = arguments + + prog, args = self.__calls[self.__callIndex] + args.extend(self.__callArgs) + self.__cmd = "{0} {1}".format(prog, " ".join(args)) + self.__logOutput(self.tr("Executing: {0}\n").format( + self.__cmd)) + self.__process.start(prog, args) + procStarted = self.__process.waitForStarted(5000) + if not procStarted: + self.__logOutput(self.tr("Failed\n\n")) + self.__nextAttempt() + + def on_buttonBox_clicked(self, button): + """ + Private slot called by a button of the button box clicked. + + @param button button that was clicked (QAbstractButton) + """ + if button == self.buttonBox.button(QDialogButtonBox.Close): + self.accept() + elif button == self.buttonBox.button(QDialogButtonBox.Cancel): + self.__finish() + + def __finish(self, exitCode, exitStatus, giveUp=False): + """ + Private slot called when the process finished. + + It is called when the process finished or + the user pressed the button. + + @param exitCode exit code of the process (integer) + @param exitStatus exit status of the process (QProcess.ExitStatus) + @keyparam giveUp flag indicating to not start another attempt (boolean) + """ + if self.__process is not None and \ + self.__process.state() != QProcess.NotRunning: + self.__process.terminate() + QTimer.singleShot(2000, self.__process.kill) + self.__process.waitForFinished(3000) + + self.buttonBox.button(QDialogButtonBox.Close).setEnabled(True) + self.buttonBox.button(QDialogButtonBox.Cancel).setEnabled(False) + self.buttonBox.button(QDialogButtonBox.Close).setDefault(True) + + if not giveUp: + if exitCode != 0: + self.__logOutput(self.tr("Failed\n\n")) + if len(self.errors.toPlainText().splitlines()) == 1: + self.errors.clear() + self.errorGroup.hide() + self.__nextAttempt() + return + + self.__process = None + + if self.__pyvenv: + self.__logOutput(self.tr('\npyvenv finished.\n')) + else: + self.__logOutput(self.tr('\nvirtualenv finished.\n')) + + if os.path.exists(self.__targetDir): + if self.__createScript: + self.__writeScriptFile() + + if self.__createLog: + self.__writeLogFile() + + if self.__openTarget: + QDesktopServices.openUrl(QUrl.fromLocalFile( + self.__targetDir)) + + self.__venvManager.addVirtualEnv(self.__venvName, + self.__targetDir) + + def __nextAttempt(self): + """ + Private method to start another attempt. + """ + self.__callIndex += 1 + if self.__callIndex < len(self.__calls): + self.start(self.__callArgs) + else: + if self.__pyvenv: + self.__logError( + self.tr('No suitable pyvenv program could be' + ' started.\n')) + else: + self.__logError( + self.tr('No suitable virtualenv program could be' + ' started.\n')) + self.__cmd = "" + self.__finish(0, 0, giveUp=True) + + def __readStdout(self): + """ + Private slot to handle the readyReadStandardOutput signal. + + It reads the output of the process, formats it and inserts it into + the contents pane. + """ + self.__process.setReadChannel(QProcess.StandardOutput) + + while self.__process.canReadLine(): + s = str(self.__process.readLine(), + Preferences.getSystem("IOEncoding"), + 'replace') + self.__logOutput(s) + + def __readStderr(self): + """ + Private slot to handle the readyReadStandardError signal. + + It reads the error output of the process and inserts it into the + error pane. + """ + self.__process.setReadChannel(QProcess.StandardError) + + while self.__process.canReadLine(): + s = str(self.__process.readLine(), + Preferences.getSystem("IOEncoding"), + 'replace') + self.__logError(s) + + def __logOutput(self, s): + """ + Private method to log some output. + + @param s output sstring to log (string) + """ + self.contents.insertPlainText(s) + self.contents.ensureCursorVisible() + + def __logError(self, s): + """ + Private method to log an error. + + @param s error string to log (string) + """ + self.errorGroup.show() + self.errors.insertPlainText(s) + self.errors.ensureCursorVisible() + + def __writeLogFile(self): + """ + Private method to write a log file to the virtualenv directory. + """ + outtxt = self.contents.toPlainText() + if self.__pyvenv: + logFile = os.path.join(self.__targetDir, "pyvenv.log") + else: + logFile = os.path.join(self.__targetDir, "virtualenv.log") + self.__logOutput(self.tr("\nWriting log file '{0}'.\n") + .format(logFile)) + + try: + f = open(logFile, "w", encoding="utf-8") + f.write(self.tr("Output:\n")) + f.write(outtxt) + errtxt = self.errors.toPlainText() + if errtxt: + f.write("\n") + f.write(self.tr("Errors:\n")) + f.write(errtxt) + f.close() + except (IOError, OSError) as err: + self.__logError( + self.tr("""The logfile '{0}' could not be written.\n""" + """Reason: {1}\n""").format(logFile, str(err))) + self.__logOutput(self.tr("Done.\n")) + + def __writeScriptFile(self): + """ + Private method to write a script file to the virtualenv directory. + """ + if self.__pyvenv: + basename = "create_pyvenv" + else: + basename = "create_virtualenv" + if isWindowsPlatform(): + script = os.path.join(self.__targetDir, basename + ".bat") + txt = self.__cmd + else: + script = os.path.join(self.__targetDir, basename + ".sh") + txt = "#!/usr/bin/env sh\n\n" + self.__cmd + + self.__logOutput(self.tr("\nWriting script file '{0}'.\n") + .format(script)) + + try: + f = open(script, "w", encoding="utf-8") + f.write(txt) + f.close() + except (IOError, OSError) as err: + self.__logError( + self.tr("""The script file '{0}' could not be written.\n""" + """Reason: {1}\n""").format(script, str(err))) + self.__logOutput(self.tr("Done.\n"))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvExecDialog.ui Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,99 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VirtualenvExecDialog</class> + <widget class="QDialog" name="VirtualenvExecDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>750</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle"> + <string>Virtualenv Creation</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout_3"> + <item> + <widget class="QGroupBox" name="messagesGroup"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>3</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Messages</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTextBrowser" name="contents"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>3</verstretch> + </sizepolicy> + </property> + <property name="whatsThis"> + <string><b>virtualenv Execution</b> +<p>This shows the output of the virtualenv command.</p></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="errorGroup"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="title"> + <string>Errors</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QTextBrowser" name="errors"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + <property name="whatsThis"> + <string><b>virtualenv Execution</b> +<p>This shows the errors of the virtualenv command.</p></string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <layoutdefault spacing="6" margin="11"/> + <pixmapfunction>qPixmapFromMimeSource</pixmapfunction> + <tabstops> + <tabstop>contents</tabstop> + <tabstop>errors</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections/> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvInterpreterSelectionDialog.py Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,79 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to enter the interpreter for a virtual +environment. +""" + +from __future__ import unicode_literals + +import os + +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtWidgets import QDialog, QDialogButtonBox + +from E5Gui.E5PathPicker import E5PathPickerModes + +from .Ui_VirtualenvInterpreterSelectionDialog import \ + Ui_VirtualenvInterpreterSelectionDialog + + +class VirtualenvInterpreterSelectionDialog( + QDialog, Ui_VirtualenvInterpreterSelectionDialog): + """ + Class implementing a dialog to enter the interpreter for a virtual + environment. + """ + def __init__(self, venvName, venvDirectory, parent=None): + """ + Constructor + + @param venvName name for the virtual environment + @type str + @param venvDirectory directory of the virtual environment + @type str + @param parent reference to the parent widget + @type QWidget + """ + super(VirtualenvInterpreterSelectionDialog, self).__init__(parent) + self.setupUi(self) + + self.pythonExecPicker.setMode(E5PathPickerModes.OpenFileMode) + self.pythonExecPicker.setWindowTitle( + self.tr("Python Interpreter")) + + self.nameEdit.setText(venvName) + self.pythonExecPicker.setText(venvDirectory) + + def __updateOK(self): + """ + Private method to update the enabled status of the OK button. + """ + interpreterPath = self.pythonExecPicker.text() + self.buttonBox.button(QDialogButtonBox.Ok).setEnabled( + bool(interpreterPath) and + os.path.isfile(interpreterPath) and + os.access(interpreterPath, os.X_OK) + ) + + @pyqtSlot(str) + def on_pythonExecPicker_textChanged(self, txt): + """ + Private slot to handle changes of the entered Python interpreter path. + + @param txt entered Python interpreter path + @type str + """ + self.__updateOK() + + def getData(self): + """ + Public method to get the entered data. + + @return path of the selected Python interpreter + @rtype str + """ + return self.pythonExecPicker.text()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvInterpreterSelectionDialog.ui Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,116 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>VirtualenvInterpreterSelectionDialog</class> + <widget class="QDialog" name="VirtualenvInterpreterSelectionDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>550</width> + <height>118</height> + </rect> + </property> + <property name="windowTitle"> + <string>Add Virtual Environment</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Name:</string> + </property> + </widget> + </item> + <item> + <widget class="QLineEdit" name="nameEdit"> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Enter interpreter for virtual environment:</string> + </property> + </widget> + </item> + <item> + <widget class="E5PathPicker" name="pythonExecPicker" native="true"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="focusPolicy"> + <enum>Qt::WheelFocus</enum> + </property> + <property name="toolTip"> + <string>Enter the Python interpreter for the virtual environment</string> + </property> + </widget> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <customwidgets> + <customwidget> + <class>E5PathPicker</class> + <extends>QWidget</extends> + <header>E5Gui/E5PathPicker.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>VirtualenvInterpreterSelectionDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>VirtualenvInterpreterSelectionDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/VirtualenvManager.py Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,138 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a class to manage Python virtual environments. +""" + +from __future__ import unicode_literals + +import os +import sys +import shutil + +from PyQt5.QtCore import pyqtSlot, QObject +from PyQt5.QtWidgets import QDialog + +from E5Gui import E5MessageBox + +import Preferences + + +class VirtualenvManager(QObject): + """ + Class implementing an object to manage Python virtual environments. + """ + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent object + @type QWidget + """ + super(VirtualenvManager, self).__init__(parent) + + self.__ui = parent + + self.__virtualEnvironments = {} + self.__virtualEnvironmentInterpreters = {} + environments = Preferences.toDict(Preferences.Prefs.settings.value( + "PyVenv/Environments", {})) + interpreters = Preferences.toDict(Preferences.Prefs.settings.value( + "PyVenv/Interpreters", {})) + for venvName, venvExe in interpreters.items(): + # remove all environments, that don't exist anymore + if os.access(venvExe, os.X_OK): + self.__virtualEnvironmentInterpreters[venvName] = venvExe + self.__virtualEnvironments[venvName] = environments[venvName] + + defaultPy = sys.executable.replace("w.exe", ".exe") + if defaultPy not in self.__virtualEnvironmentInterpreters.values(): + self.__virtualEnvironmentInterpreters["<default>"] = defaultPy + self.__virtualEnvironments["<default>"] = "" + + self.__updateSettings() + + def __updateSettings(self): + """ + Private slot to save the virtual environments. + """ + Preferences.Prefs.settings.setValue( + "PyVenv/Environments", self.__virtualEnvironments) + Preferences.Prefs.settings.setValue( + "PyVenv/Interpreters", self.__virtualEnvironmentInterpreters) + + @pyqtSlot() + def createVirtualEnv(self): + """ + Public slot to create a new virtual environment. + """ + from .VirtualenvConfigurationDialog import \ + VirtualenvConfigurationDialog + + dlg = VirtualenvConfigurationDialog() + if dlg.exec_() == QDialog.Accepted: + (pyvenv, args, name, openTarget, createLog, createScript, + targetDir, interpreter) = dlg.getData() + + # now do the call + from .VirtualenvExecDialog import VirtualenvExecDialog + dia = VirtualenvExecDialog(pyvenv, targetDir, name, openTarget, + createLog, createScript, interpreter, + self) + dia.show() + dia.start(args) + dia.exec_() + + def addVirtualEnv(self, venvName, venvDirectory): + """ + Public method to add a virtual environment. + + @param venvName logical name for the virtual environment + @type str + @param venvDirectory directory of the virtual envoronment + @type str + """ + if venvName in self.__virtualEnvironments: + ok = E5MessageBox.yesNo( + None, + self.tr("Add Virtual Environment"), + self.tr("""A virtual environment named <b>{0}</b> exists""" + """ already. Shall it be replaced?""") + .format(venvName), + icon=E5MessageBox.Warning) + if not ok: + return + + from .VirtualenvInterpreterSelectionDialog import \ + VirtualenvInterpreterSelectionDialog + dlg = VirtualenvInterpreterSelectionDialog(venvName, venvDirectory) + if dlg.exec_() == QDialog.Accepted: + venvExe = dlg.getData() + self.__virtualEnvironmentInterpreters[venvName] = venvExe + self.__virtualEnvironments[venvName] = venvDirectory + + self.__updateSettings() + + def deleteVirtualEnv(self, venvName): + """ + Public method to delete a virtual environment from disk. + + @param venvName logical name for the virtual environment + @type str + """ + if venvName in self.__virtualEnvironments: + ok = E5MessageBox.yesNo( + None, + self.tr("Delete Virtual Environment"), + self.tr("""Do you really want to delete the virtual""" + """ environment <b>{0}</b>?<br>Path: {1}""") + .format(venvName, self.__virtualEnvironments[venvName])) + if ok: + shutil.rmtree(self.__virtualEnvironments[venvName], True) + del self.__virtualEnvironments[venvName] + del self.__virtualEnvironmentInterpreters[venvName] + + self.__updateSettings()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualEnv/__init__.py Sat Jun 09 17:19:37 2018 +0200 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2018 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing virtualenv related functionality. +"""
--- a/eric6.e4p Sat Jun 09 12:09:21 2018 +0200 +++ b/eric6.e4p Sat Jun 09 17:19:37 2018 +0200 @@ -515,7 +515,6 @@ <Source>Plugins/PluginVcsMercurial.py</Source> <Source>Plugins/PluginVcsPySvn.py</Source> <Source>Plugins/PluginVcsSubversion.py</Source> - <Source>Plugins/PluginVirtualenvInterface.py</Source> <Source>Plugins/PluginVmListspace.py</Source> <Source>Plugins/PluginVmTabview.py</Source> <Source>Plugins/PluginWizardDotDesktop.py</Source> @@ -559,9 +558,6 @@ <Source>Plugins/UiExtensionPlugins/Translator/TranslatorRequest.py</Source> <Source>Plugins/UiExtensionPlugins/Translator/TranslatorWidget.py</Source> <Source>Plugins/UiExtensionPlugins/Translator/__init__.py</Source> - <Source>Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvConfigurationDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvExecDialog.py</Source> - <Source>Plugins/UiExtensionPlugins/VirtualenvInterface/__init__.py</Source> <Source>Plugins/UiExtensionPlugins/__init__.py</Source> <Source>Plugins/VcsPlugins/__init__.py</Source> <Source>Plugins/VcsPlugins/vcsGit/Config.py</Source> @@ -1400,6 +1396,11 @@ <Source>ViewManager/BookmarkedFilesDialog.py</Source> <Source>ViewManager/ViewManager.py</Source> <Source>ViewManager/__init__.py</Source> + <Source>VirtualEnv/VirtualenvConfigurationDialog.py</Source> + <Source>VirtualEnv/VirtualenvExecDialog.py</Source> + <Source>VirtualEnv/VirtualenvInterpreterSelectionDialog.py</Source> + <Source>VirtualEnv/VirtualenvManager.py</Source> + <Source>VirtualEnv/__init__.py</Source> <Source>WebBrowser/AdBlock/AdBlockDialog.py</Source> <Source>WebBrowser/AdBlock/AdBlockExceptionsDialog.py</Source> <Source>WebBrowser/AdBlock/AdBlockIcon.py</Source> @@ -1810,8 +1811,6 @@ <Form>Plugins/UiExtensionPlugins/PipInterface/PipSelectionDialog.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/ConfigurationPage/TranslatorPage.ui</Form> <Form>Plugins/UiExtensionPlugins/Translator/TranslatorWidget.ui</Form> - <Form>Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvConfigurationDialog.ui</Form> - <Form>Plugins/UiExtensionPlugins/VirtualenvInterface/VirtualenvExecDialog.ui</Form> <Form>Plugins/VcsPlugins/vcsGit/ConfigurationPage/GitPage.ui</Form> <Form>Plugins/VcsPlugins/vcsGit/GitAddRemoteDialog.ui</Form> <Form>Plugins/VcsPlugins/vcsGit/GitApplyBundleDataDialog.ui</Form> @@ -2110,6 +2109,9 @@ <Form>VCS/CommandOptionsDialog.ui</Form> <Form>VCS/RepositoryInfoDialog.ui</Form> <Form>ViewManager/BookmarkedFilesDialog.ui</Form> + <Form>VirtualEnv/VirtualenvConfigurationDialog.ui</Form> + <Form>VirtualEnv/VirtualenvExecDialog.ui</Form> + <Form>VirtualEnv/VirtualenvInterpreterSelectionDialog.ui</Form> <Form>WebBrowser/AdBlock/AdBlockDialog.ui</Form> <Form>WebBrowser/AdBlock/AdBlockExceptionsDialog.ui</Form> <Form>WebBrowser/Bookmarks/AddBookmarkDialog.ui</Form>