Beispiel #1
0
def test_ufodiff_ufo_data_dir_file_false():
    ufo = Ufo()
    test_path_1 = os.path.join("source", "Test-Regular.ufo", "datum",
                               "org.sourcefoundry.coolstuff")  # bad dir path
    test_path_2 = os.path.join("source", "Test-Regular", "data",
                               "org.sourcefoundry.coolstuff")  # not ufo dir
    assert ufo._is_data_directory_file(test_path_1) is False
    assert ufo._is_data_directory_file(test_path_2) is False
Beispiel #2
0
 def __init__(self, gitrepo_path, color_diff=False):
     self.gitrepo_path = gitrepo_path  # root path for git repository
     self.is_color_diff = color_diff  # is request for color diff = True
     self.repo = Repo(self.gitrepo_path)  # GitPython Repo object
     self.git = self.repo.git  # GitPython Repo.git object
     self.ufo = Ufo()  # ufodiff.utilities.ufo.Ufo object
     self.current_branch = self.git.rev_parse(
         "--abbrev-ref",
         "HEAD")  # current git branch automatically detected
Beispiel #3
0
def test_ufodiff_ufo_images_dir_png_file_false():
    ufo = Ufo()
    test_path_1 = os.path.join("source", "anotherdir", "images",
                               "cap_a.png")  # not a UFO source directory
    test_path_2 = os.path.join("source", "Test-Regular.ufo", "image",
                               "cap_a.png")  # incorrect images dir path
    test_path_3 = os.path.join("source", "Test-Regular.ufo", "images",
                               "cap_a.jpg")  # jpg file, not png
    assert ufo._is_images_directory_file(test_path_1) is False
    assert ufo._is_images_directory_file(test_path_2) is False
    assert ufo._is_images_directory_file(test_path_3) is False
Beispiel #4
0
def test_ufodiff_ufo_diff_filters():
    ufo = Ufo()
    filter_test_list = ufo.get_valid_file_filterlist_for_diff()
    # test for each of the nonglyph files
    for acceptable_file in ufo.acceptable_files:
        filter_file = "*" + acceptable_file
        assert filter_file in filter_test_list
    # test for inclusion of glyph files
    assert "*.glif" in filter_test_list
    assert r"*\.ufo/images/*" in filter_test_list
    assert r"*\.ufo/data/*" in filter_test_list
Beispiel #5
0
def test_ufodiff_ufo_data_dir_file_via_public_method_call():
    ufo = Ufo()
    test_path_1 = os.path.join(
        "source", "Test-Regular.ufo", "datum",
        "org.sourcefoundry.coolstuff")  # bad dir path (False)
    test_path_2 = os.path.join(
        "source", "Test-Regular", "data",
        "org.sourcefoundry.coolstuff")  # not ufo dir (False)
    test_path_3 = os.path.join(
        "source", "Test-Regular.ufo", "data",
        "org.sourcefoundry.coolstuff")  # good path (True)
    assert ufo.validate_file(test_path_1) is False
    assert ufo.validate_file(test_path_2) is False
    assert ufo.validate_file(test_path_3) is True
Beispiel #6
0
def test_ufodiff_ufo_images_dir_png_file_via_public_method_call():
    ufo = Ufo()
    test_path_1 = os.path.join(
        "source", "anotherdir", "images",
        "cap_a.png")  # not a UFO source directory (False)
    test_path_2 = os.path.join(
        "source", "Test-Regular.ufo", "image",
        "cap_a.png")  # incorrect images dir path (False)
    test_path_3 = os.path.join("source", "Test-Regular.ufo", "images",
                               "cap_a.jpg")  # jpg file, not png (False)
    test_path_4 = os.path.join("source", "Test-Regular.ufo", "images",
                               "cap_a.png")  # good path (True)
    assert ufo.validate_file(test_path_1) is False
    assert ufo.validate_file(test_path_2) is False
    assert ufo.validate_file(test_path_3) is False
    assert ufo.validate_file(test_path_4) is True
