Пример #1
0
        def getRopeProject(self, fileName=""):
            " Provides existed or creates a new rope project "
            if self.project.isLoaded():
                return self.project.getRopeProject()

            # There is no current project so create a temporary one.
            # Two cases: the buffer has been saved
            #            not saved buffer
            if os.path.isabs(fileName):
                dirName = os.path.dirname(fileName)
            else:
                # Unsaved buffer, make an assumption that
                # it is in home directory
                dirName = str(QDir.homePath())

            prefs = copy.deepcopy(ropePreferences)

            # Exclude nested dirs as it could take too long
            # Get only dir names and do not get those dirs
            # where __init__.py[3] are present
            subdirsToExclude = getSubdirs(dirName, True, True)

            if "ignored_resources" in prefs:
                prefs["ignored_resources"] += subdirsToExclude
            else:
                prefs["ignored_resources"] = subdirsToExclude

            project = RopeProject(dirName, None, None, **prefs)
            project.validate(project.root)
            return project
Пример #2
0
class RopeComplete(object):
	def __init__(self, project_path, source_code, resource_path, code_point):
		self.project = Project(project_path)
		self.project.pycore._init_python_files()
		
		self.resource = self.project.get_resource(resource_path)
		self.source_code = source_code
		self.code_point = code_point

	def __del__(self):
		self.project.close()

	def get_proposals(self):
		ret = []
		proposals = codeassist.code_assist(self.project, self.source_code, self.code_point, resource=self.resource, maxfixes=10)
		proposals = codeassist.sorted_proposals(proposals)

		if V(ROPE_VERSION) <= V('0.9.2'):
			for proposal in proposals:
				ret.append(new_completion_item(name=proposal.name, scope=proposal.kind, type=proposal.type))
		else:
			for proposal in proposals:
				ret.append(new_completion_item(name=proposal.name, scope=proposal.scope, type=proposal.type))

		return ret

	def get_calltip(self):
		calltip = codeassist.get_doc(self.project, self.source_code, self.code_point, resource=self.resource, maxfixes=10)
		return calltip
Пример #3
0
        def getRopeProject( self, fileName = "" ):
            " Provides existed or creates a new rope project "
            if self.project.isLoaded():
                return self.project.getRopeProject()

            # There is no current project so create a temporary one.
            # Two cases: the buffer has been saved
            #            not saved buffer
            if os.path.isabs( fileName ):
                dirName = os.path.dirname( fileName )
            else:
                # Unsaved buffer, make an assumption that
                # it is in home directory
                dirName = str( QDir.homePath() )

            prefs = copy.deepcopy( ropePreferences )

            # Exclude nested dirs as it could take too long
            # Get only dir names and do not get those dirs
            # where __init__.py[3] are present
            subdirsToExclude = getSubdirs( dirName, True, True )

            if "ignored_resources" in prefs:
                prefs[ "ignored_resources" ] += subdirsToExclude
            else:
                prefs[ "ignored_resources" ] = subdirsToExclude

            project = RopeProject( dirName, None, None, **prefs )
            project.validate( project.root )
            return project
Пример #4
0
class FileRefactorer:

    def __init__(self):
        pass

    def runRenaming(self):
        self.proj.do(self.change)

    def setProjectFolder(self, folderName):
        self.proj = Project(folderName)
        [f.name for f in self.proj.get_files()]

    def setFileToRename_originalName(self, originalName: str):
        self.fileToRename = self.proj.get_file(originalName)

    def setFileToRename_destinationName(self, wantedResultName: str):
        self.destinationName = wantedResultName
        try:
            self.change = Rename(
                self.proj,
                self.fileToRename
            ).get_changes(wantedResultName)
            # )._rename_module(wantedResultName)
        except FileNotFoundError as err:
            print("\n+++There is no file in given name or path to change its name or path.\n")
            print(err)
        except Exception as err:
            print("\n+++Error while searching file which you wanted to be renamed.\n")
            print(err)

    def reverseRenaming(self):
        pass
Пример #5
0
def main(config_file=None):
    """ """

    if not config_file:
        print "You need to provide a valid config file"
        sys.exit(1)

    config = Config(config_file)
    print "Tying the rope..."
    myproject = Project(config.buildout_dir+'/src', python_path=sys.path)
    handle.add_observer(update_progress)

    # analyze_modules(myproject, task_handle=handle)


    print "Done."

    print "Going to hurricane:" + PATH

    os.chdir(PATH)


    from thread import start_new_thread
    start_new_thread(temp_tornado_thread, ())

    httpd = PloneIDEServer(config, PloneIDEHandler, myproject, handle)

    try:
        httpd.run()
    except KeyboardInterrupt:
        print "Closing the project..."
        myproject.close()
        httpd.stop()
Пример #6
0
    def static_analysis(self, event):
        path    = self.get_root_path()
        project = Project(path)
        mod     = path_to_resource(project, self.area.filename)

        libutils.analyze_module(project, mod)
        project.close()
Пример #7
0
    def __init__(self, project_path, source_code, resource_path, code_point):
        self.project = Project(project_path)
        self.project.pycore._init_python_files()

        self.resource = self.project.get_resource(resource_path)
        self.source_code = source_code
        self.code_point = code_point
Пример #8
0
def _generate_wheel_file(
    pipeline_name: str,
    destination: Path,
    source_paths: Tuple[_SourcePathType, ...],
    version: str,
    metadata: ProjectMetadata,
    alias: str = None,
) -> None:
    package_name = alias or pipeline_name
    package_source, tests_source, conf_source = source_paths

    with tempfile.TemporaryDirectory() as temp_dir:
        temp_dir_path = Path(temp_dir).resolve()

        project = Project(temp_dir_path)  # project where to do refactoring
        _refactor_code_for_package(  # type: ignore
            project, package_source, tests_source, alias, metadata
        )
        project.close()

        # Copy & "refactor" config
        _, _, conf_target = _get_package_artifacts(temp_dir_path, package_name)
        _sync_path_list(conf_source, conf_target)  # type: ignore
        if conf_target.is_dir() and alias:
            _rename_files(conf_target, pipeline_name, alias)

        # Build a setup.py on the fly
        try:
            install_requires = _make_install_requires(
                package_source / "requirements.txt"  # type: ignore
            )
        except Exception as exc:
            click.secho("FAILED", fg="red")
            cls = exc.__class__
            raise KedroCliError(f"{cls.__module__}.{cls.__qualname__}: {exc}") from exc

        config_files = [str(file) for file in conf_target.rglob("*") if file.is_file()]
        setup_file = _generate_setup_file(
            package_name, version, install_requires, temp_dir_path, config_files
        )

        package_file = destination / _get_wheel_name(name=package_name, version=version)
        if package_file.is_file():
            click.secho(
                f"Package file {package_file} will be overwritten!", fg="yellow"
            )

        # python setup.py bdist_wheel --dist-dir <destination>
        call(
            [
                sys.executable,
                str(setup_file.resolve()),
                "bdist_wheel",
                "--dist-dir",
                str(destination),
            ],
            cwd=temp_dir,
        )
Пример #9
0
    def __init__(self, root_uri, lang_server=None):
        self._root_uri = root_uri
        self._root_uri_scheme = uris.urlparse(self._root_uri)[0]
        self._root_path = uris.to_fs_path(self._root_uri)
        self._docs = {}
        self._lang_server = lang_server

        # Whilst incubating, keep private
        self.__rope = Project(self._root_path)
        self.__rope.prefs.set('extension_modules', self.PRELOADED_MODULES)
Пример #10
0
 def test_source_folders_preference(self):
     testutils.create_package(self.project, 'pkg1')
     testutils.create_package(self.project, 'pkg1.src2')
     lost = testutils.create_module(self.project, 'pkg1.src2.lost')
     self.assertEqual(self.project.find_module('lost'), None)
     self.project.close()
     from rope.base.project import Project
     self.project = Project(self.project.address,
                            source_folders=['pkg1/src2'])
     self.assertEqual(self.project.find_module('lost'), lost)
Пример #11
0
def inline(inline_fns, dirname, filename):
    project = Project(dirname)
    resource = project.get_resource(filename)
    for inline_fn in inline_fns:
        try:  # FIXME: temporarily handling not implemented error
            changes = create_inline(
                project, resource,
                resource.read().index(inline_fn)).get_changes(remove=True)
            project.do(changes)
        except Exception as e:
            pass
Пример #12
0
def main():
    prj = Project(os.path.realpath("../shuup/core/models"))
    rst = Restructure(prj, "_(${str})", "")
    rst.template = LanguageTwist("./shuup_fi_to_en.po")

    twist_set = rst.get_changes()

    for chg in twist_set.changes:
        print(chg.get_description())

    prj.do(twist_set)
Пример #13
0
def main():
    prj = Project(os.path.realpath("../shuup/core/models"))
    rst = Restructure(prj, "_(${str})", "")
    rst.template = LanguageTwist("./shuup_fi_to_en.po")

    twist_set = rst.get_changes()

    for chg in twist_set.changes:
        print(chg.get_description())  # noqa

    prj.do(twist_set)
Пример #14
0
 def _on_current_project_changed(self, path):
     """
     Changes the active rope project when the current project changed in
     the IDE.
     :param path: Path of the new project.
     """
     self._main_project.close()
     self._main_project = Project(path,
                                  ropefolder=api.project.FOLDER,
                                  fscommands=FileSystemCommands())
     self._main_project.validate()
Пример #15
0
    def _rope_project_builder(self, rope_config):
        from rope.base.project import Project

        # TODO: we could keep track of dirty files and validate only those
        if self.__rope is None or self.__rope_config != rope_config:
            rope_folder = rope_config.get('ropeFolder')
            self.__rope = Project(self._root_path, ropefolder=rope_folder)
            self.__rope.prefs.set('extension_modules', self.PRELOADED_MODULES)
            self.__rope.prefs.set('ignore_syntax_errors', True)
            self.__rope.prefs.set('ignore_bad_imports', True)
        self.__rope.validate()
        return self.__rope
Пример #16
0
def main():
    from rope.base.project import Project
    from rope.base import libutils
    from rope.refactor.rename import Rename
    from rope.base.exceptions import RopeError

    path = editor.get_path()
    selection = editor.get_selection()

    if not path or not selection:
        console.hud_alert('Not a Python file', 'error')
        return

    tab.save()

    project = None
    try:
        project = Project(os.path.dirname(path), ropefolder=None)
        resource = libutils.path_to_resource(project, path)
        if not libutils.is_python_file(project, resource):
            console.hud_alert('Not a Python file', 'error')
            return

        renamer = Rename(project, resource, selection[0])
        old_name = renamer.get_old_name()

        if not old_name:
            console.hud_alert('Unable to get identifier name', 'error')
            return

        new_name = _ask_for_new_name(old_name)

        change_set = renamer.get_changes(new_name,
                                         docs=True,
                                         resources=[resource])
        if not change_set:
            console.hud_alert('No changes required')
            return

        if refactoring.ask_if_apply_change_set(change_set):
            refactoring.apply_change_set(change_set, path, selection)
            console.hud_alert('Identifier renamed')

    except RopeError as e:
        console.hud_alert(str(e), 'error')

    except KeyboardInterrupt:
        pass

    finally:
        if project:
            project.close()
Пример #17
0
    def _rope_project_builder(self, rope_config):
        # pylint: disable=import-outside-toplevel
        from rope.base.project import Project

        # TODO: we could keep track of dirty files and validate only those
        if self.__rope is None or self.__rope_config != rope_config:
            rope_folder = rope_config.get('ropeFolder')
            self.__rope = Project(self._root_path, ropefolder=rope_folder)
            self.__rope.prefs.set('extension_modules',
                                  rope_config.get('extensionModules', []))
            self.__rope.prefs.set('ignore_syntax_errors', True)
            self.__rope.prefs.set('ignore_bad_imports', True)
        self.__rope.validate()
        return self.__rope
Пример #18
0
 def test_loading_config_dot_py(self):
     self.project = testutils.sample_project(ropefolder='.ropeproject')
     config = self.project.get_file('.ropeproject/config.py')
     if not config.exists():
         config.create()
     config.write('def set_prefs(prefs):\n'
                  '    prefs["ignored_resources"] = ["myfile.txt"]\n'
                  'def project_opened(project):\n'
                  '    project.root.create_file("loaded")\n')
     self.project.close()
     self.project = Project(self.project.address, ropefolder='.ropeproject')
     self.assertTrue(self.project.get_file('loaded').exists())
     myfile = self.project.get_file('myfile.txt')
     self.assertTrue(self.project.is_ignored(myfile))
Пример #19
0
def _rename_package(project: Project, old_name: str, new_name: str) -> None:
    """
    Rename a Python package, refactoring relevant imports along the way,
    as well as references in comments.

    Args:
        project: rope.base.Project holding the scope of the refactoring.
        old_name: Old module name. Can be a fully qualified module path,
            e.g. "package.pipelines.pipeline" or "package/pipelines/pipeline",
            relative to the `project` root.
        new_name: New module name. Can't be a fully qualified module path.
    """
    folder = project.get_folder(old_name)
    change = Rename(project, folder).get_changes(new_name, docs=True)
    project.do(change)
Пример #20
0
 def test_failure_when_project_root_exists_and_is_a_file(self):
     try:
         project_root = 'sampleproject2'
         open(project_root, 'w').close()
         project = Project(project_root)
     finally:
         testutils.remove_recursively(project_root)
Пример #21
0
    def test_failure_when_project_root_exists_and_is_a_file(self):
        project_root = 'sampleproject2'
        open(project_root, 'w').close()
        with self.assertRaises(RopeError):
            Project(project_root)

        testutils.remove_recursively(project_root)
Пример #22
0
	def __init__(self, project_path, source_code, resource_path, code_point):
		self.project = Project(project_path)
		self.project.pycore._init_python_files()
		
		self.resource = self.project.get_resource(resource_path)
		self.source_code = source_code
		self.code_point = code_point
Пример #23
0
 def test_making_root_folder_if_it_does_not_exist(self):
     project = Project('sampleproject2')
     try:
         self.assertTrue(os.path.exists('sampleproject2') and
                         os.path.isdir('sampleproject2'))
     finally:
         testutils.remove_project(project)
Пример #24
0
 def _open_module(self):
     name, status = QtWidgets.QInputDialog.getText(self.main_window,
                                                   _('Open module'),
                                                   _('Python module:'))
     if status:
         project = Project(api.project.get_current_project(),
                           ropefolder=api.project.FOLDER,
                           fscommands=FileSystemCommands())
         try:
             mod = project.pycore.get_module(name)
         except ModuleNotFoundError:
             mod = None
         if mod:
             resource = mod.get_resource()
             if resource:
                 path = resource.real_path
                 if not os.path.isfile(path):
                     path = os.path.join(path, '__init__.py')
                 if os.path.exists(path):
                     api.editor.open_file(path)
                     return
         QtWidgets.QMessageBox.information(
             self.main_window, _('Module not found'),
             _('Cannot open %r, module not found or not editable...') %
             name)
Пример #25
0
class Agent(object):
    def __init__(self, target_file, dry_run):
        self.project = Project(os.getcwd())
        self.target_file = target_file
        self.dry_run = dry_run
        self.commands = []

    @property
    def resource(self):
        return File(self.project, self.target_file)

    def add_command_class(self, command_class):
        self.commands.append(command_class)

    def do(self):
        commands = [
            command_class(self.project, self.target_file, self.dry_run)
            for command_class in self.commands
        ]
        changesets = filter(
            lambda x: x is not None,
            [
                command.get_changeset()
                for command in commands
            ]
        )

        # merge changesets
        def merge_changesets(aggregated_changeset, next_changeset):
            for change in next_changeset.changes:
                aggregated_changeset.add_change(change)
            aggregated_changeset.description += next_changeset.description
            return aggregated_changeset

        new_changeset = reduce(
            merge_changesets,
            changesets,
            ChangeSet('')
        )

        if not new_changeset.changes:
            return

        if self.dry_run:
            print new_changeset.get_description()
        else:
            self.project.do(new_changeset)
Пример #26
0
 def _get_other_projects(path_only=False):
     """
     Gets the list of secondary projects (all except current).
     """
     projects = []
     current = api.project.get_current_project()
     for path in api.project.get_projects():
         if path == current:
             continue
         if not path_only:
             prj = Project(path, ropefolder=api.project.FOLDER,
                           fscommands=FileSystemCommands())
             prj.validate()
         else:
             prj = path
         projects.append(prj)
     return projects
Пример #27
0
 def test_loading_config_dot_py(self):
     self.project = testutils.sample_project(ropefolder=".ropeproject")
     config = self.project.get_file(".ropeproject/config.py")
     if not config.exists():
         config.create()
     config.write(
         dedent("""\
             def set_prefs(prefs):
                 prefs["ignored_resources"] = ["myfile.txt"]
             def project_opened(project):
                 project.root.create_file("loaded")
         """))
     self.project.close()
     self.project = Project(self.project.address, ropefolder=".ropeproject")
     self.assertTrue(self.project.get_file("loaded").exists())
     myfile = self.project.get_file("myfile.txt")
     self.assertTrue(self.project.is_ignored(myfile))
Пример #28
0
 def __init__(self, project_root, filename):
     self.project_root = project_root
     if ROPE_AVAILABLE:
         self.project = Project(project_root, ropefolder=None)
         self.resource = path_to_resource(self.project, filename)
     else:
         self.project = None
         self.resource = FakeResource(filename)
Пример #29
0
 def test_failure_when_project_root_exists_and_is_a_file(self):
     project_root = "sampleproject2"
     try:
         open(project_root, "w").close()
         with self.assertRaises(RopeError):
             Project(project_root)
     finally:
         testutils.remove_recursively(project_root)
