Skip to content

Commit

Permalink
Automate reporter injection and reporter config
Browse files Browse the repository at this point in the history
  • Loading branch information
slgobinath committed Apr 6, 2018
1 parent 6c21cf6 commit cd194c4
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 58 deletions.
10 changes: 9 additions & 1 deletion kodi_addon_checker/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import os

from kodi_addon_checker.check_repo import check_repo
from kodi_addon_checker.common import load_plugins
from kodi_addon_checker.config import ConfigManager, Config


def dir_type(dir_path):
Expand All @@ -28,6 +30,7 @@ def dir_type(dir_path):
def main():
"""The entry point to kodi-addon-checker
"""
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 \
Expand All @@ -38,8 +41,13 @@ def main():
version="%(prog)s 0.0.1")
parser.add_argument("add_on", metavar="add-on", type=dir_type, nargs="*",
help="optional add-on directories")
ConfigManager.fill_cmd_args(parser)
args = parser.parse_args()
check_repo(os.path.abspath(os.getcwd()), args.add_on)

repo_path = os.path.abspath(os.getcwd())
config = Config(repo_path, args)
ConfigManager.process_config(config)
check_repo(config, repo_path, args.add_on)


if __name__ == "__main__":
Expand Down
10 changes: 5 additions & 5 deletions kodi_addon_checker/check_addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from PIL import Image

from kodi_addon_checker.common import check_config, has_transparency
from kodi_addon_checker.common import has_transparency
from kodi_addon_checker.report import Report, PROBLEM, Record, WARNING, INFORMATION

REL_PATH = ""
Expand Down Expand Up @@ -76,18 +76,18 @@ def start(addon_path, config=None):

_check_artwork(addon_report, addon_path, addon_xml, file_index)

if check_config(config, "check_license_file_exists"):
if config.is_enabled("check_license_file_exists"):
# check if license file is existing
_addon_file_exists(addon_report, addon_path, "LICENSE\.txt|LICENSE\.md|LICENSE")

if check_config(config, "check_legacy_strings_xml"):
if config.is_enabled("check_legacy_strings_xml"):
_check_for_legacy_strings_xml(addon_report, addon_path)

if check_config(config, "check_legacy_language_path"):
if config.is_enabled("check_legacy_language_path"):
_check_for_legacy_language_path(addon_report, addon_path)