Beispiel #7
0
    def __init__(
        self,
        gitrepo_path,
        ufo_directory_list,
        is_commit_test=False,
        commit_number="0",
        is_branch_test=False,
        compare_branch_name=None,
    ):
        self.gitrepo_path = gitrepo_path  # path to root of git repository
        self.ufo_directory_list = ufo_directory_list  # used to filter results by user defined UFO source directory
        self.is_commit_test = is_commit_test  # commit test flag
        self.commit_number = (
            commit_number  # user defined number of commits in git history to compare
        )
        self.is_branch_test = is_branch_test  # branch test flag
        self.compare_branch_name = (
            compare_branch_name  # comparison branch requested by user (if branch test)
        )
        self.current_branch_name = (
            ""  # defined in _define_and_validate_ufo_diff_lists if branch test
        )
        self.ufo = Ufo()  # Ufo class used for UFO source validations
        self.git = None  # GitPython object (instantiated in class method)
        self.delta_fp_string_dict = DeltaFilepathStringDict(
            ufo_directory_list
        )  # stores delta file strings in .delta_dict attribute

        self.commit_sha1_list = (
            [])  # used to create dictionaries of report data in class methods

        # file string lists
        self.added_ufo_file_list = (
            [])  # used to create dictionaries of report data in class methods
        self.modified_ufo_file_list = (
            [])  # used to create dictionaries of report data in class methods
        self.deleted_ufo_file_list = (
            [])  # used to create dictionaries of report data in class methods

        # filters files for UFO spec and includes only diff files that are part of spec
        self._define_and_validate_ufo_diff_lists(
        )  # defines many of the class properties on object instantiation
