Plugins/UiExtensionPlugins/PipInterface/PipFreezeDialog.py

branch
maintenance
changeset 6826
c6dda2cbe081
parent 6764
d14ddbfbbd36
parent 6825
e659bb96cdfa
child 6827
14680839ad7a
equal deleted inserted replaced
6764:d14ddbfbbd36 6826:c6dda2cbe081
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to generate a requirements file.
8 """
9
10 from __future__ import unicode_literals
11 try:
12 str = unicode # __IGNORE_EXCEPTION__
13 except NameError:
14 pass
15
16 import os
17
18 from PyQt5.QtCore import pyqtSlot, Qt
19 from PyQt5.QtWidgets import QDialog, QDialogButtonBox, QAbstractButton, \
20 QApplication
21
22 from E5Gui import E5MessageBox, E5FileDialog
23 from E5Gui.E5PathPicker import E5PathPickerModes
24 from E5Gui.E5Application import e5App
25
26 from .Ui_PipFreezeDialog import Ui_PipFreezeDialog
27
28 import Utilities
29
30
31 class PipFreezeDialog(QDialog, Ui_PipFreezeDialog):
32 """
33 Class implementing a dialog to generate a requirements file.
34 """
35 def __init__(self, pip, parent=None):
36 """
37 Constructor
38
39 @param pip reference to the master object
40 @type Pip
41 @param parent reference to the parent widget
42 @type QWidget
43 """
44 super(PipFreezeDialog, self).__init__(parent)
45 self.setupUi(self)
46 self.setWindowFlags(Qt.Window)
47
48 self.__refreshButton = self.buttonBox.addButton(
49 self.tr("&Refresh"), QDialogButtonBox.ActionRole)
50
51 self.requirementsFilePicker.setMode(E5PathPickerModes.SaveFileMode)
52 self.requirementsFilePicker.setFilters(
53 self.tr("Text Files (*.txt);;All Files (*)"))
54
55 self.__pip = pip
56
57 self.venvComboBox.addItem(pip.getDefaultEnvironmentString())
58 projectVenv = self.__pip.getProjectEnvironmentString()
59 if projectVenv:
60 self.venvComboBox.addItem(projectVenv)
61 self.venvComboBox.addItems(pip.getVirtualenvNames())
62
63 self.__requirementsEdited = False
64 self.__requirementsAvailable = False
65
66 self.__updateButtons()
67
68 def closeEvent(self, e):
69 """
70 Protected slot implementing a close event handler.
71
72 @param e close event
73 @type QCloseEvent
74 """
75 QApplication.restoreOverrideCursor()
76 e.accept()
77
78 @pyqtSlot(str)
79 def on_venvComboBox_activated(self, txt):
80 """
81 Private slot handling the selection of a virtual environment.
82
83 @param txt virtual environment
84 @type str
85 """
86 self.__refresh()
87
88 @pyqtSlot(bool)
89 def on_localCheckBox_clicked(self, checked):
90 """
91 Private slot handling the switching of the local mode.
92
93 @param checked state of the local check box
94 @type bool
95 """
96 self.__refresh()
97
98 @pyqtSlot(str)
99 def on_requirementsFilePicker_textChanged(self, txt):
100 """
101 Private slot handling a change of the requirements file name.
102
103 @param txt name of the requirements file
104 @type str
105 """
106 self.__updateButtons()
107
108 @pyqtSlot()
109 def on_requirementsEdit_textChanged(self):
110 """
111 Private slot handling changes of the requirements text.
112 """
113 self.__requirementsEdited = True
114
115 @pyqtSlot(QAbstractButton)
116 def on_buttonBox_clicked(self, button):
117 """
118 Private slot called by a button of the button box clicked.
119
120 @param button button that was clicked
121 @type QAbstractButton
122 """
123 if button == self.buttonBox.button(QDialogButtonBox.Close):
124 self.close()
125 elif button == self.__refreshButton:
126 self.__refresh()
127
128 def __refresh(self):
129 """
130 Private slot to refresh the displayed list.
131 """
132 if self.__requirementsEdited:
133 ok = E5MessageBox.yesNo(
134 self,
135 self.tr("Generate Requirements"),
136 self.tr("""The requirements were changed. Do you want"""
137 """ to overwrite these changes?"""))
138 else:
139 ok = True
140 if ok:
141 self.start()
142
143 def start(self):
144 """
145 Public method to start the command.
146 """
147 self.requirementsEdit.clear()
148 self.__requirementsAvailable = False
149
150 venvName = self.venvComboBox.currentText()
151 interpreter = self.__pip.getVirtualenvInterpreter(venvName)
152 if not interpreter:
153 return
154
155 args = ["-m", "pip", "freeze"]
156 if self.localCheckBox.isChecked():
157 args.append("--local")
158 if self.requirementsFilePicker.text():
159 fileName = Utilities.toNativeSeparators(
160 self.requirementsFilePicker.text())
161 if os.path.exists(fileName):
162 args.append("--requirement")
163 args.append(fileName)
164
165 QApplication.setOverrideCursor(Qt.WaitCursor)
166 success, output = self.__pip.runProcess(args, interpreter)
167
168 if success:
169 self.requirementsEdit.setPlainText(output)
170 self.__requirementsAvailable = True
171 else:
172 self.requirementsEdit.setPlainText(
173 self.tr("No output generated by 'pip freeze'."))
174
175 QApplication.restoreOverrideCursor()
176 self.__updateButtons()
177
178 self.__requirementsEdited = False
179
180 def __updateButtons(self):
181 """
182 Private method to set the state of the various buttons.
183 """
184 self.saveButton.setEnabled(
185 self.__requirementsAvailable and
186 bool(self.requirementsFilePicker.text())
187 )
188 self.saveToButton.setEnabled(self.__requirementsAvailable)
189 self.copyButton.setEnabled(self.__requirementsAvailable)
190
191 aw = e5App().getObject("ViewManager").activeWindow()
192 if aw and self.__requirementsAvailable:
193 self.insertButton.setEnabled(True)
194 self.replaceAllButton.setEnabled(True)
195 self.replaceSelectionButton.setEnabled(
196 aw.hasSelectedText())
197 else:
198 self.insertButton.setEnabled(False)
199 self.replaceAllButton.setEnabled(False)
200 self.replaceSelectionButton.setEnabled(False)
201
202 def __writeToFile(self, fileName):
203 """
204 Private method to write the requirements text to a file.
205
206 @param fileName name of the file to write to
207 @type str
208 """
209 if os.path.exists(fileName):
210 ok = E5MessageBox.warning(
211 self,
212 self.tr("Generate Requirements"),
213 self.tr("""The file <b>{0}</b> already exists. Do you want"""
214 """ to overwrite it?""").format(fileName))
215 if not ok:
216 return
217
218 try:
219 f = open(fileName, "w")
220 f.write(self.requirementsEdit.toPlainText())
221 f.close()
222 except (OSError, IOError) as err:
223 E5MessageBox.critical(
224 self,
225 self.tr("Generate Requirements"),
226 self.tr("""<p>The requirements could not be written"""
227 """ to <b>{0}</b>.</p><p>Reason: {1}</p>""")
228 .format(fileName, str(err)))
229
230 @pyqtSlot()
231 def on_saveButton_clicked(self):
232 """
233 Private slot to save the requirements text to the requirements file.
234 """
235 fileName = self.requirementsFilePicker.text()
236 self.__writeToFile(fileName)
237
238 @pyqtSlot()
239 def on_saveToButton_clicked(self):
240 """
241 Private slot to write the requirements text to a new file.
242 """
243 fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
244 self,
245 self.tr("Generate Requirements"),
246 os.path.expanduser("~"),
247 self.tr("Text Files (*.txt);;All Files (*)"),
248 None,
249 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)
250 )
251 if fileName:
252 ext = os.path.splitext(fileName)[1]
253 if not ext:
254 ex = selectedFilter.split("(*")[1].split(")")[0]
255 if ex:
256 fileName += ex
257 self.__writeToFile(fileName)
258
259 @pyqtSlot()
260 def on_copyButton_clicked(self):
261 """
262 Private slot to copy the requirements text to the clipboard.
263 """
264 txt = self.requirementsEdit.toPlainText()
265 cb = QApplication.clipboard()
266 cb.setText(txt)
267
268 @pyqtSlot()
269 def on_insertButton_clicked(self):
270 """
271 Private slot to insert the requirements text at the cursor position
272 of the current editor.
273 """
274 aw = e5App().getObject("ViewManager").activeWindow()
275 if aw:
276 aw.beginUndoAction()
277 aw.insert(self.requirementsEdit.toPlainText())
278 aw.endUndoAction()
279
280 @pyqtSlot()
281 def on_replaceSelectionButton_clicked(self):
282 """
283 Private slot to replace the selected text of the current editor
284 with the requirements text.
285 """
286 aw = e5App().getObject("ViewManager").activeWindow()
287 if aw:
288 aw.beginUndoAction()
289 aw.replaceSelectedText(self.requirementsEdit.toPlainText())
290 aw.endUndoAction()
291
292 @pyqtSlot()
293 def on_replaceAllButton_clicked(self):
294 """
295 Private slot to replace the text of the current editor with the
296 requirements text.
297 """
298 aw = e5App().getObject("ViewManager").activeWindow()
299 if aw:
300 aw.setText(self.requirementsEdit.toPlainText())

eric ide

mercurial