RefactoringRope/RefactoringClient.py

branch
eric7
changeset 389
4f53795beff0
parent 385
9bbd74b51d88
child 409
65153bf17e8d
--- a/RefactoringRope/RefactoringClient.py	Sat Jun 25 18:06:56 2022 +0200
+++ b/RefactoringRope/RefactoringClient.py	Wed Sep 21 15:30:34 2022 +0200
@@ -11,7 +11,7 @@
 import os
 import contextlib
 
-modulePath = sys.argv[-1]   # it is always the last parameter
+modulePath = sys.argv[-1]  # it is always the last parameter
 sys.path.append(modulePath)
 
 try:
@@ -29,10 +29,11 @@
     """
     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
@@ -41,7 +42,7 @@
         @type str
         """
         super().__init__(host, port)
-        
+
         self.__methodMapping = {
             "AbortAction": self.__abortAction,
             "CloseProject": self.__closeProject,
@@ -58,8 +59,9 @@
             "ApplyChanges": self.__applyChanges,
             "ClearChanges": self.__clearChanges,
             "CalculateRenameChanges": self.__calculateRenameChanges,
-            "CalculateChangeOccurrencesChanges":
-                self.__calculateChangeOccurrencesChanges,
+            "CalculateChangeOccurrencesChanges": (
+                self.__calculateChangeOccurrencesChanges
+            ),
             "CalculateExtractChanges": self.__calculateExtractChanges,
             "RequestInlineType": self.__requestInlineType,
             "CalculateInlineChanges": self.__calculateInlineChanges,
@@ -67,112 +69,109 @@
             "CalculateMoveChanges": self.__calculateMoveChanges,
             "RequestUseFunction": self.__requestUseFunction,
             "CalculateUseFunctionChanges": self.__calculateUseFunctionChanges,
-            "CalculateIntroduceFactoryChanges":
-                self.__calculateIntroduceFactoryChanges,
-            "CalculateIntroduceParameterChanges":
-                self.__calculateIntroduceParameterChanges,
+            "CalculateIntroduceFactoryChanges": self.__calculateIntroduceFactoryChanges,
+            "CalculateIntroduceParameterChanges": (
+                self.__calculateIntroduceParameterChanges
+            ),
             "CalculateImportsChanges": self.__calculateImportsChanges,
             "CalculateRestructureChanges": self.__calculateRestructureChanges,
             "RequestSignature": self.__requestSignature,
             "CalculateSignatureChanges": self.__calculateSignatureChanges,
-            "CalculateInlineArgumentDefaultChanges":
-                self.__calculateInlineArgumentDefaultChanges,
-            "CalculateModuleToPackageChanges":
-                self.__calculateModuleToPackageChanges,
+            "CalculateInlineArgumentDefaultChanges": (
+                self.__calculateInlineArgumentDefaultChanges
+            ),
+            "CalculateModuleToPackageChanges": self.__calculateModuleToPackageChanges,
             "RequestFieldName": self.__requestFieldName,
-            "CalculateEncapsulateFieldChanges":
-                self.__calculateEncapsulateFieldChanges,
-            "CalculateLocalToAttributeChanges":
-                self.__calculateLocalToAttributeChanges,
-            "CalculateMethodObjectChanges":
-                self.__calculateMethodObjectChanges,
+            "CalculateEncapsulateFieldChanges": self.__calculateEncapsulateFieldChanges,
+            "CalculateLocalToAttributeChanges": self.__calculateLocalToAttributeChanges,
+            "CalculateMethodObjectChanges": self.__calculateMethodObjectChanges,
         }
-        
+
         from FileSystemCommands import RefactoringClientFileSystemCommands
+
         self.__fsCommands = RefactoringClientFileSystemCommands(self)
-        
+
         self.__projectpath = projectPath
         self.__project = rope.base.project.Project(
-            self.__projectpath, fscommands=self.__fsCommands)
-        
+            self.__projectpath, fscommands=self.__fsCommands
+        )
+
         self.__progressHandle = None
-        
+
         self.__changes = {}
         # dict storing the retrieved changes for various refactorings