Beispiel #8
0
class Delta(object):
    """
    Delta class stores delta subcommand data and provides methods to support creation of
    delta / deltajson / deltamd application subcommand reports through UFO file spec validation and
    filtering of user requested *.ufo source directory filters

    Uses DeltaFilepathStringDict object (this module) to (1) filter data by optional user specified *.ufo source filter;
    (2) maintain final data for reports in the DeltaFilepathStringDict.delta_dict Python dictionary property

    :param gitrepo_path: (string) absolute file path to the root level of the git repository for analysis (automatically detected in ufodiff.app.py)
    :param ufo_directory_list: (list) list of one or more UFO directories for filter of results (user specified on CL)
    :param is_commit_test: (boolean) flag for request as test of commit history in the git repository
    :param commit_number: (string) the number of commits in git commit history for analysis as string (user specified)
    :param is_branch_test: (boolean) flag for request as test of branch vs. branch in git repository
    :param compare_branch_name: (string) the branch name requested by user for test vs. current branch (user specified)
    """
    def __init__(
        self,
        gitrepo_path,
        ufo_directory_list,
        is_commit_test=False,
        commit_number="0",
        is_branch_test=False,
        compare_branch_name=None,
    ):
        self.gitrepo_path = gitrepo_path  # path to root of git repository
        self.ufo_directory_list = ufo_directory_list  # used to filter results by user defined UFO source directory
        self.is_commit_test = is_commit_test  # commit test flag
        self.commit_number = (
            commit_number  # user defined number of commits in git history to compare
        )
        self.is_branch_test = is_branch_test  # branch test flag
        self.compare_branch_name = (
            compare_branch_name  # comparison branch requested by user (if branch test)
        )
        self.current_branch_name = (
            ""  # defined in _define_and_validate_ufo_diff_lists if branch test
        )
        self.ufo = Ufo()  # Ufo class used for UFO source validations
        self.git = None  # GitPython object (instantiated in class method)
        self.delta_fp_string_dict = DeltaFilepathStringDict(
            ufo_directory_list
        )  # stores delta file strings in .delta_dict attribute

        self.commit_sha1_list = (
            [])  # used to create dictionaries of report data in class methods

        # file string lists
        self.added_ufo_file_list = (
            [])  # used to create dictionaries of report data in class methods
        self.modified_ufo_file_list = (
            [])  # used to create dictionaries of report data in class methods
        self.deleted_ufo_file_list = (
            [])  # used to create dictionaries of report data in class methods

        # filters files for UFO spec and includes only diff files that are part of spec
        self._define_and_validate_ufo_diff_lists(
        )  # defines many of the class properties on object instantiation

    # PRIVATE METHODS
    def _define_and_validate_ufo_diff_lists(self):
        """
        Defines Delta class properties on instantiation of the object in app.py module
        :return: no return object
        """
        # instantiate git Repo object
        repo = Repo(self.gitrepo_path)
        # define class attribute git object
        self.git = repo.git

        if self.is_commit_test is True:
            commit_number_string = "HEAD~" + self.commit_number  # with HEAD~N syntax
            added_file_string = self.git.diff("--name-only", "--diff-filter=A",
                                              commit_number_string)
            added_filepath_list = added_file_string.split("\n")
            deleted_file_string = self.git.diff("--name-only",
                                                "--diff-filter=D",
                                                commit_number_string)
            deleted_filepath_list = deleted_file_string.split("\n")
            modified_file_string = self.git.diff("--name-only",
                                                 "--diff-filter=M",
                                                 commit_number_string)
            modified_filepath_list = modified_file_string.split("\n")
        elif self.is_branch_test is True:
            self.current_branch_name = self.git.rev_parse(
                ["--abbrev-ref", "HEAD"])
            branch_comparison_string = (self.compare_branch_name + ".." +
                                        self.current_branch_name)
            added_file_string = self.git.diff(
                ["--name-only", "--diff-filter=A", branch_comparison_string])
            added_filepath_list = added_file_string.split("\n")
            deleted_file_string = self.git.diff(
                ["--name-only", "--diff-filter=D", branch_comparison_string])
            deleted_filepath_list = deleted_file_string.split("\n")
            modified_file_string = self.git.diff(
                ["--name-only", "--diff-filter=M", branch_comparison_string])
            modified_filepath_list = modified_file_string.split("\n")

        # load class attribute lists with the filepaths that are validated to be UFO in the following method
        self._validate_ufo_and_load_dict_from_filepath_strings(
            added_filepath_list, deleted_filepath_list, modified_filepath_list)

    def _add_commit_sha1_to_lists(self):
        """
        Adds commit SHA1 short codes for commits requested by user to the Delta.commit_sha1_list property as a Python
        list.

        :return: no return object
        """
        sha1_num_commits = "-" + self.commit_number
        sha1_args = [sha1_num_commits, "--pretty=%h"]
        sha1_string = self.git.log(
            sha1_args
        )  # git log -[N] --pretty=%h ===> newline delimited list of SHA1 x N commit
        self.commit_sha1_list = sha1_string.split(
            "\n"
        )  # do not modify to os.linesep, Win fails tests with this change

    def _validate_ufo_and_load_dict_from_filepath_strings(
            self, added_filepath_list, deleted_filepath_list,
            modified_filepath_list):
        """
        Validates filepaths for detected added, modified, and deleted files against UFO specification and includes
        valid files in Delta object property lists.  These lists are used to generate the DeltaFilepathStringDict
        delta_dict Python dictionary that maintains these data in key:value format for report generation.

        UFO validation of files occurs in this class method.

        :param added_filepath_list: (list) files that were added to repository
        :param deleted_filepath_list: (list) files that were deleted from repository
        :param modified_filepath_list: (list) files that were modified in repository
        :return: no return object
        """
        # test for valid UFO files and add the filepath string to the appropriate class instance attribute
        # load added files list
        if len(added_filepath_list) > 0:
            for added_file in added_filepath_list:
                if self.ufo.validate_file(added_file) is True:
                    self.added_ufo_file_list.append(added_file)

        # load deleted files list
        if len(deleted_filepath_list) > 0:
            for deleted_file in deleted_filepath_list:
                if self.ufo.validate_file(deleted_file) is True:
                    self.deleted_ufo_file_list.append(deleted_file)

        # load modified files list
        if len(modified_filepath_list) > 0:
            for modified_file in modified_filepath_list:
                if self.ufo.validate_file(modified_file) is True:
                    self.modified_ufo_file_list.append(modified_file)

        # define the key:value structure of the dictionary attribute on the DeltaFilepathStringDict() class
        if self.is_commit_test:
            self._add_commit_sha1_to_lists()
            self.delta_fp_string_dict.add_commit_sha1(
                self.commit_sha1_list)  # create 'commits' dict key
        elif self.is_branch_test:
            branch_list = [self.compare_branch_name, self.current_branch_name]
            self.delta_fp_string_dict.add_branches(
                branch_list)  # create 'branches' dict key
        self.delta_fp_string_dict.add_added_filepaths(
            self.added_ufo_file_list)  # create 'added' dict key
        self.delta_fp_string_dict.add_deleted_filepaths(
            self.deleted_ufo_file_list)  # create 'deleted' dict key
        self.delta_fp_string_dict.add_modified_filepaths(
            self.modified_ufo_file_list)  # create 'modified' dict key

    def _get_delta_text_string(self):
        """
        Generates plain text string format for delta subcommand reports.
        :return: (string) plain text string formatted Python string intended for standard output stream
        """
        textstring = ""
        if (self.is_commit_test is True
            ):  # include commits if this is an analysis of commit history
            # Write SHA1 commits under examination
            if len(self.delta_fp_string_dict.delta_dict["commits"]) > 0:
                textstring += (os.linesep +
                               "Commit history SHA1 for this analysis:" +
                               os.linesep)
                for sha1_commit in self.delta_fp_string_dict.delta_dict[
                        "commits"]:
                    textstring += " " + sha1_commit + os.linesep
                textstring += os.linesep
        elif (self.is_branch_test is
              True):  # include branches if this is a branch v branch analysis
            if len(self.delta_fp_string_dict.delta_dict["branches"]) > 0:
                textstring += os.linesep + "Branches under analysis:" + os.linesep
                for branch in self.delta_fp_string_dict.delta_dict["branches"]:
                    textstring += " " + branch + os.linesep
                textstring += os.linesep

        # include added files
        if len(self.delta_fp_string_dict.delta_dict["added"]) > 0:
            for added_file in self.delta_fp_string_dict.delta_dict["added"]:
                add_append_string = "[A]:" + added_file + os.linesep
                textstring += add_append_string
        # include deleted files
        if len(self.delta_fp_string_dict.delta_dict["deleted"]) > 0:
            for deleted_file in self.delta_fp_string_dict.delta_dict[
                    "deleted"]:
                del_append_string = "[D]:" + deleted_file + os.linesep
                textstring += del_append_string
        # include modified files
        if len(self.delta_fp_string_dict.delta_dict["modified"]) > 0:
            for modified_file in self.delta_fp_string_dict.delta_dict[
                    "modified"]:
                mod_append_string = "[M]:" + modified_file + os.linesep
                textstring += mod_append_string

        return textstring

    def _get_delta_json_string(self):
        """
        Generates JSON format for deltajson subcommand reports.
        :return: (string) JSON formatted Python string intended for standard output stream
        """
        return json.dumps(self.delta_fp_string_dict.delta_dict)

    def _get_delta_markdown_string(self):
        """
        Generates Markdown format for deltamd subcommand reports.
        :return: (string) Markdown formatted Python string intended for standard output stream
        """
        markdown_string = ""

        if self.is_commit_test is True:
            if len(self.delta_fp_string_dict.delta_dict["commits"]) > 0:
                markdown_string += (
                    os.linesep + "## Commit history SHA1 for this analysis:" +
                    os.linesep)
                for sha1_commit in self.delta_fp_string_dict.delta_dict[
                        "commits"]:
                    markdown_string += "- `" + sha1_commit + "`" + os.linesep
                markdown_string += os.linesep
        elif self.is_branch_test is True:
            if len(self.delta_fp_string_dict.delta_dict["branches"]) > 0:
                markdown_string += (os.linesep +
                                    "## Branches under analysis:" + os.linesep)
                for branch in self.delta_fp_string_dict.delta_dict["branches"]:
                    markdown_string += "- " + branch + os.linesep
                markdown_string += os.linesep

        # Added files block
        markdown_string += "## Added Files" + os.linesep
        if len(self.delta_fp_string_dict.delta_dict["added"]) > 0:
            for added_file in self.delta_fp_string_dict.delta_dict["added"]:
                markdown_string += "- " + added_file + os.linesep
        else:
            markdown_string += "- None" + os.linesep

        # Deleted files block
        markdown_string += os.linesep + os.linesep + "## Deleted Files" + os.linesep
        if len(self.delta_fp_string_dict.delta_dict["deleted"]) > 0:
            for deleted_file in self.delta_fp_string_dict.delta_dict[
                    "deleted"]:
                markdown_string += "- " + deleted_file + os.linesep
        else:
            markdown_string += "- None" + os.linesep

        # Modified files block
        markdown_string += os.linesep + os.linesep + "## Modified Files" + os.linesep
        if len(self.delta_fp_string_dict.delta_dict["modified"]) > 0:
            for modified_file in self.delta_fp_string_dict.delta_dict[
                    "modified"]:
                markdown_string += "- " + modified_file + os.linesep
        else:
            markdown_string += "- None" + os.linesep

        # Project URL + version footer
        markdown_string += (
            os.linesep + os.linesep + "---" + os.linesep +
            "[ufodiff](https://github.com/source-foundry/ufodiff) v" +
            major_version + "." + minor_version + "." + patch_version)

        return markdown_string

    # PUBLIC METHODS

    def get_stdout_string(self, write_format=None):
        """
        Called by app.py module with write_format type that is dependent upon the user subcommand request
        :param write_format: (string) options include 'text', 'json', and 'markdown'
        :return: (string) file change report formatted according to write_format parameter
        """
        if write_format == "text":
            return self._get_delta_text_string()
        elif write_format == "json":
            return self._get_delta_json_string()
        elif write_format == "markdown":
            return self._get_delta_markdown_string()
