RefactoringRope/RefactoringClient.py

Sat, 16 Sep 2017 16:40:50 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 16 Sep 2017 16:40:50 +0200
branch
server_client_variant
changeset 166
6fc202183b3b
parent 165
ea41742015af
child 167
3c8e875d0326
permissions
-rw-r--r--

Implemented the distributed 'query' methods.

# -*- 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')
    str = unicode   # __IGNORE_WARNING__
sys.path.insert(0, path)

import rope
import rope.base.project
import rope.base.libutils

from JsonClient import JsonClient


class RefactoringClient(JsonClient):
    """
    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
        """
        super(RefactoringClient, self).__init__(host, port)
        
        self.__methodMapping = {
            "AbortAction": self.__abortAction,
            "Validate": self.__validate,
            "QueryReferences": self.__queryReferences,
            "QueryDefinition": self.__queryDefinition,
            "QueryImplementations": self.__queryImplementations,
            "GetConfig": self.__getConfig,
            "ConfigChanged": self.__configChanged,
            "PerformSoa": self.__performSOA,
            "ReportChanged": self.__reportChanged,
        }
        
        from FileSystemCommands import RefactoringClientFileSystemCommands
        self.__fsCommands = RefactoringClientFileSystemCommands(self)
        
        self.__projectpath = projectPath
        self.__project = rope.base.project.Project(
            self.__projectpath, fscommands=self.__fsCommands)
        
        self.__progressHandle = None
    
    def handleCall(self, method, params):
        """
        Public method to handle a method call from the server.
        
        @param method requested method name
        @type str
        @param params dictionary with method specific parameters
        @type dict
        """
##        if "filename" in params and sys.version_info[0] == 2:
##            params["filename"] = params["filename"].encode(
##                sys.getfilesystemencoding())
        
        self.__methodMapping[method](params)
    
    def __handleRopeError(self, err):
        """
        Private method to process a rope error.
        
        @param err rope exception object
        @type Exception
        @return dictionary containing the error information
        @rtype dict
        """
        ropeError = str(type(err)).split()[-1]
        ropeError = ropeError[1:-2].split('.')[-1]
        errorDict = {
            "Error": ropeError,
            "ErrorString": str(err),
        }
        if ropeError == 'ModuleSyntaxError':
            errorDict["ErrorFile"] = err.filename
            errorDict["ErrorLine"] = err.lineno
        
        return errorDict
    
    def __abortAction(self, params):
        """
        Private method to abort the current action.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        if self.__progressHandle is not None and \
           not self.__progressHandle.is_stopped():
            self.__progressHandle.stop()
    
    def __validate(self, params):
        """
        Private slot to validate the project.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        self.__project.validate(self.__project.root)
    
    def __getConfig(self, params):
        """
        Private method to send some configuration data to the server.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        result = {
            "RopeFolderName": self.__project.ropefolder.real_path,
            "DefaultConfig": self.__project._default_config(),
        }
        if sys.version_info[0] >= 3:
            directory = 'rope_py3'
        else:
            directory = 'rope_py2'
        result["RopeHelpFile"] = os.path.join(
            os.path.dirname(__file__), directory,
            "rope", "docs", "overview.txt")
        
        self.sendJson("Config", result)
    
    def __configChanged(self, params):
        """
        Private method to handle a change of the configuration file.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        self.__project.close()
        self.__project = rope.base.project.Project(
            self.__projectpath, fscommands=self.__fsCommands)
    
    def __queryReferences(self, params):
        """
        Private method to handle the Find References action.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        title = params["Title"]
        filename = params["FileName"]
        offset = params["Offset"]
        
        errorDict = {}
        occurrences = []
        
        import rope.contrib.findit
        from ProgressHandle import ProgressHandle
        resource = rope.base.libutils.path_to_resource(
            self.__project, filename)
        self.__progressHandle = ProgressHandle(self, title, True)
        try:
            occurrences = rope.contrib.findit.find_occurrences(
                self.__project, resource, offset,
                unsure=True, in_hierarchy=True,
                task_handle=self.__progressHandle)
        except Exception as err:
            errorDict = self.__handleRopeError(err)
        self.__progressHandle.reset()
        self.__progressHandle = None
        
        result = {
            "Title": title,
            "EntriesCount": len(occurrences),
            "Entries": [
                [occurrence.resource.real_path, occurrence.lineno,
                 occurrence.unsure] for occurrence in occurrences
            ],
        }
        result.update(errorDict)
        
        self.sendJson("QueryReferencesResult", result)
    
    def __queryDefinition(self, params):
        """
        Private method to handle the Find Definition action.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        title = params["Title"]
        filename = params["FileName"]
        offset = params["Offset"]
        source = params["Source"]
        subcommand = params["Subcommand"]
        
        errorDict = {}
        location = None
        
        import rope.contrib.findit
        resource = rope.base.libutils.path_to_resource(
            self.__project, filename)
        try:
            location = rope.contrib.findit.find_definition(
                self.__project, source, offset, resource)
        except Exception as err:
            errorDict = self.__handleRopeError(err)
        
        result = {
            "Title": title,
            "Subcommand": subcommand,
        }
        if location is not None:
            result["Location"] = [
                location.resource.real_path, location.lineno
            ]
        result.update(errorDict)
        
        self.sendJson("QueryDefinitionResult", result)
    
    def __queryImplementations(self, params):
        """
        Private method to handle the Find Implementations action.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        title = params["Title"]
        filename = params["FileName"]
        offset = params["Offset"]
        
        errorDict = {}
        occurrences = []
        
        import rope.contrib.findit
        from ProgressHandle import ProgressHandle
        resource = rope.base.libutils.path_to_resource(
            self.__project, filename)
        self.__progressHandle = ProgressHandle(self, title, True)
        try:
            occurrences = rope.contrib.findit.find_implementations(
                self.__project, resource, offset,
                task_handle=self.__progressHandle)
        except Exception as err:
            errorDict = self.__handleRopeError(err)
        self.__progressHandle.reset()
        self.__progressHandle = None
        
        result = {
            "Title": title,
            "EntriesCount": len(occurrences),
            "Entries": [
                [occurrence.resource.real_path, occurrence.lineno,
                 occurrence.unsure] for occurrence in occurrences
            ],
        }
        result.update(errorDict)
        
        self.sendJson("QueryImplementationsResult", result)
    
    def __performSOA(self, params):
        """
        Private method to perform SOA on all modules.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        title = params["Title"]
        
        errorDict = {}
        
        from ProgressHandle import ProgressHandle
        self.__progressHandle = ProgressHandle(self, title, True)
        try:
            rope.base.libutils.analyze_modules(
                self.__project, task_handle=self.__progressHandle)
        except Exception as err:
            errorDict = self.__handleRopeError(err)
        self.__progressHandle.reset()
        self.__progressHandle = None
        
        result = {
            "Title": title,
        }
        result.update(errorDict)
        
        self.sendJson("SoaFinished", result)
    
    def __reportChanged(self, params):
        """
        Private method to register some changed sources.
        
        @param params dictionary containing the method parameters sent by
            the server
        @type dict
        """
        filename = params["FileName"]
        oldSource = params["OldSource"]
        
        try:
            rope.base.libutils.report_change(
                self.__project, filename, oldSource)
        except Exception:
            # simply ignore it
            pass

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()
    
    sys.exit(0)

#
# eflag: noqa = M801

eric ide

mercurial