-    
+
     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
         """
         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
         """
         import traceback
+
         tb = traceback.format_tb(sys.exc_info()[2])
         ropeError = str(type(err)).split()[-1]
-        ropeError = ropeError[1:-2].split('.')[-1]
+        ropeError = ropeError[1:-2].split(".")[-1]
         errorDict = {
             "Error": ropeError,
             "ErrorString": str(err),
             "Traceback": tb,
         }
-        if ropeError == 'ModuleSyntaxError':
+        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()
-        ):
+        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 __closeProject(self, params):
         """
         Private slot to validate the project.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
         """
         self.__project.close()
-    
+
     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
@@ -180,8 +179,8 @@
         result = {
             "RopeFolderName": self.__project.ropefolder.real_path,
             "RopeHelpFile": os.path.join(
-                os.path.dirname(__file__), "Documentation", "rope",
-                "overview.rst"),
+                os.path.dirname(__file__), "Documentation", "rope", "overview.rst"
+            ),
             "RopeInfo": rope.INFO,
             "RopeVersion": rope.VERSION,
             "RopeCopyright": rope.COPYRIGHT,
@@ -197,28 +196,29 @@
             with open(
                 os.path.join(os.path.dirname(__file__), "default_config.py"),
                 "r",
-                encoding="utf-8"
+                encoding="utf-8",
             ) as f:
                 result["DefaultConfig"] = f.read()
-        
+
         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)
