eric7/PipInterface/PipFreezeDialog.py

branch
eric7
changeset 8312
800c432b34c8
parent 8259
2bbec88047dd
child 8318
962bce857696
equal deleted inserted replaced
8311:4e8b98454baa 8312:800c432b34c8
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2015 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a dialog to generate a requirements file.
8 """
9
10 import os
11
12 from PyQt5.QtCore import pyqtSlot, Qt
13 from PyQt5.QtWidgets import (
14 QDialog, QDialogButtonBox, QAbstractButton, QApplication
15 )
16
17 from E5Gui import E5MessageBox, E5FileDialog
18 from E5Gui.E5PathPicker import E5PathPickerModes
19 from E5Gui.E5Application import e5App
20 from E5Gui.E5OverrideCursor import E5OverrideCursor
21
22 from .Ui_PipFreezeDialog import Ui_PipFreezeDialog
23
24 import Utilities
25
26
27 class PipFreezeDialog(QDialog, Ui_PipFreezeDialog):
28 """
29 Class implementing a dialog to generate a requirements file.
30 """
31 def __init__(self, pip, parent=None):
32 """
33 Constructor
34
35 @param pip reference to the master object
36 @type Pip
37 @param parent reference to the parent widget
38 @type QWidget
39 """
40 super().__init__(parent)
41 self.setupUi(self)
42 self.setWindowFlags(Qt.WindowType.Window)
43
44 self.__refreshButton = self.buttonBox.addButton(
45 self.tr("&Refresh"), QDialogButtonBox.ButtonRole.ActionRole)
46
47 self.__environmentName = ""
48
49 self.requirementsFilePicker.setMode(E5PathPickerModes.SaveFileMode)
50 self.requirementsFilePicker.setFilters(
51 self.tr("Text Files (*.txt);;All Files (*)"))
52
53 self.__pip = pip
54
55 self.__requirementsEdited = False
56 self.__requirementsAvailable = False
57
58 self.__updateButtons()
59
60 def closeEvent(self, e):
61 """
62 Protected slot implementing a close event handler.
63
64 @param e close event
65 @type QCloseEvent
66 """
67 e.accept()
68
69 @pyqtSlot(bool)
70 def on_localCheckBox_clicked(self, checked):
71 """
72 Private slot handling the switching of the local mode.
73
74 @param checked state of the local check box
75 @type bool
76 """
77 self.__refresh()
78
79 @pyqtSlot(str)
80 def on_requirementsFilePicker_textChanged(self, txt):
81 """
82 Private slot handling a change of the requirements file name.
83
84 @param txt name of the requirements file
85 @type str
86 """
87 self.__updateButtons()
88
89 @pyqtSlot()
90 def on_requirementsEdit_textChanged(self):
91 """
92 Private slot handling changes of the requirements text.
93 """
94 self.__requirementsEdited = True
95
96 @pyqtSlot(QAbstractButton)
97 def on_buttonBox_clicked(self, button):
98 """
99 Private slot called by a button of the button box clicked.
100
101 @param button button that was clicked
102 @type QAbstractButton
103 """
104 if button == self.buttonBox.button(
105 QDialogButtonBox.StandardButton.Close
106 ):
107 self.close()
108 elif button == self.__refreshButton:
109 self.__refresh()
110
111 def __refresh(self):
112 """
113 Private slot to refresh the displayed list.
114 """
115 ok = (
116 E5MessageBox.yesNo(
117 self,
118 self.tr("Generate Requirements"),
119 self.tr("""The requirements were changed. Do you want"""
120 """ to overwrite these changes?"""))
121 if self.__requirementsEdited else
122 True
123 )
124 if ok:
125 self.start(self.__environmentName)
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 self.__environmentName = venvName
137
138 interpreter = self.__pip.getVirtualenvInterpreter(venvName)
139 if not interpreter:
140 return
141
142 args = ["-m", "pip", "freeze"]
143 if self.localCheckBox.isChecked():
144 args.append("--local")
145 if self.requirementsFilePicker.text():
146 fileName = Utilities.toNativeSeparators(
147 self.requirementsFilePicker.text())
148 if os.path.exists(fileName):
149 args.append("--requirement")
150 args.append(fileName)
151
152 with E5OverrideCursor():
153 success, output = self.__pip.runProcess(args, interpreter)
154
155 if success:
156 self.requirementsEdit.setPlainText(output)
157 self.__requirementsAvailable = True
158 else:
159 self.requirementsEdit.setPlainText(
160 self.tr("No output generated by 'pip freeze'."))
161
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 with open(fileName, "w") as f:
206 f.write(self.requirementsEdit.toPlainText())
207 except OSError as err:
208 E5MessageBox.critical(
209 self,
210 self.tr("Generate Requirements"),
211 self.tr("""<p>The requirements could not be written"""
212 """ to <b>{0}</b>.</p><p>Reason: {1}</p>""")
213 .format(fileName, str(err)))
214
215 @pyqtSlot()
216 def on_saveButton_clicked(self):
217 """
218 Private slot to save the requirements text to the requirements file.
219 """
220 fileName = self.requirementsFilePicker.text()
221 self.__writeToFile(fileName)
222
223 @pyqtSlot()
224 def on_saveToButton_clicked(self):
225 """
226 Private slot to write the requirements text to a new file.
227 """
228 fileName, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
229 self,
230 self.tr("Generate Requirements"),
231 os.path.expanduser("~"),
232 self.tr("Text Files (*.txt);;All Files (*)"),
233 None,
234 E5FileDialog.Options(E5FileDialog.DontConfirmOverwrite)
235 )
236 if fileName:
237 ext = os.path.splitext(fileName)[1]
238 if not ext:
239 ex = selectedFilter.split("(*")[1].split(")")[0]
240 if ex:
241 fileName += ex
242 self.__writeToFile(fileName)
243
244 @pyqtSlot()
245 def on_copyButton_clicked(self):
246 """
247 Private slot to copy the requirements text to the clipboard.
248 """
249 txt = self.requirementsEdit.toPlainText()
250 cb = QApplication.clipboard()
251 cb.setText(txt)
252
253 @pyqtSlot()
254 def on_insertButton_clicked(self):
255 """
256 Private slot to insert the requirements text at the cursor position
257 of the current editor.
258 """
259 aw = e5App().getObject("ViewManager").activeWindow()
260 if aw:
261 aw.beginUndoAction()
262 aw.insert(self.requirementsEdit.toPlainText())
263 aw.endUndoAction()
264
265 @pyqtSlot()
266 def on_replaceSelectionButton_clicked(self):
267 """
268 Private slot to replace the selected text of the current editor
269 with the requirements text.
270 """
271 aw = e5App().getObject("ViewManager").activeWindow()
272 if aw:
273 aw.beginUndoAction()
274 aw.replaceSelectedText(self.requirementsEdit.toPlainText())
275 aw.endUndoAction()
276
277 @pyqtSlot()
278 def on_replaceAllButton_clicked(self):
279 """
280 Private slot to replace the text of the current editor with the
281 requirements text.
282 """
283 aw = e5App().getObject("ViewManager").activeWindow()
284 if aw:
285 aw.setText(self.requirementsEdit.toPlainText())

eric ide

mercurial