# Kodi 18 Leia + deprecations
if check_config(config, "check_kodi_leia_deprecations"):
if config.is_enabled("check_kodi_leia_deprecations"):
_find_blacklisted_strings(addon_report, addon_path,
["System.HasModalDialog", "StringCompare", "SubString", "IntegerGreaterThan",
"ListItem.ChannelNumber", "ListItem.SubChannelNumber",
Expand Down
21 changes: 3 additions & 18 deletions kodi_addon_checker/check_repo.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
import json
import os
import sys

import kodi_addon_checker.check_addon as check_addon
from kodi_addon_checker.common import colorPrint
from kodi_addon_checker.plugins.console_reporter import ConsoleReporter
from kodi_addon_checker.report import Report, INFORMATION, Record
from kodi_addon_checker.report import Report, INFORMATION, Record, ReportManager


def _read_config_for_version(repo_path):
config_path = os.path.join(repo_path, '.tests-config.json')
if os.path.isfile(config_path):
with open(config_path) as json_data:
return json.load(json_data)

return None


def check_repo(repo_path, parameters):
def check_repo(config, repo_path, parameters):
repo_report = Report()
repo_report.log(Record(INFORMATION, "Checking repository %s" % repo_path))
print("Repo path " + repo_path)
Expand All @@ -28,18 +17,14 @@ def check_repo(repo_path, parameters):

print("Toplevel folders " + str(toplevel_folders))

config = _read_config_for_version(repo_path)

for addon_folder in toplevel_folders:
if addon_folder[0] != '.':
repo_report.log(Record(INFORMATION, "Checking add-on %s" % addon_folder))
addon_path = os.path.join(repo_path, addon_folder)
addon_report = check_addon.start(addon_path, config)
repo_report.log(addon_report)

# Report using ConsoleReporter
reporter = ConsoleReporter()
reporter.report(repo_report)
ReportManager.report(repo_report)

if repo_report.problem_count > 0:
colorPrint("We found %s problems and %s warnings, please check the logfile." % (
Expand Down
23 changes: 14 additions & 9 deletions kodi_addon_checker/common.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
def colorPrint(string, color):
print("\033[%sm%s\033[0m" % (color, string))
import importlib
import os
import pkgutil
import sys


def check_config(config, value):
if config is None:
return False
elif value in config and config[value]:
return True
else:
return False
def colorPrint(string, color):
print("\033[%sm%s\033[0m" % (color, string))


def has_transparency(im):
Expand All @@ -24,3 +21,11 @@ def has_transparency(im):
return False
except StopIteration:
return False


def load_plugins():
plugins_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "plugins")
sys.path.append(plugins_dir)
for importer, package_name, _ in pkgutil.iter_modules([plugins_dir]):
if "test_" not in package_name:
importlib.import_module(package_name)
51 changes: 51 additions & 0 deletions kodi_addon_checker/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import json
import os
from argparse import ArgumentParser

from kodi_addon_checker.report import ReportManager


class Config(object):
def __init__(self, repo_path, cmd_args=None):
self.configs = {} if cmd_args is None else vars(cmd_args)
self._load_config(repo_path)

def _load_config(self, repo_path):
config_path = os.path.join(repo_path, '.tests-config.json')
if os.path.isfile(config_path):
with open(config_path) as json_data:
file_config = json.load(json_data)
if file_config is not None:
for key, value in self.configs.items():
if value is not None:
file_config[key] = value
self.configs = file_config

def is_enabled(self, value):
return self.configs.get(value, False)

def __getitem__(self, item):
return self.configs.get(item)


class ConfigManager(object):
configurations = {}

@classmethod
def register(cls, config, description, default_value, action):
cls.configurations[config] = [description, default_value, action]

@classmethod
def fill_cmd_args(cls, parser: ArgumentParser):
# Add --reporter
parser.add_argument("--reporter", action="append", choices=list(ReportManager.reporters.keys()),
help="""enable a reporter with the given id(s).
You can put this option multiple time""")

@classmethod
def process_config(cls, config):
print(config.configs)
reporters = config["reporter"]
if reporters is not None:
# To disable all, pass empty array in .tests-config.json
ReportManager.enable(reporters)
2 changes: 1 addition & 1 deletion kodi_addon_checker/plugins/console_reporter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from kodi_addon_checker.report import Reporter, Report, Record, reporter, INFORMATION, WARNING, PROBLEM


@reporter(config_property="console-reporter", enabled=True)
@reporter(name="console", enabled=True)
class ConsoleReporter(Reporter):

def report(self, report: Report):
Expand Down
33 changes: 29 additions & 4 deletions kodi_addon_checker/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
WARNING = "WARN"
INFORMATION = "INFO"

KODI_REPORTERS = {}


class Report(object):
def __init__(self):
Expand Down Expand Up @@ -67,14 +65,41 @@ def report(self, report: Report):
pass


def reporter(config_property, enabled=False):
class ReportManager(object):
reporters = {}

@classmethod
def register(cls, reporter_clazz: Reporter, name, enabled):
cls.reporters[name] = [reporter_clazz, enabled]

@classmethod
def enable(cls, names):
"""
Enable only the given list of names and disable the rest.
:param names: list of reporter names
:return: None
"""
for name, arr in cls.reporters.items():
arr[1] = name in names

@classmethod
def report(cls, report: Report):
for arr in cls.reporters.values():
if arr[1]:
# Report enabled
arr[0]().report(report)


def reporter(name, enabled=False):
def _reporter(clazz):
if inspect.isclass(clazz):
if not hasattr(clazz, "report") or len(inspect.signature(getattr(clazz, "report")).parameters.items()) != 2:
raise RuntimeError("Reporter must have a function 'report(self, report: Report)")
else:
raise RuntimeError("Reporter must be a class")
KODI_REPORTERS[config_property] = [clazz, enabled]

# Register the reporter
ReportManager.register(clazz, name, enabled)
return clazz

return _reporter
32 changes: 12 additions & 20 deletions tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,13 @@
#

import os
import json
import pytest
from PIL import Image
from kodi_addon_checker.common import check_config, has_transparency

FIXTURE_PATH = os.path.join("tests", "fixtures")

from PIL import Image

def __read_config_for_version(filename):
config_path = os.path.join(FIXTURE_PATH, filename)
if os.path.isfile(config_path):
with open(config_path) as json_data:
return json.load(json_data)
from kodi_addon_checker.common import has_transparency
from kodi_addon_checker.config import Config

return None
FIXTURE_PATH = os.path.join("tests", "fixtures")


def __load_image(filename):
Expand All @@ -25,23 +17,23 @@ def __load_image(filename):


def test_if_false_gets_picked_up():
config = __read_config_for_version('.tests-config.json')
assert check_config(config, "check_license_file_exists") is False
config = Config(FIXTURE_PATH)
assert config.is_enabled("check_license_file_exists") is False


def test_if_true_gets_picked_up():
config = __read_config_for_version('.tests-config.json')
assert check_config(config, "check_legacy_strings_xml") is True
config = Config(FIXTURE_PATH)
assert config.is_enabled("check_legacy_strings_xml") is True


def test_if_does_not_exists_default_to_false():
config = __read_config_for_version('.tests-config.json')
assert check_config(config, "does_not_exist") is False
config = Config(FIXTURE_PATH)
assert config.is_enabled("does_not_exist") is False


def test_with_missing_config():
config = __read_config_for_version('does_not_exist.json')
assert check_config(config, "does_not_exist") is False
config = Config('does_not_exist')
assert config.is_enabled("does_not_exist") is False


def test_has_transparency_rgb():
Expand Down

0 comments on commit cd194c4

Please sign in to comment.