|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2020 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the project support for flask-migrate. |
|
8 """ |
|
9 |
|
10 import os |
|
11 |
|
12 from PyQt5.QtCore import pyqtSlot, QObject, QProcess |
|
13 from PyQt5.QtWidgets import QMenu, QDialog |
|
14 |
|
15 from E5Gui import E5MessageBox |
|
16 from E5Gui.E5Application import e5App |
|
17 from E5Gui.E5Action import E5Action |
|
18 |
|
19 import Utilities |
|
20 |
|
21 from ..FlaskCommandDialog import FlaskCommandDialog |
|
22 |
|
23 |
|
24 class MigrateProject(QObject): |
|
25 """ |
|
26 Class implementing the flask-migrate project support. |
|
27 """ |
|
28 def __init__(self, plugin, project, parent=None): |
|
29 """ |
|
30 Constructor |
|
31 |
|
32 @param plugin reference to the plugin object |
|
33 @type ProjectFlaskPlugin |
|
34 @param project reference to the project object |
|
35 @type Project |
|
36 @param parent parent |
|
37 @type QObject |
|
38 """ |
|
39 super(MigrateProject, self).__init__(parent) |
|
40 |
|
41 self.__plugin = plugin |
|
42 self.__project = project |
|
43 |
|
44 # TODO: move virtual env stuff to Project |
|
45 self.__virtualEnvManager = e5App().getObject("VirtualEnvManager") |
|
46 |
|
47 def initActions(self): |
|
48 """ |
|
49 Public method to define the flask-migrate actions. |
|
50 """ |
|
51 # TODO: implement flask-migrate actions |
|
52 self.actions = [] |
|
53 |
|
54 self.migrateConfigAct = E5Action( |
|
55 self.tr('Configure Migrate'), |
|
56 self.tr('&Configure Migrate'), |
|
57 0, 0, |
|
58 self, 'flask_config_migrate') |
|
59 self.migrateConfigAct.setStatusTip(self.tr( |
|
60 'Shows a dialog to edit the configuration for flask-migrate')) |
|
61 self.migrateConfigAct.setWhatsThis(self.tr( |
|
62 """<b>Configure Migrate</b>""" |
|
63 """<p>Shows a dialog to edit the configuration for""" |
|
64 """ flask-migrate.</p>""" |
|
65 )) |
|
66 self.migrateConfigAct.triggered.connect( |
|
67 self.__configureMigrate) |
|
68 self.actions.append(self.migrateConfigAct) |
|
69 |
|
70 self.migrateInstallAct = E5Action( |
|
71 self.tr('Install flask-migrate'), |
|
72 self.tr('&Install flask-migrate'), |
|
73 0, 0, |
|
74 self, 'flask_install_migrate') |
|
75 self.migrateInstallAct.setStatusTip(self.tr( |
|
76 'Installs the flask-migrate extension into the configured' |
|
77 ' environment')) |
|
78 self.migrateInstallAct.setWhatsThis(self.tr( |
|
79 """<b>Install flask-migrate</b>""" |
|
80 """<p>Installs the flask-migrate extension into the configured""" |
|
81 """ environment using the pip interface.</p>""" |
|
82 )) |
|
83 self.migrateInstallAct.triggered.connect( |
|
84 self.__installFlaskMigrate) |
|
85 self.actions.append(self.migrateInstallAct) |
|
86 |
|
87 self.migrateAvailabilityAct = E5Action( |
|
88 self.tr('Check flask-migrate Availability'), |
|
89 self.tr('Check flask-migrate &Availability'), |
|
90 0, 0, |
|
91 self, 'flask_check_migrate') |
|
92 self.migrateAvailabilityAct.setStatusTip(self.tr( |
|
93 'Check the availability of the flask-migrate extension')) |
|
94 self.migrateAvailabilityAct.setWhatsThis(self.tr( |
|
95 """<b>Check flask-migrate Availability</b>""" |
|
96 """<p>Check the availability of the flask-migrate extension.</p>""" |
|
97 )) |
|
98 self.migrateAvailabilityAct.triggered.connect( |
|
99 self.__checkAvailability) |
|
100 self.actions.append(self.migrateAvailabilityAct) |
|
101 |
|
102 ######################################################### |
|
103 ## action to initialize the database migration system |
|
104 ######################################################### |
|
105 # TODO: add action for flask db init |
|
106 |
|
107 ######################################################### |
|
108 ## action to create a new database migration |
|
109 ######################################################### |
|
110 # TODO: add action for flask db migrate |
|
111 |
|
112 ######################################################### |
|
113 ## action to up- and downgrade a databse |
|
114 ######################################################### |
|
115 # TODO: add action for flask db upgrade |
|
116 # TODO: add action for flask db downgrade |
|
117 |
|
118 def initMenu(self): |
|
119 """ |
|
120 Public method to initialize the flask-migrate menu. |
|
121 |
|
122 @return the menu generated |
|
123 @rtype QMenu |
|
124 """ |
|
125 menu = QMenu(self.tr("Database")) |
|
126 menu.setTearOffEnabled(True) |
|
127 |
|
128 menu.addAction(self.migrateConfigAct) |
|
129 menu.addSeparator() |
|
130 menu.addAction(self.migrateAvailabilityAct) |
|
131 menu.addAction(self.migrateInstallAct) |
|
132 |
|
133 return menu |
|
134 |
|
135 def determineCapability(self): |
|
136 """ |
|
137 Public method to determine the availability of flask-migrate. |
|
138 """ |
|
139 available = self.__flaskMigrateAvailable() |
|
140 self.__project.setCapability("migrate", available) |
|
141 |
|
142 self.migrateConfigAct.setEnabled(available) |
|
143 self.migrateInstallAct.setEnabled(not available) |
|
144 |
|
145 def __flaskMigrateAvailable(self): |
|
146 """ |
|
147 Private method to check, if the 'flask-babel' package is available. |
|
148 |
|
149 @return flag indicating the availability of 'flask-babel' |
|
150 @rtype bool |
|
151 """ |
|
152 venvName = self.__plugin.getPreferences("VirtualEnvironmentNamePy3") |
|
153 interpreter = self.__virtualEnvManager.getVirtualenvInterpreter( |
|
154 venvName) |
|
155 if interpreter and Utilities.isinpath(interpreter): |
|
156 detector = os.path.join( |
|
157 os.path.dirname(__file__), "FlaskMigrateDetector.py") |
|
158 proc = QProcess() |
|
159 proc.setProcessChannelMode(QProcess.MergedChannels) |
|
160 proc.start(interpreter, [detector]) |
|
161 finished = proc.waitForFinished(30000) |
|
162 if finished and proc.exitCode() == 0: |
|
163 return True |
|
164 |
|
165 return False |
|
166 |
|
167 ######################################################## |
|
168 ## Menu related slots below |
|
169 ######################################################## |
|
170 |
|
171 @pyqtSlot() |
|
172 def __configureMigrate(self): |
|
173 """ |
|
174 Private slot to show a dialog to edit the migrate configuration. |
|
175 """ |
|
176 # TODO: implement MigrateConfigDialog |
|
177 from .MigrateConfigDialog import MigrateConfigDialog |
|
178 |
|
179 config = self.__project.getData("migrate", "") |
|
180 dlg = MigrateConfigDialog(config) |
|
181 if dlg.exec() == QDialog.Accepted: |
|
182 config = dlg.getConfiguration() |
|
183 self.__project.setData("migrate", "", config) |
|
184 |
|
185 def __ensureMigrateConfigured(self): |
|
186 """ |
|
187 Private method to ensure, that flask-migrate has been configured. |
|
188 |
|
189 @return flag indicating successful configuration |
|
190 @rtype bool |
|
191 """ |
|
192 config = self.__project.getData("migrate", "") |
|
193 if not config: |
|
194 self.__configureMigrate() |
|
195 return True |
|
196 |
|
197 return False |
|
198 |
|
199 @pyqtSlot() |
|
200 def __installFlaskMigrate(self): |
|
201 """ |
|
202 Private slot to install the flask-migrate extension into the configured |
|
203 environment. |
|
204 """ |
|
205 language = e5App().getObject("Project").getProjectLanguage() |
|
206 if language == "Python3": |
|
207 venvName = self.__plugin.getPreferences( |
|
208 "VirtualEnvironmentNamePy3") |
|
209 else: |
|
210 venvName = "" |
|
211 if venvName: |
|
212 interpreter = self.__project.getFullCommand("python") |
|
213 pip = e5App().getObject("Pip") |
|
214 pip.installPackages(["flask-migrate"], interpreter=interpreter) |
|
215 self.determineCapability() |
|
216 else: |
|
217 E5MessageBox.critical( |
|
218 None, |
|
219 self.tr("Install flask-migrate"), |
|
220 self.tr("The 'flask-migrate' extension could not be installed" |
|
221 " because no virtual environment has been" |
|
222 " configured.")) |
|
223 |
|
224 @pyqtSlot() |
|
225 def __checkAvailability(self): |
|
226 """ |
|
227 Private slot to check the availability of the 'flask-babel' extension. |
|
228 """ |
|
229 self.determineCapability() |
|
230 if self.__project.hasCapability("migrate"): |
|
231 msg = self.tr("The 'flask-migrate' extension is installed.") |
|
232 else: |
|
233 msg = self.tr("The 'flask-migrate' extension is not installed.") |
|
234 E5MessageBox.information( |
|
235 None, |
|
236 self.tr("flask-migrate Availability"), |
|
237 msg) |
|
238 |
|
239 ######################################################### |
|
240 ## slot to initialize the database migration system |
|
241 ######################################################### |
|
242 |
|
243 ######################################################### |
|
244 ## slot to create a new database migration |
|
245 ######################################################### |
|
246 |
|
247 ######################################################### |
|
248 ## slots to up- and downgrade a databse |
|
249 ######################################################### |