def moving_code_with_imports(project, resource, source): import_tools = importutils.ImportTools(project) pymodule = libutils.get_string_module(project, source, resource) origin = project.get_pymodule(resource) imports = [] for stmt in import_tools.module_imports(origin).imports: imports.append(stmt.import_info) back_names = [] for name in origin: if name not in pymodule: back_names.append(name) imports.append(import_tools.get_from_import(resource, back_names)) source = _add_imports_to_module(import_tools, pymodule, imports) pymodule = libutils.get_string_module(project, source, resource) source = import_tools.relatives_to_absolutes(pymodule) pymodule = libutils.get_string_module(project, source, resource) source = import_tools.organize_imports(pymodule, selfs=False) pymodule = libutils.get_string_module(project, source, resource) # extracting imports after changes module_imports = import_tools.module_imports(pymodule) imports = [import_stmt.import_info for import_stmt in module_imports.imports] start = 1 if module_imports.imports: start = module_imports.imports[-1].end_line lines = codeanalyze.SourceLinesAdapter(source) while start < lines.length() and not lines.get_line(start).strip(): start += 1 moving = source[lines.get_line_start(start):] return moving, imports
def _dest_module_changes(self, dest): # Changing occurrences pymodule = self.project.get_pymodule(dest) source = self.tools.rename_in_module(self.old_name, pymodule) pymodule = self.tools.new_pymodule(pymodule, source) moving, imports = self._get_moving_element_with_imports() pymodule, has_changed = self._add_imports2(pymodule, imports) module_with_imports = self.import_tools.module_imports(pymodule) source = pymodule.source_code lineno = 0 if module_with_imports.imports: lineno = module_with_imports.imports[-1].end_line - 1 else: while lineno < pymodule.lines.length() and pymodule.lines.get_line(lineno + 1).lstrip().startswith("#"): lineno += 1 if lineno > 0: cut = pymodule.lines.get_line_end(lineno) + 1 result = source[:cut] + "\n\n" + moving + source[cut:] else: result = moving + source # Organizing imports source = result pymodule = libutils.get_string_module(self.project, source, dest) source = self.import_tools.organize_imports(pymodule, sort=False, unused=False) # Remove unused imports of the old module pymodule = libutils.get_string_module(self.project, source, dest) source = self.import_tools.organize_imports( pymodule, sort=False, selfs=False, unused=True, import_filter=self._import_filter ) return ChangeContents(dest, source)
def _calculate_definition(self, primary, pyname, call, host_vars, returns): header, to_be_inlined = self._calculate_header(primary, pyname, call) source = header + self.body mod = libutils.get_string_module(self.project, source) name_dict = mod.get_scope().get_names() all_names = [x for x in name_dict if not isinstance(name_dict[x], rope.base.builtins.BuiltinName)] # If there is a name conflict, all variable names # inside the inlined function are renamed if len(set(all_names).intersection(set(host_vars))) > 0: prefix = _DefinitionGenerator.unique_prefix.next() guest = libutils.get_string_module(self.project, source, self.resource) to_be_inlined = [prefix + item for item in to_be_inlined] for item in all_names: pyname = guest[item] occurrence_finder = occurrences.create_finder(self.project, item, pyname) source = rename.rename_in_module(occurrence_finder, prefix + item, pymodule=guest) guest = libutils.get_string_module(self.project, source, self.resource) # parameters not reassigned inside the functions are now inlined. for name in to_be_inlined: pymodule = libutils.get_string_module(self.project, source, self.resource) pyname = pymodule[name] source = _inline_variable(self.project, pymodule, pyname, name) return self._replace_returns_with(source, returns)
def _add_imports(project, source, resource, imports): if not imports: return source pymodule = libutils.get_string_module(project, source, resource) module_import = importutils.get_module_imports(project, pymodule) for import_info in imports: module_import.add_import(import_info) source = module_import.get_changed_source() pymodule = libutils.get_string_module(project, source, resource) import_tools = importutils.ImportTools(project) return import_tools.organize_imports(pymodule, unused=False, sort=False)
def moving_code_with_imports(project, resource, source): import_tools = importutils.ImportTools(project) pymodule = libutils.get_string_module(project, source, resource) # Strip comment prefix, if any. These need to stay before the moving # section, but imports would be added between them. lines = codeanalyze.SourceLinesAdapter(source) start = 1 while start < lines.length() and lines.get_line(start).startswith('#'): start += 1 moving_prefix = source[:lines.get_line_start(start)] pymodule = libutils.get_string_module(project, source[lines.get_line_start(start):], resource) origin = project.get_pymodule(resource) imports = [] for stmt in import_tools.module_imports(origin).imports: imports.append(stmt.import_info) back_names = [] for name in origin: if name not in pymodule: back_names.append(name) imports.append(import_tools.get_from_import(resource, back_names)) source = _add_imports_to_module(import_tools, pymodule, imports) pymodule = libutils.get_string_module(project, source, resource) source = import_tools.relatives_to_absolutes(pymodule) pymodule = libutils.get_string_module(project, source, resource) source = import_tools.organize_imports(pymodule, selfs=False) pymodule = libutils.get_string_module(project, source, resource) # extracting imports after changes module_imports = import_tools.module_imports(pymodule) imports = [ import_stmt.import_info for import_stmt in module_imports.imports ] start = 1 if module_imports.imports: start = module_imports.imports[-1].end_line lines = codeanalyze.SourceLinesAdapter(source) while start < lines.length() and not lines.get_line(start).strip(): start += 1 # Reinsert the prefix which was removed at the beginning moving = moving_prefix + source[lines.get_line_start(start):] return moving, imports
def _source_module_changes(self, dest): placeholder = "__rope_moving_%s_" % self.old_name handle = _ChangeMoveOccurrencesHandle(placeholder) occurrence_finder = occurrences.create_finder(self.project, self.old_name, self.old_pyname) start, end = self._get_moving_region() renamer = ModuleSkipRenamer(occurrence_finder, self.source, handle, start, end) source = renamer.get_changed_module() pymodule = libutils.get_string_module(self.project, source, self.source) source = self.import_tools.organize_imports(pymodule, sort=False) if handle.occurred: pymodule = libutils.get_string_module(self.project, source, self.source) # Adding new import source, imported = importutils.add_import(self.project, pymodule, self._new_modname(dest), self.old_name) source = source.replace(placeholder, imported) return ChangeContents(self.source, source)
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_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_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_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_mixing_subscript_with_tuple_assigns(self): code = 'class C(object):\n attr = 0\n' \ 'd = {}\nd[0], b = (0, C())\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['b'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_lambda_functions(self): code = 'class C(object):\n pass\n' \ 'l = lambda: C()\na_var = l()' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['a_var'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_mixing_slice_with_tuple_assigns(self): mod = libutils.get_string_module( self.project, "class C(object):\n attr = 0\n" "d = [None] * 3\nd[0:2], b = ((0,), C())\n" ) c_class = mod["C"].get_object() a_var = mod["b"].get_object() self.assertEquals(c_class, a_var.get_type())
def _change_module(self, resources, changes, factory_name, global_, job_set): if global_: replacement = '__rope_factory_%s_' % factory_name else: replacement = self._new_function_name(factory_name, global_) for file_ in resources: job_set.started_job(file_.path) if file_ == self.resource: self._change_resource(changes, factory_name, global_) job_set.finished_job() continue changed_code = self._rename_occurrences(file_, replacement, global_) if changed_code is not None: if global_: new_pymodule = libutils.get_string_module( self.project, changed_code, self.resource) modname = libutils.modname(self.resource) changed_code, imported = importutils.add_import( self.project, new_pymodule, modname, factory_name) changed_code = changed_code.replace(replacement, imported) changes.add_change(ChangeContents(file_, changed_code)) job_set.finished_job()
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_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_mixing_ass_attr_with_tuple_assignment(self): code = 'class C(object):\n attr = 0\n' \ 'c = C()\nc.attr, b = (0, C())\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['b'].get_object() self.assertEquals(c_class, a_var.get_type())
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_considering_nones_to_be_unknowns(self): code = 'class C(object):\n pass\n' \ 'a_var = None\na_var = C()\na_var = None\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['a_var'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_basic_list_comprehensions(self): code = 'class C(object):\n pass\n' \ 'l = [C() for i in range(1)]\na_var = l[0]\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['a_var'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_basic_generator_expressions(self): code = 'class C(object):\n pass\n' \ 'l = (C() for i in range(1))\na_var = list(l)[0]\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['a_var'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_inheriting_dotted_base_class(self): code = 'import samplemod\n' \ 'class Derived(samplemod.SampleClass):\n' \ ' pass\n' mod = libutils.get_string_module(self.project, code) derived = mod['Derived'].get_object() self.assertTrue('sample_method' in derived)
def get_pymodule(self): """Get a `PyModule`""" msg = None code = self.code tries = 0 while True: try: if ( tries == 0 and self.resource is not None and self.resource.read() == code ): return self.project.get_pymodule(self.resource, force_errors=True) return libutils.get_string_module( self.project, code, resource=self.resource, force_errors=True ) except exceptions.ModuleSyntaxError as e: if msg is None: msg = "%s:%s %s" % (e.filename, e.lineno, e.message_) if tries < self.maxfixes: tries += 1 self.commenter.comment(e.lineno) code = "\n".join(self.commenter.lines) else: raise exceptions.ModuleSyntaxError( e.filename, e.lineno, "Failed to fix error: {0}".format(msg) )
def test_first_parameter_of_class_methods(self): code = 'class AClass(object):\n' \ ' @classmethod\n def a_func(cls):\n pass\n' a_class = libutils.get_string_module(self.project, code)['AClass'].\ get_object() function_scope = a_class['a_func'].get_object().get_scope() self.assertEquals(a_class, function_scope['cls'].get_object())
def get_pymodule(self): """Get a `PyModule`""" msg = None code = self.code tries = 0 while True: try: if tries == 0 and self.resource is not None and \ self.resource.read() == code: return self.project.get_pymodule(self.resource, force_errors=True) return libutils.get_string_module( self.project, code, resource=self.resource, force_errors=True) except exceptions.ModuleSyntaxError as e: if msg is None: msg = '%s:%s %s' % (e.filename, e.lineno, e.message_) if tries < self.maxfixes: tries += 1 self.commenter.comment(e.lineno) code = '\n'.join(self.commenter.lines) else: raise exceptions.ModuleSyntaxError( e.filename, e.lineno, 'Failed to fix error: {0}'.format(msg))
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 organize_imports( self, pymodule, unused=True, duplicates=True, selfs=True, sort=True, import_filter=None, ): if unused or duplicates: module_imports = self.module_imports(pymodule, import_filter) if unused: module_imports.remove_unused_imports() if self.project.prefs.get("split_imports"): module_imports.force_single_imports() if duplicates: module_imports.remove_duplicates() source = module_imports.get_changed_source() if source is not None: pymodule = libutils.get_string_module(self.project, source, pymodule.get_resource()) if selfs: pymodule = self._remove_self_imports(pymodule, import_filter) if sort: return self.sort_imports(pymodule, import_filter) else: return pymodule.source_code
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_first_parameter_of_class_methods(self): code = 'class AClass(object):\n' \ ' @classmethod\n def a_func(cls):\n pass\n' a_class = libutils.get_string_module(self.project, code)['AClass'].\ get_object() function_scope = a_class['a_func'].get_object().get_scope() self.assertEqual(a_class, function_scope['cls'].get_object())
def _rename_in_module(self, pymodule, name, new_name, till_dot=False): old_name = name.split(".")[-1] old_pyname = rope.base.evaluate.eval_str(pymodule.get_scope(), name) occurrence_finder = occurrences.create_finder(self.project, old_name, old_pyname, imports=False) changes = rope.base.codeanalyze.ChangeCollector(pymodule.source_code) for occurrence in occurrence_finder.find_occurrences( pymodule=pymodule): start, end = occurrence.get_primary_range() if till_dot: new_end = pymodule.source_code.index(".", end) + 1 space = pymodule.source_code[end:new_end - 1].strip() if not space == "": for c in space: if not c.isspace() and c not in "\\": raise ValueError() end = new_end changes.add_change(start, end, new_name) source = changes.get_changed() if source is not None: pymodule = libutils.get_string_module(self.project, source, pymodule.get_resource()) return pymodule
def _dest_module_changes(self, dest): # Changing occurrences pymodule = self.project.get_pymodule(dest) source = self.tools.rename_in_module(self.old_name, pymodule) pymodule = self.tools.new_pymodule(pymodule, source) moving, imports = self._get_moving_element_with_imports() source = self.tools.remove_old_imports(pymodule) pymodule = self.tools.new_pymodule(pymodule, source) pymodule, has_changed = self._add_imports2(pymodule, imports) module_with_imports = self.import_tools.module_imports(pymodule) source = pymodule.source_code lineno = 0 if module_with_imports.imports: lineno = module_with_imports.imports[-1].end_line - 1 else: while lineno < pymodule.lines.length() and \ pymodule.lines.get_line(lineno + 1).\ lstrip().startswith('#'): lineno += 1 if lineno > 0: cut = pymodule.lines.get_line_end(lineno) + 1 result = source[:cut] + '\n\n' + moving + source[cut:] else: result = moving + source # Organizing imports source = result pymodule = libutils.get_string_module(self.project, source, dest) source = self.import_tools.organize_imports(pymodule, sort=False, unused=False) return ChangeContents(dest, source)
def test_from_import_nonexistent_name(self): code = 'from samplemod import DoesNotExistClass\n' mod = libutils.get_string_module(self.project, code) self.assertTrue('DoesNotExistClass' in mod) self.assertEquals(get_base_type('Unknown'), mod['DoesNotExistClass']. get_object().get_type())
def test_mixing_slice_with_tuple_assigns(self): mod = libutils.get_string_module( self.project, 'class C(object):\n attr = 0\n' 'd = [None] * 3\nd[0:2], b = ((0,), C())\n') c_class = mod['C'].get_object() a_var = mod['b'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_we_know_the_type_of_catched_multiple_excepts(self): code = 'class MyError(Exception):\n pass\n' \ 'try:\n raise MyError()\n' \ 'except (MyError, Exception), e:\n pass\n' mod = libutils.get_string_module(self.project, code) my_error = mod['MyError'].get_object() e_var = mod['e'].get_object() self.assertEquals(my_error, e_var.get_type())
def test_list_comprehensions_and_loop_var(self): code = 'class C(object):\n pass\n' \ 'c_objects = [C(), C()]\n' \ 'l = [c for c in c_objects]\na_var = l[0]\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['a_var'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_handling_generator_functions(self): code = 'class C(object):\n pass\n' \ 'def f():\n yield C()\n' \ 'for c in f():\n a_var = c\n' mod = libutils.get_string_module(self.project, code) c_class = mod['C'].get_object() a_var = mod['a_var'].get_object() self.assertEquals(c_class, a_var.get_type())
def test_multi_dot_imports_as(self): pkg = testutils.create_package(self.project, 'pkg') mod1 = testutils.create_module(self.project, 'mod1', pkg) mod1.write('def f():\n pass\n') mod = libutils.get_string_module( self.project, 'import pkg.mod1 as mod1\n') module = mod['mod1'].get_object() self.assertTrue('f' in module)
def test_from_import_star_overwriting(self): code = 'from samplemod import *\n' \ 'class SampleClass(object):\n pass\n' mod = libutils.get_string_module(self.project, code) samplemod = self.project.get_module('samplemod') sample_class = samplemod['SampleClass'].get_object() self.assertNotEquals(sample_class, mod.get_attributes()['SampleClass'].get_object())
def xxx_test_from_package_import_package(self): pkg1 = testutils.create_package(self.project, 'pkg1') pkg2 = testutils.create_package(self.project, 'pkg2', pkg1) testutils.create_module(self.project, 'mod', pkg2) mod = libutils.get_string_module( self.project, 'from pkg1 import pkg2\n') package = mod['pkg2'] self.assertEquals(0, len(package.get_attributes()))
def test_using_property_as_decorators_and_passing_parameter(self): code = 'class B(object):\n' \ ' @property\n def f(self):\n return self\n' \ 'b = B()\nvar = b.f\n' mod = libutils.get_string_module(self.project, code) var = mod['var'].get_object() a = mod['B'].get_object() self.assertEquals(a, var.get_type())
def test_from_import_star(self): mod = libutils.get_string_module( self.project, 'from samplemod import *\n') self.assertEquals(get_base_type('Type'), mod['SampleClass'].get_object().get_type()) self.assertEquals(get_base_type('Function'), mod['sample_func'].get_object().get_type()) self.assertTrue(mod['sample_var'] is not None)
def test_multi_dot_imports(self): pkg = testutils.create_package(self.project, 'pkg') pkg_mod = testutils.create_module(self.project, 'mod', pkg) pkg_mod.write('def sample_func():\n pass\n') mod = libutils.get_string_module(self.project, 'import pkg.mod\n') self.assertTrue('pkg' in mod) self.assertTrue('sample_func' in mod['pkg'].get_object()['mod']. get_object())
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_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 xxx_test_from_package_import_package(self): pkg1 = testutils.create_package(self.project, 'pkg1') pkg2 = testutils.create_package(self.project, 'pkg2', pkg1) testutils.create_module(self.project, 'mod', pkg2) mod = libutils.get_string_module(self.project, 'from pkg1 import pkg2\n') package = mod['pkg2'] self.assertEquals(0, len(package.get_attributes()))
def test_multi_dot_imports_as(self): pkg = testutils.create_package(self.project, 'pkg') mod1 = testutils.create_module(self.project, 'mod1', pkg) mod1.write('def f():\n pass\n') mod = libutils.get_string_module(self.project, 'import pkg.mod1 as mod1\n') module = mod['mod1'].get_object() self.assertTrue('f' in module)