Exemple #1
0
def get_correct_indentation_diff(code, filename):
    """
    Generate a diff to make code correctly indented.

    :param code: a string containing a file's worth of Python code
    :param filename: the filename being considered (used in diff generation only)
    :returns: a unified diff to make code correctly indented, or
              None if code is already correctedly indented
    """
    code_buffer = StringIO(code)
    output_buffer = StringIO()
    reindenter = reindent.Reindenter(code_buffer)
    reindenter.run()
    reindenter.write(output_buffer)
    reindent_output = output_buffer.getvalue()
    output_buffer.close()
    if code != reindent_output:
        diff_generator = difflib.unified_diff(code.splitlines(True), reindent_output.splitlines(True),
                                              fromfile=filename, tofile=filename + " (reindented)")
        # work around http://bugs.python.org/issue2142
        diff_tuple = map(clean_diff_line_for_python_bug_2142, diff_generator)
        diff = "".join(diff_tuple)
        return diff
    else:
        return None
Exemple #2
0
class FileChecker(object):
    """
    Picks up a given file and performs various checks, looking after problems
    and eventually suggesting solutions.
    """
    def __init__(self, path=None, vcs=None, confirm=False):
        """
        Class constructor, sets the path attribute.

        @param path: Path to the file that will be checked.
        @param vcs: Version control system being used.
        @param confirm: Whether to answer yes to all questions asked without
                prompting the user.
        """
        if path is not None:
            self.set_path(path=path, vcs=vcs, confirm=confirm)

    def set_path(self, path, vcs=None, confirm=False):
        self.path = path
        self.vcs = vcs
        self.confirm = confirm
        self.basename = os.path.basename(self.path)

        if self.basename.endswith('.py'):
            self.is_python = True
        else:
            self.is_python = False

        mode = os.stat(self.path)[stat.ST_MODE]
        self.is_executable = mode & stat.S_IXUSR

        checked_file = open(self.path, "r")
        self.first_line = checked_file.readline()
        checked_file.close()
        if "python" in self.first_line:
            self.is_python = True

        self.corrective_actions = []

        self.indent_exceptions = []
        version = sys.version_info[0:2]
        self.check_exceptions = []
        if version < (2, 5):
            self.check_exceptions = [
                'qemu/tests/stepmaker.py', 'virttest/step_editor.py',
                'shared/scripts/cb.py'
            ]

        if self.is_python:
            logging.debug("Checking file %s", self.path)
        if self.is_python and not self.path.endswith(".py"):
            self.bkp_path = "%s-cp.py" % self.path
            shutil.copyfile(self.path, self.bkp_path)
        else:
            self.bkp_path = None

    def _get_checked_filename(self):
        if self.bkp_path is not None:
            return self.bkp_path
        else:
            return self.path

    def _check_indent(self):
        """
        Verifies the file with the reindent module

        This tool performs the following checks on python files:

          * Trailing whitespaces
          * Tabs
          * End of line
          * Incorrect indentation

        And will automatically correct problems.
        """
        success = True
        for exc in self.indent_exceptions:
            if re.search(exc, self.path):
                return success

        path = self._get_checked_filename()
        try:
            f = open(path)
        except IOError, msg:
            logging.error("Error opening %s: %s", path, str(msg))
            return False

        r = reindent.Reindenter(f)
        f.close()
        try:
            if r.run():
                success = False
                logging.info("Reindenting %s", path)
                f = open(path, "w")
                r.write(f)
                f.close()
        except:
            pass

        if not success and path != self.path:
            shutil.copyfile(path, self.path)

        return success