RefactoringRope/Refactoring.py

branch
server_client_variant
changeset 163
6a9e7b37a18b
parent 162
55eaaed9d590
child 164
121d426d4ed7
equal deleted inserted replaced
162:55eaaed9d590 163:6a9e7b37a18b
22 22
23 import rope 23 import rope
24 import rope.base.libutils 24 import rope.base.libutils
25 import rope.base.exceptions 25 import rope.base.exceptions
26 26
27 from PyQt5.QtCore import pyqtSlot, QProcess
28 from PyQt5.QtWidgets import QMenu, QApplication, QDialog, QAction 27 from PyQt5.QtWidgets import QMenu, QApplication, QDialog, QAction
29 from PyQt5.Qsci import QsciScintilla 28 from PyQt5.Qsci import QsciScintilla
30 from PyQt5.QtNetwork import QTcpServer, QHostAddress
31 29
32 from E5Gui.E5Application import e5App 30 from E5Gui.E5Application import e5App
33 from E5Gui import E5MessageBox 31 from E5Gui import E5MessageBox
34 from E5Gui.E5Action import E5Action 32 from E5Gui.E5Action import E5Action
33
34 from .JsonServer import JsonServer
35 35
36 import Utilities 36 import Utilities
37 import Preferences 37 import Preferences
38 38
39 39
40 # TODO: rename this (and the module) to RefactoringServer once done 40 # TODO: rename this (and the module) to RefactoringServer once done
41 class Refactoring(QTcpServer): 41 class Refactoring(JsonServer):
42 """ 42 """
43 Class implementing the refactoring interface to rope. 43 Class implementing the refactoring interface to rope.
44 """ 44 """
45 def __init__(self, plugin, parent=None): 45 def __init__(self, plugin, parent=None):
46 """ 46 """
59 self.__projectopen = False 59 self.__projectopen = False
60 60
61 self.__mainMenu = None 61 self.__mainMenu = None
62 self.__helpDialog = None 62 self.__helpDialog = None
63 63
64 self.__refactoringProcess = None
65 self.__refactoringConnection = None
66
67 # Rope objects
68 # TODO: move this to RefactoringClient
69 ## self.__project = None
70
71 from FileSystemCommands import E5FileSystemCommands 64 from FileSystemCommands import E5FileSystemCommands
72 self.__fsCommands = E5FileSystemCommands(self.__e5project) 65 self.__fsCommands = E5FileSystemCommands(self.__e5project)
73
74 # setup the network interface
75 networkInterface = Preferences.getDebugger("NetworkInterface")
76 if networkInterface == "all" or '.' in networkInterface:
77 # IPv4
78 self.__hostAddress = '127.0.0.1'
79 else:
80 # IPv6
81 self.__hostAddress = '::1'
82 self.listen(QHostAddress(self.__hostAddress))
83
84 self.newConnection.connect(self.__handleNewConnection)
85
86 port = self.serverPort()
87 ## Note: Need the port if started external in debugger:
88 print('Refactoring server listening on: {0:d}'.format(port))
89 # __IGNORE_WARNING__
90 66
91 def initActions(self): 67 def initActions(self):
92 """ 68 """
93 Public method to define the refactoring actions. 69 Public method to define the refactoring actions.
94 """ 70 """
2240 elif self.__projectLanguage == "Python3": 2216 elif self.__projectLanguage == "Python3":
2241 interpreter = Preferences.getDebugger("Python3Interpreter") 2217 interpreter = Preferences.getDebugger("Python3Interpreter")
2242 else: 2218 else:
2243 interpreter = "" 2219 interpreter = ""
2244 if interpreter: 2220 if interpreter:
2245 process = self.__startRefactoringClient(interpreter) 2221 ok = self.__startRefactoringClient(interpreter)
2246 if process is None: 2222 if not ok:
2247 self.__ui.appendToStderr(self.tr( 2223 self.__ui.appendToStderr(self.tr(
2248 "Project language '{0}' is not supported because" 2224 "Project language '{0}' is not supported because"
2249 " the configured interpreter could not be started." 2225 " the configured interpreter could not be started."
2250 " Refactoring is disabled." 2226 " Refactoring is disabled."
2251 ).format(self.__projectLanguage)) 2227 ).format(self.__projectLanguage))
2252 else: 2228 else:
2253 self.__refactoringProcess = process
2254 ## import rope.base.project
2255 ## self.__project = rope.base.project.Project(
2256 ## self.__projectpath, fscommands=self.__fsCommands)
2257 for act in self.actions: 2229 for act in self.actions:
2258 act.setEnabled(True) 2230 act.setEnabled(True)
2259 else: 2231 else:
2260 self.__ui.appendToStderr(self.tr( 2232 self.__ui.appendToStderr(self.tr(
2261 "Project language '{0}' is not supported because no" 2233 "Project language '{0}' is not supported because no"
2268 Public slot to handle the projectClosed signal. 2240 Public slot to handle the projectClosed signal.
2269 """ 2241 """
2270 for act in self.actions: 2242 for act in self.actions:
2271 act.setEnabled(False) 2243 act.setEnabled(False)
2272 2244
2273 self.__stopRefactoringClient() 2245 self.stopClient()
2274 ## if self.__project is not None:
2275 ## self.__project.close()
2276 ## self.__project = None
2277 2246
2278 self.__projectopen = False 2247 self.__projectopen = False
2279 self.__projectpath = '' 2248 self.__projectpath = ''
2280 self.__projectLanguage = "" 2249 self.__projectLanguage = ""
2281 2250
2357 2326
2358 ####################################################################### 2327 #######################################################################
2359 ## Methods below handle the network connection 2328 ## Methods below handle the network connection
2360 ####################################################################### 2329 #######################################################################
2361 2330
2362 @pyqtSlot() 2331 def handleCall(self, method, params):
2363 def __handleNewConnection(self): 2332 """
2364 """ 2333 Public method to handle a method call from the client.
2365 Private slot for new incomming connections from the refactoring client. 2334
2366 """ 2335 Note: This is an empty implementation that must be overridden in
2367 if self.__refactoringConnection is not None: 2336 derived classes.
2368 self.__refactoringConnection.close() 2337
2369 self.__refactoringConnection = None 2338 @param method requested method name
2370
2371 connection = self.nextPendingConnection()
2372 if not connection.isValid():
2373 return
2374
2375 self.__refactoringConnection = connection
2376 connection.readyRead.connect(self.__receiveJson)
2377 connection.disconnected.connect(self.__handleDisconnect)
2378
2379 self.__sendJson("ping", {})
2380
2381 @pyqtSlot()
2382 def __handleDisconnect(self):
2383 """
2384 Private slot handling a disconnect of the refactoring client.
2385 """
2386 if self.__refactoringConnection is not None:
2387 self.__refactoringConnection.close()
2388
2389 self.__refactoringConnection = None
2390
2391 @pyqtSlot()
2392 def __receiveJson(self):
2393 """
2394 Private slot handling received data from the refactoring client.
2395 """
2396 while self.__refactoringConnection and \
2397 self.__refactoringConnection.canReadLine():
2398 data = self.__refactoringConnection.readLine()
2399 jsonLine = bytes(data).decode()
2400
2401 print("Refactoring Server: ", jsonLine) ##debug
2402
2403 self.__processJson(jsonLine)
2404 continue
2405
2406 def __processJson(self, jsonStr):
2407 """
2408 Private method to process the JSON serialized client data.
2409
2410 @param jsonStr string containing the data structure received
2411 from the refactoring client
2412 @type str 2339 @type str
2413 """ 2340 @param params dictionary with method specific parameters
2414 import json 2341 @type dict
2415 2342 """
2416 try:
2417 clientDict = json.loads(jsonStr.strip())
2418 except (TypeError, ValueError) as err:
2419 E5MessageBox.critical(
2420 None,
2421 self.tr("Refactoring Protocol Error"),
2422 self.tr("""<p>The response received from the refactoring"""
2423 """ client could not be decoded. Please report"""
2424 """ this issue with the received data to the"""
2425 """ eric bugs email address.</p>"""
2426 """<p>Error: {0}</p>"""
2427 """<p>Data:<br/>{0}</p>""").format(
2428 str(err), Utilities.html_encode(jsonStr.strip())),
2429 E5MessageBox.StandardButtons(
2430 E5MessageBox.Ok))
2431 return
2432
2433 method = clientDict["method"]
2434 params = clientDict["params"]
2435
2436 print("Method:", method)
2437 print("Params:", params)
2438
2439 if method == "pong": 2343 if method == "pong":
2440 pass 2344 pass
2441 2345
2442 elif method == "ClientException": 2346 elif method == "ClientException":
2443 if params["ExceptionType"] == "ProtocolError": 2347 if params["ExceptionType"] == "ProtocolError":
2473 E5MessageBox.Ok)) 2377 E5MessageBox.Ok))
2474 2378
2475 elif method == "FileSystemCommand": 2379 elif method == "FileSystemCommand":
2476 self.__fsCommands.processFileSystemCommand(params) 2380 self.__fsCommands.processFileSystemCommand(params)
2477 2381
2478 def __sendJson(self, command, params):
2479 """
2480 Private method to send a single refactoring command to the client.
2481
2482 @param command command name to be sent
2483 @type str
2484 @param params dictionary of named parameters for the command
2485 @type dict
2486 """
2487 import json
2488
2489 commandDict = {
2490 "jsonrpc": "2.0",
2491 "method": command,
2492 "params": params,
2493 }
2494 cmd = json.dumps(commandDict) + '\n'
2495 if self.__refactoringConnection is not None:
2496 self.__refactoringConnection.write(
2497 cmd.encode('utf8', 'backslashreplace'))
2498
2499 def __startRefactoringClient(self, interpreter): 2382 def __startRefactoringClient(self, interpreter):
2500 """ 2383 """
2501 Private method to start the refactoring client. 2384 Private method to start the refactoring client.
2502 2385
2503 @param interpreter interpreter to be used for the refactoring client 2386 @param interpreter interpreter to be used for the refactoring client
2504 @type str 2387 @type str
2505 @return reference to the refactoring client process 2388 @return flag indicating a successful client start
2506 """ 2389 @rtype bool
2507 if interpreter == "" or not Utilities.isinpath(interpreter): 2390 """
2508 return None
2509
2510 client = os.path.join(os.path.dirname(__file__), 2391 client = os.path.join(os.path.dirname(__file__),
2511 "RefactoringClient.py") 2392 "RefactoringClient.py")
2512 proc = QProcess() 2393 ok = self.startClient(interpreter, client, [self.__projectpath])
2513 proc.setProcessChannelMode(QProcess.ForwardedChannels) 2394 return ok
2514 args = [client, self.__hostAddress, str(self.serverPort()),
2515 self.__projectpath]
2516 proc.start(interpreter, args)
2517 if not proc.waitForStarted(10000):
2518 proc = None
2519
2520 return proc
2521
2522 def __stopRefactoringClient(self):
2523 """
2524 Private method to stop the refactoring client process.
2525 """
2526 self.__refactoringProcess.close()
2527 self.__refactoringProcess = None
2528
2529 #
2530 # eflag: noqa = M801

eric ide

mercurial