Beispiel #9
0
def test_ufodiff_ufo_version_false():
    ufo = Ufo()
    assert ufo.is_ufo_version_file("fontinfo.plist") is False
Beispiel #10
0
def test_ufodiff_ufo_version_true():
    ufo = Ufo()
    assert ufo.is_ufo_version_file("metainfo.plist") is True
Beispiel #11
0
def test_ufodiff_ufo_glyph_false():
    ufo = Ufo()
    for nonglyph_file in ufo_acceptable_files:
        assert ufo.is_glyph_file(nonglyph_file) is False
Beispiel #12
0
def test_ufodiff_ufo_glyph_true():
    ufo = Ufo()
    assert ufo.is_glyph_file("A.glif") is True
    assert ufo.is_glyph_file("A__.glif") is True
    assert ufo.is_glyph_file("0012.glif") is True
Beispiel #13
0
def test_ufodiff_ufo_nonglyph_true():
    ufo = Ufo()
    for (nonglyph_file) in (
            ufo_acceptable_files
    ):  # this file set only includes nonglyph files (i.e. not *.glif)
        assert ufo.is_nonglyph_file(nonglyph_file) is True
Beispiel #14
0
def test_ufodiff_ufo_images_dir_png_file_true():
    ufo = Ufo()
    test_path_1 = os.path.join("source", "Test-Regular.ufo", "images",
                               "cap_a.png")
    assert ufo._is_images_directory_file(test_path_1) is True