-    
+            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
@@ -226,40 +226,44 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         occurrences = []
-        
+
         import rope.contrib.findit
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        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)
+                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
+                [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
@@ -268,34 +272,33 @@
         filename = params["FileName"]
         offset = params["Offset"]
         source = params["Source"]
-        
+
         errorDict = {}
         location = None
-        
+
         import rope.contrib.findit
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             location = rope.contrib.findit.find_definition(
-                self.__project, source, offset, resource)
+                self.__project, source, offset, resource
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         result = {
             "Title": title,
         }
         if location is not None:
-            result["Location"] = [
-                location.resource.real_path, location.lineno
-            ]
+            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
@@ -303,82 +306,82 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         occurrences = []
-        
+
         import rope.contrib.findit
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        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)
+                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
+                [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 = {}
-        
+
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
             rope.base.libutils.analyze_modules(
-                self.__project, task_handle=self.__progressHandle)
+                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"]
-        
+
         with contextlib.suppress(Exception):
-            rope.base.libutils.report_change(
-                self.__project, filename, oldSource)
-    
+            rope.base.libutils.report_change(self.__project, filename, oldSource)
+
     def __processHistory(self, params):
         """
         Private method to process the various history related requests.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -389,7 +392,8 @@
             if params["Filename"]:
                 # file history
                 resource = rope.base.libutils.path_to_resource(
-                    self.__project, params["Filename"])
+                    self.__project, params["Filename"]
+                )
                 undoList = []
                 for change in reversed(self.__project.history.undo_list):
                     if resource in change.get_changed_resources():
@@ -402,9 +406,11 @@
                 # project history
                 undoList = list(reversed(self.__project.history.undo_list))
                 redoList = self.__project.history.redo_list
-            
-            result = {"Subcommand": "Histories"}
-            result["Undo"] = []
+
+            result = {
+                "Subcommand": "Histories",
+                "Undo": [],
+            }
             for change in undoList:
                 changes[id(change)] = change
                 result["Undo"].append([str(change), id(change)])
@@ -412,70 +418,68 @@
             for change in redoList:
                 changes[id(change)] = change
                 result["Redo"].append([str(change), id(change)])
-            
+
             self.__changes["History"] = changes
-            
+
             self.sendJson("HistoryResult", result)
-        
+
         elif subcommand == "GetChange":
             result = {
                 "Subcommand": "ChangeDescription",
-                "Description":
-                    self.__changes["History"][params["Id"]].get_description()
+                "Description": self.__changes["History"][
+                    params["Id"]
+                ].get_description(),
             }
-            
+
             self.sendJson("HistoryResult", result)
-        
+
         elif subcommand in ["Undo", "Redo"]:
             change = self.__changes["History"][params["Id"]]
-            self.__progressHandle = ProgressHandle(self, change.description,
-                                                   False)
+            self.__progressHandle = ProgressHandle(self, change.description, False)
             if subcommand == "Undo":
-                self.__project.history.undo(
-                    change, task_handle=self.__progressHandle)
+                self.__project.history.undo(change, task_handle=self.__progressHandle)
             else:
-                self.__project.history.redo(
-                    change, task_handle=self.__progressHandle)
+                self.__project.history.redo(change, task_handle=self.__progressHandle)
             self.__progressHandle.reset()
             self.__progressHandle = None
-            
+
             result = {
                 "Subcommand": subcommand,
                 "ChangedFiles": [
                     res.real_path for res in change.get_changed_resources()
                 ],
             }
-            
+
             self.sendJson("HistoryResult", result)
-        
+
         elif subcommand == "Clear":
             self.__project.history.clear()
-        
+
         elif subcommand == "ClearChanges":
             with contextlib.suppress(KeyError):
                 del self.__changes["History"]
-    
+
     def __clearChanges(self, params):
         """
         Private method to clear the changes cache of a given change group.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
         """
         with contextlib.suppress(KeyError):
             del self.__changes[params["ChangeGroup"]]
-    
+
     def __applyChanges(self, params):
         """
         Private method to apply the changes of a given change group.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
         """
         errorDict = {}
-        
+
         self.__progressHandle = ProgressHandle(self, params["Title"], False)
         try:
             changes = self.__changes[params["ChangeGroup"]]
@@ -485,23 +489,21 @@
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         result = {
             "Subcommand": "ChangesApplied",
             "ChangeGroup": params["ChangeGroup"],
             "Title": params["Title"],
-            "ChangedFiles": [
-                res.real_path for res in changes.get_changed_resources()
-            ],
+            "ChangedFiles": [res.real_path for res in changes.get_changed_resources()],
         }
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __previewChanges(self, params):
         """
         Private method to determine the changes data for a preview.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -512,7 +514,7 @@
         except KeyError:
             changes = None
             description = ""
-        
+
         changesData = []
         if changes is not None:
             for change in changes.changes:
@@ -522,21 +524,21 @@
                 except AttributeError:
                     changeText = None
                 changesData.append([changeTitle, changeText])
-        
+
         result = {
             "Subcommand": "PreviewChanges",
             "ChangeGroup": params["ChangeGroup"],
             "Description": description,
             "Changes": changesData,
         }
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateRenameChanges(self, params):
         """
         Private method to calculate the rename changes based on the parameters
         sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -549,47 +551,47 @@
         newName = params["NewName"]
         renameHierarchy = params["RenameHierarchy"]
         renameInStrings = params["RenameInStrings"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.rename
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
-        
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
+
         resources = [resource] if isLocal else None
-        
+
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
-            renamer = rope.refactor.rename.Rename(
-                self.__project, resource, offset)
+            renamer = rope.refactor.rename.Rename(self.__project, resource, offset)
             changes = renamer.get_changes(
                 newName,
                 resources=resources,
                 in_hierarchy=renameHierarchy,
                 unsure=lambda o: self.__confirmUnsure(o, changeGroup),
                 docs=renameInStrings,
-                task_handle=self.__progressHandle)
+                task_handle=self.__progressHandle,
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __confirmUnsure(self, occurrence, changeGroup):
         """
         Private method to confirm unsure occurrences.
-        
+
         @param occurrence reference to the occurrence object
         @type rope.refactor.occurrences.Occurrence
         @param changeGroup name of the change group
@@ -599,24 +601,27 @@
         """
         filename = occurrence.resource.real_path
         start, end = occurrence.get_primary_range()
-        
-        self.sendJson("Changes", {
-            "Subcommand": "ConfirmUnsure",
-            "ChangeGroup": changeGroup,
-            "FileName": filename,
-            "StartOffset": start,
-            "EndOffset": end,
-        })
-        
+
+        self.sendJson(
+            "Changes",
+            {
+                "Subcommand": "ConfirmUnsure",
+                "ChangeGroup": changeGroup,
+                "FileName": filename,
+                "StartOffset": start,
+                "EndOffset": end,
+            },
+        )
+
         answer = self.poll(waitMethod="ConfirmUnsure")
-        
+
         return answer["Answer"]
-    
+
     def __calculateChangeOccurrencesChanges(self, params):
         """
         Private method to calculate the 'Change Occurrences' changes based on
         the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -629,37 +634,39 @@
         onlyCalls = params["OnlyCalls"]
         reads = params["Reads"]
         writes = params["Writes"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.rename
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             renamer = rope.refactor.rename.ChangeOccurrences(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             changes = renamer.get_changes(
-                newName, only_calls=onlyCalls, reads=reads, writes=writes)
+                newName, only_calls=onlyCalls, reads=reads, writes=writes
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateExtractChanges(self, params):
         """
         Private method to calculate the 'Extract' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -674,43 +681,44 @@
         newName = params["NewName"]
         similar = params["Similar"]
         global_ = params["Global"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.extract
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             if kind not in ("variable", "method"):
                 raise Exception("Invalid extraction kind <{0}>.".format(kind))
             elif kind == "variable":
                 extractor = rope.refactor.extract.ExtractVariable(
-                    self.__project, resource, startOffset, endOffset)
+                    self.__project, resource, startOffset, endOffset
+                )
             elif kind == "method":
                 extractor = rope.refactor.extract.ExtractMethod(
-                    self.__project, resource, startOffset, endOffset)
-            changes = extractor.get_changes(
-                newName, similar=similar, global_=global_)
+                    self.__project, resource, startOffset, endOffset
+                )
+            changes = extractor.get_changes(newName, similar=similar, global_=global_)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __requestInlineType(self, params):
         """
         Private method to determine the 'Inline' changes type based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -719,36 +727,39 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         result = {
             "Subcommand": "InlineType",
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.inline
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             inliner = rope.refactor.inline.create_inline(
-                self.__project, resource, offset)
-            result.update({
-                "Name": inliner.name,
-                "Kind": inliner.get_kind(),
-            })
+                self.__project, resource, offset
+            )
+            result.update(
+                {
+                    "Name": inliner.name,
+                    "Kind": inliner.get_kind(),
+                }
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateInlineChanges(self, params):
         """
         Private method to calculate the 'Inline' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -758,46 +769,50 @@
         filename = params["FileName"]
         offset = params["Offset"]
         kind = params["Kind"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.extract
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
             inliner = rope.refactor.inline.create_inline(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             opts = (
-                {"in_hierarchy": params["Hierarchy"], }
-                if kind == "parameter" else
-                {"remove": params["Remove"],
-                 "only_current": params["OnlyCurrent"], }
+                {
+                    "in_hierarchy": params["Hierarchy"],
+                }
+                if kind == "parameter"
+                else {
+                    "remove": params["Remove"],
+                    "only_current": params["OnlyCurrent"],
+                }
             )
-            changes = inliner.get_changes(
-                task_handle=self.__progressHandle, **opts)
+            changes = inliner.get_changes(task_handle=self.__progressHandle, **opts)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __requestMoveType(self, params):
         """
         Private method to determine the 'Move Method' changes type based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -806,42 +821,45 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         result = {
             "Subcommand": "MoveType",
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.move
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
-            mover = rope.refactor.move.create_move(
-                self.__project, resource, offset)
+            mover = rope.refactor.move.create_move(self.__project, resource, offset)
             if isinstance(mover, rope.refactor.move.MoveGlobal):
-                result.update({
-                    "Kind": "move_global_method",
-                    "Method": "",
-                })
+                result.update(
+                    {
+                        "Kind": "move_global_method",
+                        "Method": "",
+                    }
+                )
             else:
-                result.update({
-                    "Kind": "move_method",
-                    "Method": mover.get_method_name(),
-                })
+                result.update(
+                    {
+                        "Kind": "move_method",
+                        "Method": mover.get_method_name(),
+                    }
+                )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateMoveChanges(self, params):
         """
         Private method to calculate the 'Move ...' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -854,53 +872,52 @@
         newName = params["NewName"]
         attribute = params["Attribute"]
         destination = params["DestinationModule"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.move
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
-            mover = rope.refactor.move.create_move(
-                self.__project, resource, offset)
+            mover = rope.refactor.move.create_move(self.__project, resource, offset)
             if kind == "move_method":
                 changes = mover.get_changes(
-                    attribute, newName, task_handle=self.__progressHandle)
+                    attribute, newName, task_handle=self.__progressHandle
+                )
             else:
                 if kind == "move_global_method":
                     dest = self.__project.get_pycore().find_module(
-                        os.path.splitext(destination)[0])
+                        os.path.splitext(destination)[0]
+                    )
                 else:
                     # move_module
                     if destination.endswith(os.sep):
                         destination = destination[:-1]
-                    dest = self.__project.get_pycore().find_module(
-                        destination)
-                changes = mover.get_changes(
-                    dest, task_handle=self.__progressHandle)
+                    dest = self.__project.get_pycore().find_module(destination)
+                changes = mover.get_changes(dest, task_handle=self.__progressHandle)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __requestUseFunction(self, params):
         """
         Private method to determine the 'Use Function' function name based on
         the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -909,33 +926,34 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         result = {
             "Subcommand": "UseFunctionName",
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.usefunction
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             user = rope.refactor.usefunction.UseFunction(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             result["FunctionName"] = user.get_function_name()
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateUseFunctionChanges(self, params):
         """
         Private method to calculate the 'Use Function' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -944,39 +962,40 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.usefunction
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
             user = rope.refactor.usefunction.UseFunction(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             changes = user.get_changes(task_handle=self.__progressHandle)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateIntroduceFactoryChanges(self, params):
         """
         Private method to calculate the 'Introduce Factory' changes based on
         the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -987,43 +1006,44 @@
         offset = params["Offset"]
         factoryName = params["Name"]
         globalFactory = params["GlobalFactory"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.introduce_factory
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
-            introducer = (
-                rope.refactor.introduce_factory.IntroduceFactoryRefactoring(
-                    self.__project, resource, offset)
+            introducer = rope.refactor.introduce_factory.IntroduceFactoryRefactoring(
+                self.__project, resource, offset
             )
             changes = introducer.get_changes(
-                factoryName, global_factory=globalFactory,
-                task_handle=self.__progressHandle)
+                factoryName,
+                global_factory=globalFactory,
+                task_handle=self.__progressHandle,
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateIntroduceParameterChanges(self, params):
         """
         Private method to calculate the 'Introduce Parameter' changes based on
         the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1033,36 +1053,37 @@
         filename = params["FileName"]
         offset = params["Offset"]
         parameterName = params["Name"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.introduce_parameter
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             introducer = rope.refactor.introduce_parameter.IntroduceParameter(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             changes = introducer.get_changes(parameterName)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateImportsChanges(self, params):
         """
         Private method to calculate the 'Import' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1072,15 +1093,16 @@
         filename = params["FileName"]
         offset = params["Offset"]
         methodName = params["MethodName"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         from rope.refactor.importutils import ImportOrganizer
+
         method = {
             "organize_imports": ImportOrganizer.organize_imports,
             "expand_star_imports": ImportOrganizer.expand_star_imports,
@@ -1089,34 +1111,36 @@
             "handle_long_imports": ImportOrganizer.handle_long_imports,
         }[methodName]
         importOrganizer = ImportOrganizer(self.__project)
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             changes = method(importOrganizer, resource, offset=offset)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         # send the change description first
         description = changes.description if changes else ""
-        self.sendJson("Changes", {
-            "ChangeGroup": changeGroup,
-            "Title": title,
-            "Subcommand": "ChangeDescription",
-            "Description": description,
-        })
-        
+        self.sendJson(
+            "Changes",
+            {
+                "ChangeGroup": changeGroup,
+                "Title": title,
+                "Subcommand": "ChangeDescription",
+                "Description": description,
+            },
+        )
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateRestructureChanges(self, params):
         """
         Private method to calculate the 'Restructure' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1127,39 +1151,40 @@
         goal = params["Goal"]
         args = params["Args"]
         imports = params["Imports"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.restructure
+
         self.__project.validate(self.__project.root)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
             restructuring = rope.refactor.restructure.Restructure(
-                self.__project, pattern, goal, args=args, imports=imports)
-            changes = restructuring.get_changes(
-                task_handle=self.__progressHandle)
+                self.__project, pattern, goal, args=args, imports=imports
+            )
+            changes = restructuring.get_changes(task_handle=self.__progressHandle)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __requestSignature(self, params):
         """
         Private method to calculate the 'Signature' based on the parameters
         sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1168,33 +1193,34 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         result = {
             "Subcommand": "Signature",
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.change_signature
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             changer = rope.refactor.change_signature.ChangeSignature(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             result["DefinitionInfo"] = changer.get_args()
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateSignatureChanges(self, params):
         """
         Private method to calculate the 'Signature' changes based on the
         parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1208,16 +1234,17 @@
         newOrdering = params["Ordering"]
         autodef = params["AutoDef"]
         doHierarchy = params["Hierarchy"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         changers = []
         import rope.refactor.change_signature
+
         # removals
         for index in removals:
             remover = rope.refactor.change_signature.ArgumentRemover(index)
@@ -1225,38 +1252,42 @@
         # additions
         for index, name, default, value in additions:
             adder = rope.refactor.change_signature.ArgumentAdder(
-                index, name, default, value)
+                index, name, default, value
+            )
             changers.append(adder)
         # new ordering
-        changers.append(rope.refactor.change_signature.ArgumentReorderer(
-            newOrdering, autodef=autodef))
-        
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+        changers.append(
+            rope.refactor.change_signature.ArgumentReorderer(
+                newOrdering, autodef=autodef
+            )
+        )
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
             changer = rope.refactor.change_signature.ChangeSignature(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             changes = changer.get_changes(
-                changers, in_hierarchy=doHierarchy,
-                task_handle=self.__progressHandle)
+                changers, in_hierarchy=doHierarchy, task_handle=self.__progressHandle
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateInlineArgumentDefaultChanges(self, params):
         """
         Private method to calculate the 'Inline Argument Default' changes
         based on the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1266,41 +1297,41 @@
         filename = params["FileName"]
         offset = params["Offset"]
         argumentIndex = params["Index"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
             changer = rope.refactor.change_signature.ChangeSignature(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             inliner = rope.refactor.change_signature.ArgumentDefaultInliner(
-                argumentIndex)
-            changes = changer.get_changes(
-                [inliner], task_handle=self.__progressHandle)
+                argumentIndex
+            )
+            changes = changer.get_changes([inliner], task_handle=self.__progressHandle)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateModuleToPackageChanges(self, params):
         """
         Private method to calculate the 'Module to Package' changes
         based on the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1308,44 +1339,48 @@
         changeGroup = params["ChangeGroup"]
         title = params["Title"]
         filename = params["FileName"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.topackage
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             changes = rope.refactor.topackage.ModuleToPackage(
-                self.__project, resource).get_changes()
+                self.__project, resource
+            ).get_changes()
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         # send the change description first
         description = changes.description if changes else ""
-        self.sendJson("Changes", {
-            "ChangeGroup": changeGroup,
-            "Title": title,
-            "Subcommand": "ChangeDescription",
-            "Description": description,
-        })
-        
+        self.sendJson(
+            "Changes",
+            {
+                "ChangeGroup": changeGroup,
+                "Title": title,
+                "Subcommand": "ChangeDescription",
+                "Description": description,
+            },
+        )
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __requestFieldName(self, params):
         """
         Private method to calculate the 'Field Name' based on the parameters
         sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1354,35 +1389,34 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         result = {
             "Subcommand": "FieldName",
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.encapsulate_field
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
-            encapsulateField = (
-                rope.refactor.encapsulate_field.EncapsulateField(
-                    self.__project, resource, offset)
+            encapsulateField = rope.refactor.encapsulate_field.EncapsulateField(
+                self.__project, resource, offset
             )
             result["Name"] = encapsulateField.get_field_name()
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateEncapsulateFieldChanges(self, params):
         """
         Private method to calculate the 'Encapsulate Field' changes based on
         the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1393,43 +1427,42 @@
         offset = params["Offset"]
         getter = params["Getter"]
         setter = params["Setter"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.encapsulate_field
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         self.__progressHandle = ProgressHandle(self, title, True)
         try:
-            encapsulateField = (
-                rope.refactor.encapsulate_field.EncapsulateField(
-                    self.__project, resource, offset)
+            encapsulateField = rope.refactor.encapsulate_field.EncapsulateField(
+                self.__project, resource, offset
             )
             changes = encapsulateField.get_changes(
-                getter=getter, setter=setter,
-                task_handle=self.__progressHandle)
+                getter=getter, setter=setter, task_handle=self.__progressHandle
+            )
         except Exception as err:
             errorDict = self.__handleRopeError(err)
         self.__progressHandle.reset()
         self.__progressHandle = None
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateLocalToAttributeChanges(self, params):
         """
         Private method to calculate the 'Local Variabe to Attribute' changes
         based on the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1438,44 +1471,48 @@
         title = params["Title"]
         filename = params["FileName"]
         offset = params["Offset"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.localtofield
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             changes = rope.refactor.localtofield.LocalToField(
-                self.__project, resource, offset).get_changes()
+                self.__project, resource, offset
+            ).get_changes()
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         # send the change description first
         description = changes.description if changes else ""
-        self.sendJson("Changes", {
-            "ChangeGroup": changeGroup,
-            "Title": title,
-            "Subcommand": "ChangeDescription",
-            "Description": description,
-        })
-        
+        self.sendJson(
+            "Changes",
+            {
+                "ChangeGroup": changeGroup,
+                "Title": title,
+                "Subcommand": "ChangeDescription",
+                "Description": description,
+            },
+        )
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
-    
+
     def __calculateMethodObjectChanges(self, params):
         """
         Private method to calculate the 'Method to Method Object' changes
         based on the parameters sent by the server.
-        
+
         @param params dictionary containing the method parameters sent by
             the server
         @type dict
@@ -1485,40 +1522,42 @@
         filename = params["FileName"]
         offset = params["Offset"]
         name = params["Name"]
-        
+
         errorDict = {}
         changes = None
         result = {
             "ChangeGroup": changeGroup,
             "Title": title,
         }
-        
+
         import rope.refactor.method_object
-        resource = rope.base.libutils.path_to_resource(
-            self.__project, filename)
+
+        resource = rope.base.libutils.path_to_resource(self.__project, filename)
         try:
             converter = rope.refactor.method_object.MethodObject(
-                self.__project, resource, offset)
+                self.__project, resource, offset
+            )
             changes = converter.get_changes(name)
         except Exception as err:
             errorDict = self.__handleRopeError(err)
-        
+
         self.__changes[changeGroup] = changes
-        
+
         result["Subcommand"] = "ChangesCalculated"
         result.update(errorDict)
-        
+
         self.sendJson("Changes", result)
 
 
-if __name__ == '__main__':
+if __name__ == "__main__":
     if len(sys.argv) != 5:
-        print('Host, port, project path and module path parameters are'
-              ' missing. Abort.')
+        print(
+            "Host, port, project path and module path parameters are" " missing. Abort."
+        )
         sys.exit(1)
-    
+
     host, port, projectPath = sys.argv[1:-1]
-    
+
     # Create a Qt6 application object in order to allow the processing of
     # modules containing Qt stuff.
     try:
@@ -1527,11 +1566,11 @@
         QCoreApplication = None
     if QCoreApplication is not None:
         app = QCoreApplication([])
-    
+
     client = RefactoringClient(host, int(port), projectPath)
     # Start the main loop
     client.run()
-    
+
     sys.exit(0)
 
 #

eric ide

mercurial