Пример #30
0
    def _create_single_file_project(self, path):
        folder = os.path.dirname(path)
        ignored_res = os.listdir(folder)
        ignored_res.remove(os.path.basename(path))

        project = Project(
            folder, ropefolder=None,
            ignored_resources=ignored_res, fscommands=None)
        return project
Пример #31
0
 def __init__(self, project_root, filename):
     self.project_root = project_root
     if not ROPE_AVAILABLE:
         raise Fault('rope not installed, cannot refactor code.', code=400)
     if not os.path.exists(project_root):
         raise Fault("cannot do refactoring without a local project root",
                     code=400)
     self.project = Project(project_root, ropefolder=None)
     self.resource = path_to_resource(self.project, filename)
Пример #32
0
 def _get_other_projects(path_only=False):
     """
     Gets the list of secondary projects (all except current).
     """
     projects = []
     current = api.project.get_current_project()
     for path in api.project.get_projects():
         if path == current:
             continue
         if not path_only:
             prj = Project(path,
                           ropefolder=api.project.FOLDER,
                           fscommands=FileSystemCommands())
             prj.validate()
         else:
             prj = path
         projects.append(prj)
     return projects
Пример #33
0
 def activate(self):
     self._preview_dock = None
     self._occurrences_dock = None
     self._occurrences_results = None
     self._review_widget = None
     api.signals.connect_slot(api.signals.CURRENT_PROJECT_CHANGED,
                              self._on_current_project_changed)
     api.signals.connect_slot(api.signals.EDITOR_CREATED,
                              self._on_editor_created)
     api.signals.connect_slot(api.signals.CURRENT_EDITOR_CHANGED,
                              self._update_edit_actions_state)
     path = api.project.get_current_project()
     self._main_project = Project(path,
                                  ropefolder=api.project.FOLDER,
                                  fscommands=FileSystemCommands())
     self._main_project.validate()
     api.signals.connect_slot(api.signals.DOCUMENT_SAVED,
                              self._on_document_saved)
Пример #34
0
 def __init__(self, project_root, filename):
     self.project_root = project_root
     if ROPE_AVAILABLE:
         self.project = Project(project_root)
         self.resource = path_to_resource(self.project, filename)
     else:
         self.project = None
         with open(filename) as f:
             self.resource = StringIO(f.read())
Пример #35
0
def _move_package(project: Project, source: str, target: str) -> None:
    """
    Move a Python package, refactoring relevant imports along the way.
    A target of empty string means moving to the root of the `project`.

    Args:
        project: rope.base.Project holding the scope of the refactoring.
        source: Name of the Python package to be moved. Can be a fully
            qualified module path relative to the `project` root, e.g.
            "package.pipelines.pipeline" or "package/pipelines/pipeline".
        target: Destination of the Python package to be moved. Can be a fully
            qualified module path relative to the `project` root, e.g.
            "package.pipelines.pipeline" or "package/pipelines/pipeline".
    """
    src_folder = project.get_module(source).get_resource()
    target_folder = project.get_module(target).get_resource()
    change = MoveModule(project, src_folder).get_changes(dest=target_folder)
    project.do(change)
Пример #36
0
 def __init__(self, project_path=None, module_path=None):
     """ initialize using project path and optional sub module path to limit rename scope """
     if project_path:
         self.project = Project(project_path)
     self.module_path = module_path
     self.words = set()
     self.files = []
     self.namemap = {}
     self.classname_regex = re.compile('class\s+(?P<name>[a-zA-Z0-9_]+)')
     self.methodname_regex = re.compile('def\s+(?P<name>[a-zA-Z0-9_]+)')
def test_rope_completion():
    # Over 'i' in os.path.isabs(...)
    com_position = {'line': 1, 'character': 15}
    rope = Project(LOCATION)
    rope.prefs.set('extension_modules', get_preferred_submodules())
    doc = Document(DOC_URI, DOC, rope=rope)
    items = pyls_rope_completions(doc, com_position)

    assert len(items) > 0
    assert items[0]['label'] == 'isabs'
Пример #38
0
def main():
    from rope.base.project import Project
    from rope.base import libutils
    from rope.refactor.importutils import ImportOrganizer
    from rope.base.exceptions import RopeError

    path = editor.get_path()
    selection = editor.get_selection()

    if not path or not selection:
        console.hud_alert('Not a Python file', 'error')
        return

    tab.save()

    project = None
    try:
        project = Project(os.path.dirname(path), ropefolder=None)
        resource = libutils.path_to_resource(project, path)
        if not libutils.is_python_file(project, resource):
            console.hud_alert('Not a Python file', 'error')
            return

        organizer = ImportOrganizer(project)
        change_set = organizer.organize_imports(resource)

        if not change_set:
            console.hud_alert('No changes required')
            return

        if refactoring.ask_if_apply_change_set(change_set):
            refactoring.apply_change_set(change_set, path, selection)
            console.hud_alert('Imports organized')

    except RopeError as e:
        console.hud_alert(str(e), 'error')

    except KeyboardInterrupt:
        pass

    finally:
        if project:
            project.close()
Пример #39
0
 def test_source_folders_preference(self):
     testutils.create_package(self.project, 'pkg1')
     testutils.create_package(self.project, 'pkg1.src2')
     lost = testutils.create_module(self.project, 'pkg1.src2.lost')
     self.assertEqual(self.project.find_module('lost'), None)
     self.project.close()
     from rope.base.project import Project
     self.project = Project(self.project.address,
                            source_folders=['pkg1/src2'])
     self.assertEqual(self.project.find_module('lost'), lost)
Пример #40
0
 def _on_current_project_changed(self, path):
     """
     Changes the active rope project when the current project changed in
     the IDE.
     :param path: Path of the new project.
     """
     self._main_project.close()
     self._main_project = Project(path, ropefolder=api.project.FOLDER,
                                  fscommands=FileSystemCommands())
     self._main_project.validate()
Пример #41
0
    def complete(self):
        if TM_PROJECT_DIRECTORY is None:
            return ''
        #from rope.contrib import autoimport
        project = Project(TM_PROJECT_DIRECTORY)
        #autoimport = autoimport.AutoImport(project)
        resource = project.get_resource(TM_FILEPATH.replace(TM_PROJECT_DIRECTORY, '')[1:])
        #project.validate(self.project_path)
        caret_index = self.source.find(TM_CURRENT_LINE) + TM_LINE_INDEX
        try:
            proposals = codeassist.code_assist(project, self.source, caret_index, resource)
        except:
            ass = PythonCodeAssist(project)
            proposals = ass.assist(self.source, caret_index, resource)
        try:
            if len(proposals) == 0:
                return ''
        except:
            return ''
        if len(proposals) == 1:
            selection = proposals[0].name
        else:
            proposals = codeassist.sorted_proposals(proposals)
            #autoimport.generate_cache()
            #autoimport.generate_modules_cache(modules)
            #project.pycore.analyze_module(resource)
            names = [proposal.name for proposal in proposals]
            #if self.starting.strip() and '.' not in self.expression:
            #        import_assists = self.autoimport.import_assist(self.starting)
            #        names.extend(x[0] + ' : ' + x[1] for x in import_assists)

            #plist = "{ menuItems=(%s);}"
            selection = dialog.menu(names)
            if selection is None:
                return ''
        if TM_CURRENT_WORD is None:
            return selection
        else:
            return selection.replace(TM_CURRENT_WORD, '')
Пример #42
0
def main():
    # TODO: Determine if this is necessary. Can we still provide basic completion in a 'standalone' file?
    if textmate.PROJECT_DIRECTORY is None:
        textmate.exit_show_tool_tip('No completions.')

    source = sys.stdin.read()

    #from rope.contrib import autoimport
    project = Project(textmate.PROJECT_DIRECTORY)
    #autoimport = autoimport.AutoImport(project)
    resource = project.get_resource(textmate.FILEPATH.replace(textmate.PROJECT_DIRECTORY, '')[1:])
    #project.validate(self.project_path)
    caret_index = source.find(textmate.CURRENT_LINE) + textmate.LINE_INDEX

    current_word = textmate.current_word(r"[a-zA-Z_]*", 'both')

    proposals = codeassist.code_assist(project, source, caret_index, resource)
    
    try:
        if len(proposals) == 0:
            raise 'no proposals found'
    except:
        textmate.exit_show_tool_tip("No completions.")
    
    if len(proposals) == 1:
        textmate.exit_insert_text(proposals[0].name.replace(current_word, '', 1))
    else:
        proposals = codeassist.sorted_proposals(proposals)
        #autoimport.generate_cache()
        #autoimport.generate_modules_cache(modules)
        #project.pycore.analyze_module(resource)
        names = [proposal.name for proposal in proposals]
        #if self.starting.strip() and '.' not in self.expression:
        #        import_assists = self.autoimport.import_assist(self.starting)
        #        names.extend(x[0] + ' : ' + x[1] for x in import_assists)

        #plist = "{ menuItems=(%s);}"
        ui.complete(names, {'initial_filter': current_word, 'extra_chars': "_"})
Пример #43
0
 def test_loading_config_dot_py(self):
     self.project = testutils.sample_project(ropefolder='.ropeproject')
     config = self.project.get_file('.ropeproject/config.py')
     if not config.exists():
         config.create()
     config.write('def set_prefs(prefs):\n'
                  '    prefs["ignored_resources"] = ["myfile.txt"]\n'
                  'def project_opened(project):\n'
                  '    project.root.create_file("loaded")\n')
     self.project.close()
     self.project = Project(self.project.address, ropefolder='.ropeproject')
     self.assertTrue(self.project.get_file('loaded').exists())
     myfile = self.project.get_file('myfile.txt')
     self.assertTrue(self.project.is_ignored(myfile))
Пример #44
0
 def activate(self):
     self._preview_dock = None
     self._occurrences_dock = None
     self._occurrences_results = None
     self._review_widget = None
     api.signals.connect_slot(api.signals.CURRENT_PROJECT_CHANGED,
                              self._on_current_project_changed)
     api.signals.connect_slot(api.signals.EDITOR_CREATED,
                              self._on_editor_created)
     api.signals.connect_slot(api.signals.CURRENT_EDITOR_CHANGED,
                              self._update_edit_actions_state)
     path = api.project.get_current_project()
     self._main_project = Project(path, ropefolder=api.project.FOLDER,
                                  fscommands=FileSystemCommands())
     self._main_project.validate()
     api.signals.connect_slot(api.signals.DOCUMENT_SAVED,
                              self._on_document_saved)
Пример #45
0
    def __createRopeProject( self ):
        " Creates a rope library project "
        if self.__ropeProject is not None:
            self.__ropeProject.close()
            self.__ropeProject = None
            self.__ropeSourceDirs = []

        # Deal with import dirs and preferences first
        self.__ropeSourceDirs = self.__getImportDirsForRope()
        prefs = copy.deepcopy( ropePreferences )
        if len( self.__ropeSourceDirs ) != 0:
            prefs[ "source_folders" ] = self.__ropeSourceDirs

        # Rope folder is default here, so it will be created
        self.__ropeProject = RopeProject( self.getProjectDir(),
                                          **prefs )
        self.__ropeProject.validate( self.__ropeProject.root )
        return
Пример #46
0
        option_arg = arg
    elif opt in ('-p', '--project'):
        project_arg = arg
    elif opt == '-s':
        source_code_arg = arg
    elif opt == '-r':
        res_arg = arg
    elif opt == '-f':
        offset_arg = arg

option = option_arg;
projectpath = project_arg
if projectpath.startswith("file://"):
	projectpath = projectpath.replace("file://", "")

proj = Project(projectpath)
proj.pycore._init_python_files()

input = open(source_code_arg, 'r')
source_code = input.read()
respath = relpath(projectpath, res_arg)
res = proj.get_resource(respath)

position = int(offset_arg)

try:
	if option == "autocomplete":
		proposals = codeassist.code_assist(proj, source_code, position, resource=res, maxfixes=10)
		proposals = codeassist.sorted_proposals(proposals)

		for proposal in proposals:
Пример #47
0
def find_usages(_, main_project, other_projects, file_path, offset):
    """
    Find usages of symbol under cursor.
    """
    try:
        occurrences = []
        if other_projects:
            for path in [main_project] + other_projects:
                prj = Project(path, ropefolder=api.project.FOLDER,
                              fscommands=FileSystemCommands())
                prj.validate()
                mod = libutils.path_to_resource(prj, file_path)
                occurrences += find_occurrences(
                    prj, mod, offset, unsure=False, in_hierarchy=True)
                prj.close()
        else:
            prj = Project(main_project, ropefolder=api.project.FOLDER,
                          fscommands=FileSystemCommands())
            prj.validate()
            mod = libutils.path_to_resource(prj, file_path)
            occurrences = find_occurrences(prj, mod, offset, unsure=False,
                                           in_hierarchy=True)
        # transform results to a serialisable list of usages that is ready
        # to use by the find_results widget.
        occurrences_map = {}
        for location in occurrences:
            path = location.resource.real_path
            lineno = location.lineno - 1
            # convert file region to line region
            content = location.resource.read()
            offset = location.offset
            char = content[offset]
            while char != '\n':  # find start of line
                offset -= 1
                char = content[offset]
            # update offsets
            start = location.offset - offset - 1
            end = location.region[1] - offset - 1
            line_text = content.splitlines()[lineno]
            data = (lineno, line_text, [(start, end)])
            if path not in occurrences_map:
                occurrences_map[path] = [data]
            else:
                occurrences_map[path].append(data)
        results = []
        for key, value in occurrences_map.items():
            results.append((key, value))
        results = sorted(results, key=lambda x: x[0])
        return results
    except RopeError as e:
        error = RefactoringError()
        error.exc = str(e)
        error.traceback = traceback.format_exc()
        error.critical = False
        return error
    except Exception as e:
        error = RefactoringError()
        error.exc = str(e)
        error.traceback = traceback.format_exc()
        error.critical = True
        return error
Пример #48
0
class RopeFolderTest(unittest.TestCase):

    def setUp(self):
        super(RopeFolderTest, self).setUp()
        self.project = None

    def tearDown(self):
        if self.project:
            testutils.remove_project(self.project)
        super(RopeFolderTest, self).tearDown()

    def test_none_project_rope_folder(self):
        self.project = testutils.sample_project(ropefolder=None)
        self.assertTrue(self.project.ropefolder is None)

    def test_getting_project_rope_folder(self):
        self.project = testutils.sample_project(ropefolder='.ropeproject')
        self.assertTrue(self.project.ropefolder.exists())
        self.assertTrue('.ropeproject', self.project.ropefolder.path)

    def test_setting_ignored_resources(self):
        self.project = testutils.sample_project(
            ignored_resources=['myfile.txt'])
        myfile = self.project.get_file('myfile.txt')
        file2 = self.project.get_file('file2.txt')
        self.assertTrue(self.project.is_ignored(myfile))
        self.assertFalse(self.project.is_ignored(file2))

    def test_ignored_folders(self):
        self.project = testutils.sample_project(ignored_resources=['myfolder'])
        myfolder = self.project.root.create_folder('myfolder')
        self.assertTrue(self.project.is_ignored(myfolder))
        myfile = myfolder.create_file('myfile.txt')
        self.assertTrue(self.project.is_ignored(myfile))

    def test_ignored_resources_and_get_files(self):
        self.project = testutils.sample_project(
            ignored_resources=['myfile.txt'], ropefolder=None)
        myfile = self.project.get_file('myfile.txt')
        self.assertEquals(0, len(self.project.get_files()))
        myfile.create()
        self.assertEquals(0, len(self.project.get_files()))

    def test_ignored_resources_and_get_files2(self):
        self.project = testutils.sample_project(
            ignored_resources=['myfile.txt'], ropefolder=None)
        myfile = self.project.root.create_file('myfile.txt')  # noqa
        self.assertEquals(0, len(self.project.get_files()))

    def test_setting_ignored_resources_patterns(self):
        self.project = testutils.sample_project(ignored_resources=['m?file.*'])
        myfile = self.project.get_file('myfile.txt')
        file2 = self.project.get_file('file2.txt')
        self.assertTrue(self.project.is_ignored(myfile))
        self.assertFalse(self.project.is_ignored(file2))

    def test_star_should_not_include_slashes(self):
        self.project = testutils.sample_project(ignored_resources=['f*.txt'])
        folder = self.project.root.create_folder('folder')
        file1 = folder.create_file('myfile.txt')
        file2 = folder.create_file('file2.txt')
        self.assertFalse(self.project.is_ignored(file1))
        self.assertTrue(self.project.is_ignored(file2))

    def test_normal_fscommands(self):
        fscommands = _MockFSCommands()
        self.project = testutils.sample_project(fscommands=fscommands)
        myfile = self.project.get_file('myfile.txt')
        myfile.create()
        self.assertTrue('create_file ', fscommands.log)

    def test_fscommands_and_ignored_resources(self):
        fscommands = _MockFSCommands()
        self.project = testutils.sample_project(
            fscommands=fscommands,
            ignored_resources=['myfile.txt'], ropefolder=None)
        myfile = self.project.get_file('myfile.txt')
        myfile.create()
        self.assertEquals('', fscommands.log)

    def test_ignored_resources_and_prefixes(self):
        self.project = testutils.sample_project(
            ignored_resources=['.hg'])
        myfile = self.project.root.create_file('.hgignore')
        self.assertFalse(self.project.is_ignored(myfile))

    def test_loading_config_dot_py(self):
        self.project = testutils.sample_project(ropefolder='.ropeproject')
        config = self.project.get_file('.ropeproject/config.py')
        if not config.exists():
            config.create()
        config.write('def set_prefs(prefs):\n'
                     '    prefs["ignored_resources"] = ["myfile.txt"]\n'
                     'def project_opened(project):\n'
                     '    project.root.create_file("loaded")\n')
        self.project.close()
        self.project = Project(self.project.address, ropefolder='.ropeproject')
        self.assertTrue(self.project.get_file('loaded').exists())
        myfile = self.project.get_file('myfile.txt')
        self.assertTrue(self.project.is_ignored(myfile))

    def test_ignoring_syntax_errors(self):
        self.project = testutils.sample_project(ropefolder=None,
                                                ignore_syntax_errors=True)
        mod = testutils.create_module(self.project, 'mod')
        mod.write('xyz print')
        pymod = self.project.get_pymodule(mod)  # noqa

    def test_compressed_history(self):
        self.project = testutils.sample_project(compress_history=True)
        mod = testutils.create_module(self.project, 'mod')
        mod.write('')

    def test_compressed_objectdb(self):
        self.project = testutils.sample_project(compress_objectdb=True)
        mod = testutils.create_module(self.project, 'mod')
        self.project.pycore.analyze_module(mod)

    def test_nested_dot_ropeproject_folder(self):
        self.project = testutils.sample_project(ropefolder='.f1/f2')
        ropefolder = self.project.ropefolder
        self.assertEquals('.f1/f2', ropefolder.path)
        self.assertTrue(ropefolder.exists())
