RefactoringRope/RefactoringClient.py

branch
server_client_variant
changeset 161
f5d6fb1a009b
child 162
55eaaed9d590
equal deleted inserted replaced
160:989cd767992b 161:f5d6fb1a009b
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing the refactoring client interface to rope.
8 """
9
10 from __future__ import unicode_literals
11
12 import sys
13 import os
14
15 sys.path.insert(0, os.path.dirname(__file__))
16 if sys.version_info[0] >= 3:
17 path = os.path.join(os.path.dirname(__file__), 'rope_py3')
18 else:
19 path = os.path.join(os.path.dirname(__file__), 'rope_py2')
20 sys.path.insert(0, path)
21
22 try:
23 bytes = unicode
24 import StringIO as io # __IGNORE_EXCEPTION__
25 except NameError:
26 import io # __IGNORE_WARNING__
27
28 import socket
29 import select
30 import traceback
31 import time
32 import json
33
34 import rope.base.project
35
36
37 class RefactoringClient(object):
38 """
39 Class implementing the refactoring client interface to rope.
40 """
41 def __init__(self, host, port, projectPath):
42 """
43 Constructor
44
45 @param host ip address the background service is listening
46 @type str
47 @param port port of the background service
48 @type int
49 @param projectPath path to the project
50 @type str
51 """
52 self.__connection = socket.create_connection((host, port))
53
54 self.__projectpath = projectPath
55 self.__project = rope.base.project.Project(
56 self.__projectpath)#, fscommands=self.__fsCommands)
57
58 def __processJson(self, jsonStr):
59 """
60 Public method to handle a command serialized as a JSON string.
61
62 @param jsonStr string containing the command received from the IDE
63 @type str
64 """
65 try:
66 commandDict = json.loads(jsonStr.strip())
67 except (TypeError, ValueError) as err:
68 self.__sendJson("ClientException", {
69 "ExceptionType": "ProtocolError",
70 "ExceptionValue": str(err),
71 "ProtocolData": jsonStr.strip(),
72 })
73 return
74
75 method = commandDict["method"]
76 params = commandDict["params"]
77 if "filename" in params and sys.version_info[0] == 2:
78 params["filename"] = params["filename"].encode(
79 sys.getfilesystemencoding())
80
81 if method == "ping":
82 self.__sendJson("pong", {})
83
84 def __sendJson(self, command, params):
85 """
86 Private method to send a single refactoring command to the client.
87
88 @param command command name to be sent
89 @type str
90 @param params dictionary of named parameters for the command
91 @type dict
92 """
93 import json
94
95 commandDict = {
96 "jsonrpc": "2.0",
97 "method": command,
98 "params": params,
99 }
100 cmd = json.dumps(commandDict) + '\n'
101 self.__connection.sendall(cmd.encode('utf8', 'backslashreplace'))
102
103 def __receiveJson(self):
104 """
105 Private method to receive a JSON encode command and data from the
106 server.
107 """
108 line = self.__connection.recv(1024 * 1024, socket.MSG_PEEK) # 1M buffer
109
110 eol = line.find(b'\n')
111
112 if eol >= 0:
113 size = eol + 1
114
115 # Now we know how big the line is, read it for real.
116 line = self.__connection.recv(size).decode(
117 'utf8', 'backslashreplace')
118 self.__processJson(line)
119
120 def run(self):
121 """
122 Public method implementing the main loop of the client.
123 """
124 try:
125 while True:
126 try:
127 rrdy, wrdy, xrdy = select.select(
128 [self.__connection], [self.__connection], [])
129 except (select.error, KeyboardInterrupt, socket.error):
130 # just carry on
131 continue
132
133 if self.__connection in rrdy:
134 self.__receiveJson()
135 ##
136 ## if self.__connection in wrdy:
137 ## self.__connection.flush()
138
139 except Exception:
140 exctype, excval, exctb = sys.exc_info()
141 tbinfofile = io.StringIO()
142 traceback.print_tb(exctb, None, tbinfofile)
143 tbinfofile.seek(0)
144 tbinfo = tbinfofile.read()
145 del exctb
146 self.__sendJson("ClientException", {
147 "ExceptionType": str(exctype),
148 "ExceptionValue": str(excval),
149 "Traceback": tbinfo,
150 })
151
152 # Give time to process latest response on server side
153 time.sleep(0.5)
154 self.__connection.shutdown(socket.SHUT_RDWR)
155 self.__connection.close()
156
157 if __name__ == '__main__':
158 if len(sys.argv) != 4:
159 print('Host, port and project path parameters are missing. Abort.')
160 sys.exit(1)
161
162 host, port, projectPath = sys.argv[1:]
163 client = RefactoringClient(host, int(port), projectPath)
164 # Start the main loop
165 client.run()
166
167 #
168 # eflag: noqa = M801

eric ide

mercurial