def test_check_for_invalid_strings_po_missing_header(self):
        ReportManager.getEnabledReporters()[0].reports = []

        path = join(self.path, "missing_header")
        full_path = join(path, "strings.po")

        file_index = [{"path": path, "name": "strings.po"}]

        expected = ['ERROR: Invalid PO file {path}:\n'
                    'Missing required header:\n'
                    '\tmsgid ""\n\tmsgstr ""'.format(path=relative_path(full_path))]

        check_for_invalid_strings_po(self.report, file_index)

        records = [Record.__str__(r) for r in ReportManager.getEnabledReporters()[0].reports]
        output = [s for s in records if s.startswith(self.report_matches)]

        self.assertListEqual(expected, output)
示例#2
0
    def test_start(self):
        result = start(self.path, self.args, self.all_repo_addons, self.config)
        records = [
            Record.__str__(r)
            for r in ReportManager.getEnabledReporters()[0].reports
        ]

        # Comparing the whitelist with the list of output we get from addon-checker tool
        for white_str in self.whitelist:
            for value in records:
                if white_str.lower() == value.lower():
                    break
            else:
                flag = False
        else:
            flag = True

        self.assertTrue(flag)
示例#3
0
    def test_check_for_invalid_strings_po_valid_file(self):
        ReportManager.getEnabledReporters()[0].reports = []

        path = join(self.path, "valid_file")
        language_path = join(path, "resources", "language",
                             "resource.language.en_gb")

        file_index = [{"path": language_path, "name": "strings.po"}]

        expected = []
        check_for_invalid_strings_po(self.report, file_index)

        records = [
            Record.__str__(r)
            for r in ReportManager.getEnabledReporters()[0].reports
        ]
        output = [s for s in records if s.startswith(self.report_matches)]

        self.assertListEqual(expected, output)
示例#4
0
def _check_artwork(report: Report, addon_path, addon_xml, file_index):
    # icon, fanart, screenshot - these will also check if the addon.xml links correctly
    _check_image_type(report, "icon", addon_xml, addon_path)
    _check_image_type(report, "fanart", addon_xml, addon_path)
    _check_image_type(report, "screenshot", addon_xml, addon_path)

    # go through all but the above and try to open the image
    for file in file_index:
        if re.match(r"(?!fanart\.jpg|icon\.png).*\.(png|jpg|jpeg|gif)$",
                    file["name"]) is not None:
            image_path = os.path.join(file["path"], file["name"])
            try:
                # Just try if we can successfully open it
                Image.open(image_path)
            except IOError:
                report.add(
                    Record(
                        PROBLEM,
                        "Could not open image, is the file corrupted? %s" %
                        relative_path(image_path)))
示例#5
0
    def test_check_for_invalid_strings_po_syntax_error(self):
        ReportManager.getEnabledReporters()[0].reports = []

        path = join(self.path, "syntax_error")
        language_path = join(path, "resources", "language",
                             "resource.language.en_gb")
        full_path = join(language_path, "strings.po")

        file_index = [{"path": language_path, "name": "strings.po"}]

        expected = [
            "ERROR: Invalid PO file {path}: "
            "Syntax error on line 23".format(path=relative_path(full_path))
        ]

        check_for_invalid_strings_po(self.report, file_index)

        records = [
            Record.__str__(r)
            for r in ReportManager.getEnabledReporters()[0].reports
        ]
        output = [s for s in records if s.startswith(self.report_matches)]

        self.assertListEqual(expected, output)
示例#6
0
def _check_for_legacy_strings_xml(report: Report, addon_path):
    if _find_file_recursive("strings.xml", addon_path) is not None:
        report.add(
            Record(PROBLEM, "Found strings.xml in folder %s please migrate to strings.po." % relative_path(addon_path)))
示例#7
0
def _addon_xml_matches_folder(report: Report, addon_path, addon_xml):
    addon = addon_xml.getroot()
    if os.path.basename(os.path.normpath(addon_path)) == addon.attrib.get("id"):
        report.add(Record(INFORMATION, "Addon id matches folder name"))
    else:
        report.add(Record(PROBLEM, "Addon id and folder name does not match."))
示例#8
0
def _addon_file_exists(report: Report, addon_path, file_name):
    if _find_file(file_name, addon_path) is None:
        report.add(Record(PROBLEM, "Not found %s in folder %s" % (file_name, relative_path(addon_path))))
