RefactoringRope/RefactoringClient.py

Mon, 11 Sep 2017 19:15:44 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 11 Sep 2017 19:15:44 +0200
branch
server_client_variant
changeset 161
f5d6fb1a009b
child 162
55eaaed9d590
permissions
-rw-r--r--

Added the client file.

# -*- coding: utf-8 -*-

# Copyright (c) 2017 Detlev Offenbach <detlev@die-offenbachs.de>
#

"""
Module implementing the refactoring client interface to rope.
"""

from __future__ import unicode_literals

import sys
import os

sys.path.insert(0, os.path.dirname(__file__))
if sys.version_info[0] >= 3:
    path = os.path.join(os.path.dirname(__file__), 'rope_py3')
else:
    path = os.path.join(os.path.dirname(__file__), 'rope_py2')
sys.path.insert(0, path)

try:
    bytes = unicode
    import StringIO as io   # __IGNORE_EXCEPTION__
except NameError:
    import io       # __IGNORE_WARNING__

import socket
import select
import traceback
import time
import json

import rope.base.project


class RefactoringClient(object):
    """
    Class implementing the refactoring client interface to rope.
    """
    def __init__(self, host, port, projectPath):
        """
        Constructor
        
        @param host ip address the background service is listening
        @type str
        @param port port of the background service
        @type int
        @param projectPath path to the project
        @type str
        """
        self.__connection = socket.create_connection((host, port))
        
        self.__projectpath = projectPath
        self.__project = rope.base.project.Project(
            self.__projectpath)#, fscommands=self.__fsCommands)
    
    def __processJson(self, jsonStr):
        """
        Public method to handle a command serialized as a JSON string.
        
        @param jsonStr string containing the command received from the IDE
        @type str
        """
        try:
            commandDict = json.loads(jsonStr.strip())
        except (TypeError, ValueError) as err:
            self.__sendJson("ClientException", {
                "ExceptionType": "ProtocolError",
                "ExceptionValue": str(err),
                "ProtocolData": jsonStr.strip(),
            })
            return
        
        method = commandDict["method"]
        params = commandDict["params"]
        if "filename" in params and sys.version_info[0] == 2:
            params["filename"] = params["filename"].encode(
                sys.getfilesystemencoding())
        
        if method == "ping":
            self.__sendJson("pong", {})
    
    def __sendJson(self, command, params):
        """
        Private method to send a single refactoring command to the client.
        
        @param command command name to be sent
        @type str
        @param params dictionary of named parameters for the command
        @type dict
        """
        import json
        
        commandDict = {
            "jsonrpc": "2.0",
            "method": command,
            "params": params,
        }
        cmd = json.dumps(commandDict) + '\n'
        self.__connection.sendall(cmd.encode('utf8', 'backslashreplace'))
    
    def __receiveJson(self):
        """
        Private method to receive a JSON encode command and data from the
        server.
        """
        line = self.__connection.recv(1024 * 1024, socket.MSG_PEEK) # 1M buffer

        eol = line.find(b'\n')

        if eol >= 0:
            size = eol + 1

            # Now we know how big the line is, read it for real.
            line = self.__connection.recv(size).decode(
                'utf8', 'backslashreplace')
            self.__processJson(line)
    
    def run(self):
        """
        Public method implementing the main loop of the client.
        """
        try:
            while True:
                try:
                    rrdy, wrdy, xrdy = select.select(
                        [self.__connection], [self.__connection], [])
                except (select.error, KeyboardInterrupt, socket.error):
                    # just carry on
                    continue
                
                if self.__connection in rrdy:
                    self.__receiveJson()
##                
##                if self.__connection in wrdy:
##                    self.__connection.flush()
            
        except Exception:
            exctype, excval, exctb = sys.exc_info()
            tbinfofile = io.StringIO()
            traceback.print_tb(exctb, None, tbinfofile)
            tbinfofile.seek(0)
            tbinfo = tbinfofile.read()
            del exctb
            self.__sendJson("ClientException", {
                "ExceptionType": str(exctype),
                "ExceptionValue": str(excval),
                "Traceback": tbinfo,
            })

        # Give time to process latest response on server side
        time.sleep(0.5)
        self.__connection.shutdown(socket.SHUT_RDWR)
        self.__connection.close()

if __name__ == '__main__':
    if len(sys.argv) != 4:
        print('Host, port and project path parameters are missing. Abort.')
        sys.exit(1)
    
    host, port, projectPath = sys.argv[1:]
    client = RefactoringClient(host, int(port), projectPath)
    # Start the main loop
    client.run()

#
# eflag: noqa = M801

eric ide

mercurial