Пример #49
0
class PyCoreTest(unittest.TestCase):

    def setUp(self):
        super(PyCoreTest, self).setUp()
        self.project = testutils.sample_project()
        self.pycore = self.project.pycore

    def tearDown(self):
        testutils.remove_project(self.project)
        super(PyCoreTest, self).tearDown()

    def test_simple_module(self):
        testutils.create_module(self.project, 'mod')
        result = self.project.get_module('mod')
        self.assertEquals(get_base_type('Module'), result.type)
        self.assertEquals(0, len(result.get_attributes()))

    def test_nested_modules(self):
        pkg = testutils.create_package(self.project, 'pkg')
        mod = testutils.create_module(self.project, 'mod', pkg)  # noqa
        package = self.project.get_module('pkg')
        self.assertEquals(get_base_type('Module'), package.get_type())
        self.assertEquals(1, len(package.get_attributes()))
        module = package['mod'].get_object()
        self.assertEquals(get_base_type('Module'), module.get_type())

    def test_package(self):
        pkg = testutils.create_package(self.project, 'pkg')
        mod = testutils.create_module(self.project, 'mod', pkg)  # noqa
        result = self.project.get_module('pkg')
        self.assertEquals(get_base_type('Module'), result.type)

    def test_simple_class(self):
        mod = testutils.create_module(self.project, 'mod')
        mod.write('class SampleClass(object):\n    pass\n')
        mod_element = self.project.get_module('mod')
        result = mod_element['SampleClass'].get_object()
        self.assertEquals(get_base_type('Type'), result.get_type())

    def test_simple_function(self):
        mod = testutils.create_module(self.project, 'mod')
        mod.write('def sample_function():\n    pass\n')
        mod_element = self.project.get_module('mod')
        result = mod_element['sample_function'].get_object()
        self.assertEquals(get_base_type('Function'), result.get_type())

    def test_class_methods(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'class SampleClass(object):\n' \
               '    def sample_method(self):\n' \
               '        pass\n'
        mod.write(code)
        mod_element = self.project.get_module('mod')
        sample_class = mod_element['SampleClass'].get_object()
        self.assertTrue('sample_method' in sample_class)
        method = sample_class['sample_method'].get_object()
        self.assertEquals(get_base_type('Function'), method.get_type())

    def test_global_variables(self):
        mod = testutils.create_module(self.project, 'mod')
        mod.write('var = 10')
        mod_element = self.project.get_module('mod')
        result = mod_element['var']  # noqa

    def test_class_variables(self):
        mod = testutils.create_module(self.project, 'mod')
        mod.write('class SampleClass(object):\n    var = 10\n')
        mod_element = self.project.get_module('mod')
        sample_class = mod_element['SampleClass'].get_object()
        var = sample_class['var']  # noqa

    def test_class_attributes_set_in_init(self):
        mod = testutils.create_module(self.project, 'mod')
        mod.write('class C(object):\n'
                  '    def __init__(self):\n        self.var = 20\n')
        mod_element = self.project.get_module('mod')
        sample_class = mod_element['C'].get_object()
        var = sample_class['var']  # noqa

    def test_class_attributes_set_in_init_overwriting_a_defined(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'class C(object):\n' \
               '    def __init__(self):\n' \
               '        self.f = 20\n' \
               '    def f():\n' \
               '        pass\n'
        mod.write(code)
        mod_element = self.project.get_module('mod')
        sample_class = mod_element['C'].get_object()
        f = sample_class['f'].get_object()
        self.assertTrue(isinstance(f, AbstractFunction))

    def test_classes_inside_other_classes(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'class SampleClass(object):\n' \
               '    class InnerClass(object):\n' \
               '        pass\n\n'
        mod.write(code)
        mod_element = self.project.get_module('mod')
        sample_class = mod_element['SampleClass'].get_object()
        var = sample_class['InnerClass'].get_object()
        self.assertEquals(get_base_type('Type'), var.get_type())

    def test_non_existent_module(self):
        with self.assertRaises(exceptions.ModuleNotFoundError):
            self.project.get_module('doesnotexistmodule')

    def test_imported_names(self):
        testutils.create_module(self.project, 'mod1')
        mod = testutils.create_module(self.project, 'mod2')
        mod.write('import mod1\n')
        module = self.project.get_module('mod2')
        imported_sys = module['mod1'].get_object()
        self.assertEquals(get_base_type('Module'), imported_sys.get_type())

    def test_imported_as_names(self):
        testutils.create_module(self.project, 'mod1')
        mod = testutils.create_module(self.project, 'mod2')
        mod.write('import mod1 as my_import\n')
        module = self.project.get_module('mod2')
        imported_mod = module['my_import'].get_object()
        self.assertEquals(get_base_type('Module'), imported_mod.get_type())

    def test_get_string_module(self):
        mod = libutils.get_string_module(
            self.project, 'class Sample(object):\n    pass\n')
        sample_class = mod['Sample'].get_object()
        self.assertEquals(get_base_type('Type'), sample_class.get_type())

    def test_get_string_module_with_extra_spaces(self):
        mod = libutils.get_string_module(
            self.project, 'a = 10\n    ')  # noqa

    def test_parameter_info_for_functions(self):
        code = 'def func(param1, param2=10, *param3, **param4):\n    pass'
        mod = libutils.get_string_module(self.project, code)
        sample_function = mod['func']
        self.assertEquals(['param1', 'param2', 'param3', 'param4'],
                          sample_function.get_object().get_param_names())

    # FIXME: Not found modules
    def xxx_test_not_found_module_is_module(self):
        mod = libutils.get_string_module(
            self.project, 'import doesnotexist\n')
        self.assertEquals(get_base_type('Module'),
                          mod['doesnotexist'].
                          get_object().get_type())

    def test_mixing_scopes_and_objects_hierarchy(self):
        mod = libutils.get_string_module(self.project, 'var = 200\n')
        scope = mod.get_scope()
        self.assertTrue('var' in scope.get_names())

    def test_inheriting_base_class_attributes(self):
        code = 'class Base(object):\n' \
               '    def method(self):\n' \
               '        pass\n' \
               'class Derived(Base):\n' \
               '    pass\n'
        mod = libutils.get_string_module(self.project, code)
        derived = mod['Derived'].get_object()
        self.assertTrue('method' in derived)
        self.assertEquals(get_base_type('Function'),
                          derived['method'].get_object().get_type())

    def test_inheriting_multiple_base_class_attributes(self):
        code = 'class Base1(object):\n    def method1(self):\n        pass\n' \
               'class Base2(object):\n    def method2(self):\n        pass\n' \
               'class Derived(Base1, Base2):\n    pass\n'
        mod = libutils.get_string_module(self.project, code)
        derived = mod['Derived'].get_object()
        self.assertTrue('method1' in derived)
        self.assertTrue('method2' in derived)

    def test_inherit_multiple_base_class_attrs_with_the_same_name(self):
        code = 'class Base1(object):\n    def method(self):\n        pass\n' \
               'class Base2(object):\n    def method(self):\n        pass\n' \
               'class Derived(Base1, Base2):\n    pass\n'
        mod = libutils.get_string_module(self.project, code)
        base1 = mod['Base1'].get_object()
        derived = mod['Derived'].get_object()
        self.assertEquals(base1['method'].get_object(),
                          derived['method'].get_object())

    def test_inheriting_unknown_base_class(self):
        code = 'class Derived(NotFound):\n' \
               '    def f(self):\n' \
               '        pass\n'
        mod = libutils.get_string_module(self.project, code)
        derived = mod['Derived'].get_object()
        self.assertTrue('f' in derived)

    def test_module_creation(self):
        new_module = testutils.create_module(self.project, 'module')
        self.assertFalse(new_module.is_folder())
        self.assertEquals(self.project.get_resource('module.py'), new_module)

    def test_packaged_module_creation(self):
        package = self.project.root.create_folder('package')  # noqa
        new_module = testutils.create_module(self.project, 'package.module')
        self.assertEquals(self.project.get_resource('package/module.py'),
                          new_module)

    def test_packaged_module_creation_with_nested_src(self):
        src = self.project.root.create_folder('src')
        src.create_folder('pkg')
        new_module = testutils.create_module(self.project, 'pkg.mod', src)
        self.assertEquals(self.project.get_resource('src/pkg/mod.py'),
                          new_module)

    def test_package_creation(self):
        new_package = testutils.create_package(self.project, 'pkg')
        self.assertTrue(new_package.is_folder())
        self.assertEquals(self.project.get_resource('pkg'), new_package)
        self.assertEquals(self.project.get_resource('pkg/__init__.py'),
                          new_package.get_child('__init__.py'))

    def test_nested_package_creation(self):
        testutils.create_package(self.project, 'pkg1')
        nested_package = testutils.create_package(self.project, 'pkg1.pkg2')
        self.assertEquals(self.project.get_resource('pkg1/pkg2'),
                          nested_package)

    def test_packaged_package_creation_with_nested_src(self):
        src = self.project.root.create_folder('src')
        testutils.create_package(self.project, 'pkg1', src)
        nested_package = testutils.create_package(self.project, 'pkg1.pkg2',
                                                  src)
        self.assertEquals(self.project.get_resource('src/pkg1/pkg2'),
                          nested_package)

    def test_find_module(self):
        src = self.project.root.create_folder('src')
        samplemod = testutils.create_module(self.project, 'samplemod', src)
        found_module = self.project.find_module('samplemod')
        self.assertEquals(samplemod, found_module)

    def test_find_nested_module(self):
        src = self.project.root.create_folder('src')
        samplepkg = testutils.create_package(self.project, 'samplepkg', src)
        samplemod = testutils.create_module(self.project, 'samplemod',
                                            samplepkg)
        found_module = self.project.find_module('samplepkg.samplemod')
        self.assertEquals(samplemod, found_module)

    def test_find_multiple_module(self):
        src = self.project.root.create_folder('src')
        samplemod1 = testutils.create_module(self.project, 'samplemod', src)
        samplemod2 = testutils.create_module(self.project, 'samplemod')
        test = self.project.root.create_folder('test')
        samplemod3 = testutils.create_module(self.project, 'samplemod', test)
        found_module = self.project.find_module('samplemod')
        self.assertTrue(samplemod1 == found_module or
                        samplemod2 == found_module or
                        samplemod3 == found_module)

    def test_find_module_packages(self):
        src = self.project.root
        samplepkg = testutils.create_package(self.project, 'samplepkg', src)
        found_module = self.project.find_module('samplepkg')
        self.assertEquals(samplepkg, found_module)

    def test_find_module_when_module_and_package_with_the_same_name(self):
        src = self.project.root
        testutils.create_module(self.project, 'sample', src)
        samplepkg = testutils.create_package(self.project, 'sample', src)
        found_module = self.project.find_module('sample')
        self.assertEquals(samplepkg, found_module)

    def test_source_folders_preference(self):
        testutils.create_package(self.project, 'pkg1')
        testutils.create_package(self.project, 'pkg1.src2')
        lost = testutils.create_module(self.project, 'pkg1.src2.lost')
        self.assertEqual(self.project.find_module('lost'), None)
        self.project.close()
        from rope.base.project import Project
        self.project = Project(self.project.address,
                               source_folders=['pkg1/src2'])
        self.assertEqual(self.project.find_module('lost'), lost)

    def test_get_pyname_definition_location(self):
        mod = libutils.get_string_module(self.project, 'a_var = 20\n')
        a_var = mod['a_var']
        self.assertEquals((mod, 1), a_var.get_definition_location())

    def test_get_pyname_definition_location_functions(self):
        mod = libutils.get_string_module(
            self.project, 'def a_func():\n    pass\n')
        a_func = mod['a_func']
        self.assertEquals((mod, 1), a_func.get_definition_location())

    def test_get_pyname_definition_location_class(self):
        code = 'class AClass(object):\n    pass\n\n'
        mod = libutils.get_string_module(self.project, code)
        a_class = mod['AClass']
        self.assertEquals((mod, 1), a_class.get_definition_location())

    def test_get_pyname_definition_location_local_variables(self):
        mod = libutils.get_string_module(
            self.project, 'def a_func():\n    a_var = 10\n')
        a_func_scope = mod.get_scope().get_scopes()[0]
        a_var = a_func_scope['a_var']
        self.assertEquals((mod, 2), a_var.get_definition_location())

    def test_get_pyname_definition_location_reassigning(self):
        mod = libutils.get_string_module(
            self.project, 'a_var = 20\na_var=30\n')
        a_var = mod['a_var']
        self.assertEquals((mod, 1), a_var.get_definition_location())

    def test_get_pyname_definition_location_importes(self):
        testutils.create_module(self.project, 'mod')
        mod = libutils.get_string_module(self.project, 'import mod\n')
        imported_module = self.project.get_module('mod')
        module_pyname = mod['mod']
        self.assertEquals((imported_module, 1),
                          module_pyname.get_definition_location())

    def test_get_pyname_definition_location_imports(self):
        module_resource = testutils.create_module(self.project, 'mod')
        module_resource.write('\ndef a_func():\n    pass\n')
        imported_module = self.project.get_module('mod')
        mod = libutils.get_string_module(
            self.project, 'from mod import a_func\n')
        a_func = mod['a_func']
        self.assertEquals((imported_module, 2),
                          a_func.get_definition_location())

    def test_get_pyname_definition_location_parameters(self):
        code = 'def a_func(param1, param2):\n    a_var = param\n'
        mod = libutils.get_string_module(self.project, code)
        a_func_scope = mod.get_scope().get_scopes()[0]
        param1 = a_func_scope['param1']
        self.assertEquals((mod, 1), param1.get_definition_location())
        param2 = a_func_scope['param2']
        self.assertEquals((mod, 1), param2.get_definition_location())

    def test_module_get_resource(self):
        module_resource = testutils.create_module(self.project, 'mod')
        module = self.project.get_module('mod')
        self.assertEquals(module_resource, module.get_resource())
        string_module = libutils.get_string_module(
            self.project, 'from mod import a_func\n')
        self.assertEquals(None, string_module.get_resource())

    def test_get_pyname_definition_location_class2(self):
        code = 'class AClass(object):\n' \
               '    def __init__(self):\n' \
               '        self.an_attr = 10\n'
        mod = libutils.get_string_module(self.project, code)
        a_class = mod['AClass'].get_object()
        an_attr = a_class['an_attr']
        self.assertEquals((mod, 3), an_attr.get_definition_location())

    def test_import_not_found_module_get_definition_location(self):
        mod = libutils.get_string_module(
            self.project, 'import doesnotexist\n')
        does_not_exist = mod['doesnotexist']
        self.assertEquals((None, None),
                          does_not_exist.get_definition_location())

    def test_from_not_found_module_get_definition_location(self):
        mod = libutils.get_string_module(
            self.project, 'from doesnotexist import Sample\n')
        sample = mod['Sample']
        self.assertEquals((None, None), sample.get_definition_location())

    def test_from_package_import_module_get_definition_location(self):
        pkg = testutils.create_package(self.project, 'pkg')
        testutils.create_module(self.project, 'mod', pkg)
        pkg_mod = self.project.get_module('pkg.mod')
        mod = libutils.get_string_module(
            self.project, 'from pkg import mod\n')
        imported_mod = mod['mod']
        self.assertEquals((pkg_mod, 1),
                          imported_mod.get_definition_location())

    def test_get_module_for_defined_pyobjects(self):
        mod = libutils.get_string_module(
            self.project, 'class AClass(object):\n    pass\n')
        a_class = mod['AClass'].get_object()
        self.assertEquals(mod, a_class.get_module())

    def test_get_definition_location_for_packages(self):
        testutils.create_package(self.project, 'pkg')
        init_module = self.project.get_module('pkg.__init__')
        mod = libutils.get_string_module(self.project, 'import pkg\n')
        pkg_pyname = mod['pkg']
        self.assertEquals((init_module, 1),
                          pkg_pyname.get_definition_location())

    def test_get_definition_location_for_filtered_packages(self):
        pkg = testutils.create_package(self.project, 'pkg')
        testutils.create_module(self.project, 'mod', pkg)
        init_module = self.project.get_module('pkg.__init__')
        mod = libutils.get_string_module(self.project, 'import pkg.mod')
        pkg_pyname = mod['pkg']
        self.assertEquals((init_module, 1),
                          pkg_pyname.get_definition_location())

    def test_out_of_project_modules(self):
        scope = libutils.get_string_scope(
            self.project, 'import rope.base.project as project\n')
        imported_module = scope['project'].get_object()
        self.assertTrue('Project' in imported_module)

    def test_file_encoding_reading(self):
        contents = u'# -*- coding: utf-8 -*-\n' + \
            u'#\N{LATIN SMALL LETTER I WITH DIAERESIS}\n'
        mod = testutils.create_module(self.project, 'mod')
        mod.write(contents)
        self.project.get_module('mod')

    def test_global_keyword(self):
        contents = 'a_var = 1\ndef a_func():\n    global a_var\n'
        mod = libutils.get_string_module(self.project, contents)
        global_var = mod['a_var']
        func_scope = mod['a_func'].get_object().get_scope()
        local_var = func_scope['a_var']
        self.assertEquals(global_var, local_var)

    def test_not_leaking_for_vars_inside_parent_scope(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'class C(object):\n' \
               '    def f(self):\n' \
               '        for my_var1, my_var2 in []:\n' \
               '            pass\n'
        mod.write(code)
        pymod = self.pycore.resource_to_pyobject(mod)
        c_class = pymod['C'].get_object()
        self.assertFalse('my_var1' in c_class)
        self.assertFalse('my_var2' in c_class)

    def test_not_leaking_for_vars_inside_parent_scope2(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'class C(object):\n' \
               '    def f(self):\n' \
               '        for my_var in []:\n' \
               '            pass\n'
        mod.write(code)
        pymod = self.pycore.resource_to_pyobject(mod)
        c_class = pymod['C'].get_object()
        self.assertFalse('my_var' in c_class)

    def test_variables_defined_in_excepts(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'try:\n' \
               '    myvar1 = 1\n' \
               'except:\n' \
               '    myvar2 = 1\n' \
               'finally:\n' \
               '    myvar3 = 1\n'
        mod.write(code)
        pymod = self.pycore.resource_to_pyobject(mod)
        self.assertTrue('myvar1' in pymod)
        self.assertTrue('myvar2' in pymod)
        self.assertTrue('myvar3' in pymod)

    def test_not_leaking_tuple_assigned_names_inside_parent_scope(self):
        mod = testutils.create_module(self.project, 'mod')
        code = 'class C(object):\n' \
               '    def f(self):\n' \
               '        var1, var2 = range(2)\n'
        mod.write(code)
        pymod = self.pycore.resource_to_pyobject(mod)
        c_class = pymod['C'].get_object()
        self.assertFalse('var1' in c_class)

    @testutils.only_for('2.5')
    def test_with_statement_variables(self):
        code = 'import threading\nwith threading.lock() as var:    pass\n'
        if sys.version_info < (2, 6, 0):
            code = 'from __future__ import with_statement\n' + code
        pymod = libutils.get_string_module(self.project, code)
        self.assertTrue('var' in pymod)

    @testutils.only_for('2.5')
    def test_with_statement_variables_and_tuple_assignment(self):
        code = 'class A(object):\n' \
               '    def __enter__(self):' \
               '        return (1, 2)\n' \
               '    def __exit__(self, type, value, tb):\n' \
               '        pass\n'\
               'with A() as (a, b):\n' \
               '    pass\n'
        if sys.version_info < (2, 6, 0):
            code = 'from __future__ import with_statement\n' + code
        pymod = libutils.get_string_module(self.project, code)
        self.assertTrue('a' in pymod)
        self.assertTrue('b' in pymod)

    @testutils.only_for('2.5')
    def test_with_statement_variable_type(self):
        code = 'class A(object):\n' \
               '    def __enter__(self):\n' \
               '        return self\n'\
               '    def __exit__(self, type, value, tb):\n' \
               '        pass\n' \
               'with A() as var:\n' \
               '    pass\n'
        if sys.version_info < (2, 6, 0):
            code = 'from __future__ import with_statement\n' + code
        pymod = libutils.get_string_module(self.project, code)
        a_class = pymod['A'].get_object()
        var = pymod['var'].get_object()
        self.assertEquals(a_class, var.get_type())

    @testutils.only_for('2.5')
    def test_with_statement_with_no_vars(self):
        code = 'with open("file"):    pass\n'
        if sys.version_info < (2, 6, 0):
            code = 'from __future__ import with_statement\n' + code
        pymod = libutils.get_string_module(self.project, code)
        pymod.get_attributes()

    def test_check_for_else_block(self):
        code = 'for i in range(10):\n' \
               '    pass\n' \
               'else:\n' \
               '    myvar = 1\n'
        mod = libutils.get_string_module(self.project, code)
        a_var = mod['myvar']
        self.assertEquals((mod, 4), a_var.get_definition_location())

    def test_check_names_defined_in_whiles(self):
        mod = libutils.get_string_module(
            self.project, 'while False:\n    myvar = 1\n')
        a_var = mod['myvar']
        self.assertEquals((mod, 2), a_var.get_definition_location())

    def test_get_definition_location_in_tuple_assnames(self):
        mod = libutils.get_string_module(
            self.project, 'def f(x):\n    x.z, a = range(2)\n')
        x = mod['f'].get_object().get_scope()['x']
        a = mod['f'].get_object().get_scope()['a']
        self.assertEquals((mod, 1), x.get_definition_location())
        self.assertEquals((mod, 2), a.get_definition_location())

    def test_syntax_errors_in_code(self):
        with self.assertRaises(exceptions.ModuleSyntaxError):
            libutils.get_string_module(self.project, 'xyx print\n')

    def test_holding_error_location_information(self):
        try:
            libutils.get_string_module(self.project, 'xyx print\n')
        except exceptions.ModuleSyntaxError as e:
            self.assertEquals(1, e.lineno)

    def test_no_exceptions_on_module_encoding_problems(self):
        mod = testutils.create_module(self.project, 'mod')
        contents = '\nsdsdsd\n\xa9\n'
        file = open(mod.real_path, 'wb')
        file.write(contents)
        file.close()
        mod.read()

    def test_syntax_errors_when_cannot_decode_file2(self):
        mod = testutils.create_module(self.project, 'mod')
        contents = '\n\xa9\n'
        file = open(mod.real_path, 'wb')
        file.write(contents)
        file.close()
        with self.assertRaises(exceptions.ModuleSyntaxError):
            self.pycore.resource_to_pyobject(mod)

    def test_syntax_errors_when_null_bytes(self):
        mod = testutils.create_module(self.project, 'mod')
        contents = '\n\x00\n'
        file = open(mod.real_path, 'wb')
        file.write(contents)
        file.close()
        with self.assertRaises(exceptions.ModuleSyntaxError):
            self.pycore.resource_to_pyobject(mod)

    def test_syntax_errors_when_bad_strs(self):
        mod = testutils.create_module(self.project, 'mod')
        contents = '\n"\\x0"\n'
        file = open(mod.real_path, 'wb')
        file.write(contents)
        file.close()
        with self.assertRaises(exceptions.ModuleSyntaxError):
            self.pycore.resource_to_pyobject(mod)

    def test_not_reaching_maximum_recursions_with_from_star_imports(self):
        mod1 = testutils.create_module(self.project, 'mod1')
        mod2 = testutils.create_module(self.project, 'mod2')
        mod1.write('from mod2 import *\n')
        mod2.write('from mod1 import *\n')
        pymod1 = self.pycore.resource_to_pyobject(mod1)
        pymod1.get_attributes()

    def test_not_reaching_maximum_recursions_when_importing_variables(self):
        mod1 = testutils.create_module(self.project, 'mod1')
        mod2 = testutils.create_module(self.project, 'mod2')
        mod1.write('from mod2 import myvar\n')
        mod2.write('from mod1 import myvar\n')
        pymod1 = self.pycore.resource_to_pyobject(mod1)
        pymod1['myvar'].get_object()

    def test_not_reaching_maximum_recursions_when_importing_variables2(self):
        mod1 = testutils.create_module(self.project, 'mod1')
        mod1.write('from mod1 import myvar\n')
        pymod1 = self.pycore.resource_to_pyobject(mod1)
        pymod1['myvar'].get_object()

    def test_pyobject_equality_should_compare_types(self):
        mod1 = testutils.create_module(self.project, 'mod1')
        mod1.write('var1 = ""\nvar2 = ""\n')
        pymod1 = self.pycore.resource_to_pyobject(mod1)
        self.assertEquals(pymod1['var1'].get_object(),
                          pymod1['var2'].get_object())
Пример #50
0
class rename:

    def __init__(self, project_path=None, module_path=None):
        """ initialize using project path and optional sub module path to limit rename scope """
        if project_path:
            self.project = Project(project_path)
        self.module_path = module_path
        self.words = set()
        self.files = []
        self.namemap = {}
        self.classname_regex = re.compile('class\s+(?P<name>[a-zA-Z0-9_]+)')
        self.methodname_regex = re.compile('def\s+(?P<name>[a-zA-Z0-9_]+)')

    def load_words(self):
        """ load all known words """
        with open('words') as f:
            for line in f:
                self.words.add(line.strip().lower())

    def load_dict(self, dictionary_path):
        """ load a custom dict with new (recognized) and restricted (unrecognized) words """
        doc = etree.parse(dictionary_path)
        for recognized in doc.xpath('/dictionary/recognized/word'):
            self.words.add(recognized.text)
        for unrecognized in doc.xpath('/dictionary/unrecognized/word'):
            if unrecognized.text in self.words:
                self.words.remove(unrecognized.text)

    def wash_word(self, string):
        """ clean up word by separating prefix, suffix and word without underscores """
        prefix = string[:string.find(string.lstrip('_'))]
        suffix = string[len(string.rstrip('_')):]
        word = string.lower().replace('_', '')
        return (prefix, word, suffix)

    def find_word(self, string, index):
        """ find the longest word from index """
        word = ''
        i = index + 1
        while i <= len(string):
            if string[index:i] in self.words:
                word = string[index:i]
            i += 1
        return word

    def reverse_find_word(self, string, index):
        """ backwards find the longest word from index """
        word = ''
        i = index - 1
        while i >= 0:
            if string[i:index] in self.words:
                word = string[i:index]
            i -= 1
        return word

    def find_words(self, string, index=-1):
        """ find all known words in a string """
        words = []
        if index == -1:
            index = len(string)
        if index == 0:
            return words
        word = self.reverse_find_word(string, index)
        if word:
            words.insert(0, word)
            index -= len(word)
        else:
            index -= 1
        w = self.find_words(string, index)
        w.extend(words)
        words = w
        #words.extend(self.find_words(string, index))
        return words

    def rename(self, string):
        """ rename string to PEP8 standard """
        index = 0
        last_index = 0
        new_name = ''
        prefix, old_name, suffix = self.wash_word(string)
        for word in self.find_words(old_name):
            index = old_name.find(word, index)
            if last_index != index:
                new_name += old_name[last_index: index]
            if len(new_name) > 0:
                new_name += '_'
            new_name += word
            index += len(word)
            last_index = index
        if last_index != len(old_name):
            if len(new_name) > 0:
                new_name += '_'
            new_name += old_name[last_index:]
        return '%s%s%s' % (prefix, new_name, suffix)

    def index_file(self, content):
        """ get all indexes for methods to rename in context
            return list of old name, position and new name """
        index = 0
        methods = []
        running = True
        while running:
            method = self.methodname_regex.search(content, index)
            if method:
                old_name = method.group('name')
                pos = method.start() + method.string[method.start():].find(old_name)
                new_name = self.rename(old_name)
                if old_name != new_name:
                    methods.append((old_name, pos, new_name))
                index = pos + len(old_name)
            else:
                running = False
        return methods

    def get_files(self):
        """ iterator for all valid project files """
        for file_resource in self.project.get_files():
            if self.module_path and not self.module_path in file_resource.real_path:
                continue
            yield file_resource

    def dry_run(self):
        """ list all methods to be renamed without updating any files """
        for file_resource in self.get_files():
            methods = self.index_file(file_resource.read())
            print('%s' % file_resource.path)
            for method in methods:
                print('    %s:%d->%s' % (method[0], method[1], method[2]))

    def refactor(self):
        """ renames all methods to PEP8 standard """
        for file_resource in self.get_files():
            while True:
                self.project.validate()
                methods = self.index_file(file_resource.read())
                if len(methods) == 0:
                    break
                method = methods[0]
                old_name = method[0]
                pos = method[1]
                new_name = method[2]
                print('rename: %s:%d->%s' % (old_name, pos, new_name))
                changes = Rename(self.project, file_resource, pos).get_changes(new_name)
                self.project.do(changes)
Пример #51
0
    def __init__(self, editorTabWidget, busyWidget, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.editorTabWidget = editorTabWidget
        self.busyWidget = busyWidget
        self.root = editorTabWidget.pathDict["sourcedir"]
        ropeFolder = editorTabWidget.pathDict["ropeFolder"]

        prefs = {
            'ignored_resources': ['*.pyc', '*~', '.ropeproject',
                                  '.hg', '.svn', '_svn', '.git',
                                  '__pycache__'],
            'python_files': ['*.py'],
            'save_objectdb': True,
            'compress_objectdb': False,
            'automatic_soa': True,
            'soa_followed_calls': 0,
            'perform_doa': True,
            'validate_objectdb': True,
            'max_history_items': 32,
            'save_history': True,
            'compress_history': False,
            'indent_size': 4,
            'extension_modules': [
                "PyQt4", "PyQt4.QtGui", "QtGui", "PyQt4.QtCore", "QtCore",
                "PyQt4.QtScript", "QtScript", "os.path", "numpy", "scipy", "PIL",
                "OpenGL", "array", "audioop", "binascii", "cPickle", "cStringIO",
                "cmath", "collections", "datetime", "errno", "exceptions", "gc",
                "imageop", "imp", "itertools", "marshal", "math", "mmap", "msvcrt",
                "nt", "operator", "os", "parser", "rgbimg", "signal", "strop", "sys",
                "thread", "time", "wx", "wxPython", "xxsubtype", "zipimport", "zlib"
            ],
            'import_dynload_stdmods': True,
            'ignore_syntax_errors': True,
            'ignore_bad_imports': True
        }

        self.ropeProject = Project(
            projectroot=self.root, ropefolder=ropeFolder, **prefs)
        self.ropeProject.prefs.add('python_path', 'c:/Python33')
        self.ropeProject.prefs.add('source_folders', 'c:/Python33/Lib')
        self.ropeProject.validate()

        self.noProject = Project(projectroot="temp", ropefolder=None)

        self.findThread = FindUsageThread()
        self.findThread.finished.connect(self.findOccurrencesFinished)

        self.renameThread = RenameThread()
        self.renameThread.finished.connect(self.renameFinished)

        self.inlineThread = InlineThread()
        self.inlineThread.finished.connect(self.inlineFinished)

        self.localToFieldThread = LocalToFieldThread()
        self.localToFieldThread.finished.connect(self.localToFieldFinished)

        self.moduleToPackageThread = ModuleToPackageThread()
        self.moduleToPackageThread.finished.connect(
            self.moduleToPackageFinished)

        self.createActions()

        self.refactorMenu = QtGui.QMenu("Refactor")
        self.refactorMenu.addAction(self.renameAttributeAct)
        self.refactorMenu.addAction(self.inlineAct)
        self.refactorMenu.addAction(self.localToFieldAct)
Пример #52
0
    def __init__(self, editorTabWidget, busyWidget, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.editorTabWidget = editorTabWidget
        self.busyWidget = busyWidget
        self.root = editorTabWidget.projectPathDict["sourcedir"]
        self.useData = editorTabWidget.useData
        ropeFolder = editorTabWidget.projectPathDict["ropeFolder"]

        libraryList = []
        for i, v in self.useData.libraryDict.items():
            libraryList.extend(v[0])
        prefs = {
            'ignored_resources': ['*.pyc', '*~', '.ropeproject',
                                  '.hg', '.svn', '_svn', '.git',
                                  '__pycache__'],
            'python_files': ['*.py', '*.pyw'],
            'save_objectdb': True,
            'compress_objectdb': False,
            'automatic_soa': True,
            'soa_followed_calls': 0,
            'perform_doa': True,
            'validate_objectdb': True,
            'max_history_items': 32,
            'save_history': True,
            'compress_history': False,
            'indent_size': 4,
            'extension_modules': libraryList,
            'import_dynload_stdmods': True,
            'ignore_syntax_errors': True,
            'ignore_bad_imports': True
            }

        self.ropeProject = Project(
            projectroot=self.root, ropefolder=ropeFolder, **prefs)
        self.ropeProject.prefs.add('python_path', 'c:/Python33')
        self.ropeProject.prefs.add('source_folders', 'c:/Python33/Lib')
        self.ropeProject.validate()

        self.noProject = Project(projectroot="temp", ropefolder=None)

        self.findThread = FindUsageThread()
        self.findThread.finished.connect(self.findOccurrencesFinished)

        self.renameThread = RenameThread()
        self.renameThread.finished.connect(self.renameFinished)

        self.inlineThread = InlineThread()
        self.inlineThread.finished.connect(self.inlineFinished)

        self.localToFieldThread = LocalToFieldThread()
        self.localToFieldThread.finished.connect(self.localToFieldFinished)

        self.moduleToPackageThread = ModuleToPackageThread()
        self.moduleToPackageThread.finished.connect(
            self.moduleToPackageFinished)

        self.createActions()

        self.refactorMenu = QtGui.QMenu("Refactor")
        self.refactorMenu.addAction(self.renameAttributeAct)
        self.refactorMenu.addAction(self.inlineAct)
        self.refactorMenu.addAction(self.localToFieldAct)
Пример #53
0
class RopeFolderTest(unittest.TestCase):
    def setUp(self):
        super(RopeFolderTest, self).setUp()
        self.project = None

    def tearDown(self):
        if self.project:
            testutils.remove_project(self.project)
        super(RopeFolderTest, self).tearDown()

    def test_none_project_rope_folder(self):
        self.project = testutils.sample_project(ropefolder=None)
        self.assertTrue(self.project.ropefolder is None)

    def test_getting_project_rope_folder(self):
        self.project = testutils.sample_project(ropefolder=".ropeproject")
        self.assertTrue(self.project.ropefolder.exists())
        self.assertTrue(".ropeproject", self.project.ropefolder.path)

    def test_setting_ignored_resources(self):
        self.project = testutils.sample_project(ignored_resources=["myfile.txt"])
        myfile = self.project.get_file("myfile.txt")
        file2 = self.project.get_file("file2.txt")
        self.assertTrue(self.project.is_ignored(myfile))
        self.assertFalse(self.project.is_ignored(file2))

    def test_ignored_folders(self):
        self.project = testutils.sample_project(ignored_resources=["myfolder"])
        myfolder = self.project.root.create_folder("myfolder")
        self.assertTrue(self.project.is_ignored(myfolder))
        myfile = myfolder.create_file("myfile.txt")
        self.assertTrue(self.project.is_ignored(myfile))

    def test_ignored_resources_and_get_files(self):
        self.project = testutils.sample_project(ignored_resources=["myfile.txt"], ropefolder=None)
        myfile = self.project.get_file("myfile.txt")
        self.assertEquals(0, len(self.project.get_files()))
        myfile.create()
        self.assertEquals(0, len(self.project.get_files()))

    def test_ignored_resources_and_get_files2(self):
        self.project = testutils.sample_project(ignored_resources=["myfile.txt"], ropefolder=None)
        myfile = self.project.root.create_file("myfile.txt")
        self.assertEquals(0, len(self.project.get_files()))

    def test_setting_ignored_resources_patterns(self):
        self.project = testutils.sample_project(ignored_resources=["m?file.*"])
        myfile = self.project.get_file("myfile.txt")
        file2 = self.project.get_file("file2.txt")
        self.assertTrue(self.project.is_ignored(myfile))
        self.assertFalse(self.project.is_ignored(file2))

    def test_star_should_not_include_slashes(self):
        self.project = testutils.sample_project(ignored_resources=["f*.txt"])
        folder = self.project.root.create_folder("folder")
        file1 = folder.create_file("myfile.txt")
        file2 = folder.create_file("file2.txt")
        self.assertFalse(self.project.is_ignored(file1))
        self.assertTrue(self.project.is_ignored(file2))

    def test_normal_fscommands(self):
        fscommands = _MockFSCommands()
        self.project = testutils.sample_project(fscommands=fscommands)
        myfile = self.project.get_file("myfile.txt")
        myfile.create()
        self.assertTrue("create_file ", fscommands.log)

    def test_fscommands_and_ignored_resources(self):
        fscommands = _MockFSCommands()
        self.project = testutils.sample_project(
            fscommands=fscommands, ignored_resources=["myfile.txt"], ropefolder=None
        )
        myfile = self.project.get_file("myfile.txt")
        myfile.create()
        self.assertEquals("", fscommands.log)

    def test_ignored_resources_and_prefixes(self):
        self.project = testutils.sample_project(ignored_resources=[".hg"])
        myfile = self.project.root.create_file(".hgignore")
        self.assertFalse(self.project.is_ignored(myfile))

    def test_loading_config_dot_py(self):
        self.project = testutils.sample_project(ropefolder=".ropeproject")
        config = self.project.get_file(".ropeproject/config.py")
        if not config.exists():
            config.create()
        config.write(
            "def set_prefs(prefs):\n"
            '    prefs["ignored_resources"] = ["myfile.txt"]\n'
            "def project_opened(project):\n"
            '    project.root.create_file("loaded")\n'
        )
        self.project.close()
        self.project = Project(self.project.address, ropefolder=".ropeproject")
        self.assertTrue(self.project.get_file("loaded").exists())
        myfile = self.project.get_file("myfile.txt")
        self.assertTrue(self.project.is_ignored(myfile))

    def test_ignoring_syntax_errors(self):
        self.project = testutils.sample_project(ropefolder=None, ignore_syntax_errors=True)
        pycore = self.project.pycore
        mod = testutils.create_module(self.project, "mod")
        mod.write("xyz print")
        pymod = pycore.resource_to_pyobject(mod)

    def test_compressed_history(self):
        self.project = testutils.sample_project(compress_history=True)
        mod = testutils.create_module(self.project, "mod")
        mod.write("")

    def test_compressed_objectdb(self):
        self.project = testutils.sample_project(compress_objectdb=True)
        mod = testutils.create_module(self.project, "mod")
        self.project.pycore.analyze_module(mod)

    def test_nested_dot_ropeproject_folder(self):
        self.project = testutils.sample_project(ropefolder=".f1/f2")
        ropefolder = self.project.ropefolder
        self.assertEquals(".f1/f2", ropefolder.path)
        self.assertTrue(ropefolder.exists())
Пример #54
0
class PyRefactor(plugins.WorkspacePlugin):
    """
    Adds some refactoring capabilities to the IDE (using the rope library).

    Supported operations:
        - Rename
        - Extract method
        - Extract variable
        - Find occurrences
        - Organize imports

    """
    def activate(self):
        self._preview_dock = None
        self._occurrences_dock = None
        self._occurrences_results = None
        self._review_widget = None
        api.signals.connect_slot(api.signals.CURRENT_PROJECT_CHANGED,
                                 self._on_current_project_changed)
        api.signals.connect_slot(api.signals.EDITOR_CREATED,
                                 self._on_editor_created)
        api.signals.connect_slot(api.signals.CURRENT_EDITOR_CHANGED,
                                 self._update_edit_actions_state)
        path = api.project.get_current_project()
        self._main_project = Project(path, ropefolder=api.project.FOLDER,
                                     fscommands=FileSystemCommands())
        self._main_project.validate()
        api.signals.connect_slot(api.signals.DOCUMENT_SAVED,
                                 self._on_document_saved)

    def close(self):
        self._main_project.close()

    def rename(self):
        """
        Renames word under cursor.
        """
        editor = api.editor.get_current_editor()
        if editor is None:
            return
        editor.file.save()
        assert isinstance(editor, PyCodeEdit)
        module = libutils.path_to_resource(
            self._main_project, editor.file.path)
        self._main_project.validate()
        cursor_position = self._get_real_position(
            editor.textCursor().position())
        try:
            renamer = Rename(self._main_project, module, cursor_position)
        except RopeError:
            return
        if not renamer.get_old_name():
            return
        preview, replacement = DlgRope.rename(
            self.main_window, renamer.get_old_name())
        if preview is None and replacement is None:
            return
        multiproj = self._has_multiple_projects()
        other_projects = self._get_other_projects()
        main_project = self._main_project
        self._preview = preview
        api.tasks.start(_('Refactoring: rename'), rename_symbol,
                        self._on_changes_available,
                        args=(
                            main_project, multiproj, other_projects,
                            editor.file.path, cursor_position, replacement),
                        cancellable=True, use_thread=True)

    def organise_imports(self):
        editor = api.editor.get_current_editor()
        api.editor.save_all_editors()
        if editor is None:
            return
        self._preview = True
        file_path = editor.file.path
        project = self.get_project_for_file(file_path)
        if project:
            api.tasks.start(
                _('Refactoring: organize imports'), organize_imports,
                self._on_changes_available,
                args=(project, file_path),
                cancellable=True, use_thread=True)

    def extract_method(self):
        """
        Extracts a method from the selected text (if possible, otherwise a
        warning message will appear).
        """
        api.editor.save_all_editors()
        self._main_project.validate()
        editor = api.editor.get_current_editor()
        if editor is None or not editor.textCursor().hasSelection():
            return
        editor.file.save()
        if not editor.textCursor().hasSelection():
            TextHelper(editor).select_whole_line()
        start = self._get_real_position(editor.textCursor().selectionStart())
        end = self._get_real_position(editor.textCursor().selectionEnd())
        preview, replacement = DlgRope.extract_method(self.main_window)
        if preview is None and replacement is None:
            return
        multiproj = self._has_multiple_projects()
        other_projects = self._get_other_projects()
        main_project = self._main_project
        cursor_position_start = start
        cursor_position_end = end
        replacement = replacement
        self._preview = preview
        api.tasks.start(
            _('Refactoring: extract method'), extract_method,
            self._on_changes_available,
            args=(multiproj, main_project, other_projects, editor.file.path,
                  cursor_position_start, cursor_position_end, replacement),
            cancellable=True, use_thread=True)

    def extract_variable(self):
        """
        Extracts a variable from the selected statement (if possible).
        """
        api.editor.save_all_editors()
        self._main_project.validate()
        editor = api.editor.get_current_editor()
        if editor is None or not editor.textCursor().hasSelection():
            return
        editor.file.save()
        if not editor.textCursor().hasSelection():
            TextHelper(editor).select_whole_line()
        start = self._get_real_position(editor.textCursor().selectionStart())
        end = self._get_real_position(editor.textCursor().selectionEnd())
        preview, replacement = DlgRope.extract_variable(self.main_window)
        if preview is None and replacement is None:
            return
        multiproj = self._has_multiple_projects()
        other_projects = self._get_other_projects()
        main_project = self._main_project
        cursor_position_start = start
        cursor_position_end = end
        replacement = replacement
        self._preview = preview
        api.tasks.start(
            _('Refactoring: extract variable'), extract_variable,
            self._on_changes_available,
            args=(multiproj, main_project, other_projects, editor.file.path,
                  cursor_position_start, cursor_position_end, replacement),
            cancellable=True, use_thread=True)

    def find_usages(self):
        """
        Find all usages of the word under cursor.
        """
        api.editor.save_all_editors()
        if api.editor.get_current_editor() is None:
            return
        file_path = api.editor.get_current_path()
        api.editor.save_current_editor()
        offset = self._get_real_position(
            api.editor.get_current_editor().textCursor().position())
        self._occurrence_to_search = worder.get_name_at(
            libutils.path_to_resource(self._main_project, file_path), offset)
        main_project = api.project.get_current_project()
        other_projects = self._get_other_projects(path_only=True)
        file_path = file_path
        api.tasks.start(
            _('Refactoring: find usages'), find_usages,
            self._on_find_usages_finished,
            args=(main_project, other_projects, file_path, offset),
            cancellable=True, use_thread=True)

    def get_project_for_file(self, path):
        for prj in [self._main_project] + self._get_other_projects():
            p = prj.address + os.path.sep
            if p in path:
                return prj
        return None

    @staticmethod
    def clean_changes(pending_changes):
        if hasattr(pending_changes, '__iter__'):
            cleaned = []
            for prj, changeset in pending_changes:
                for change in changeset.changes:
                    if isinstance(change.resource.project, NoProject):
                        break
                else:
                    cleaned.append((prj, changeset))
            return cleaned
        return pending_changes

    def _on_changes_available(self, changes):
        if isinstance(changes, RefactoringError):
            api.events.post(RefactoringErrorEvent(changes), False)
            return
        _, self._pending_changes = changes

        self._pending_changes = self.clean_changes(self._pending_changes)

        if self._pending_changes is None:
            return
        if self._preview and self._pending_changes:
            self._create_review_dock()
            self._update_preview()
        else:
            self._refactor()

    def _on_find_usages_finished(self, results):
        if results is None:
            # todo: show no results notification
            return
        if isinstance(results, RefactoringError):
            api.events.post(RefactoringErrorEvent(results), False)
            return
        if self._occurrences_results is None:
            self._create_occurrences_dock()
        else:
            self._occurrences_dock.show()
            self._occurrences_dock.button.show()
            self._occurrences_dock.button.action.setVisible(True)
        self._occurrences_results.show_results(
            results, self._occurrence_to_search)

    @staticmethod
    def apply_preferences():
        for editor in api.editor.get_all_editors(True):
            if isinstance(editor, PyCodeEdit):
                actions = editor.refactoring_actions
                items = [
                    ('usages', 'Find usages', _('Find usages'), 'Alt+F7'),
                    ('rename', 'Refactor: rename', _('Refactor: rename'),
                     'Shift+F6'),
                    ('extract_method', 'Refactor: extract method',
                     _('Refactor: extract method'), 'Ctrl+Alt+M'),
                    ('extract_var', 'Refactor: extract variable',
                     _('Refactor: extract variable'), 'Ctrl+Alt+V'),
                    ('imports', 'Refactor: organize imports',
                     _('Refactor: organize imports'), 'Alt+F8')
                ]
                for id, name, text, default in items:
                    actions[id].setShortcut(api.shortcuts.get(
                        name, text, default))

                actions['extract_var'].setIcon(special_icons.variable_icon())

    def create_refactor_menu(self, editor):
        """
        Creates the refactor menu; this menu will appear in the menu bar of the
        main window and in the context menu of any python editor.
        """
        mnu_refactor = QtWidgets.QMenu(editor)
        mnu_refactor.setTitle(_('Refactor'))
        mnu_refactor.setIcon(QtGui.QIcon.fromTheme('edit-rename'))

        action_find_usages = mnu_refactor.addAction(_('Find usages'))
        action_find_usages.setToolTip(
            _('Find occurrences of symbol under cursor'))
        action_find_usages.setIcon(QtGui.QIcon.fromTheme('edit-find'))
        action_find_usages.setShortcut(
            api.shortcuts.get('Find usages', _('Find usages'), 'Alt+F7'))
        action_find_usages.triggered.connect(self.find_usages)

        # Rename
        action_rename = mnu_refactor.addAction(_('Rename'))
        action_rename.setToolTip(_('Rename symnbol under cursor'))
        action_rename.setIcon(QtGui.QIcon.fromTheme('edit-find-replace'))
        action_rename.setShortcut(
            api.shortcuts.get('Refactor: rename', _('Refactor: rename'),
                              'Shift+F6'))
        action_rename.triggered.connect(self.rename)

        # Extract variable
        action_extract_var = mnu_refactor.addAction(_('Extract variable'))
        action_extract_var.setToolTip(
            _('Extract variable (a statement must be selected)'))
        action_extract_var.setIcon(special_icons.variable_icon())
        action_extract_var.setShortcut(
            api.shortcuts.get('Refactor: extract variable',
                              _('Refactor: extract variable'), 'Ctrl+Alt+V'))
        action_extract_var.triggered.connect(self.extract_variable)

        # Extract method
        action_extract_method = mnu_refactor.addAction(_('Extract method'))
        action_extract_method.setToolTip(
            _('Extract method (some statements must be selected)'))
        action_extract_method.setIcon(special_icons.function_icon())
        action_extract_method.setShortcut(
            api.shortcuts.get('Refactor: extract method',
                              _('Refactor: extract method'), 'Ctrl+Alt+M'))
        action_extract_method.triggered.connect(self.extract_method)

        mnu_refactor.addSeparator()

        action_organize_imports = mnu_refactor.addAction(_('Organize imports'))
        action_organize_imports.setToolTip(
            _('Organize top level imports (sort, remove unused,...)'))
        action_organize_imports.setIcon(special_icons.namespace_icon())
        action_organize_imports.setShortcut(
            api.shortcuts.get('Refactor: organize imports',
                              _('Refactor: organize imports'), 'Alt+F8'))
        action_organize_imports.triggered.connect(self.organise_imports)

        actions = {
            'usages': action_find_usages,
            'rename': action_rename,
            'extract_method': action_extract_method,
            'extract_var': action_extract_var,
            'imports': action_organize_imports
        }

        return mnu_refactor, actions

    def _on_current_project_changed(self, path):
        """
        Changes the active rope project when the current project changed in
        the IDE.
        :param path: Path of the new project.
        """
        self._main_project.close()
        self._main_project = Project(path, ropefolder=api.project.FOLDER,
                                     fscommands=FileSystemCommands())
        self._main_project.validate()

    def _on_editor_created(self, editor):
        """
        Adds the refactor menu to the editor that have just been created.
        :param editor: editor to modify.
        """
        if isinstance(editor, PyCodeEdit):
            sep = QtWidgets.QAction(editor)
            sep.setSeparator(True)
            menu, actions = self.create_refactor_menu(editor)
            editor.insert_action(menu.menuAction(), 0)
            editor.refactoring_actions = actions
            editor.insert_action(sep, 1)
            editor.cursorPositionChanged.connect(
                self._update_edit_actions_state)

    @staticmethod
    def _update_edit_actions_state(editor=None):
        if editor is None:
            editor = api.editor.get_current_editor()
        if isinstance(editor, PyCodeEdit):
            flg = bool(TextHelper(editor).word_under_cursor(
                select_whole_word=True).selectedText())
            try:
                editor.refactoring_actions
            except AttributeError:
                return
            else:
                editor.refactoring_actions['usages'].setEnabled(flg)
                editor.refactoring_actions['rename'].setEnabled(flg)
                flg = editor.textCursor().hasSelection()
                editor.refactoring_actions['extract_method'].setEnabled(flg)
                editor.refactoring_actions['extract_var'].setEnabled(flg)

    def _create_occurrences_dock(self):
        """
        Creates the dock widget that shows all the occurrences of a python
        name.
        """
        self._occurrences_widget = QtWidgets.QWidget()
        vlayout = QtWidgets.QVBoxLayout()
        # buttons
        self._setup_occurrences_buttons(vlayout)
        self._occurrences_results = FindResultsWidget(term='usages')
        self._occurrences_results.itemActivated.connect(
            self._on_occurrence_activated)
        vlayout.addWidget(self._occurrences_results)
        self._occurrences_widget.setLayout(vlayout)
        # Dock widget
        self._occurrences_dock = api.window.add_dock_widget(
            self._occurrences_widget, _('Find usages'),
            QtGui.QIcon.fromTheme('edit-find'),
            QtCore.Qt.BottomDockWidgetArea)

    @staticmethod
    def _on_occurrence_activated(item):
        assert isinstance(item, QtWidgets.QTreeWidgetItem)
        data = item.data(0, QtCore.Qt.UserRole)
        try:
            l = data['line']
        except TypeError:
            return  # file item or root item
        l = data['line']
        start = data['start']
        lenght = data['end'] - start
        if data is not None:
            # open editor and go to line/column
            editor = api.editor.open_file(
                data['path'], data['line'], data['start'])
            if editor is None:
                return
            # select text
            helper = TextHelper(editor)
            cursor = helper.select_lines(start=l, end=l)
            cursor.movePosition(cursor.StartOfBlock)
            cursor.movePosition(cursor.Right, cursor.MoveAnchor, start)
            cursor.movePosition(cursor.Right, cursor.KeepAnchor, lenght)
            editor.setTextCursor(cursor)

    def _setup_occurrences_buttons(self, vlayout):
        """
        Creates the occurrences dock widget buttons
        :param vlayout: main layout
        """
        buttons = QtWidgets.QWidget()
        buttons_layout = QtWidgets.QHBoxLayout()
        buttons_layout.setContentsMargins(0, 0, 0, 0)
        # Close
        bt = QtWidgets.QPushButton()
        bt.setText(_('Close'))
        bt.clicked.connect(self._remove_occurrences_dock)
        buttons_layout.addWidget(bt)
        # Spacer
        buttons_layout.addSpacerItem(QtWidgets.QSpacerItem(
            20, 20, QtWidgets.QSizePolicy.Expanding))
        buttons.setLayout(buttons_layout)
        vlayout.addWidget(buttons)

    def _create_review_dock(self):
        """
        Creates the dock widget that shows the refactor diff.
        """
        if self._review_widget:
            self._preview_dock.show()
            self._preview_dock.button.show()
            self._preview_dock.button.action.setVisible(True)
            return
        self._review_widget = QtWidgets.QWidget()
        vlayout = QtWidgets.QVBoxLayout()
        # buttons
        bt_refactor = self._setup_review_buttons(vlayout)
        # Diff viewer
        self._viewer = DiffViewer()
        vlayout.addWidget(self._viewer)
        self._review_widget.setLayout(vlayout)

        # Dock widget
        self._preview_dock = api.window.add_dock_widget(
            self._review_widget, _('Review'),
            QtGui.QIcon.fromTheme('edit-find'),
            QtCore.Qt.BottomDockWidgetArea)
        bt_refactor.setFocus()

    def _update_preview(self):
        try:
            texts = []
            for prj, changes in self._pending_changes:
                lines = ''
                for subchanges in changes.changes:
                    resource = subchanges.get_changed_resources()[0]
                    resource_path = resource.real_path
                    if prj.address + os.sep in resource_path:
                        desc = subchanges.get_description()
                        lines += desc
                if lines:
                    texts.append('%s\n\n*** Project: %s\n\n%s\n' %
                                 (str(changes), prj.address, lines))
            self._viewer.setPlainText('\n'.join(texts))
        except TypeError:
            # not multiproj, one single change set
            self._viewer.setPlainText(self._pending_changes.get_description())

    def _setup_review_buttons(self, vlayout):
        """
        Creates the buttons of the preview dock widget
        :param vlayout: main layout
        """
        buttons = QtWidgets.QWidget()
        buttons_layout = QtWidgets.QHBoxLayout()
        buttons_layout.setContentsMargins(0, 0, 0, 0)
        bt_refactor = bt = QtWidgets.QPushButton()
        bt.setText(_('Refactor'))
        bt.clicked.connect(self._refactor)
        buttons_layout.addWidget(bt)
        # Close
        bt = QtWidgets.QPushButton()
        bt.setText(_('Cancel'))
        bt.clicked.connect(self._remove_preview_dock)
        buttons_layout.addWidget(bt)
        # Spacer
        buttons_layout.addSpacerItem(QtWidgets.QSpacerItem(
            20, 20, QtWidgets.QSizePolicy.Expanding))
        buttons.setLayout(buttons_layout)
        vlayout.addWidget(buttons)

        return bt_refactor

    def _remove_preview_dock(self):
        """
        Removes the preview dock widget
        """
        if self._preview_dock is not None:
            self._preview_dock.hide()
            self._preview_dock.button.hide()
            self._preview_dock.button.action.setVisible(False)

    def _remove_occurrences_dock(self):
        """
        Removes the occurrences dock widget.
        """
        if self._occurrences_dock is not None:
            self._occurrences_dock.hide()
            self._occurrences_dock.button.hide()
            self._occurrences_dock.button.action.setVisible(False)

    def _refactor(self):
        """
        Performs the refactoring.
        """
        main_project = self._main_project
        multiproj = self._has_multiple_projects()
        pending_changes = self._pending_changes
        api.tasks.start(_('Refactoring: apply pending changes'),
                        apply_pending_changes, self._on_refactoring_finished,
                        args=(main_project, multiproj, pending_changes),
                        use_thread=True)

    def _on_refactoring_finished(self, ret_val):
        self._remove_preview_dock()
        if ret_val is not True:
            api.events.post(RefactoringErrorEvent(ret_val), False)

    @staticmethod
    def _get_other_projects(path_only=False):
        """
        Gets the list of secondary projects (all except current).
        """
        projects = []
        current = api.project.get_current_project()
        for path in api.project.get_projects():
            if path == current:
                continue
            if not path_only:
                prj = Project(path, ropefolder=api.project.FOLDER,
                              fscommands=FileSystemCommands())
                prj.validate()
            else:
                prj = path
            projects.append(prj)
        return projects

    @staticmethod
    def _has_multiple_projects():
        """
        Checks whether multiple project have been opened in the main window.
        :return: True if window has multiple project, False if window only has
                 one project.
        """
        return len(api.project.get_projects()) > 1

    @staticmethod
    def _on_document_saved(path, old_content):
        if not path:
            return
        project = None
        for project in api.project.get_projects():
            prj_path = project + os.sep
            if prj_path in path:
                project = Project(prj_path, ropefolder=api.project.FOLDER,
                                  fscommands=FileSystemCommands())
                break
        if project:
            if path.endswith('_rc.py'):
                return
            api.tasks.start(_('Refactoring: reporting changes'),
                            report_changes, None,
                            args=(project, path, old_content),
                            use_thread=False)

    @staticmethod
    def _get_real_position(position):
        """
        Gets the real cursor position (there might be a difference between
        editor content and file system content because of clean_trailing
        whitespaces on save). This function will converts the absolute position
        into a line/column pair and use this info to get the position in the
        file.
        """
        tc = api.editor.get_current_editor().textCursor()
        tc.setPosition(position)
        l = tc.blockNumber()
        c = tc.positionInBlock()
        e = api.editor.get_current_editor().file.encoding
        path = api.editor.get_current_editor().file.path
        try:
            with open(path, 'r', encoding=e) as f:
                lines = f.readlines()
        except OSError:
            _logger().exception('failed to read file %s', path)
            lines = []
        real_pos = 0
        for i, line in enumerate(lines):
            if i == l:
                real_pos += c
                break
            else:
                real_pos += len(line)
        return real_pos
Пример #55
0
from rope.base.project import Project
from rope.refactor.rename import Rename
from rope.contrib import generate
project = Project('.')
pycore = project.pycore
package = pycore.find_module('sindice')
changes = Rename(project, package).get_changes('core')
project.do(changes)
Пример #56
0
class CodimensionProject( QObject ):
    " Provides codimension project singleton facility "

    # Constants for the projectChanged signal
    CompleteProject = 0     # It is a completely new project
    Properties      = 1     # Project properties were updated

    projectChanged = pyqtSignal( int )
    fsChanged = pyqtSignal( list )

    def __init__( self ):
        QObject.__init__( self )

        self.__dirWatcher = None
        self.__formatOK = True

        # Avoid pylint complains
        self.fileName = ""
        self.userProjectDir = ""    # Directory in ~/.codimension/uuidNN/
        self.filesList = set()

        self.scriptName = ""        # Script to run the project
        self.creationDate = ""
        self.author = ""
        self.license = ""
        self.copyright = ""
        self.version = ""
        self.email = ""
        self.description = ""
        self.uuid = ""

        self.__ropeProject = None
        self.__ropeSourceDirs = []

        # Coming from separate files from ~/.codimension/uuidN/
        self.todos = []
        self.bookmarks = []
        self.runParamsCache = RunParametersCache()
        self.topLevelDirs = []
        self.findHistory = []
        self.findNameHistory = []
        self.findFileHistory = []
        self.replaceHistory = []
        self.tabsStatus = []

        self.findFilesWhat = []
        self.findFilesDirs = []
        self.findFilesMasks = []

        self.findClassHistory = []
        self.findFuncHistory = []
        self.findGlobalHistory = []

        self.recentFiles = []
        self.importDirs = []
        self.fileBrowserPaths = []

        self.ignoredExcpt = []
        self.breakpoints = []
        self.watchpoints = []

        # Precompile the exclude filters
        self.__excludeFilter = []
        for flt in Settings().projectFilesFilters:
            self.__excludeFilter.append( re.compile( flt ) )

        return

    def shouldExclude( self, name ):
        " Tests if a file must be excluded "
        for excl in self.__excludeFilter:
            if excl.match( name ):
                return True
        return False

    def __resetValues( self ):
        """ Initializes or resets all the project members """

        # Empty file name means that the project has not been loaded or
        # created. This must be an absolute path.
        self.fileName = ""
        self.userProjectDir = ""

        # Generated having the project dir Full paths are stored.
        # The set holds all files and directories. The dirs end with os.path.sep
        self.filesList = set()

        self.scriptName = ""
        self.creationDate = ""
        self.author = ""
        self.license = ""
        self.copyright = ""
        self.version = ""
        self.email = ""
        self.description = ""
        self.uuid = ""

        # Coming from separate files from ~/.codimension/uuidN/
        self.todos = []
        self.bookmarks = []
        self.runParamsCache = RunParametersCache()
        self.topLevelDirs = []
        self.findHistory = []
        self.findNameHistory = []
        self.findFileHistory = []
        self.replaceHistory = []
        self.tabsStatus = []

        self.findFilesWhat = []
        self.findFilesDirs = []
        self.findFilesMasks = []

        self.findClassHistory = []
        self.findFuncHistory = []
        self.findGlobalHistory = []

        self.recentFiles = []
        self.importDirs = []
        self.fileBrowserPaths = []

        self.ignoredExcpt = []
        self.breakpoints = []
        self.watchpoints = []

        # Reset the dir watchers if so
        if self.__dirWatcher is not None:
            del self.__dirWatcher
        self.__dirWatcher = None
        return

    def createNew( self, fileName, scriptName, importDirs, author, lic,
                   copyRight, description, creationDate, version, email ):
        " Creates a new project "

        # Try to create the user project directory
        projectUuid = str( uuid.uuid1() )
        userProjectDir = settingsDir + projectUuid + sep
        if not os.path.exists( userProjectDir ):
            try:
                os.mkdir( userProjectDir )
            except:
                logging.error( "Cannot create user project directory: " +
                               self.userProjectDir + ". Please check the "
                               "available disk space and re-create the "
                               "project." )
                raise
        else:
            logging.warning( "The user project directory existed! "
                             "The content will be overwritten." )
            self.__removeProjectFiles( userProjectDir )

        # Basic pre-requisites are met. We can reset the current project
        self.__resetValues()

        self.fileName = str( fileName )
        self.importDirs = importDirs
        self.scriptName = scriptName
        self.creationDate = creationDate
        self.author = author
        self.license = lic
        self.copyright = copyRight
        self.version = version
        self.email = email
        self.description = description
        self.uuid = projectUuid
        self.userProjectDir = userProjectDir

        self.__createProjectFile()  # ~/.codimension/uuidNN/project

        self.__generateFilesList()

        self.saveProject()

        # Update the watcher
        self.__dirWatcher = Watcher( Settings().projectFilesFilters,
                                     self.getProjectDir() )
        self.__dirWatcher.fsChanged.connect( self.onFSChanged )

        self.__createRopeProject()
        self.projectChanged.emit( self.CompleteProject )
        return

    @staticmethod
    def __safeRemove( path ):
        " Safe file removal "
        try:
            os.remove( path )
        except:
            return

    def __removeProjectFiles( self, userProjectDir ):
        " Removes user project files "

        self.__safeRemove( userProjectDir + "project" )
        self.__safeRemove( userProjectDir + "bookmarks" )
        self.__safeRemove( userProjectDir + "todos" )
        self.__safeRemove( userProjectDir + "searchhistory" )
        self.__safeRemove( userProjectDir + "topleveldirs" )
        self.__safeRemove( userProjectDir + "tabsstatus" )
        self.__safeRemove( userProjectDir + "findinfiles" )
        self.__safeRemove( userProjectDir + "recentfiles" )
        self.__safeRemove( userProjectDir + "filebrowser" )
        self.__safeRemove( userProjectDir + "ignoredexcpt" )
        self.__safeRemove( userProjectDir + "breakpoints" )
        self.__safeRemove( userProjectDir + "watchpoints" )
        return

    def __createProjectFile( self ):
        " Helper function to create the user project file "
        try:
            f = open( self.userProjectDir + "project", "w" )
            f.write( self.fileName )
            f.close()
        except:
            return

    def saveProject( self ):
        " Writes all the settings into the file "
        if not self.isLoaded():
            return

        # Project properties part
        propertiesPart = "[properties]\n" \
                         "scriptname=" + self.scriptName + "\n" \
                         "creationdate=" + self.creationDate + "\n" \
                         "author=" + self.author + "\n" \
                         "license=" + self.license + "\n" \
                         "copyright=" + self.copyright + "\n" \
                         "description=" + \
                            self.description.replace( '\n', '<CR><LF>' ) + \
                            "\n" \
                         "version=" + self.version + "\n" \
                         "email=" + self.email + "\n" \
                         "uuid=" + self.uuid + "\n"

        # It could be another user project file without write permissions
        skipProjectFile = False
        if os.path.exists( self.fileName ):
            if not os.access( self.fileName, os.W_OK ):
                skipProjectFile = True
        else:
            if not os.access( os.path.dirname( self.fileName ), os.W_OK ):
                skipProjectFile = True

        if not skipProjectFile:
            f = open( self.fileName, "w" )
            self.__writeHeader( f )
            self.__writeList( f, "importdirs", "dir", self.importDirs )
            f.write( propertiesPart + "\n\n\n" )
            f.close()

        self.serializeRunParameters()
        self.__saveTopLevelDirs()
        self.__saveSearchHistory()
        self.__saveTabsStatus()
        self.__saveFindFiles()
        self.__saveFindObjects()
        self.__saveRecentFiles()
        self.__saveIgnoredExcpt()
        self.__saveBreakpoints()
        self.__saveWatchpoints()

        self.__formatOK = True
        return

    def serializeRunParameters( self ):
        " Saves the run parameters cache "
        self.runParamsCache.serialize( self.userProjectDir + "runparamscache" )
        return

    def __saveTabsStatus( self ):
        " Helper to save tabs status "
        if self.isLoaded():
            f = open( self.userProjectDir + "tabsstatus", "w" )
            self.__writeHeader( f )
            self.__writeList( f, "tabsstatus", "tab", self.tabsStatus )
            f.close()
        return

    def __saveSearchHistory( self ):
        " Helper to save the project search history "
        if self.isLoaded():
            f = open( self.userProjectDir + "searchhistory", "w" )
            self.__writeHeader( f )
            self.__writeList( f, "findhistory", "find",
                              self.findHistory )
            self.__writeList( f, "replacehistory", "replace",
                              self.replaceHistory )
            self.__writeList( f, "findnamehistory", "find",
                              self.findNameHistory )
            self.__writeList( f, "findfilehistory", "find",
                              self.findFileHistory )
            f.close()
        return

    def __saveTopLevelDirs( self ):
        " Helper to save the project top level dirs "
        if self.isLoaded():
            f = open( self.userProjectDir + "topleveldirs", "w" )
            self.__writeHeader( f )
            self.__writeList( f, "topleveldirs", "dir", self.topLevelDirs )
            f.close()
        return

    def __saveFindFiles( self ):
        " Helper to save the find in files history "
        if self.isLoaded():
            f = open( self.userProjectDir + "findinfiles", "w" )
            self.__writeHeader( f )
            self.__writeList( f, "whathistory", "what", self.findFilesWhat )
            self.__writeList( f, "dirhistory", "dir", self.findFilesDirs )
            self.__writeList( f, "maskhistory", "mask", self.findFilesMasks )
            f.close()
        return

    def __saveFindObjects( self ):
        " Helper to save find objects history "
        if self.isLoaded():
            f = open( self.userProjectDir + "findobjects", "w" )
            self.__writeHeader( f )
            self.__writeList( f, "classhistory", "class",
                              self.findClassHistory )
            self.__writeList( f, "funchistory", "func",
                              self.findFuncHistory )
            self.__writeList( f, "globalhistory", "global",
                              self.findGlobalHistory )
            f.close()
        return

    def __saveSectionToFile( self, fileName, sectionName, itemName, values ):
        " Saves the given values into a file "
        if self.isLoaded():
            f = open( self.userProjectDir + fileName, "w" )
            self.__writeHeader( f )
            self.__writeList( f, sectionName, itemName, values )
            f.close()
        return

    def __saveRecentFiles( self ):
        " Helper to save recent files list "
        self.__saveSectionToFile( "recentfiles", "recentfiles", "file",
                                  self.recentFiles )
        return

    def __saveIgnoredExcpt( self ):
        " Helper to save ignored exceptions list "
        self.__saveSectionToFile( "ignoredexcpt", "ignoredexcpt",
                                  "excpttype", self.ignoredExcpt )
        return

    def __saveBreakpoints( self ):
        " Helper to save breakpoints "
        self.__saveSectionToFile( "breakpoints", "breakpoints",
                                  "bpoint", self.breakpoints )
        return

    def __saveWatchpoints( self ):
        " helper to save watchpoints "
        self.__saveSectionToFile( "watchpoints", "watchpoints",
                                  "wpoint", self.watchpoints )
        return

    @staticmethod
    def __writeHeader( fileObj ):
        " Helper to write a header with a warning "
        fileObj.write( "#\n"
                       "# Generated automatically.\n"
                       "# Don't edit it manually unless you "
                       "know what you are doing.\n"
                       "#\n\n" )
        return

    @staticmethod
    def __writeList( fileObj, header, prefix, items ):
        " Helper to write a list "
        fileObj.write( "[" + header + "]\n" )
        index = 0
        for item in items:
            fileObj.write( prefix + str( index ) + "=" + item + "\n" )
            index += 1
        fileObj.write( "\n" )
        return

    def __getStr( self, conf, sec, key, default ):
        " Helper to read a config value "
        try:
            return conf.get( sec, key ).strip()
        except:
            self.__formatOK = False
        return default

    def loadProject( self, projectFile ):
        """ Loads a project from the given file """

        absPath = os.path.abspath( projectFile )
        if not os.path.exists( absPath ):
            raise Exception( "Cannot open project file " + projectFile )
        if not absPath.endswith( ".cdm" ):
            raise Exception( "Unexpected project file extension. "
                             "Expected: .cdm" )

        config = ConfigParser.ConfigParser()

        try:
            config.read( absPath )
        except:
            # Bad error - cannot load project file at all
            config = None
            raise Exception( "Bad project file" )


        self.__resetValues()
        self.fileName = str( absPath )

        # Properties part
        self.scriptName = self.__getStr( config, 'properties',
                                                 'scriptname', '' )
        self.creationDate = self.__getStr( config, 'properties',
                                                   'creationdate', '' )
        self.author = self.__getStr( config, 'properties', 'author', '' )
        self.license = self.__getStr( config, 'properties', 'license', '' )
        self.copyright = self.__getStr( config, 'properties', 'copyright', '' )
        self.description = self.__getStr( config, 'properties', 'description',
                                          '' ).replace( '<CR><LF>', '\n' )
        self.version = self.__getStr( config, 'properties', 'version', '' )
        self.email = self.__getStr( config, 'properties', 'email', '' )
        self.uuid = self.__getStr( config, 'properties', 'uuid', '' )
        if self.uuid == "":
            logging.warning( "Project file does not have UUID. "
                             "Re-generate it..." )
            self.uuid = str( uuid.uuid1() )
        self.userProjectDir = settingsDir + self.uuid + sep
        if not os.path.exists( self.userProjectDir ):
            os.mkdir( self.userProjectDir )

        # import dirs part
        index = 0
        try:
            while True:
                dirName = config.get( 'importdirs',
                                      'dir' + str( index ) ).strip()
                index += 1
                if os.path.isabs( dirName ):
                    absPath = dirName
                else:
                    absPath = self.getProjectDir() + dirName
                if not os.path.exists( absPath ):
                    logging.error( "Codimension project: cannot find "
                                   "import directory: " + dirName )
                elif not isdir( absPath ):
                    logging.error( "Codimension project: the import path: " +
                                   dirName + " is not a directory" )
                self.importDirs.append( dirName )
        except ConfigParser.NoSectionError:
            self.__formatOK = False
        except ConfigParser.NoOptionError:
            # just continue
            pass
        except:
            self.__formatOK = False

        config = None

        # Read the other config files
        self.__loadTopLevelDirs()
        self.__loadSearchHistory()
        self.__loadTabsStatus()
        self.__loadFindFiles()
        self.__loadFindObjects()
        self.__loadRecentFiles()
        self.__loadProjectBrowserExpandedDirs()
        self.__loadIgnoredExceptions()
        self.__loadBreakpoints()
        self.__loadWatchpoints()

        # The project might have been moved...
        self.__createProjectFile()  # ~/.codimension/uuidNN/project
        self.__generateFilesList()

        if os.path.exists( self.userProjectDir + "runparamscache" ):
            self.runParamsCache.deserialize( self.userProjectDir +
                                             "runparamscache" )

        if not self.__formatOK:
            logging.info( "Project files are broken or absent. "
                          "Overwriting the project files." )
            self.saveProject()

        # Update the recent list
        Settings().addRecentProject( self.fileName )

        # Setup the new watcher
        self.__dirWatcher = Watcher( Settings().projectFilesFilters,
                                     self.getProjectDir() )
        self.__dirWatcher.fsChanged.connect( self.onFSChanged )

        self.__createRopeProject()
        self.projectChanged.emit( self.CompleteProject )
        self.emit( SIGNAL( 'restoreProjectExpandedDirs' ) )
        return

    def getImportDirsAsAbsolutePaths( self ):
        " Provides a list of import dirs as absolute paths "
        result = []
        for path in self.importDirs:
            if os.path.isabs( path ):
                result.append( path )
            else:
                result.append( self.getProjectDir() + path )
        return result

    def __getImportDirsForRope( self ):
        " Provides the list of import dirs for the rope library "
        result = []
        for path in self.importDirs:
            if not os.path.isabs( path ):
                # The only relative paths can be accepted by rope
                result.append( path )
        result.sort()
        return result

    def getRopeProject( self ):
        " Provides the rope project "
        if self.__getImportDirsForRope() != self.__ropeSourceDirs:
            # The user changed the project import dirs, so let's
            # re-create the project
            self.__createRopeProject()
        return self.__ropeProject

    def validateRopeProject( self, fileName ):
        " Validates the rope project "
        # Currently rope can validate a directory only so the argument
        # is ignored
        self.__ropeProject.validate()
        return

    def __createRopeProject( self ):
        " Creates a rope library project "
        if self.__ropeProject is not None:
            self.__ropeProject.close()
            self.__ropeProject = None
            self.__ropeSourceDirs = []

        # Deal with import dirs and preferences first
        self.__ropeSourceDirs = self.__getImportDirsForRope()
        prefs = copy.deepcopy( ropePreferences )
        if len( self.__ropeSourceDirs ) != 0:
            prefs[ "source_folders" ] = self.__ropeSourceDirs

        # Rope folder is default here, so it will be created
        self.__ropeProject = RopeProject( self.getProjectDir(),
                                          **prefs )
        self.__ropeProject.validate( self.__ropeProject.root )
        return

    def onFSChanged( self, items ):
        " Triggered when the watcher detects changes "
##        report = "REPORT: "
##        projectItems = []
        for item in items:
            item = str( item )

#            if not islink( item ):
#                realPath = realpath( item[ 1: ] )
#                isDir = item.endswith( sep )
#                if isDir:
#                    if self.isProjectDir( realPath + sep ):
#                        item = item[ 0 ] + realPath + sep
#                else:
#                    if self.isProjectFile( realPath + sep ):
#                        item = item[ 0 ] + realPath

#            projectItems.append( item )
##            report += " " + item
            try:
                if item.startswith( '+' ):
                    self.filesList.add( item[ 1: ] )
                else:
                    self.filesList.remove( item[ 1: ] )
##                projectItems.append( item )
            except:
#                print "EXCEPTION for '" + item + "'"
                pass
#        print "'" + report + "'"

        self.fsChanged.emit( items )
#        self.__dirWatcher.debug()
        return

    def __loadTabsStatus( self ):
        " Loads the last tabs status "
        configFile = self.userProjectDir + "tabsstatus"
        if not os.path.exists( configFile ):
            logging.info( "Cannot find tabsstatus project file. "
                          "Expected here: " + configFile )
            self.__formatOK = False
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( configFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read tabsstatus project file "
                             "from here: " + configFile )
            return

        # tabs part
        self.tabsStatus = self.__loadListSection( config, 'tabsstatus', 'tab' )

        config = None
        return

    def __loadProjectBrowserExpandedDirs( self ):
        " Loads the project browser expanded dirs "
        configFile = self.userProjectDir + "filebrowser"
        if not os.path.exists( configFile ):
            self.fileBrowserPaths = []
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( configFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.fileBrowserPaths = []
            return

        # dirs part
        self.fileBrowserPaths = self.__loadListSection( config, 'filebrowser',
                                                        'path' )
        config = None
        return

    def __loadTopLevelDirs( self ):
        " Loads the top level dirs "
        configFile = self.userProjectDir + "topleveldirs"
        if not os.path.exists( configFile ):
            logging.info( "Cannot find topleveldirs project file. "
                          "Expected here: " + configFile )
            self.__formatOK = False
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( configFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read topleveldirs project file "
                             "from here: " + configFile )
            return

        # dirs part
        self.topLevelDirs = self.__loadListSection(
                config, 'topleveldirs', 'dir' )

        config = None
        return

    def __loadSearchHistory( self ):
        " Loads the search history file content "
        confFile = self.userProjectDir + "searchhistory"
        if not os.path.exists( confFile ):
            logging.info( "Cannot find searchhistory project file. "
                          "Expected here: " + confFile )
            self.__formatOK = False
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( confFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read searchhistory project file "
                             "from here: " + confFile )
            return

        # find part
        self.findHistory = self.__loadListSection(
                config, 'findhistory', 'find' )
        self.findNameHistory = self.__loadListSection(
                config, 'findnamehistory', 'find' )
        self.findFileHistory = self.__loadListSection(
                config, 'findfilehistory', 'find' )

        # replace part
        self.replaceHistory = self.__loadListSection(
                config, 'replacehistory', 'replace' )

        config = None
        return

    def __loadFindObjects( self ):
        " Loads the find objects history "
        confFile = self.userProjectDir + "findobjects"
        if not os.path.exists( confFile ):
            logging.info( "Cannot find findobjects project file. "
                          "Expected here: " + confFile )
            self.__formatOK = False
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( confFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read findobjects project file "
                             "from here: " + confFile )
            return

        self.findClassHistory = self.__loadListSection(
                config, 'classhistory', 'class' )
        self.findFuncHistory = self.__loadListSection(
                config, 'funchistory', 'func' )
        self.findGlobalHistory = self.__loadListSection(
                config, 'globalhistory', 'global' )
        config = None
        return

    def __loadFindFiles( self ):
        " Loads the find in files history "
        confFile = self.userProjectDir + "findinfiles"
        if not os.path.exists( confFile ):
            logging.info( "Cannot find findinfiles project file. "
                          "Expected here: " + confFile )
            self.__formatOK = False
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( confFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read findinfiles project file "
                             "from here: " + confFile )
            return

        self.findFilesWhat = self.__loadListSection(
                config, 'whathistory', 'what' )
        self.findFilesDirs = self.__loadListSection(
                config, 'dirhistory', 'dir' )
        self.findFilesMasks = self.__loadListSection(
                config, 'maskhistory', 'mask' )
        config = None
        return

    def __loadRecentFiles( self ):
        " Loads the recent files list "
        confFile = self.userProjectDir + "recentfiles"
        if not os.path.exists( confFile ):
            logging.info( "Cannot find recentfiles project file. "
                          "Expected here: " + confFile )
            self.__formatOK = False
            return

        config = ConfigParser.ConfigParser()
        try:
            config.read( confFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read recentfiles project file "
                             "from here: " + confFile )
            return

        self.recentFiles = self.__loadListSection(
                config, 'recentfiles', 'file' )

        # Due to a bug there could be the same files twice in the list.
        # The difference is doubled path separator. Fix it here.
        temp = set()
        for path in self.recentFiles:
            temp.add( os.path.normpath( path ) )
        self.recentFiles = list( temp )

        config = None
        return

    def __loadSectionFromFile( self, fileName, sectionName, itemName,
                               errMessageEntity ):
        " Loads the given section from the given file "
        confFile = self.userProjectDir + fileName
        if not os.path.exists( confFile ):
            logging.info( "Cannot find " + errMessageEntity + " file. "
                          "Expected here: " + confFile )
            self.__formatOK = False
            return []

        config = ConfigParser.ConfigParser()
        try:
            config.read( confFile )
        except:
            # Bad error - cannot load project file at all
            config = None
            self.__formatOK = False
            logging.warning( "Cannot read " + errMessageEntity + " file "
                             "from here: " + confFile )
            return []

        values = self.__loadListSection( config, sectionName, itemName )
        config = None
        return values

    def __loadIgnoredExceptions( self ):
        " Loads the ignored exceptions list "
        self.ignoredExcpt = self.__loadSectionFromFile(
                                    "ignoredexcpt", "ignoredexcpt",
                                    "excpttype", "ignored exceptions" )
        return

    def __loadBreakpoints( self ):
        " Loads the project breakpoints "
        self.breakpoints = self.__loadSectionFromFile(
                                    "breakpoints", "breakpoints",
                                    "bpoint", "breakpoints" )
        return

    def __loadWatchpoints( self ):
        " Loads the project watchpoints "
        self.watchpoints = self.__loadSectionFromFile(
                                    "watchpoints", "watchpoints",
                                    "wpoint", "watchpoints" )
        return

    def __loadListSection( self, config, section, listPrefix ):
        " Loads a list off the given section from the given file "
        items = []
        index = 0
        try:
            while True:
                item = config.get( section, listPrefix + str(index) ).strip()
                index += 1
                items.append( item )
        except ConfigParser.NoSectionError:
            self.__formatOK = False
        except ConfigParser.NoOptionError:
            pass    # Just continue
        except:
            self.__formatOK = False
        return items

    def unloadProject( self, emitSignal = True ):
        """ Unloads the current project if required """
        self.emit( SIGNAL( 'projectAboutToUnload' ) )
        if self.isLoaded():
            self.__saveProjectBrowserExpandedDirs()
        self.__resetValues()
        if emitSignal:
            # No need to send a signal e.g. if IDE is closing
            self.projectChanged.emit( self.CompleteProject )
        if self.__ropeProject is not None:
            try:
                # If the project directory is read only then closing the
                # rope project generates exception
                self.__ropeProject.close()
            except:
                pass
        self.__ropeProject = None
        self.__ropeSourceDirs = []
        return

    def __saveProjectBrowserExpandedDirs( self ):
        " Saves the pathes expanded in the project browser "
        if not self.isLoaded():
            return

        try:
            f = open( self.userProjectDir + "filebrowser", "w" )
            self.__writeHeader( f )
            self.__writeList( f, "filebrowser", "path", self.fileBrowserPaths )
            f.close()
        except:
            pass
        return

    def setImportDirs( self, paths ):
        " Sets a new set of the project import dirs "
        if self.importDirs != paths:
            self.importDirs = paths
            self.saveProject()
            self.projectChanged.emit( self.Properties )
        return

    def __generateFilesList( self ):
        """ Generates the files list having the list of dirs """
        self.filesList = set()
        path = self.getProjectDir()
        self.filesList.add( path )
        self.__scanDir( path )
        return

    def __scanDir( self, path ):
        """ Recursive function to scan one dir """
        # The path is with '/' at the end
        for item in os.listdir( path ):
            if self.shouldExclude( item ):
                continue

            # Exclude symlinks if they point to the other project
            # covered pieces
            candidate = path + item
            if islink( candidate ):
                realItem = realpath( candidate )
                if isdir( realItem ):
                    if self.isProjectDir( realItem ):
                        continue
                else:
                    if self.isProjectDir( os.path.dirname( realItem ) ):
                        continue

            if isdir( candidate ):
                self.filesList.add( candidate + sep )
                self.__scanDir( candidate + sep )
                continue
            self.filesList.add( candidate )
        return

    def isProjectDir( self, path ):
        " Returns True if the path belongs to the project "
        if not self.isLoaded():
            return False
        path = realpath( str( path ) )     # it could be a symlink
        if not path.endswith( sep ):
            path += sep
        return path.startswith( self.getProjectDir() )

    def isProjectFile( self, path ):
        " Returns True if the path belongs to the project "
        if not self.isLoaded():
            return False
        return self.isProjectDir( os.path.dirname( path ) )

    def isTopLevelDir( self, path ):
        " Checks if the path is a top level dir "
        if not path.endswith( sep ):
            path += sep
        return path in self.topLevelDirs

    def addTopLevelDir( self, path ):
        " Adds the path to the top level dirs list "
        if not path.endswith( sep ):
            path += sep
        if path in self.topLevelDirs:
            logging.warning( "Top level dir " + path +
                             " is already in the list of dirs. "
                             "Ignore adding..." )
            return
        self.topLevelDirs.append( path )
        self.__saveTopLevelDirs()
        return

    def removeTopLevelDir( self, path ):
        " Removes the path from the top level dirs list "
        if not path.endswith( sep ):
            path += sep
        if path not in self.topLevelDirs:
            logging.warning( "Top level dir " + path +
                             " is not in the list of dirs. Ignore removing..." )
            return
        self.topLevelDirs.remove( path )
        self.__saveTopLevelDirs()
        return

    def setFindNameHistory( self, history ):
        " Sets the new find name history and saves it into a file "
        self.findNameHistory = history
        self.__saveSearchHistory()
        return

    def setFindFileHistory( self, history ):
        " Sets the new find file history and saves it into a file "
        self.findFileHistory = history
        self.__saveSearchHistory()
        return

    def setFindHistory( self, history ):
        " Sets the new find history and save it into a file "
        self.findHistory = history
        self.__saveSearchHistory()
        return

    def setReplaceHistory( self, whatHistory, toHistory ):
        " Sets the new replace history and save it into a file "
        self.findHistory = whatHistory
        self.replaceHistory = toHistory
        self.__saveSearchHistory()
        return

    def setTabsStatus( self, status ):
        " Sets the new tabs status and save it into a file "
        self.tabsStatus = status
        self.__saveTabsStatus()
        return

    def setFindInFilesHistory( self, what, dirs, masks ):
        " Sets the new lists and save them into a file "
        self.findFilesWhat = what
        self.findFilesDirs = dirs
        self.findFilesMasks = masks
        self.__saveFindFiles()
        return

    def setFindClassHistory( self, history ):
        " Sets the new history and saves it into a file "
        self.findClassHistory = history
        self.__saveFindObjects()
        return

    def setFindFuncHistory( self, history ):
        " Sets the new history and saves it into a file "
        self.findFuncHistory = history
        self.__saveFindObjects()
        return

    def setFindGlobalHistory( self, history ):
        " Sets the new history and saves it into a file "
        self.findGlobalHistory = history
        self.__saveFindObjects()
        return

    def updateProperties( self, scriptName, importDirs, creationDate, author,
                          lic, copy_right, version,
                          email, description ):
        " Updates the project properties "

        if self.scriptName == scriptName and \
           self.creationDate == creationDate and \
           self.author == author and \
           self.license == lic and \
           self.copyright == copy_right and \
           self.version == version and \
           self.email == email and \
           self.description == description and \
           self.importDirs == importDirs:
            # No real changes
            return

        self.importDirs = importDirs
        self.scriptName = scriptName
        self.creationDate = creationDate
        self.author = author
        self.license = lic
        self.copyright = copy_right
        self.version = version
        self.email = email
        self.description = description
        self.saveProject()
        self.projectChanged.emit( self.Properties )
        return

    def onProjectFileUpdated( self ):
        " Called when a project file is updated via direct editing "

        scriptName, importDirs, \
        creationDate, author, \
        lic, copy_right, \
        description, version, \
        email, projectUuid = getProjectProperties( self.fileName )

        self.importDirs = importDirs
        self.scriptName = scriptName
        self.creationDate = creationDate
        self.author = author
        self.license = lic
        self.copyright = copy_right
        self.version = version
        self.email = email
        self.description = description

        # no need to save, but signal just in case
        self.projectChanged.emit( self.Properties )
        return

    def isLoaded( self ):
        " returns True if a project is loaded "
        return self.fileName != ""

    def getProjectDir( self ):
        " Provides an absolute path to the project dir "
        if not self.isLoaded():
            return ""
        return os.path.dirname( realpath( self.fileName ) ) + sep

    def getProjectScript( self ):
        " Provides the project script file name "
        if not self.isLoaded():
            return ""
        if self.scriptName == "":
            return ""
        if os.path.isabs( self.scriptName ):
            return self.scriptName
        return os.path.normpath( self.getProjectDir() + self.scriptName )

    def addRecentFile( self, path ):
        " Adds a single recent file. True if a new file was inserted. "
        if path in self.recentFiles:
            self.recentFiles.remove( path )
            self.recentFiles.insert( 0, path )
            self.__saveRecentFiles()
            return False
        self.recentFiles.insert( 0, path )
        self.__saveRecentFiles()
        if len( self.recentFiles ) > 32:
            self.recentFiles = self.recentFiles[ 0 : 32 ]
        self.emit( SIGNAL( 'recentFilesChanged' ) )
        return True

    def removeRecentFile( self, path ):
        " Removes a single recent file "
        if path in self.recentFiles:
            self.recentFiles.remove( path )
            self.__saveRecentFiles()
        return

    def addExceptionFilter( self, excptType ):
        " Adds a new ignored exception type "
        if excptType not in self.ignoredExcpt:
            self.ignoredExcpt.append( excptType )
            self.__saveIgnoredExcpt()
        return

    def deleteExceptionFilter( self, excptType ):
        " Remove ignored exception type "
        if excptType in self.ignoredExcpt:
            self.ignoredExcpt.remove( excptType )
            self.__saveIgnoredExcpt()
        return

    def setExceptionFilters( self, newFilters ):
        " Sets the new filters "
        self.ignoredExcpt = newFilters
        self.__saveIgnoredExcpt()
        return

    def addBreakpoint( self, bpointStr ):
        " Adds serialized breakpoint "
        if bpointStr not in self.breakpoints:
            self.breakpoints.append( bpointStr )
            self.__saveBreakpoints()
        return

    def deleteBreakpoint( self, bpointStr ):
        " Deletes serialized breakpoint "
        if bpointStr in self.breakpoints:
            self.breakpoints.remove( bpointStr )
            self.__saveBreakpoints()
        return

    def setBreakpoints( self, bpointStrList ):
        " Sets breakpoints list "
        self.breakpoints = bpointStrList
        self.__saveBreakpoints()
        return

    def addWatchpoint( self, wpointStr ):
        " Adds serialized watchpoint "
        if wpointStr not in self.watchpoints:
            self.watchpoints.append( wpointStr )
            self.__saveWatchpoints()
        return

    def deleteWatchpoint( self, wpointStr ):
        " Deletes serialized watchpoint "
        if wpointStr in self.watchpoints:
            self.watchpoints.remove( wpointStr )
            self.__saveWatchpoints()
        return

    def setWatchpoints( self, wpointStrList ):
        " Sets watchpoints list "
        self.watchpoints = wpointStrList
        self.__saveWatchpoints()
        return
Пример #57
0
 def __init__(self, target_file, dry_run):
     self.project = Project(os.getcwd())
     self.target_file = target_file
     self.dry_run = dry_run
     self.commands = []
Пример #58
0
from rope.base.project import Project
from rope.refactor.move import MoveModule

project = Project('.')

utils = project.find_module('utils')
move = MoveModule(project, utils)
cfme = project.find_module('cfme')
print(cfme)
changes = move.get_changes(cfme)
changes.do()
Пример #59
0
class Refactor(QtGui.QWidget):

    def __init__(self, editorTabWidget, busyWidget, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.editorTabWidget = editorTabWidget
        self.busyWidget = busyWidget
        self.root = editorTabWidget.pathDict["sourcedir"]
        ropeFolder = editorTabWidget.pathDict["ropeFolder"]

        prefs = {
            'ignored_resources': ['*.pyc', '*~', '.ropeproject',
                                  '.hg', '.svn', '_svn', '.git',
                                  '__pycache__'],
            'python_files': ['*.py'],
            'save_objectdb': True,
            'compress_objectdb': False,
            'automatic_soa': True,
            'soa_followed_calls': 0,
            'perform_doa': True,
            'validate_objectdb': True,
            'max_history_items': 32,
            'save_history': True,
            'compress_history': False,
            'indent_size': 4,
            'extension_modules': [
                "PyQt4", "PyQt4.QtGui", "QtGui", "PyQt4.QtCore", "QtCore",
                "PyQt4.QtScript", "QtScript", "os.path", "numpy", "scipy", "PIL",
                "OpenGL", "array", "audioop", "binascii", "cPickle", "cStringIO",
                "cmath", "collections", "datetime", "errno", "exceptions", "gc",
                "imageop", "imp", "itertools", "marshal", "math", "mmap", "msvcrt",
                "nt", "operator", "os", "parser", "rgbimg", "signal", "strop", "sys",
                "thread", "time", "wx", "wxPython", "xxsubtype", "zipimport", "zlib"
            ],
            'import_dynload_stdmods': True,
            'ignore_syntax_errors': True,
            'ignore_bad_imports': True
        }

        self.ropeProject = Project(
            projectroot=self.root, ropefolder=ropeFolder, **prefs)
        self.ropeProject.prefs.add('python_path', 'c:/Python33')
        self.ropeProject.prefs.add('source_folders', 'c:/Python33/Lib')
        self.ropeProject.validate()

        self.noProject = Project(projectroot="temp", ropefolder=None)

        self.findThread = FindUsageThread()
        self.findThread.finished.connect(self.findOccurrencesFinished)

        self.renameThread = RenameThread()
        self.renameThread.finished.connect(self.renameFinished)

        self.inlineThread = InlineThread()
        self.inlineThread.finished.connect(self.inlineFinished)

        self.localToFieldThread = LocalToFieldThread()
        self.localToFieldThread.finished.connect(self.localToFieldFinished)

        self.moduleToPackageThread = ModuleToPackageThread()
        self.moduleToPackageThread.finished.connect(
            self.moduleToPackageFinished)

        self.createActions()

        self.refactorMenu = QtGui.QMenu("Refactor")
        self.refactorMenu.addAction(self.renameAttributeAct)
        self.refactorMenu.addAction(self.inlineAct)
        self.refactorMenu.addAction(self.localToFieldAct)

    def close(self):
        self.ropeProject.close()

    def createActions(self):
        self.findDefAct = \
            QtGui.QAction(
                QtGui.QIcon(os.path.join("Resources", "images", "map_marker")),
                "Go-to Definition", self, statusTip="Go-to Definition",
                triggered=self.findDefinition)

        self.findOccurrencesAct = \
            QtGui.QAction("Usages", self, statusTip="Usages",
                          triggered=self.findOccurrences)

        self.moduleToPackageAct = \
            QtGui.QAction(
                "Convert to Package", self, statusTip="Convert to Package",
                triggered=self.moduleToPackage)

        self.renameModuleAct = \
            QtGui.QAction("Rename", self, statusTip="Rename",
                          triggered=self.renameModule)

        self.renameAttributeAct = \
            QtGui.QAction("Rename", self, statusTip="Rename",
                          triggered=self.renameAttribute)

        self.inlineAct = \
            QtGui.QAction("Inline", self, statusTip="Inline",
                          triggered=self.inline)

        self.localToFieldAct = \
            QtGui.QAction("Local-to-Field", self, statusTip="Local-to-Field",
                          triggered=self.localToField)

        self.getDocAct = \
            QtGui.QAction("Documentation", self, statusTip="Documentation",
                          triggered=self.getDoc)

        self.getCallTipAct = \
            QtGui.QAction("CallTip", self, statusTip="CallTip",
                          triggered=self.getCallTip)

    def renameModule(self):
        index = self.editorTabWidget.currentIndex()
        moduleName = self.editorTabWidget.tabText(index)
        moduleName = os.path.splitext(moduleName)[0]
        newName = GetName("Rename", moduleName, self)
        project = self.getProject()
        if newName.accepted:
            saved = self.editorTabWidget.saveProject()
            if saved:
                path = self.editorTabWidget.getEditorData("filePath")
                self.renameThread.rename(newName.text, path, project, None)
                self.busyWidget.showBusy(True, "Renaming... please wait!")

    def renameAttribute(self):
        objectName = self.editorTabWidget.get_current_word()
        newName = GetName("Rename", objectName, self)
        if newName.accepted:
            project = self.getProject()
            saved = self.editorTabWidget.saveProject()
            if saved:
                offset = self.getOffset()
                path = self.editorTabWidget.getEditorData("filePath")
                self.renameThread.rename(newName.text, path, project, offset)
                self.busyWidget.showBusy(True, "Renaming... please wait!")

    def renameFinished(self):
        self.busyWidget.showBusy(False)
        if self.renameThread.error is not None:
            message = QtGui.QMessageBox.warning(self, "Failed Rename",
                                                self.renameThread.error)
            return
        if self.renameThread.offset is None:
            # filename has been changed
            oldPath = self.editorTabWidget.getEditorData("filePath")
            ext = os.path.splitext(oldPath)[1]
            newPath = os.path.join(os.path.dirname(oldPath),
                                   self.renameThread.new_name + ext)
            self.editorTabWidget.updateEditorData("filePath", newPath)
        else:
            if len(self.renameThread.changedFiles) > 0:
                self.editorTabWidget.reloadModules(
                    self.renameThread.changedFiles)

    def inline(self):
        offset = self.getOffset()
        path = self.editorTabWidget.getEditorData("filePath")
        project = self.getProject()
        resource = project.get_file(path)
        saved = self.editorTabWidget.saveProject()
        if saved:
            self.inlineThread.inline(project, resource, offset)
            self.busyWidget.showBusy(True, "Inlining... please wait!")

    def inlineFinished(self):
        self.busyWidget.showBusy(False)
        if self.inlineThread.error is not None:
            message = QtGui.QMessageBox.warning(self, "Failed Inline",
                                                self.inlineThread.error)
            return
        if len(self.inlineThread.changedFiles) > 0:
            self.editorTabWidget.reloadModules(self.inlineThread.changedFiles)

    def localToField(self):
        offset = self.getOffset()
        path = self.editorTabWidget.getEditorData("filePath")
        project = self.getProject()
        resource = project.get_file(path)
        saved = self.editorTabWidget.saveProject()
        if saved:
            self.localToFieldThread.convert(project, resource, offset)
            self.busyWidget.showBusy(
                True, "Converting Local to Field... please wait!")

    def localToFieldFinished(self):
        self.busyWidget.showBusy(False)
        if self.localToFieldThread.error is not None:
            message = QtGui.QMessageBox.warning(self, "Failed Local-to-Field",
                                                self.localToFieldThread.error)
            return
        if len(self.localToFieldThread.changedFiles) > 0:
            self.editorTabWidget.reloadModules(
                self.localToFieldThread.changedFiles)

    def findDefinition(self):
        saved = self.editorTabWidget.saveProject()
        if saved:
            offset = self.getOffset()
            path = self.editorTabWidget.getEditorData("filePath")
            project = self.getProject()
            resource = project.get_file(path)
            try:
                result = find_definition(project,
                                         self.editorTabWidget.getSource(), offset, resource)
                if result is None:
                    self.editorTabWidget.showNotification(
                        "No definition found.")
                else:
                    start, end = result.region
                    offset = result.offset
                    line = result.lineno
                    result_path = result.resource.path
                    sourcePath = self.editorTabWidget.pathDict["sourcedir"]
                    if not os.path.isabs(result_path):
                        result_path = os.path.join(sourcePath, result_path)
                    if os.path.samefile(result_path, path):
                        pass
                    else:
                        self.editorTabWidget.loadfile(result_path)
                    editor = self.editorTabWidget.focusedEditor()
                    start = editor.lineIndexFromPosition(start)
                    end = editor.lineIndexFromPosition(end)
                    editor.setSelection(start[0], start[1], end[0], end[1])
                    editor.ensureLineVisible(line - 1)
            except Exception as err:
                self.editorTabWidget.showNotification(str(err))

    def moduleToPackage(self):
        path = self.editorTabWidget.getEditorData("filePath")
        project = self.getProject()
        saved = self.editorTabWidget.saveProject()
        if saved:
            self.moduleToPackageThread.convert(path, project)
            self.busyWidget.showBusy(True, "Converting... please wait!")

    def moduleToPackageFinished(self):
        self.busyWidget.showBusy(False)
        if self.moduleToPackageThread.error is not None:
            message = QtGui.QMessageBox.warning(self, "Failed to convert",
                                                self.moduleToPackageThread.error)

    def findOccurrences(self):
        offset = self.getOffset()
        project = self.getProject()
        saved = self.editorTabWidget.saveProject()
        if saved:
            path = self.editorTabWidget.getEditorData("filePath")
            self.objectName = self.editorTabWidget.get_current_word()
            self.findThread.find(path, project, offset)
            self.busyWidget.showBusy(True, "Finding usages... please wait!")

    def findOccurrencesFinished(self):
        self.busyWidget.showBusy(False)
        if self.findThread.error is not None:
            self.editorTabWidget.showNotification(self.findThread.error)
            return
        if len(self.findThread.itemsDict) > 0:
            foundList = []
            for parent, lines in self.findThread.itemsDict.items():
                parentItem = QtGui.QTreeWidgetItem()
                parentItem.setForeground(0, QtGui.QBrush(
                    QtGui.QColor("#003366")))
                parentItem.setText(0, parent)
                for line in lines:
                    childItem = QtGui.QTreeWidgetItem()
                    childItem.setText(0, str(line))
                    childItem.setFirstColumnSpanned(True)
                    parentItem.addChild(childItem)
                    foundList.append(parentItem)
            usageDialog = UsageDialog(
                self.editorTabWidget, "Usages: " + self.objectName, foundList, self)
        else:
            self.editorTabWidget.showNotification("No usages found.")

    def getOffset(self):
        return self.editorTabWidget.getOffset()

    def get_absolute_coordinates(self):
        editor = self.editorTabWidget.focusedEditor()
        point = editor.get_absolute_coordinates()
        return point

    def getCompletions(self):
        offset = self.getOffset()
        project = self.getProject()
        proposals = codeassist.code_assist(project,
                                           self.editorTabWidget.getSource(), offset)
        proposals = codeassist.sorted_proposals(proposals)
        if len(proposals) > 0:
            cmpl = []
            for i in proposals:
                cmpl.append(str(i))

            return cmpl
        else:
            return []

    def getDoc(self, offset=None):
        if offset is None:
            offset = self.getOffset()
        project = self.getProject()
        try:
            doc = codeassist.get_doc(project,
                                     self.editorTabWidget.getSource(), offset)
            return doc
        except Exception as err:
            return None

    def getCallTip(self, offset=None):
        if offset is None:
            offset = self.getOffset()
        project = self.getProject()
        try:
            calltip = codeassist.get_calltip(project,
                                             self.editorTabWidget.getSource(), offset)

            return calltip
        except Exception as err:
            return None

    def getProject(self):
        path = self.editorTabWidget.getEditorData("filePath")
        if path is None:
            return self.noProject
        if path.startswith(self.editorTabWidget.pathDict["sourcedir"]):
            return self.ropeProject
        else:
            return self.noProject