Source

rope_py3k / rope / contrib / fixsyntax.py

Full commit
Ali Gholami Rudi 04968ee 

Ali Gholami Rudi b0b2a6c 
Ali Gholami Rudi 04968ee 


Ali Gholami Rudi b0b2a6c 
Ali Gholami Rudi 04968ee 
Ali Gholami Rudi b0b2a6c 




Ali Gholami Rudi 04968ee 
Ali Gholami Rudi b0b2a6c 













zjes 65846d1 
Ali Gholami Rudi b0b2a6c 
















Ali Gholami Rudi ef814b3 
Ali Gholami Rudi b0b2a6c 









Ali Gholami Rudi ef814b3 
Ali Gholami Rudi b0b2a6c 
Ali Gholami Rudi ef814b3 

Ali Gholami Rudi b0b2a6c 


Ali Gholami Rudi ef814b3 
Ali Gholami Rudi b0b2a6c 

Ali Gholami Rudi 04968ee 



Ali Gholami Rudi ef814b3 



zjes 65846d1 
Ali Gholami Rudi ef814b3 
Ali Gholami Rudi 04968ee 


Ali Gholami Rudi ef814b3 


Ali Gholami Rudi 04968ee 





Ali Gholami Rudi b0b2a6c 
Ali Gholami Rudi 04968ee 
Ali Gholami Rudi b0b2a6c 
Ali Gholami Rudi 04968ee 

Ali Gholami Rudi ef814b3 




Ali Gholami Rudi 04968ee 














Ali Gholami Rudi ef814b3 







Ali Gholami Rudi 04968ee 















Ali Gholami Rudi b0b2a6c 

Ali Gholami Rudi 04968ee 












Ali Gholami Rudi b0b2a6c 
Ali Gholami Rudi ef814b3 
Ali Gholami Rudi b0b2a6c 


Ali Gholami Rudi ef814b3 

Ali Gholami Rudi b0b2a6c 

Ali Gholami Rudi 04968ee 














import rope.base.codeanalyze
import rope.base.evaluate
from rope.base import worder, exceptions, utils
from rope.base.codeanalyze import ArrayLinesAdapter, LogicalLineFinder


class FixSyntax(object):

    def __init__(self, pycore, code, resource, maxfixes=1):
        self.pycore = pycore
        self.code = code
        self.resource = resource
        self.maxfixes = maxfixes

    @utils.saveit
    def get_pymodule(self):
        """Get a `PyModule`"""
        errors = []
        code = self.code
        tries = 0
        while True:
            try:
                if tries == 0 and self.resource is not None and \
                   self.resource.read() == code:
                    return self.pycore.resource_to_pyobject(self.resource,
                                                            force_errors=True)
                return self.pycore.get_string_module(
                    code, resource=self.resource, force_errors=True)
            except exceptions.ModuleSyntaxError as e:
                if tries < self.maxfixes:
                    tries += 1
                    self.commenter.comment(e.lineno)
                    code = '\n'.join(self.commenter.lines)
                    errors.append('  * line %s: %s ... fixed' % (e.lineno,
                                                                 e.message_))
                else:
                    errors.append('  * line %s: %s ... raised!' % (e.lineno,
                                                                   e.message_))
                    new_message = ('\nSyntax errors in file %s:\n' % e.filename) \
                                   + '\n'.join(errors)
                    raise exceptions.ModuleSyntaxError(e.filename, e.lineno,
                                                       new_message)

    @property
    @utils.saveit
    def commenter(self):
        return _Commenter(self.code)

    def pyname_at(self, offset):
        pymodule = self.get_pymodule()
        def old_pyname():
            word_finder = worder.Worder(self.code, True)
            expression = word_finder.get_primary_at(offset)
            expression = expression.replace('\\\n', ' ').replace('\n', ' ')
            lineno = self.code.count('\n', 0, offset)
            scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
            return rope.base.evaluate.eval_str(scope, expression)
        new_code = pymodule.source_code
        def new_pyname():
            newoffset = self.commenter.transfered_offset(offset)
            return rope.base.evaluate.eval_location(pymodule, newoffset)
        if new_code.startswith(self.code[:offset + 1]):
            return new_pyname()
        result = old_pyname()
        if result is None:
            return new_pyname()
        return result


