2021-05-23 18:17:06 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
import xml.etree.ElementTree as ET
|
|
|
|
import zipfile
|
|
|
|
from datetime import datetime
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
import yaml
|
|
|
|
|
|
|
|
|
|
|
|
def indent(elem: ET.Element, level: int = 0) -> None:
|
|
|
|
"""
|
|
|
|
Nicely formats output xml with newlines and spaces
|
|
|
|
https://stackoverflow.com/a/33956544
|
|
|
|
"""
|
|
|
|
i = "\n" + level * " "
|
|
|
|
if len(elem):
|
|
|
|
if not elem.text or not elem.text.strip():
|
|
|
|
elem.text = i + " "
|
|
|
|
if not elem.tail or not elem.tail.strip():
|
|
|
|
elem.tail = i
|
|
|
|
for elem in elem:
|
|
|
|
indent(elem, level + 1)
|
|
|
|
if not elem.tail or not elem.tail.strip():
|
|
|
|
elem.tail = i
|
|
|
|
else:
|
|
|
|
if level and (not elem.tail or not elem.tail.strip()):
|
|
|
|
elem.tail = i
|
|
|
|
|
|
|
|
|
|
|
|
def create_addon_xml(config: dict, source: str, py_version: str) -> None:
|
|
|
|
"""
|
|
|
|
Create addon.xml from template file
|
|
|
|
"""
|
|
|
|
# Load template file
|
2021-05-27 21:33:54 +00:00
|
|
|
with open("{}/.build/template.xml".format(source), "r") as f:
|
2021-05-23 18:17:06 +00:00
|
|
|
tree = ET.parse(f)
|
|
|
|
root = tree.getroot()
|
|
|
|
|
|
|
|
# Populate dependencies in template
|
|
|
|
dependencies = config["dependencies"].get(py_version)
|
|
|
|
for dep in dependencies:
|
|
|
|
ET.SubElement(root.find("requires"), "import", attrib=dep)
|
|
|
|
|
|
|
|
# Populate version string
|
|
|
|
addon_version = config.get("version")
|
|
|
|
root.attrib["version"] = "{}+{}".format(addon_version, py_version)
|
|
|
|
|
|
|
|
# Populate Changelog
|
|
|
|
date = datetime.today().strftime("%Y-%m-%d")
|
|
|
|
changelog = config.get("changelog")
|
|
|
|
for section in root.findall("extension"):
|
|
|
|
news = section.findall("news")
|
|
|
|
if news:
|
|
|
|
news[0].text = "v{} ({}):\n{}".format(addon_version, date, changelog)
|
|
|
|
|
|
|
|
# Format xml tree
|
|
|
|
indent(root)
|
|
|
|
|
|
|
|
# Write addon.xml
|
|
|
|
tree.write("{}/addon.xml".format(source), encoding="utf-8", xml_declaration=True)
|
|
|
|
|
|
|
|
|
2021-07-04 16:43:38 +00:00
|
|
|
def zip_files(py_version: str, source: str, target: str, dev: bool) -> None:
|
2021-05-23 18:17:06 +00:00
|
|
|
"""
|
|
|
|
Create installable addon zip archive
|
|
|
|
"""
|
|
|
|
archive_name = "plugin.video.jellyfin+{}.zip".format(py_version)
|
|
|
|
|
|
|
|
with zipfile.ZipFile("{}/{}".format(target, archive_name), "w") as z:
|
|
|
|
for root, dirs, files in os.walk(args.source):
|
|
|
|
for filename in filter(file_filter, files):
|
|
|
|
file_path = os.path.join(root, filename)
|
2021-07-05 01:02:46 +00:00
|
|
|
if dev or folder_filter(file_path):
|
2021-05-23 18:17:06 +00:00
|
|
|
relative_path = os.path.join(
|
|
|
|
"plugin.video.jellyfin", os.path.relpath(file_path, source)
|
2024-06-10 09:19:47 +00:00
|
|
|
)
|
2021-05-23 18:17:06 +00:00
|
|
|
z.write(file_path, relative_path)
|
|
|
|
|
|
|
|
|
|
|
|
def file_filter(file_name: str) -> bool:
|
|
|
|
"""
|
|
|
|
True if file_name is meant to be included
|
|
|
|
"""
|
2021-10-17 20:40:34 +00:00
|
|
|
return (
|
|
|
|
not (
|
|
|
|
file_name.startswith("plugin.video.jellyfin") and file_name.endswith(".zip")
|
2024-06-10 09:19:47 +00:00
|
|
|
)
|
2021-10-17 20:40:34 +00:00
|
|
|
and not file_name.endswith(".pyo")
|
|
|
|
and not file_name.endswith(".pyc")
|
|
|
|
and not file_name.endswith(".pyd")
|
|
|
|
)
|
2021-05-23 18:17:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
def folder_filter(folder_name: str) -> bool:
|
|
|
|
"""
|
|
|
|
True if folder_name is meant to be included
|
|
|
|
"""
|
2021-10-17 20:40:34 +00:00
|
|
|
filters = [
|
|
|
|
".ci",
|
|
|
|
".git",
|
|
|
|
".github",
|
|
|
|
".build",
|
|
|
|
".mypy_cache",
|
|
|
|
".pytest_cache",
|
|
|
|
"__pycache__",
|
|
|
|
]
|
|
|
|
for f in filters:
|
|
|
|
if f in folder_name.split(os.path.sep):
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
2021-05-23 18:17:06 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
parser = argparse.ArgumentParser(description="Build flags:")
|
2021-07-04 16:43:38 +00:00
|
|
|
parser.add_argument("--version", type=str, choices=("py2", "py3"), default="py3")
|
2021-05-23 18:17:06 +00:00
|
|
|
|
|
|
|
parser.add_argument("--source", type=Path, default=Path(__file__).absolute().parent)
|
|
|
|
|
|
|
|
parser.add_argument("--target", type=Path, default=Path(__file__).absolute().parent)
|
|
|
|
|
2021-07-04 16:43:38 +00:00
|
|
|
parser.add_argument("--dev", dest="dev", action="store_true")
|
|
|
|
parser.set_defaults(dev=False)
|
|
|
|
|
2021-05-23 18:17:06 +00:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
# Load config file
|
|
|
|
config_path = os.path.join(args.source, "release.yaml")
|
|
|
|
with open(config_path, "r") as fh:
|
|
|
|
release_config = yaml.safe_load(fh)
|
|
|
|
|
|
|
|
create_addon_xml(release_config, args.source, args.version)
|
|
|
|
|
2021-07-04 16:43:38 +00:00
|
|
|
zip_files(args.version, args.source, args.target, args.dev)
|