From 046bbf325ecb51c353bbeb15f84d4e1ace8e01ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Odd=20Str=C3=A5b=C3=B8?= Date: Thu, 1 Oct 2020 05:53:46 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9B=8F=EF=B8=8F=20Initial=20work=20on=20buil?= =?UTF-8?q?d.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.py | 84 ++++++++++++++++++++++++++++++++++++++++++++ release.yaml | 27 ++++++++++++++ requirements-dev.txt | 2 ++ tests/test_build.py | 33 +++++++++++++++++ tox.ini | 11 +++--- 5 files changed, 152 insertions(+), 5 deletions(-) create mode 100644 build.py create mode 100644 tests/test_build.py diff --git a/build.py b/build.py new file mode 100644 index 00000000..7b0d794f --- /dev/null +++ b/build.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +from __future__ import division, absolute_import, print_function, unicode_literals + +import os +import zipfile +from fnmatch import fnmatchcase as fnmatch + +import yaml + + +def zip_items(file_name, items, base_path=None): + if base_path is None: + base_path = os.path.splitext(file_name)[0] + + elif not base_path: + base_path = "" + + with zipfile.ZipFile(file_name, "w", zipfile.ZIP_DEFLATED) as z: + for item, path, _pattern in items: + print(path) + archive_path = os.path.join(base_path, path) + if path not in ["."]: + z.write(item, archive_path) + + return file_name + + +def get_config(filename='release.yaml'): + with open(filename, 'r') as fh: + return yaml.safe_load(fh) + + +def match_item(item, include, exclude): + for pattern in exclude: + if fnmatch(item, pattern): + print('-', item, pattern) + return False, pattern + + for pattern in include: + if fnmatch(item, pattern): + print('+', item, pattern) + return True, pattern + + return None, None + + +def get_items(include, exclude, basepath='.'): + for base, dirs, files in os.walk(basepath): + for dir_name in dirs: + dir_path = os.path.join(base, dir_name) + normalized_dir_path = os.path.normpath(os.path.relpath(dir_path, basepath)) + match, pattern = match_item(normalized_dir_path, include, exclude) + if match: + yield dir_path, normalized_dir_path, pattern + + for file_name in files: + file_path = os.path.join(base, file_name) + normalized_file_path = os.path.normpath(os.path.relpath(file_path, basepath)) + match, pattern = match_item(normalized_file_path, include, exclude) + if match: + yield file_path, normalized_file_path, pattern + + +def main(): + relpath = os.path.dirname(__file__) or '.' + + config = get_config(os.path.join(relpath, 'release.yaml')) + build_config = config.get('build', {}) + include = build_config.get('include', []) + exclude = build_config.get('exclude', []) + + print("Relpath:", relpath) + print("Include:", include) + print("Exclude:", exclude) + print("Config:", config) + + items = get_items(include, exclude, relpath) + + zip_file_name = zip_items('test.zip', items, base_path='plugin.video.jellyfin') + print(zip_file_name) + + +if __name__ == "__main__": + main() diff --git a/release.yaml b/release.yaml index 74d36be7..6ab45749 100644 --- a/release.yaml +++ b/release.yaml @@ -6,3 +6,30 @@ changelog: | - #385 Normalize path for os.mkdir - #387 Optimize music sync for large libraries - #392 Fix the pipeline. Again. + +build: + include: + - jellyfin_kodi/* + - resources/* + - default.py + - service.py + - context.py + - context_play.py + - addon.xml + + - .config/* + - tests/* + - build.py + - requirements-dev.txt + - tox.ini + - .editorconfig + - .env + + - README.md + - LICENSE.txt + - CONTRIBUTING.md + + exclude: + - .gitignore + - "*.py[ocd]" + - "*/__pycache__" diff --git a/requirements-dev.txt b/requirements-dev.txt index 265c7918..c9e2473c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -11,3 +11,5 @@ pytest >= 4.6.11 coverage >= 5.2 flake8 >= 3.8 flake8-import-order >= 0.18 + +PyYAML >= 5.3 diff --git a/tests/test_build.py b/tests/test_build.py new file mode 100644 index 00000000..fbc86a97 --- /dev/null +++ b/tests/test_build.py @@ -0,0 +1,33 @@ + +import pytest + +from build import get_config, get_items + +config = get_config() +build_config = config.get('build', {}) +include = build_config.get('include', []) +exclude = build_config.get('exclude', []) + +items = list(get_items(include, exclude)) + + +def test_config(): + assert 'version' in config and type(config['version']) is str + assert 'changelog' in config and type(config['changelog']) is str + + assert 'build' in config + build = config['build'] + assert type(build) is dict + + assert 'include' in build and type(build['include']) is list + assert 'exclude' in build and type(build['exclude']) is list + + +@pytest.mark.parametrize("pattern", include) +def test_include_pattern_matched(pattern): + matched = False + for _fp, _nfp, item_pattern in items: + if pattern == item_pattern: + matched = True + + assert matched, "Pattern `{}` matches no files.".format(pattern) diff --git a/tox.ini b/tox.ini index ae876e22..f9de15e3 100644 --- a/tox.ini +++ b/tox.ini @@ -15,10 +15,11 @@ testpaths = [coverage:run] source = jellyfin_kodi - context.py - context_play.py - default.py - service.py - .config/generate_xml.py + context # Clashes with multiprocessing.context? + context_play + default + service + .config/generate_xml.py # Can't import this file. + build omit = tests/* command_line = -m pytest