Project/ProjectProtocolsBrowser.py

changeset 5970
411f7ba577d5
parent 5969
584c21b6587a
child 5974
dfb291b5b620
equal deleted inserted replaced
5969:584c21b6587a 5970:411f7ba577d5
14 except NameError: 14 except NameError:
15 pass 15 pass
16 16
17 import os 17 import os
18 import glob 18 import glob
19 import sys
19 20
20 from PyQt5.QtCore import QThread, pyqtSignal, QProcess 21 from PyQt5.QtCore import QThread, pyqtSignal, QProcess
21 from PyQt5.QtWidgets import QDialog, QApplication, QMenu 22 from PyQt5.QtWidgets import QDialog, QApplication, QMenu
22 23
23 from E5Gui.E5Application import e5App 24 from E5Gui.E5Application import e5App
59 @param project reference to the project object 60 @param project reference to the project object
60 @type Project 61 @type Project
61 @param parent parent widget of this browser 62 @param parent parent widget of this browser
62 @type QWidget 63 @type QWidget
63 """ 64 """
64 self.__protoc = Preferences.getProtobuf("protoc")
65 if self.__protoc == "":
66 self.__protoc = Utilities.isWindowsPlatform() and \
67 "protoc.exe" or "protoc"
68 if not Utilities.isinpath(self.__protoc):
69 self.__protoc = None
70
71 ProjectBaseBrowser.__init__(self, project, 65 ProjectBaseBrowser.__init__(self, project,
72 ProjectBrowserProtocolsType, parent) 66 ProjectBrowserProtocolsType, parent)
73 67
74 self.selectedItemsFilter = \ 68 self.selectedItemsFilter = \
75 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem] 69 [ProjectBrowserFileItem, ProjectBrowserSimpleDirectoryItem]
94 self.multiMenuActions = [] 88 self.multiMenuActions = []
95 self.dirMenuActions = [] 89 self.dirMenuActions = []
96 self.dirMultiMenuActions = [] 90 self.dirMultiMenuActions = []
97 91
98 self.sourceMenu = QMenu(self) 92 self.sourceMenu = QMenu(self)
99 if self.__protoc is not None: 93 self.sourceMenu.addAction(
100 self.sourceMenu.addAction( 94 self.tr('Compile protocol'), self.__compileProtocol)
101 self.tr('Compile protocol'), self.__compileProtocol) 95 self.sourceMenu.addAction(
102 self.sourceMenu.addAction( 96 self.tr('Compile all protocols'),
103 self.tr('Compile all protocols'), 97 self.__compileAllProtocols)
104 self.__compileAllProtocols) 98 self.sourceMenu.addSeparator()
99 self.sourceMenu.addAction(
100 self.tr('Compile protocol as grpc'),
101 lambda: self.__compileProtocol(grpc=True))
102 self.sourceMenu.addAction(
103 self.tr('Compile all protocols as grpc'),
104 lambda: self.__compileAllProtocols(grpc=True))
105 self.sourceMenu.addSeparator()
105 self.sourceMenu.addAction(self.tr('Open'), self._openItem) 106 self.sourceMenu.addAction(self.tr('Open'), self._openItem)
106 self.sourceMenu.addSeparator() 107 self.sourceMenu.addSeparator()
107 act = self.sourceMenu.addAction( 108 act = self.sourceMenu.addAction(
108 self.tr('Rename file'), self._renameFile) 109 self.tr('Rename file'), self._renameFile)
109 self.menuActions.append(act) 110 self.menuActions.append(act)
131 self.sourceMenu.addAction(self.tr('Configure...'), self._configure) 132 self.sourceMenu.addAction(self.tr('Configure...'), self._configure)
132 self.sourceMenu.addAction( 133 self.sourceMenu.addAction(
133 self.tr('Configure Protobuf...'), self.__configureProtobuf) 134 self.tr('Configure Protobuf...'), self.__configureProtobuf)
134 135
135 self.menu = QMenu(self) 136 self.menu = QMenu(self)
136 if self.__protoc is not None: 137 self.menu.addAction(
137 self.menu.addAction( 138 self.tr('Compile protocol'), self.__compileProtocol)
138 self.tr('Compile protocol'), self.__compileProtocol) 139 self.menu.addAction(
139 self.menu.addAction( 140 self.tr('Compile all protocols'),
140 self.tr('Compile all protocols'), 141 self.__compileAllProtocols)
141 self.__compileAllProtocols) 142 self.menu.addSeparator()
143 self.menu.addAction(
144 self.tr('Compile protocol as grpc'),
145 lambda: self.__compileProtocol(grpc=True))
146 self.menu.addAction(
147 self.tr('Compile all protocols as grpc'),
148 lambda: self.__compileAllProtocols(grpc=True))
149 self.menu.addSeparator()
142 self.menu.addAction(self.tr('Open'), self._openItem) 150 self.menu.addAction(self.tr('Open'), self._openItem)
143 self.menu.addSeparator() 151 self.menu.addSeparator()
144 self.menu.addAction( 152 self.menu.addAction(
145 self.tr('Add protocols...'), self.__addProtocolFiles) 153 self.tr('Add protocols...'), self.__addProtocolFiles)
146 self.menu.addAction( 154 self.menu.addAction(
155 self.menu.addAction(self.tr('Configure...'), self._configure) 163 self.menu.addAction(self.tr('Configure...'), self._configure)
156 self.menu.addAction( 164 self.menu.addAction(
157 self.tr('Configure Protobuf...'), self.__configureProtobuf) 165 self.tr('Configure Protobuf...'), self.__configureProtobuf)
158 166
159 self.backMenu = QMenu(self) 167 self.backMenu = QMenu(self)
160 if self.__protoc is not None: 168 self.backMenu.addAction(
161 self.backMenu.addAction( 169 self.tr('Compile all protocols'),
162 self.tr('Compile all protocols'), 170 self.__compileAllProtocols)
163 self.__compileAllProtocols) 171 self.backMenu.addSeparator()
164 self.backMenu.addSeparator() 172 self.backMenu.addAction(
173 self.tr('Compile all protocols as grpc'),
174 lambda: self.__compileAllProtocols(grpc=True))
175 self.backMenu.addSeparator()
165 self.backMenu.addAction( 176 self.backMenu.addAction(
166 self.tr('Add protocols...'), self.project.addProtoFiles) 177 self.tr('Add protocols...'), self.project.addProtoFiles)
167 self.backMenu.addAction( 178 self.backMenu.addAction(
168 self.tr('Add protocols directory...'), self.project.addProtoDir) 179 self.tr('Add protocols directory...'), self.project.addProtoDir)
169 self.backMenu.addSeparator() 180 self.backMenu.addSeparator()
177 self.tr('Configure Protobuf...'), self.__configureProtobuf) 188 self.tr('Configure Protobuf...'), self.__configureProtobuf)
178 self.backMenu.setEnabled(False) 189 self.backMenu.setEnabled(False)
179 190
180 # create the menu for multiple selected files 191 # create the menu for multiple selected files
181 self.multiMenu = QMenu(self) 192 self.multiMenu = QMenu(self)
182 if self.__protoc is not None: 193 self.multiMenu.addAction(
183 self.multiMenu.addAction( 194 self.tr('Compile protocols'),
184 self.tr('Compile protocols'), 195 self.__compileSelectedProtocols)
185 self.__compileSelectedProtocols) 196 self.multiMenu.addSeparator()
197 self.multiMenu.addAction(
198 self.tr('Compile protocols as grpc'),
199 lambda: self.__compileSelectedProtocols(grpc=True))
200 self.multiMenu.addSeparator()
186 self.multiMenu.addAction(self.tr('Open'), self._openItem) 201 self.multiMenu.addAction(self.tr('Open'), self._openItem)
187 self.multiMenu.addSeparator() 202 self.multiMenu.addSeparator()
188 act = self.multiMenu.addAction( 203 act = self.multiMenu.addAction(
189 self.tr('Remove from project'), self._removeFile) 204 self.tr('Remove from project'), self._removeFile)
190 self.multiMenuActions.append(act) 205 self.multiMenuActions.append(act)
200 self.multiMenu.addAction(self.tr('Configure...'), self._configure) 215 self.multiMenu.addAction(self.tr('Configure...'), self._configure)
201 self.multiMenu.addAction( 216 self.multiMenu.addAction(
202 self.tr('Configure Protobuf...'), self.__configureProtobuf) 217 self.tr('Configure Protobuf...'), self.__configureProtobuf)
203 218
204 self.dirMenu = QMenu(self) 219 self.dirMenu = QMenu(self)
205 if self.__protoc is not None: 220 self.dirMenu.addAction(
206 self.dirMenu.addAction( 221 self.tr('Compile all protocols'),
207 self.tr('Compile all protocols'), 222 self.__compileAllProtocols)
208 self.__compileAllProtocols) 223 self.dirMenu.addSeparator()
209 self.dirMenu.addSeparator() 224 self.dirMenu.addAction(
225 self.tr('Compile all protocols as grpc'),
226 lambda: self.__compileAllProtocols(grpc=True))
210 act = self.dirMenu.addAction( 227 act = self.dirMenu.addAction(
211 self.tr('Remove from project'), self._removeFile) 228 self.tr('Remove from project'), self._removeFile)
212 self.dirMenuActions.append(act) 229 self.dirMenuActions.append(act)
213 act = self.dirMenu.addAction( 230 act = self.dirMenu.addAction(
214 self.tr('Delete'), self._deleteDirectory) 231 self.tr('Delete'), self._deleteDirectory)
231 self.dirMenu.addAction(self.tr('Configure...'), self._configure) 248 self.dirMenu.addAction(self.tr('Configure...'), self._configure)
232 self.dirMenu.addAction( 249 self.dirMenu.addAction(
233 self.tr('Configure Protobuf...'), self.__configureProtobuf) 250 self.tr('Configure Protobuf...'), self.__configureProtobuf)
234 251
235 self.dirMultiMenu = QMenu(self) 252 self.dirMultiMenu = QMenu(self)
236 if self.__protoc is not None: 253 self.dirMultiMenu.addAction(
237 self.dirMultiMenu.addAction( 254 self.tr('Compile all protocols'),
238 self.tr('Compile all protocols'), 255 self.__compileAllProtocols)
239 self.__compileAllProtocols) 256 self.dirMultiMenu.addSeparator()
240 self.dirMultiMenu.addSeparator() 257 self.dirMultiMenu.addAction(
258 self.tr('Compile all protocols as grpc'),
259 lambda: self.__compileAllProtocols(grpc=True))
241 self.dirMultiMenu.addAction( 260 self.dirMultiMenu.addAction(
242 self.tr('Add protocols...'), self.project.addProtoFiles) 261 self.tr('Add protocols...'), self.project.addProtoFiles)
243 self.dirMultiMenu.addAction( 262 self.dirMultiMenu.addAction(
244 self.tr('Add protocols directory...'), self.project.addProtoDir) 263 self.tr('Add protocols directory...'), self.project.addProtoDir)
245 self.dirMultiMenu.addSeparator() 264 self.dirMultiMenu.addSeparator()
435 454
436 ########################################################################### 455 ###########################################################################
437 ## Methods to handle the various compile commands 456 ## Methods to handle the various compile commands
438 ########################################################################### 457 ###########################################################################
439 458
459 def __getCompilerCommand(self, grpc):
460 """
461 Private method to get the compiler command.
462
463 @param grpc flag indicating to get a grpc command
464 @type bool
465 @return tuple giving the executable and its parameter list
466 @rtype tuple of (str, list of str)
467 """
468 exe = None
469 exeArgs = []
470
471 if grpc:
472 exe = Preferences.getProtobuf("grpcPython")
473 if exe == "":
474 exe = sys.executable
475 exeArgs = ['-m', 'grpc_tools.protoc']
476 else:
477 exe = Preferences.getProtobuf("protoc")
478 if exe == "":
479 exe = Utilities.isWindowsPlatform() and \
480 "protoc.exe" or "protoc"
481 if not Utilities.isinpath(exe):
482 exe = None
483
484 return exe, exeArgs
485
440 def __readStdout(self): 486 def __readStdout(self):
441 """ 487 """
442 Private slot to handle the readyReadStandardOutput signal of the 488 Private slot to handle the readyReadStandardOutput signal of the
443 protoc process. 489 protoc process.
444 """ 490 """
469 s = 'protoc: ' 515 s = 'protoc: '
470 error = str(self.compileProc.readLine(), ioEncoding, 'replace') 516 error = str(self.compileProc.readLine(), ioEncoding, 'replace')
471 s += error 517 s += error
472 self.appendStderr.emit(s) 518 self.appendStderr.emit(s)
473 519
474 def __compileProtocolDone(self, exitCode, exitStatus): 520 def __compileProtoDone(self, exitCode, exitStatus, grpc):
475 """ 521 """
476 Private slot to handle the finished signal of the protoc process. 522 Private slot to handle the finished signal of the protoc process.
477 523
478 @param exitCode exit code of the process (integer) 524 @param exitCode exit code of the process
479 @param exitStatus exit status of the process (QProcess.ExitStatus) 525 @type int
526 @param exitStatus exit status of the process
527 @type QProcess.ExitStatus
528 @param grpc flag indicating to compile as grpc files
529 @type bool
480 """ 530 """
481 self.__compileRunning = False 531 self.__compileRunning = False
482 ui = e5App().getObject("UserInterface") 532 ui = e5App().getObject("UserInterface")
483 if exitStatus == QProcess.NormalExit and exitCode == 0: 533 if exitStatus == QProcess.NormalExit and exitCode == 0:
484 path = os.path.dirname(self.__protoFile) 534 path = os.path.dirname(self.__protoFile)
485 fileList = glob.glob(os.path.join(path, "*_pb2.py")) 535 fileList = glob.glob(os.path.join(path, "*_pb2.py"))
536 if grpc:
537 fileList += glob.glob(os.path.join(path, "*_pb2_grpc.py"))
486 for file in fileList: 538 for file in fileList:
487 self.project.appendFile(file) 539 self.project.appendFile(file)
488 if not self.noDialog and not ui.notificationsEnabled(): 540 if not self.noDialog and not ui.notificationsEnabled():
489 E5MessageBox.information( 541 E5MessageBox.information(
490 self, 542 self,
512 self.tr("Protocol Compilation"), 564 self.tr("Protocol Compilation"),
513 self.tr( 565 self.tr(
514 "The compilation of the protocol file failed.")) 566 "The compilation of the protocol file failed."))
515 self.compileProc = None 567 self.compileProc = None
516 568
517 def __compileProto(self, fn, noDialog=False, progress=None): 569 def __compileProto(self, fn, noDialog=False, progress=None, grpc=False):
518 """ 570 """
519 Private method to compile a .proto file to Python. 571 Private method to compile a .proto file to Python.
520 572
521 @param fn filename of the .proto file to be compiled (string) 573 @param fn filename of the .proto file to be compiled
522 @param noDialog flag indicating silent operations (boolean) 574 @type str
523 @param progress reference to the progress dialog (E5ProgressDialog) 575 @param noDialog flag indicating silent operations
524 @return reference to the compile process (QProcess) 576 @type bool
525 """ 577 @param progress reference to the progress dialog
526 self.compileProc = QProcess() 578 @type E5ProgressDialog
527 args = [] 579 @param grpc flag indicating to compile as grpc files
528 580 @type bool
529 fn = os.path.join(self.project.ppath, fn) 581 @return reference to the compile process
530 self.__protoFile = fn 582 @rtype QProcess
531 583 """
532 srcPath = os.path.dirname(fn) 584 exe, exeArgs = self.__getCompilerCommand(grpc)
533 args.append("--proto_path={0}".format(srcPath)) 585 if exe:
534 args.append("--python_out={0}".format(srcPath)) 586 self.compileProc = QProcess()
535 args.append(fn) 587 args = []
536 588
537 self.compileProc.finished.connect(self.__compileProtocolDone) 589 fn = os.path.join(self.project.ppath, fn)
538 self.compileProc.readyReadStandardOutput.connect(self.__readStdout) 590 self.__protoFile = fn
539 self.compileProc.readyReadStandardError.connect(self.__readStderr) 591
540 592 srcPath = os.path.dirname(fn)
541 self.noDialog = noDialog 593 args.append("--proto_path={0}".format(srcPath))
542 self.compileProc.start(self.__protoc, args) 594 args.append("--python_out={0}".format(srcPath))
543 procStarted = self.compileProc.waitForStarted(5000) 595 if grpc:
544 if procStarted: 596 args.append("--grpc_python_out={0}".format(srcPath))
545 self.__compileRunning = True 597 args.append(fn)
546 return self.compileProc 598
599 self.compileProc.finished.connect(
600 lambda c, s: self.__compileProtoDone(c, s, grpc))
601 self.compileProc.readyReadStandardOutput.connect(self.__readStdout)
602 self.compileProc.readyReadStandardError.connect(self.__readStderr)
603
604 self.noDialog = noDialog
605 self.compileProc.start(exe, exeArgs + args)
606 procStarted = self.compileProc.waitForStarted(5000)
607 if procStarted:
608 self.__compileRunning = True
609 return self.compileProc
610 else:
611 self.__compileRunning = False
612 if progress is not None:
613 progress.cancel()
614 E5MessageBox.critical(
615 self,
616 self.tr('Process Generation Error'),
617 self.tr(
618 '<p>Could not start {0}.<br>'
619 'Ensure that it is in the search path.</p>'
620 ).format(exe))
621 return None
547 else: 622 else:
548 self.__compileRunning = False
549 if progress is not None:
550 progress.cancel()
551 E5MessageBox.critical( 623 E5MessageBox.critical(
552 self, 624 self,
553 self.tr('Process Generation Error'), 625 self.tr('Compiler Invalid'),
554 self.tr( 626 self.tr('The configured compiler is invalid.'))
555 '<p>Could not start {0}.<br>'
556 'Ensure that it is in the search path.</p>'
557 ).format(self.__protoc))
558 return None 627 return None
559 628
560 def __compileProtocol(self): 629 def __compileProtocol(self, grpc=False):
561 """ 630 """
562 Private method to compile a protocol to Python. 631 Private method to compile a protocol to Python.
563 """ 632
564 if self.__protoc is not None: 633 @param grpc flag indicating to compile as grpc files
634 @type bool
635 """
636 if self.__getCompilerCommand(grpc)[0] is not None:
565 itm = self.model().item(self.currentIndex()) 637 itm = self.model().item(self.currentIndex())
566 fn2 = itm.fileName() 638 fn2 = itm.fileName()
567 fn = self.project.getRelativePath(fn2) 639 fn = self.project.getRelativePath(fn2)
568 self.__compileProto(fn) 640 self.__compileProto(fn, grpc=grpc)
569 641
570 def __compileAllProtocols(self): 642 def __compileAllProtocols(self, grpc=False):
571 """ 643 """
572 Private method to compile all protocols to Python. 644 Private method to compile all protocols to Python.
573 """ 645
574 if self.__protoc is not None: 646 @param grpc flag indicating to compile as grpc files
647 @type bool
648 """
649 if self.__getCompilerCommand(grpc)[0] is not None:
575 numProtos = len(self.project.pdata["PROTOCOLS"]) 650 numProtos = len(self.project.pdata["PROTOCOLS"])
576 progress = E5ProgressDialog( 651 progress = E5ProgressDialog(
577 self.tr("Compiling Protocols..."), 652 self.tr("Compiling Protocols..."),
578 self.tr("Abort"), 0, numProtos, 653 self.tr("Abort"), 0, numProtos,
579 self.tr("%v/%m Protocols"), self) 654 self.tr("%v/%m Protocols"), self)
584 659
585 for fn in self.project.pdata["PROTOCOLS"]: 660 for fn in self.project.pdata["PROTOCOLS"]:
586 progress.setValue(i) 661 progress.setValue(i)
587 if progress.wasCanceled(): 662 if progress.wasCanceled():
588 break 663 break
589 proc = self.__compileProto(fn, True, progress) 664 proc = self.__compileProto(fn, True, progress, grpc=grpc)
590 if proc is not None: 665 if proc is not None:
591 while proc.state() == QProcess.Running: 666 while proc.state() == QProcess.Running:
592 QApplication.processEvents() 667 QApplication.processEvents()
593 QThread.msleep(300) 668 QThread.msleep(300)
594 QApplication.processEvents() 669 QApplication.processEvents()
596 break 671 break
597 i += 1 672 i += 1
598 673
599 progress.setValue(numProtos) 674 progress.setValue(numProtos)
600 675
601 def __compileSelectedProtocols(self): 676 def __compileSelectedProtocols(self, grpc=False):
602 """ 677 """
603 Private method to compile selected protocols to Python. 678 Private method to compile selected protocols to Python.
604 """ 679
605 if self.__protoc is not None: 680 @param grpc flag indicating to compile as grpc files
681 @type bool
682 """
683 if self.__getCompilerCommand(grpc)[0] is not None:
606 items = self.getSelectedItems() 684 items = self.getSelectedItems()
607 685
608 files = [self.project.getRelativePath(itm.fileName()) 686 files = [self.project.getRelativePath(itm.fileName())
609 for itm in items] 687 for itm in items]
610 numProtos = len(files) 688 numProtos = len(files)
619 697
620 for fn in files: 698 for fn in files:
621 progress.setValue(i) 699 progress.setValue(i)
622 if progress.wasCanceled(): 700 if progress.wasCanceled():
623 break 701 break
624 proc = self.__compileProto(fn, True, progress) 702 proc = self.__compileProto(fn, True, progress, grpc=grpc)
625 if proc is not None: 703 if proc is not None:
626 while proc.state() == QProcess.Running: 704 while proc.state() == QProcess.Running:
627 QApplication.processEvents() 705 QApplication.processEvents()
628 QThread.msleep(300) 706 QThread.msleep(300)
629 QApplication.processEvents() 707 QApplication.processEvents()

eric ide

mercurial