示例#9
0
def _check_image_type(report: Report, image_type, addon_xml, addon_path):
    images = addon_xml.findall("*//" + image_type)

    icon_fallback = False
    fanart_fallback = False
    if not images and image_type == "icon":
        icon_fallback = True
        image = type('image', (object,),
                     {'text': 'icon.png'})()
        images.append(image)
    elif not images and image_type == "fanart":
        skip_addon_types = [".module.", "metadata.", "context.", ".language."]
        for addon_type in skip_addon_types:
            if addon_type in addon_path:
                break
        else:
            fanart_fallback = True
            image = type('image', (object,),
                         {'text': 'fanart.jpg'})()
            images.append(image)

    for image in images:
        if image.text:
            filepath = os.path.join(addon_path, image.text)
            if os.path.isfile(filepath):
                report.add(Record(INFORMATION, "Image %s exists" % image_type))
                try:
                    im = Image.open(filepath)
                    width, height = im.size

                    if image_type == "icon":
                        if has_transparency(im):
                            report.add(Record(PROBLEM, "Icon.png should be solid. It has transparency."))
                        if (width != 256 and height != 256) and (width != 512 and height != 512):
                            report.add(Record(PROBLEM, "Icon should have either 256x256 or 512x512 but it has %sx%s" % (
                                width, height)))
                        else:
                            report.add(
                                Record(INFORMATION, "%s dimensions are fine %sx%s" % (image_type, width, height)))
                    elif image_type == "fanart":
                        fanart_sizes = [(1280, 720), (1920, 1080), (3840, 2160)]
                        fanart_sizes_str = " or ".join(["%dx%d" % (w, h) for w, h in fanart_sizes])
                        if (width, height) not in fanart_sizes:
                            report.add(Record(PROBLEM, "Fanart should have either %s but it has %sx%s" % (
                                fanart_sizes_str, width, height)))
                        else:
                            report.add(Record(INFORMATION, "%s dimensions are fine %sx%s" %
                                              (image_type, width, height)))
                    else:
                        # screenshots have no size definitions
                        pass
                except IOError:
                    report.add(
                        Record(PROBLEM, "Could not open image, is the file corrupted? %s" % relative_path(filepath)))

            else:
                # if it's a fallback path addons.xml should still be able to
                # get build
                if fanart_fallback or icon_fallback:
                    if icon_fallback:
                        report.add(Record(INFORMATION, "You might want to add a icon"))
                    elif fanart_fallback:
                        report.add(Record(INFORMATION, "You might want to add a fanart"))
                # it's no fallback path, so building addons.xml will crash -
                # this is a problem ;)
                else:
                    report.add(Record(PROBLEM, "%s does not exist at specified path." % image_type))
        else:
            report.add(Record(WARNING, "Empty image tag found for %s" % image_type))
示例#10
0
def main():
    """The entry point to kodi-addon-checker
    """
    choice = ['gotham', 'helix', 'isengard', 'jarvis', 'krypton', 'leia']
    load_plugins()
    parser = argparse.ArgumentParser(
        prog="kodi-addon-checker",
        description="Checks Kodi repo for best practices and creates \
                                     problem and warning reports.\r\nIf optional add-on \
                                     directories are provided, check only those add-ons. \
                                     Otherwise, scan current repository and check all add-ons in \
                                     the current directory.")
    parser.add_argument("--version",
                        action="version",
                        version="%(prog)s 0.0.1")
    parser.add_argument("dir",
                        type=dir_type,
                        nargs="*",
                        help="optional add-on or repo directories")
    parser.add_argument(
        "--branch",
        choices=choice,
        required=True,
        help="Target branch name where the checker will resolve dependencies")
    parser.add_argument(
        "--PR",
        help="Tell if tool is to run on a pull requests or not",
        action='store_true')
    parser.add_argument(
        "--allow-folder-id-mismatch",
        help="Allow the addon's folder name and id to mismatch",
        action="store_true")
    ConfigManager.fill_cmd_args(parser)
    args = parser.parse_args()

    log_file_name = os.path.join(os.getcwd(), "kodi-addon-checker.log")
    logger.Logger.create_logger(log_file_name, __package__)

    all_repo_addons = check_addon.all_repo_addons()

    if args.dir:
        # Following report is a wrapper for all sub reports
        report = Report("")
        for directory in args.dir:
            report.add(check_artifact(directory, args, all_repo_addons))
    else:
        report = check_artifact(os.getcwd(), args, all_repo_addons)

    if report.problem_count > 0:
        report.add(
            Record(
                PROBLEM,
                "We found %s problems and %s warnings, please check the logfile."
                % (report.problem_count, report.warning_count)))
        sys.exit(1)
    elif report.warning_count > 0:
        report.add(
            Record(
                WARNING,
                "We found no problems and %s warnings, please check the logfile."
                % report.warning_count))
    else:
        report.add(
            Record(
                INFORMATION,
                "We found no problems and no warnings, please enjoy your day.")
        )