PipInterface/PipFreezeDialog.py

branch
maintenance
changeset 6826
c6dda2cbe081
parent 6726
bf2ec89b1975
parent 6798
3985c1a67fa2
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.__requirementsEdited = False
58 self.__requirementsAvailable = False
59
60 self.__updateButtons()
61
62 def closeEvent(self, e):
63 """
64 Protected slot implementing a close event handler.
65
66 @param e close event
67 @type QCloseEvent
68 """
69 QApplication.restoreOverrideCursor()
70 e.accept()
71
72 @pyqtSlot(bool)
73 def on_localCheckBox_clicked(self, checked):
74 """
75 Private slot handling the switching of the local mode.
76
77 @param checked state of the local check box
78 @type bool
79 """
80 self.__refresh()
81
82 @pyqtSlot(str)
83 def on_requirementsFilePicker_textChanged(self, txt):
84 """
85 Private slot handling a change of the requirements file name.
86
87 @param txt name of the requirements file
88 @type str
89 """
90 self.__updateButtons()
91
92 @pyqtSlot()
93 def on_requirementsEdit_textChanged(self):
94 """
95 Private slot handling changes of the requirements text.
96 """
97 self.__requirementsEdited = True
98
99 @pyqtSlot(QAbstractButton)
100 def on_buttonBox_clicked(self, button):
101 """
102 Private slot called by a button of the button box clicked.
103
104 @param button button that was clicked
105 @type QAbstractButton
106 """
107 if button == self.buttonBox.button(QDialogButtonBox.Close):
108 self.close()
109 elif button == self.__refreshButton:
110 self.__refresh()
111
112 def __refresh(self):
113 """
114 Private slot to refresh the displayed list.
115 """
116 if self.__requirementsEdited:
117 ok = E5MessageBox.yesNo(
118 self,
119 self.tr("Generate Requirements"),
120 self.tr("""The requirements were changed. Do you want"""
121 """ to overwrite these changes?"""))
122 else:
123 ok = True
124 if ok:
125 self.start()
126
127 def start(self, venvName):
128 """
129 Public method to start the command.
130
131 @param venvName name of the environment to act upon
132 @type str
133 """
134 self.requirementsEdit.clear()
135 self.__requirementsAvailable = False
136
137 interpreter = self.__pip.getVirtualenvInterpreter(venvName)
138 if not interpreter:
139 return
140
141 args = ["-m", "pip", "freeze"]
142 if self.localCheckBox.isChecked():
143 args.append("--local")
144 if self.requirementsFilePicker.text():
145 fileName = Utilities.toNativeSeparators(
146 self.requirementsFilePicker.text())
147 if os.path.exists(fileName):
148 args.append("--requirement")
149 args.append(fileName)
150
151 QApplication.setOverrideCursor(Qt.WaitCursor)
152 success, output = self.__pip.runProcess(args, interpreter)
153
154 if success:
155 self.requirementsEdit.setPlainText(output)
156 self.__requirementsAvailable = True
157 else:
158 self.requirementsEdit.setPlainText(
159 self.tr("No output generated by 'pip freeze'."))
160
161 QApplication.restoreOverrideCursor()
162 self.__updateButtons()
163
164 self.__requirementsEdited = False
165
166 def __updateButtons(self):
167 """
168 Private method to set the state of the various buttons.
169 """
170 self.saveButton.setEnabled(
171 self.__requirementsAvailable and
172 bool(self.requirementsFilePicker.text())
173 )
174 self.saveToButton.setEnabled(self.__requirementsAvailable)
175 self.copyButton.setEnabled(self.__requirementsAvailable)
176
177 aw = e5App().getObject("ViewManager").activeWindow()
178 if aw and self.__requirementsAvailable:
179 self.insertButton.setEnabled(True)
180 self.replaceAllButton.setEnabled(True)
181 self.replaceSelectionButton.setEnabled(
182 aw.hasSelectedText())
183 else:
184 self.insertButton.setEnabled(False)
185 self.replaceAllButton.setEnabled(False)
186 self.replaceSelectionButton.setEnabled(False)
187
188 def __writeToFile(self, fileName):
189 """
190 Private method to write the requirements text to a file.
191
192 @param fileName name of the file to write to
193 @type str
194 """
195 if os.path.exists(fileName):
196 ok = E5MessageBox.warning(
197 self,
198 self.tr("Generate Requirements"),
199 self.tr("""The file <b>{0}</b> already exists. Do you want"""
200 """ to overwrite it?""").format(fileName))
201 if not ok:
202 return
203
204 try:
205 f = open(fileName, "w")
206 f.write(self.requirementsEdit.toPlainText())
207 f.close()
208 except (OSError, IOError) as err:
209 E5MessageBox.critical(
210 self,
211 self.tr("Generate Requirements"),
212 self.tr("""<p>The requirements could not be written"""
213 """ to <b>{0}</b>.</p><p>Reason: {1}</p>""")
214 .format(fileName, str(err)))
215
216 @pyqtSlot()
217 def on_saveButton_clicked(self):
218 """
219 Private slot to save the requirements text to the requirements file.
220 """
221 fileName = self.requirementsFilePicker.text()
222 self.__writeToFile(fileName)
223
224 @pyqtSlot()
225 def on_saveToButton_clicked(self):
226 """
227 Private slot to write the requirements text to a new file.
228 """
229 fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
230 self,
231 self.tr("Generate Requirements"),
232 os.path.expanduser("~"),
233 self.tr("Text Files (*.txt);;All Files (*)"),
234 None,
235 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)
236 )
237 if fileName:
238 ext = os.path.splitext(fileName)[1]
239 if not ext:
240 ex = selectedFilter.split("(*")[1].split(")")[0]
241 if ex:
242 fileName += ex
243 self.__writeToFile(fileName)
244
245 @pyqtSlot()
246 def on_copyButton_clicked(self):
247 """
248 Private slot to copy the requirements text to the clipboard.
249 """
250 txt = self.requirementsEdit.toPlainText()
251 cb = QApplication.clipboard()
252 cb.setText(txt)
253
254 @pyqtSlot()
255 def on_insertButton_clicked(self):
256 """
257 Private slot to insert the requirements text at the cursor position
258 of the current editor.
259 """
260 aw = e5App().getObject("ViewManager").activeWindow()
261 if aw:
262 aw.beginUndoAction()
263 aw.insert(self.requirementsEdit.toPlainText())
264 aw.endUndoAction()
265
266 @pyqtSlot()
267 def on_replaceSelectionButton_clicked(self):
268 """
269 Private slot to replace the selected text of the current editor
270 with the requirements text.
271 """
272 aw = e5App().getObject("ViewManager").activeWindow()
273 if aw:
274 aw.beginUndoAction()
275 aw.replaceSelectedText(self.requirementsEdit.toPlainText())
276 aw.endUndoAction()
277
278 @pyqtSlot()
279 def on_replaceAllButton_clicked(self):
280 """
281 Private slot to replace the text of the current editor with the
282 requirements text.
283 """
284 aw = e5App().getObject("ViewManager").activeWindow()
285 if aw:
286 aw.setText(self.requirementsEdit.toPlainText())

eric ide

mercurial