175 lines
5.6 KiB
Python
175 lines
5.6 KiB
Python
# Copyright (c) 2019-2022 Artem Bulgakov
|
|
#
|
|
# This file is distributed under the terms of the same license,
|
|
# as the Kivy framework.
|
|
|
|
"""
|
|
Tool for updating Iconic font
|
|
=============================
|
|
|
|
Downloads archive from https://github.com/Templarian/MaterialDesign-Webfont and
|
|
updates font file with icon_definitions.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import re
|
|
import shutil
|
|
import sys
|
|
import zipfile
|
|
|
|
import requests
|
|
|
|
os.environ["KIVY_NO_ARGS"] = "1"
|
|
|
|
from kivymd.tools.release.git_commands import git_commit # NOQA E402
|
|
|
|
# Paths to files in kivymd repository
|
|
kivymd_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
|
font_path = os.path.join(
|
|
kivymd_path, "fonts", "materialdesignicons-webfont.ttf"
|
|
)
|
|
icon_definitions_path = os.path.join(kivymd_path, "icon_definitions.py")
|
|
|
|
font_version = "master"
|
|
# URL to download new archive (set None if already downloaded)
|
|
url = (
|
|
f"https://github.com/Templarian/MaterialDesign-Webfont"
|
|
f"/archive/{font_version}.zip"
|
|
)
|
|
# url = None
|
|
|
|
# Paths to files in loaded archive
|
|
temp_path = os.path.join(os.path.dirname(__file__), "temp")
|
|
temp_repo_path = os.path.join(
|
|
temp_path, f"MaterialDesign-Webfont-{font_version}"
|
|
)
|
|
temp_font_path = os.path.join(
|
|
temp_repo_path, "fonts", "materialdesignicons-webfont.ttf"
|
|
)
|
|
temp_preview_path = os.path.join(temp_repo_path, "preview.html")
|
|
|
|
# Regex
|
|
re_icons_json = re.compile(r"(?<=var icons = )[\S ]+(?=;)")
|
|
re_additional_icons = re.compile(r"(?<=icons\.push\()[\S ]+(?=\);)")
|
|
re_version = re.compile(r"(?<=<span class=\"version\">)[\d.]+(?=</span>)")
|
|
re_quote_keys = re.compile(r"([{\s,])(\w+)(:)")
|
|
re_icon_definitions = re.compile(r"md_icons = {\n([ ]{4}[\s\S]*,\n)*}")
|
|
re_version_in_file = re.compile(r"(?<=LAST UPDATED: Version )[\d.]+(?=\n)")
|
|
|
|
|
|
def download_file(url, path):
|
|
response = requests.get(url, stream=True)
|
|
if response.status_code != 200:
|
|
return False
|
|
with open(path, "wb") as f:
|
|
shutil.copyfileobj(response.raw, f)
|
|
return True
|
|
|
|
|
|
def unzip_archive(archive_path, dir_path):
|
|
with zipfile.ZipFile(archive_path, "r") as zip_ref:
|
|
zip_ref.extractall(dir_path)
|
|
|
|
|
|
def get_icons_list():
|
|
# There is js array with icons in file preview.html
|
|
with open(temp_preview_path, "r") as f:
|
|
preview_file = f.read()
|
|
# Find version
|
|
version = re_version.findall(preview_file)[0]
|
|
# Load icons
|
|
jsons_icons = re_icons_json.findall(preview_file)[0]
|
|
json_icons = re_quote_keys.sub(r'\1"\2"\3', jsons_icons)
|
|
icons = json.loads(json_icons)
|
|
# Find additional icons (like a blank icon)
|
|
# jsons_additional_icons = re_additional_icons.findall(preview_file)
|
|
# for j in jsons_additional_icons:
|
|
# json_additional_icons = re_quote_keys.sub(r'\1"\2"\3', j)
|
|
# icons.append(json.loads(json_additional_icons))
|
|
return icons, version
|
|
|
|
|
|
def make_icon_definitions(icons):
|
|
# Make python dict ("name": hex)
|
|
icon_definitions = "md_icons = {\n"
|
|
for i in icons:
|
|
icon_definitions += " " * 4
|
|
if len(i["hex"]) != 4:
|
|
# Some icons has 5-digit unicode
|
|
i["hex"] = "0" * (8 - len(i["hex"])) + i["hex"]
|
|
icon_definitions += f'"{i["name"]}": "\\U{i["hex"].upper()}",\n'
|
|
else:
|
|
icon_definitions += f'"{i["name"]}": "\\u{i["hex"].upper()}",\n'
|
|
icon_definitions += " " * 4 + '"blank": " ",\n' # Add blank icon (space)
|
|
icon_definitions += "}"
|
|
return icon_definitions
|
|
|
|
|
|
def export_icon_definitions(icon_definitions, version):
|
|
with open(icon_definitions_path, "r") as f:
|
|
icon_definitions_file = f.read()
|
|
# Change md_icons list
|
|
new_icon_definitions = re_icon_definitions.sub(
|
|
icon_definitions.replace("\\", "\\\\"), icon_definitions_file, 1
|
|
)
|
|
# Change version
|
|
new_icon_definitions = re_version_in_file.sub(
|
|
version, new_icon_definitions, 1
|
|
)
|
|
with open(icon_definitions_path, "w") as f:
|
|
f.write(new_icon_definitions)
|
|
|
|
|
|
def update_icons(make_commit: bool = False):
|
|
if url is not None:
|
|
print(f"Downloading Material Design Icons from {url}")
|
|
if download_file(url, "iconic-font.zip"):
|
|
print("Archive downloaded")
|
|
else:
|
|
print("Error: Could not download archive", file=sys.stderr)
|
|
else:
|
|
print("URL is None. Do not download archive")
|
|
if os.path.exists("iconic-font.zip"):
|
|
unzip_archive("iconic-font.zip", temp_path)
|
|
print("Unzip successful")
|
|
os.remove("iconic-font.zip")
|
|
if os.path.exists(temp_repo_path):
|
|
shutil.copy2(temp_font_path, font_path)
|
|
print("Font copied")
|
|
icons, version = get_icons_list()
|
|
print(f"Version {version}. {len(icons)} icons loaded")
|
|
icon_definitions = make_icon_definitions(icons)
|
|
export_icon_definitions(icon_definitions, version)
|
|
print("File icon_definitions.py updated")
|
|
shutil.rmtree(temp_path, ignore_errors=True)
|
|
|
|
if make_commit:
|
|
git_commit(
|
|
f"Update Iconic font (v{version})",
|
|
allow_error=True,
|
|
add_files=[
|
|
"kivymd/icon_definitions.py",
|
|
"kivymd/fonts/materialdesignicons-webfont.ttf",
|
|
],
|
|
)
|
|
print("\nSuccessful. You can now push changes")
|
|
else:
|
|
print(
|
|
f'\nSuccessful. Commit message: "Update Iconic font (v{version})"'
|
|
)
|
|
else:
|
|
print(f"Error: {temp_repo_path} not exists", file=sys.stderr)
|
|
exit(1)
|
|
|
|
|
|
def main():
|
|
make_commit = "--commit" in sys.argv
|
|
if "--commit" in sys.argv:
|
|
sys.argv.remove("--commit")
|
|
update_icons(make_commit=make_commit)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|