class _Commenter(object):

    def __init__(self, code):
        self.code = code
        self.lines = self.code.split('\n')
        self.lines.append('\n')
        self.origs = list(range(len(self.lines) + 1))
        self.diffs = [0] * (len(self.lines) + 1)

    def comment(self, lineno):
        start = _logical_start(self.lines, lineno, check_prev=True) - 1
        # using self._get_stmt_end() instead of self._get_block_end()
        # to lower commented lines
        end = self._get_stmt_end(start)
        indents = _get_line_indents(self.lines[start])
        if 0 < start:
            last_lineno = self._last_non_blank(start - 1)
            last_line = self.lines[last_lineno]
            if last_line.rstrip().endswith(':'):
                indents = _get_line_indents(last_line) + 4
        self._set(start, ' ' * indents + 'pass')
        for line in range(start + 1, end + 1):
            self._set(line, self.lines[start])
        self._fix_incomplete_try_blocks(lineno, indents)

    def transfered_offset(self, offset):
        lineno = self.code.count('\n', 0, offset)
        diff = sum(self.diffs[:lineno])
        return offset + diff

    def _last_non_blank(self, start):
        while start > 0 and self.lines[start].strip() == '':
            start -= 1
        return start

    def _get_block_end(self, lineno):
        end_line = lineno
        base_indents = _get_line_indents(self.lines[lineno])
        for i in range(lineno + 1, len(self.lines)):
            if _get_line_indents(self.lines[i]) >= base_indents:
                end_line = i
            else:
                break
        return end_line

    def _get_stmt_end(self, lineno):
        end_line = lineno
        base_indents = _get_line_indents(self.lines[lineno])
        for i in range(lineno + 1, len(self.lines)):
            if _get_line_indents(self.lines[i]) <= base_indents:
                return i - 1
        return lineno

    def _fix_incomplete_try_blocks(self, lineno, indents):
        block_start = lineno
        last_indents = current_indents = indents
        while block_start > 0:
            block_start = rope.base.codeanalyze.get_block_start(
                ArrayLinesAdapter(self.lines), block_start) - 1
            if self.lines[block_start].strip().startswith('try:'):
                indents = _get_line_indents(self.lines[block_start])
                if indents > last_indents:
                    continue
                last_indents = indents
                block_end = self._find_matching_deindent(block_start)
                line = self.lines[block_end].strip()
                if not (line.startswith('finally:') or
                        line.startswith('except ') or
                        line.startswith('except:')):
                    self._insert(block_end, ' ' * indents + 'finally:')
                    self._insert(block_end + 1, ' ' * indents + '    pass')

    def _find_matching_deindent(self, line_number):
        indents = _get_line_indents(self.lines[line_number])
        current_line = line_number + 1
        while current_line < len(self.lines):
            line = self.lines[current_line]
            if not line.strip().startswith('#') and not line.strip() == '':
                # HACK: We should have used logical lines here
                if _get_line_indents(self.lines[current_line]) <= indents:
                    return current_line
            current_line += 1
        return len(self.lines) - 1

    def _set(self, lineno, line):
        self.diffs[self.origs[lineno]] += len(line) - len(self.lines[lineno])
        self.lines[lineno] = line

    def _insert(self, lineno, line):
        self.diffs[self.origs[lineno]] += len(line) + 1
        self.origs.insert(lineno, self.origs[lineno])
        self.lines.insert(lineno, line)

def _logical_start(lines, lineno, check_prev=False):
    logical_finder = LogicalLineFinder(ArrayLinesAdapter(lines))
    if check_prev:
        prev = lineno - 1
        while prev > 0:
            start, end = logical_finder.logical_line_in(prev)
            if end is None or start <= lineno < end:
                return start
            if start <= prev:
                break
            prev -= 1
    return logical_finder.logical_line_in(lineno)[0]


def _get_line_indents(line):
    return rope.base.codeanalyze.count_line_indents(line)