def _rename(names, replace_str): """ For both rename and inline. """ order = sorted(names, key=lambda x: (x.module_path, x.line, x.column), reverse=True) def process(path, old_lines, new_lines): if new_lines is not None: # goto next file, save last dct[path] = path, old_lines, new_lines dct = {} current_path = object() new_lines = old_lines = None for name in order: if name.in_builtin_module(): continue if current_path != name.module_path: current_path = name.module_path process(current_path, old_lines, new_lines) if current_path is not None: # None means take the source that is a normal param. with open(current_path) as f: source = f.read() new_lines = modules.source_to_unicode(source).splitlines() old_lines = new_lines[:] nr, indent = name.line, name.column line = new_lines[nr - 1] new_lines[nr - 1] = line[:indent] + replace_str + \ line[indent + len(name.text):] process(current_path, old_lines, new_lines) return dct
def __init__(self, source, line=None, column=None, path=None, source_encoding='utf-8', source_path=None): if source_path is not None: warnings.warn("Use path instead of source_path.", DeprecationWarning) path = source_path lines = source.splitlines() or [''] if source and source[-1] == '\n': lines.append('') self._line = max(len(lines), 1) if line is None else line self._column = len(lines[-1]) if column is None else column api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, source_encoding) self._pos = self._line, self._column self._module = modules.ModuleWithCursor(path, source=self.source, position=self._pos) self._source_path = path self.path = None if path is None else os.path.abspath(path) debug.speed('init')
def _rename(names, replace_str): """ For both rename and inline. """ order = sorted(names, key=lambda x: (x.module_path, x.start_pos), reverse=True) def process(path, old_lines, new_lines): if new_lines is not None: # goto next file, save last dct[path] = path, old_lines, new_lines dct = {} current_path = object() new_lines = old_lines = None for name in order: if name.in_builtin_module(): continue if current_path != name.module_path: current_path = name.module_path process(current_path, old_lines, new_lines) if current_path is not None: # None means take the source that is a normal param. with open(current_path) as f: source = f.read() new_lines = modules.source_to_unicode(source).splitlines() old_lines = new_lines[:] nr, indent = name.start_pos line = new_lines[nr - 1] new_lines[nr - 1] = line[:indent] + replace_str + \ line[indent + len(name.text):] process(current_path, old_lines, new_lines) return dct
def __init__(self, source=None, line=None, column=None, path=None, encoding='utf-8', source_path=None): if source_path is not None: warnings.warn("Use path instead of source_path.", DeprecationWarning) path = source_path if source is None: with open(path) as f: source = f.read() lines = source.splitlines() or [''] if source and source[-1] == '\n': lines.append('') self._line = max(len(lines), 1) if line is None else line if not (0 < self._line <= len(lines)): raise ValueError('`line` parameter is not in a valid range.') line_len = len(lines[self._line - 1]) self._column = line_len if column is None else column if not (0 <= self._column <= line_len): raise ValueError('`column` parameter is not in a valid range.') api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, encoding) self._pos = self._line, self._column self._module = modules.ModuleWithCursor( path, source=self.source, position=self._pos) self._source_path = path self.path = None if path is None else os.path.abspath(path) debug.speed('init')
def extract(script, new_name): """ The `args` / `kwargs` params are the same as in `api.Script`. :param operation: The refactoring operation to execute. :type operation: str :type source: str :return: list of changed lines/changed files """ new_lines = modules.source_to_unicode(script.source).splitlines() old_lines = new_lines[:] user_stmt = script._parser.user_stmt # TODO care for multiline extracts dct = {} if user_stmt: pos = script.pos line_index = pos[0] - 1 arr, index = helpers.array_for_pos(user_stmt, pos) if arr is not None: start_pos = arr[index].start_pos end_pos = arr[index].end_pos # take full line if the start line is different from end line e = end_pos[1] if end_pos[0] == start_pos[0] else None start_line = new_lines[start_pos[0] - 1] text = start_line[start_pos[1]:e] for l in range(start_pos[0], end_pos[0] - 1): text += '\n' + l if e is None: end_line = new_lines[end_pos[0] - 1] text += '\n' + end_line[:end_pos[1]] # remove code from new lines t = text.lstrip() del_start = start_pos[1] + len(text) - len(t) text = t.rstrip() del_end = len(t) - len(text) if e is None: new_lines[end_pos[0] - 1] = end_line[end_pos[1] - del_end:] e = len(start_line) else: e = e - del_end start_line = start_line[:del_start] + new_name + start_line[e:] new_lines[start_pos[0] - 1] = start_line new_lines[start_pos[0]:end_pos[0] - 1] = [] # add parentheses in multiline case open_brackets = ['(', '[', '{'] close_brackets = [')', ']', '}'] if '\n' in text and not (text[0] in open_brackets and text[-1] == close_brackets[open_brackets.index(text[0])]): text = '(%s)' % text # add new line before statement indent = user_stmt.start_pos[1] new = "%s%s = %s" % (' ' * indent, new_name, text) new_lines.insert(line_index, new) dct[script.path] = script.path, old_lines, new_lines return Refactoring(dct)
def extract(script, new_name): """ The `args` / `kwargs` params are the same as in `api.Script`. :param operation: The refactoring operation to execute. :type operation: str :type source: str :return: list of changed lines/changed files """ new_lines = modules.source_to_unicode(script.source).splitlines() old_lines = new_lines[:] user_stmt = script._parser.user_stmt # TODO care for multiline extracts dct = {} if user_stmt: pos = script._pos line_index = pos[0] - 1 arr, index = helpers.array_for_pos(user_stmt, pos) if arr is not None: start_pos = arr[index].start_pos end_pos = arr[index].end_pos # take full line if the start line is different from end line e = end_pos[1] if end_pos[0] == start_pos[0] else None start_line = new_lines[start_pos[0] - 1] text = start_line[start_pos[1]:e] for l in range(start_pos[0], end_pos[0] - 1): text += '\n' + l if e is None: end_line = new_lines[end_pos[0] - 1] text += '\n' + end_line[:end_pos[1]] # remove code from new lines t = text.lstrip() del_start = start_pos[1] + len(text) - len(t) text = t.rstrip() del_end = len(t) - len(text) if e is None: new_lines[end_pos[0] - 1] = end_line[end_pos[1] - del_end:] e = len(start_line) else: e = e - del_end start_line = start_line[:del_start] + new_name + start_line[e:] new_lines[start_pos[0] - 1] = start_line new_lines[start_pos[0]:end_pos[0] - 1] = [] # add parentheses in multiline case open_brackets = ['(', '[', '{'] close_brackets = [')', ']', '}'] if '\n' in text and not (text[0] in open_brackets and text[-1] == close_brackets[open_brackets.index(text[0])]): text = '(%s)' % text # add new line before statement indent = user_stmt.start_pos[1] new = "%s%s = %s" % (' ' * indent, new_name, text) new_lines.insert(line_index, new) dct[script.path] = script.path, old_lines, new_lines return Refactoring(dct)
def __init__(self, source, line, column, source_path, source_encoding="utf-8"): api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, source_encoding) self.pos = line, column self._module = modules.ModuleWithCursor(source_path, source=self.source, position=self.pos) self._source_path = source_path self.source_path = None if source_path is None else os.path.abspath(source_path) debug.speed("init")
def defined_names(source, source_path=None, source_encoding="utf-8"): """ Get all definitions in `source` sorted by its position. This functions can be used for listing functions, classes and data defined in a file. This can be useful if you want to list them in "sidebar". Each element in the returned list also has `defined_names` method which can be used to get sub-definitions (e.g., methods in class). :rtype: list of api_classes.Definition """ parser = parsing.Parser(modules.source_to_unicode(source, source_encoding), module_path=source_path) return api_classes._defined_names(parser.scope)
def __init__(self, source, line=None, column=None, source_path=None, source_encoding='utf-8'): lines = source.splitlines() line = len(lines) if line is None else line column = len(lines[-1]) if column is None else column api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, source_encoding) self.pos = line, column self._module = modules.ModuleWithCursor( source_path, source=self.source, position=self.pos) self._source_path = source_path self.source_path = None if source_path is None \ else os.path.abspath(source_path) debug.speed('init')
def inline(script): """ :type script: api.Script """ new_lines = modules.source_to_unicode(script.source).splitlines() dct = {} definitions = script.goto() with common.ignored(AssertionError): assert len(definitions) == 1 stmt = definitions[0]._definition usages = script.usages() inlines = [ r for r in usages if not stmt.start_pos <= r.start_pos <= stmt.end_pos ] inlines = sorted(inlines, key=lambda x: (x.module_path, x.start_pos), reverse=True) commands = stmt.get_commands() # don't allow multiline refactorings for now. assert stmt.start_pos[0] == stmt.end_pos[0] index = stmt.start_pos[0] - 1 line = new_lines[index] replace_str = line[commands[0].start_pos[1]:stmt.end_pos[1] + 1] replace_str = replace_str.strip() # tuples need parentheses if commands and isinstance(commands[0], pr.Array): arr = commands[0] if replace_str[0] not in ['(', '[', '{'] and len(arr) > 1: replace_str = '(%s)' % replace_str # if it's the only assignment, remove the statement if len(stmt.set_vars) == 1: line = line[:stmt.start_pos[1]] + line[stmt.end_pos[1]:] dct = _rename(inlines, replace_str) # remove the empty line new_lines = dct[script.source_path][2] if line.strip(): new_lines[index] = line else: new_lines.pop(index) return Refactoring(dct)
def inline(script): """ :type script: api.Script """ new_lines = modules.source_to_unicode(script.source).splitlines() dct = {} definitions = script.goto() try: assert len(definitions) == 1 stmt = definitions[0].definition related_names = script.related_names() inlines = [r for r in related_names if not stmt.start_pos <= r.start_pos <= stmt.end_pos] inlines = sorted(inlines, key=lambda x: (x.module_path, x.start_pos), reverse=True) commands = stmt.get_commands() # don't allow multiline refactorings for now. assert stmt.start_pos[0] == stmt.end_pos[0] index = stmt.start_pos[0] - 1 line = new_lines[index] replace_str = line[commands[0].start_pos[1]:stmt.end_pos[1] + 1] replace_str = replace_str.strip() # tuples need parentheses if commands and isinstance(commands[0], pr.Array): arr = commands[0] if replace_str[0] not in ['(', '[', '{'] and len(arr) > 1: replace_str = '(%s)' % replace_str # if it's the only assignment, remove the statement if len(stmt.set_vars) == 1: line = line[:stmt.start_pos[1]] + line[stmt.end_pos[1]:] dct = _rename(inlines, replace_str) # remove the empty line new_lines = dct[script.source_path][2] if line.strip(): new_lines[index] = line else: new_lines.pop(index) except AssertionError: pass return Refactoring(dct)
def __init__(self, source, line, column, source_path, source_encoding='utf-8'): api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, source_encoding) self.pos = line, column self._module = modules.ModuleWithCursor(source_path, source=self.source, position=self.pos) self._source_path = source_path self.source_path = None if source_path is None \ else os.path.abspath(source_path) debug.speed('init')
def defined_names(source, path=None, source_encoding='utf-8'): """ Get all definitions in `source` sorted by its position. This functions can be used for listing functions, classes and data defined in a file. This can be useful if you want to list them in "sidebar". Each element in the returned list also has `defined_names` method which can be used to get sub-definitions (e.g., methods in class). :rtype: list of api_classes.Definition """ parser = Parser( modules.source_to_unicode(source, source_encoding), module_path=path, ) return api_classes._defined_names(parser.module)
def __init__(self, source, line=None, column=None, path=None, source_encoding='utf-8', source_path=None): if source_path is not None: warnings.warn("Use path instead of source_path.", DeprecationWarning) path = source_path lines = source.splitlines() if source and source[-1] == '\n': lines.append('') self._line = max(len(lines), 1) if line is None else line self._column = len(lines[-1]) if column is None else column api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, source_encoding) self.pos = self._line, self._column self._module = modules.ModuleWithCursor( path, source=self.source, position=self.pos) self._source_path = path self.path = None if path is None else os.path.abspath(path) debug.speed('init')
def __init__(self, source=None, line=None, column=None, path=None, source_encoding='utf-8', source_path=None): if source_path is not None: warnings.warn("Use path instead of source_path.", DeprecationWarning) path = source_path if source is None: with open(path) as f: source = f.read() lines = source.splitlines() or [''] if source and source[-1] == '\n': lines.append('') self._line = max(len(lines), 1) if line is None else line if not (0 < self._line <= len(lines)): raise ValueError('`line` parameter is not in a valid range.') line_len = len(lines[self._line - 1]) self._column = line_len if column is None else column if not (0 <= self._column <= line_len): raise ValueError('`column` parameter is not in a valid range.') api_classes._clear_caches() debug.reset_time() self.source = modules.source_to_unicode(source, source_encoding) self._pos = self._line, self._column self._module = modules.ModuleWithCursor(path, source=self.source, position=self._pos) self._source_path = path self.path = None if path is None else os.path.abspath(path) debug.speed('init')
def check_fs(path): with open(path) as f: source = modules.source_to_unicode(f.read()) if name in source: return modules.Module(path, source).parser.module