def get_changed_module(self): word_finder = worder.Worder(self.source) change_collector = codeanalyze.ChangeCollector(self.source) for occurrence in self.occurrence_finder.find_occurrences( self.resource): if not occurrence.is_called() and not occurrence.is_defined(): continue start, end = occurrence.get_primary_range() begin_parens, end_parens = word_finder.\ get_word_parens_range(end - 1) if occurrence.is_called(): primary, pyname = occurrence.get_primary_and_pyname() changed_call = self.call_changer.change_call( primary, pyname, self.source[start:end_parens]) else: changed_call = self.call_changer.change_definition( self.source[start:end_parens]) if changed_call is not None: change_collector.add_change(start, end_parens, changed_call) return change_collector.get_changed()
def experiment_with_scoping_classes(project, source_file_name): """This is not used; just for experimenting with `PyObject` and `Scope` objects.""" def dir_no_magic(obj): return [s for s in dir(obj) if s[:2] != "__"] source_string = get_source_string(source_file_name) # Get a `Worder` for the code. w = worder.Worder(source_string) print("\nGot a Worder. The dir is", dir_no_magic(w)) # Get a PyObject for the code. py_object = get_string_module(project, source_string, resource=None, force_errors=False) print("\nGot a PyObject. The dir is", dir_no_magic(py_object)) # Get a Scope object for the code. scope_object = get_string_scope(project, source_string, resource=None) print("\nGot a Scope object. The dir is", dir_no_magic(scope_object)) print("The names in the Scope are:\n", scope_object.get_names())
def _keyword_parameters(self, pymodule, scope): offset = self.offset if offset == 0: return {} word_finder = worder.Worder(self.code, True) lines = SourceLinesAdapter(self.code) lineno = lines.get_line_number(offset) if word_finder.is_on_function_call_keyword(offset - 1): name_finder = rope.base.evaluate.ScopeNameFinder(pymodule) function_parens = word_finder.\ find_parens_start_from_inside(offset - 1) primary = word_finder.get_primary_at(function_parens - 1) try: function_pyname = rope.base.evaluate.\ eval_str(scope, primary) except exceptions.BadIdentifierError, e: return {} if function_pyname is not None: pyobject = function_pyname.get_object() if isinstance(pyobject, pyobjects.AbstractFunction): pass elif isinstance(pyobject, pyobjects.AbstractClass) and \ '__init__' in pyobject: pyobject = pyobject['__init__'].get_object() elif '__call__' in pyobject: pyobject = pyobject['__call__'].get_object() if isinstance(pyobject, pyobjects.AbstractFunction): param_names = [] param_names.extend( pyobject.get_param_names(special_args=False)) result = {} for name in param_names: if name.startswith(self.starting): result[name + '='] = NamedParamProposal( name, pyobject ) return result
def __init__(self, pymodule): self.module_scope = pymodule.get_scope() self.lines = pymodule.lines self.worder = worder.Worder(pymodule.source_code, True)
def test_word_finder_on_word_ending(self): code = 'print a_var\n' word_finder = worder.Worder(code) result = word_finder.get_word_at(code.index('a_var') + 5) self.assertEquals('a_var', result)
def test_is_on_function_keyword(self): code = 'myfunc(va' finder = worder.Worder(code) self.assertTrue(finder.is_on_function_call_keyword(len(code) - 1))
def test_find_parens_start_with_parens_in_strs(self): code = 'myfunc(p1, "(", p4\n' finder = worder.Worder(code) self.assertEquals(code.index('('), finder.find_parens_start_from_inside(len(code) - 1))
def test_underlined_find_parens_start(self): code = 'f(p="")\n' finder = worder.Worder(code) self.assertEquals(1, finder._find_parens_start(len(code) - 2))
def test_one_letter_function_keyword_arguments(self): code = 'f(p=1)\n' word_finder = worder.Worder(code) index = code.rindex('p') self.assertTrue(word_finder.is_function_keyword_parameter(index))
def test_is_from_with_from_import_and_multiline_parens(self): code = 'from mod import \\\n (f,\n g, h)\n' word_finder = worder.Worder(code) self.assertTrue(word_finder.is_from_statement(code.rindex('g')))
def test_empty_splitted_statement3(self): word_finder = worder.Worder('') self.assertEquals(('', '', 0), word_finder.get_splitted_primary_before(0))
def test_empty_splitted_statement2(self): word_finder = worder.Worder('an_object.') self.assertEquals(('an_object', '', 10), word_finder.get_splitted_primary_before(10))
def test_splitted_statement(self): word_finder = worder.Worder('an_object.an_attr') self.assertEquals(('an_object', 'an_at', 10), word_finder.get_splitted_primary_before(15))
def rope_iterate_worder(source_file_name, fun_name_defs=False, fun_arguments=False, fun_keywords=False, assigned_vars=False, class_names=False, unfiltered=False): """Get all the names of a given type and their offsets. The `project` argument is not currently used. Due to how rope works these are split up in an unusual way. The function arguments without default values are parsed out of the string representing the function and its arguments. fun_name_defs = all function and method defs fun_arguments = function arguments which do now have default values fun_keywords = function keywords (which duplicate the assigned vars changes) assigned_vars = any variables which are assigned, including keyword parameters """ # Currently based on Worder class: # https://github.com/python-rope/rope/blob/master/rope/base/worder.py if unfiltered: fun_name_defs = True fun_arguments = True fun_keywords = True assigned_vars = True class_names = True source_string = get_source_string(source_file_name) w = worder.Worder(source_string) possible_changes = [] unidentified_words = [] upcoming = None offset = 0 while True: try: word = w.get_word_at(offset) except (ValueError, IndexError): break if w.is_function_keyword_parameter(offset) and fun_keywords: possible_changes.append([word, offset, camel_to_snake(word)]) elif ( w.is_assigned_here(offset) or w.is_assigned_in_a_tuple_assignment(offset) ) and assigned_vars: # Tuple is check probably redundant; doesn't work. possible_changes.append([word, offset, camel_to_snake(word)]) elif word == "for": upcoming = "for" elif word == "def": upcoming = "def" elif word == "class": upcoming = "class" elif upcoming == "for" and assigned_vars: possible_changes.append([word, offset, camel_to_snake(word)]) upcoming = None elif upcoming == "def" and w.is_a_class_or_function_name_in_header( offset): if fun_name_defs: possible_changes.append([word, offset, camel_to_snake(word)]) upcoming = None try: # TODO? NOTE: Adding -4 to offset below was needed to make the # CURRENT function name being detected in this branch of the # `if` match the function and args that are returned by the # call below! Otherwise, you always got a function name, but # the function below returned the string for the one that is # ahead in text... # # The value -4 is the minimum (in abs) to make them match, and # it makes the offsets of the parameters without default # arguments exactly match the ones found below in the # "unidentified" section... This works, but I do not know why. fun_and_args = w.get_function_and_args_in_header(offset - 4) except (ValueError, IndexError): fun_and_args = None #print("Fun and args string from rope is:", fun_and_args) if fun_arguments: param_and_offset_list = get_function_param_names( fun_and_args, offset, word) param_list_and_new = [ n + [camel_to_snake(n[0])] for n in param_and_offset_list ] #print("param_list_and_new", param_list_and_new) possible_changes += param_list_and_new elif upcoming == "class" and w.is_a_class_or_function_name_in_header( offset): if class_names: possible_changes.append([word, offset, snake_to_camel(word)]) upcoming = None else: unidentified_words.append([word, offset]) # Move the offset pointer ahead until the recognized word changes. break_outer = False while True: offset += 1 try: next_word = w.get_word_at(offset) if next_word != word: break except (ValueError, IndexError): break_outer = True break if break_outer: break if unfiltered: return possible_changes + unidentified_words # Filter out the possible changes that are already in snake case, save new name. filtered_changes = [] for c in possible_changes: name = c[0] new_name = c[2] if REJECTED_CHANGE_MAGIC_COOKIE in name: continue if new_name == name: continue filtered_changes.append(tuple(c)) # Remove duplicates and return. unique_changes_generator = unique_everseen(filtered_changes) filtered_changes = [c for c in unique_changes_generator] return filtered_changes
def word_finder(self): return worder.Worder(self.source_code, self.docs)
def test_is_assigned_here_for_not_equal_test(self): code = 'a != 1\n' word_finder = worder.Worder(code) self.assertFalse(word_finder.is_assigned_here(0))
def xxx_test_is_assigned_here_for_tuple_assignment(self): code = 'a, b = (1, 2)\n' word_finder = worder.Worder(code) self.assertTrue(word_finder.is_assigned_here(0))
def test_empty_splitted_statement4(self): word_finder = worder.Worder('a_var = ') self.assertEquals(('', '', 8), word_finder.get_splitted_primary_before(8))
def test_is_from_with_from_import_and_line_breaks_in_the_middle(self): code = 'from mod import f,\\\n g\n' word_finder = worder.Worder(code) self.assertTrue(word_finder.is_from_statement(code.rindex('g')))
def test_empty_splitted_statement5(self): word_finder = worder.Worder('a.') self.assertEquals(('a', '', 2), word_finder.get_splitted_primary_before(2))
def test_find_parens_start(self): code = 'f(p)\n' finder = worder.Worder(code) self.assertEquals(1, finder.find_parens_start_from_inside(2))
def test_import_statement_finding(self): code = 'import mod\na_var = 10\n' word_finder = worder.Worder(code) self.assertTrue(word_finder.is_import_statement(code.index('mod') + 1)) self.assertFalse( word_finder.is_import_statement(code.index('a_var') + 1))
def test_find_parens_start_with_multiple_entries(self): code = 'myfunc(p1, p2, p3\n' finder = worder.Worder(code) self.assertEquals(code.index('('), finder.find_parens_start_from_inside(len(code) - 1))
def test_import_statement_finding2(self): code = 'import a.b.c.d\nresult = a.b.c.d.f()\n' word_finder = worder.Worder(code) self.assertFalse(word_finder.is_import_statement(code.rindex('d') + 1))
def test_find_parens_start_with_parens_in_strs_in_multiple_lines(self): code = 'myfunc (\np1\n , \n "(" \n, \np4\n' finder = worder.Worder(code) self.assertEquals(code.index('('), finder.find_parens_start_from_inside(len(code) - 1))
def test_word_parens_range(self): code = 's = str()\ns.title()\n' word_finder = worder.Worder(code) result = word_finder.get_word_parens_range(code.rindex('()') - 1) self.assertEquals((len(code) - 3, len(code) - 1), result)
def _find_primary(self, code, offset): word_finder = worder.Worder(code) result = word_finder.get_primary_at(offset) return result
def test_is_a_function_being_called_with_parens_on_next_line(self): code = 'func\n(1, 2)\n' word_finder = worder.Worder(code) self.assertFalse(word_finder.is_a_function_being_called(1))
def get_old_name(self): word_finder = worder.Worder(self.resource.read()) return word_finder.get_primary_at(self.offset)
def test_get_word_parens_range_and_string_literals(self): code = 'f(1, ")", 2)\n' word_finder = worder.Worder(code) result = word_finder.get_word_parens_range(0) self.assertEquals((1, len(code) - 1), result)