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
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
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
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
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()
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()
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 _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, )
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)
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 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
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)
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)
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 _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
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()
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
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 _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)
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)
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)
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)
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)
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)
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
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))
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)
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)
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
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)
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 __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())
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)
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'
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()
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, '')
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': "_"})
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
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:
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
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())
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())
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)
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 __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)
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())
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
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)
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
def __init__(self, target_file, dry_run): self.project = Project(os.getcwd()) self.target_file = target_file self.dry_run = dry_run self.commands = []
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()
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