Beispiel #15
0
def test_ufodiff_ufo_validate_file_true():
    ufo = Ufo()
    for the_file in ufo_acceptable_files:
        assert ufo.validate_file(the_file) is True
Beispiel #16
0
def test_ufodiff_ufo_unacceptable_file():
    ufo = Ufo()
    assert (unacceptable_file in ufo.acceptable_files) is False
Beispiel #17
0
def test_ufodiff_ufo_acceptable_files():
    ufo = Ufo()
    for the_file in ufo.acceptable_files:
        assert the_file in ufo_acceptable_files
Beispiel #18
0
class Diff(object):
    """
    Diff class performs git diff on repository with filters for the UFO specification, cleans diff reports for
    improved readability and prepends branch names to the report for branch vs. branch analyses.  Supports git diff
    reports with ANSI color codes and without ANSI color codes.

    :param gitrepo_path: (string) path to root of git repository
    :param color_diff: (boolean) indicator for request for color diff (True) or uncolored diff (False)
    """
    def __init__(self, gitrepo_path, color_diff=False):
        self.gitrepo_path = gitrepo_path  # root path for git repository
        self.is_color_diff = color_diff  # is request for color diff = True
        self.repo = Repo(self.gitrepo_path)  # GitPython Repo object
        self.git = self.repo.git  # GitPython Repo.git object
        self.ufo = Ufo()  # ufodiff.utilities.ufo.Ufo object
        self.current_branch = self.git.rev_parse(
            "--abbrev-ref",
            "HEAD")  # current git branch automatically detected

    # PRIVATE METHODS

    def _clean_diff_string(self, dirty_diff_string):
        """
        'Cleans' the raw git diff string to improve readability and eliminate data that was not felt to be warranted in
        ufodiff text diff reports.

        :param dirty_diff_string: (string) the raw git diff string
        :return: (string) the cleaned git diff string
        """
        dirty_diffstring_list = dirty_diff_string.split("\n")
        clean_diff_string = ""
        for a_string in dirty_diffstring_list:
            if a_string.startswith("\x1b[1mdiff --git") or a_string.startswith(
                    "diff --git"):
                clean_a_string = a_string.replace("diff --git", "")
                clean_a_string = clean_a_string.replace(" ", os.linesep)
                clean_diff_string += clean_a_string + os.linesep
            elif "100644" in a_string:
                clean_a_string = a_string.replace("100644", "")
                clean_a_string = clean_a_string.replace("mode", "")
                clean_diff_string += clean_a_string + os.linesep
            else:
                clean_diff_string += a_string + os.linesep
        # remove two lead lines from text diffs (unnecessary duplication of the two files)
        if "---" in clean_diff_string and "+++" in clean_diff_string:
            clean_diff_string_list = clean_diff_string.split(os.linesep)
            purged_head_paths_diff_string_list = clean_diff_string_list[3:]
            clean_diff_string = (
                ""  # reset the diff string to empty string and start again
            )
            for line in purged_head_paths_diff_string_list:
                clean_diff_string += line + os.linesep
        return clean_diff_string

    # PUBLIC METHODS

    def get_diff_string_generator(self, git_user_diff_string):
        """
        Creates a Python generator that returns individual diff reports for filepaths that match UFO spec filters.

        Generator used as the creation of diff string across large numbers of *.glif file changes can take time to
        create.
        :param git_user_diff_string: (string) the string provided as third argument in user command (ufodiff diff [arg3])
        :return: (Python generator of strings) iterable list of diff text strings intended for standard output
        """
        ufo_file_list = self.ufo.get_valid_file_filterlist_for_diff(
        )  # valid UFO files
        is_branch_test = False  # default is a test between commits, not a test between branches, modified below

        if git_user_diff_string.startswith("commits:"):
            commits_list = git_user_diff_string.split(":")
            commits_number = commits_list[1]
            diff_arg_string = "HEAD~" + commits_number
        elif git_user_diff_string.startswith("branch:"):
            is_branch_test = True
            diff_arg_string = git_user_diff_string[
                7:] + ".." + self.current_branch
        else:
            diff_arg_string = git_user_diff_string

        if self.is_color_diff is True:
            for ufo_file in ufo_file_list:
                dirty_diff_string = self.git.diff(diff_arg_string, "--minimal",
                                                  "--color", "--", ufo_file)
                cleaned_diff_string = self._clean_diff_string(
                    dirty_diff_string)
                if (
                        len(cleaned_diff_string) > 1
                ):  # eliminates diff filters that did not include identified files
                    if is_branch_test is True:
                        cleaned_diff_string = ("branch " + diff_arg_string +
                                               os.linesep +
                                               cleaned_diff_string)
                    yield cleaned_diff_string
        else:
            for ufo_file in ufo_file_list:
                dirty_diff_string = self.git.diff(diff_arg_string, "--minimal",
                                                  "--", ufo_file)
                cleaned_diff_string = self._clean_diff_string(
                    dirty_diff_string)
                if (
                        len(cleaned_diff_string) > 1
                ):  # eliminates diff filters that did not include identified files
                    if (
                            is_branch_test is True
                    ):  # add branch descriptions to the output from the diff
                        cleaned_diff_string = ("branch " + diff_arg_string +
                                               os.linesep +
                                               cleaned_diff_string)
                    yield cleaned_diff_string
Beispiel #19
0
def test_ufodiff_ufo_nonglyph_false():
    ufo = Ufo()
    assert ufo.is_nonglyph_file("A.glif") is False
Beispiel #20
0
def test_ufodiff_ufo_validate_file_false():
    ufo = Ufo()
    assert ufo.validate_file("testing.py") is False
Beispiel #21
0
def test_ufodiff_ufo_data_dir_file_true():
    ufo = Ufo()
    test_path_1 = os.path.join("source", "Test-Regular.ufo", "data",
                               "org.sourcefoundry.coolstuff")
    assert ufo._is_data_directory_file(test_path_1) is True