Skip to content

Commit

Permalink
Merge pull request #257 from dalthviz/fix_236
Browse files Browse the repository at this point in the history
PR: Add version to fonts assets, some error handling for Windows font installation logic and keep up to date update scripts/commands
  • Loading branch information
ccordoba12 authored Mar 26, 2024
2 parents 15a3e6a + 87837af commit 43bcbb5
Show file tree
Hide file tree
Showing 25 changed files with 127 additions and 80 deletions.
43 changes: 34 additions & 9 deletions UPDATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
To update _FontAwesome_ icons, one must:

- check what is the latest released version here: https://github.com/FortAwesome/Font-Awesome/releases/
- update font version in \_\_init__.py
- remove outdated files in the fonts dir
- run: `python setup.py update_fa5 --fa-version X.X.X`
- update FA version number, icon counts and URLs inside:
- README.md
Expand Down Expand Up @@ -55,18 +57,29 @@ import json
import urllib.request
import hashlib


VERSION = '6.9.96' # Update version as required
TTF_URL = 'https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/fonts/materialdesignicons-webfont.ttf'
CSS_URL = 'https://raw.githubusercontent.com/Templarian/MaterialDesign-Webfont/master/css/materialdesignicons.css'
FONT_FILENAME = "materialdesignicons6-webfont-{version}.ttf".format(
version=VERSION
)
FONT_CHARMAP_FILENAME = (
"materialdesignicons6-webfont-charmap-{version}.json".format(
version=VERSION
)
)


with open('materialdesignicons6-webfont.ttf', 'wb') as fp:
with open(FONT_FILENAME, 'wb') as fp:
req = urllib.request.urlopen(TTF_URL)
if req.status != 200:
raise Exception('Failed to download TTF')
fp.write(req.read())
req.close()

hasher = hashlib.md5()
with open('materialdesignicons6-webfont.ttf', 'rb') as f:
with open(FONT_FILENAME, 'rb') as f:
content = f.read()
hasher.update(content)

Expand All @@ -89,7 +102,7 @@ for name, key in data:
name = name.lower()
charmap[name] = key

with open('materialdesignicons6-webfont-charmap.json', 'w') as fp:
with open(FONT_CHARMAP_FILENAME, 'w') as fp:
json.dump(charmap, fp, indent=4, sort_keys=True)

```
Expand All @@ -112,18 +125,23 @@ import json
import urllib.request
import hashlib

VERSION = '1.3.0' # Update version as required
TTF_URL = 'https://raw.githubusercontent.com/phosphor-icons/phosphor-icons/master/src/font/phosphor.ttf'
CSS_URL = 'https://raw.githubusercontent.com/phosphor-icons/phosphor-icons/master/src/css/phosphor.css'
FONT_FILENAME = 'phosphor-{version}.ttf'.format(version=VERSION)
FONT_CHARMAP_FILENAME = "phosphor-charmap-{version}.json".format(
version=VERSION
)

with open('phosphor.ttf', 'wb') as fp:
with open(FONT_FILENAME, 'wb') as fp:
req = urllib.request.urlopen(TTF_URL)
if req.status != 200:
raise Exception('Failed to download TTF')
fp.write(req.read())
req.close()

hasher = hashlib.md5()
with open('phosphor.ttf', 'rb') as f:
with open(FONT_FILENAME, 'rb') as f:
content = f.read()
hasher.update(content)

Expand All @@ -145,7 +163,7 @@ for name, key in data:
name = name.lower()
charmap[name] = key

with open('phosphor-charmap.json', 'w') as fp:
with open(FONT_CHARMAP_FILENAME, 'w') as fp:
json.dump(charmap, fp, indent=4, sort_keys=True)

```
Expand All @@ -168,18 +186,23 @@ import json
import urllib.request
import hashlib

VERSION = '2.5.0' # Update version as required
TTF_URL = 'https://raw.githubusercontent.com/Remix-Design/RemixIcon/master/fonts/remixicon.ttf'
CSS_URL = 'https://raw.githubusercontent.com/Remix-Design/RemixIcon/master/fonts/remixicon.css'
FONT_FILENAME = 'remixicon-{version}.ttf'.format(version=VERSION)
FONT_CHARMAP_FILENAME = "remixicon-charmap-{version}.json".format(
version=VERSION
)

with open('remixicon.ttf', 'wb') as fp:
with open(FONT_FILENAME, 'wb') as fp:
req = urllib.request.urlopen(TTF_URL)
if req.status != 200:
raise Exception('Failed to download TTF')
fp.write(req.read())
req.close()

hasher = hashlib.md5()
with open('remixicon.ttf', 'rb') as f:
with open(FONT_FILENAME, 'rb') as f:
content = f.read()
hasher.update(content)

Expand All @@ -201,7 +224,7 @@ for name, key in data:
name = name.lower()
charmap[name] = key

with open('remixicon-charmap.json', 'w') as fp:
with open(FONT_CHARMAP_FILENAME, 'w') as fp:
json.dump(charmap, fp, indent=4, sort_keys=True)

```
Expand All @@ -211,6 +234,8 @@ with open('remixicon-charmap.json', 'w') as fp:
To update _Codicons_ icons, one must:

- check what is the latest released version here: https://github.com/microsoft/vscode-codicons/releases
- update font version in \_\_init__.py
- remove outdated files in the fonts dir
- run: `python setup.py update_msc`
- update Codicons version number, icon counts and URLs inside:
- README.md
Expand Down
60 changes: 30 additions & 30 deletions qtawesome/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,50 +34,50 @@

_BUNDLED_FONTS = (
('fa',
'fontawesome4.7-webfont.ttf',
'fontawesome4.7-webfont-charmap.json'),
'fontawesome4-webfont-4.7.ttf',
'fontawesome4-webfont-charmap-4.7.json'),
('fa5',
'fontawesome5-regular-webfont.ttf',
'fontawesome5-regular-webfont-charmap.json'),
'fontawesome5-regular-webfont-5.15.4.ttf',
'fontawesome5-regular-webfont-charmap-5.15.4.json'),
('fa5s',
'fontawesome5-solid-webfont.ttf',
'fontawesome5-solid-webfont-charmap.json'),
'fontawesome5-solid-webfont-5.15.4.ttf',
'fontawesome5-solid-webfont-charmap-5.15.4.json'),
('fa5b',
'fontawesome5-brands-webfont.ttf',
'fontawesome5-brands-webfont-charmap.json'),
'fontawesome5-brands-webfont-5.15.4.ttf',
'fontawesome5-brands-webfont-charmap-5.15.4.json'),
('ei',
'elusiveicons-webfont.ttf',
'elusiveicons-webfont-charmap.json'),
'elusiveicons-webfont-2.0.ttf',
'elusiveicons-webfont-charmap-2.0.json'),
('mdi',
'materialdesignicons5-webfont.ttf',
'materialdesignicons5-webfont-charmap.json'),
'materialdesignicons5-webfont-5.9.55.ttf',
'materialdesignicons5-webfont-charmap-5.9.55.json'),
('mdi6',
'materialdesignicons6-webfont.ttf',
'materialdesignicons6-webfont-charmap.json'),
'materialdesignicons6-webfont-6.9.96.ttf',
'materialdesignicons6-webfont-charmap-6.9.96.json'),
('ph',
'phosphor.ttf',
'phosphor-charmap.json'),
'phosphor-1.3.0.ttf',
'phosphor-charmap-1.3.0.json'),
('ri',
'remixicon.ttf',
'remixicon-charmap.json'),
'remixicon-2.5.0.ttf',
'remixicon-charmap-2.5.0.json'),
('msc',
'codicon.ttf',
'codicon-charmap.json'),
'codicon-0.0.35.ttf',
'codicon-charmap-0.0.35.json'),
)


# MD5 Hashes for font files bundled with qtawesome:
_MD5_HASHES = {
'fontawesome4.7-webfont.ttf': 'b06871f281fee6b241d60582ae9369b9',
'fontawesome5-regular-webfont.ttf': 'dc47e4089f5bcb25f241bdeb2de0fb58',
'fontawesome5-solid-webfont.ttf': '5de19800fc9ae73438c2e5c61d041b48',
'fontawesome5-brands-webfont.ttf': '513aa607d398efaccc559916c3431403',
'elusiveicons-webfont.ttf': '207966b04c032d5b873fd595a211582e',
'materialdesignicons5-webfont.ttf': 'b7d40e7ef80c1d4af6d94902af66e524',
'materialdesignicons6-webfont.ttf': 'ecaabfbb23fdac4ddbaf897b97257a92',
'phosphor.ttf': '5b8dc57388b2d86243566b996cc3a789',
'remixicon.ttf': '888e61f04316f10bddfff7bee10c6dd0',
'codicon.ttf': '2b89de3354b7768e193c0ec14571422b',
'fontawesome4-webfont-4.7.ttf': 'b06871f281fee6b241d60582ae9369b9',
'fontawesome5-regular-webfont-5.15.4.ttf': 'dc47e4089f5bcb25f241bdeb2de0fb58',
'fontawesome5-solid-webfont-5.15.4.ttf': '5de19800fc9ae73438c2e5c61d041b48',
'fontawesome5-brands-webfont-5.15.4.ttf': '513aa607d398efaccc559916c3431403',
'elusiveicons-webfont-2.0.ttf': '207966b04c032d5b873fd595a211582e',
'materialdesignicons5-webfont-5.9.55.ttf': 'b7d40e7ef80c1d4af6d94902af66e524',
'materialdesignicons6-webfont-6.9.96.ttf': 'ecaabfbb23fdac4ddbaf897b97257a92',
'phosphor-1.3.0.ttf': '5b8dc57388b2d86243566b996cc3a789',
'remixicon-2.5.0.ttf': '888e61f04316f10bddfff7bee10c6dd0',
'codicon-0.0.35.ttf': '2b89de3354b7768e193c0ec14571422b',
}


Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
29 changes: 17 additions & 12 deletions qtawesome/iconic_font.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

# Standard library imports
import ctypes
import filecmp
import json
import os
import shutil
Expand Down Expand Up @@ -611,27 +610,33 @@ def _install_fonts(self, fonts_directory):

# Setup bundled fonts on the LOCALAPPDATA fonts directory
for root, __, files in os.walk(fonts_directory):
for name in files:
src_path = os.path.join(root, name)
for filename in files:
src_path = os.path.join(root, filename)
dst_filename = filename
dst_path = os.path.join(
user_fonts_dir,
os.path.basename(src_path))
dst_filename
)

# Check if font already exists and copy font
if os.path.isfile(dst_path) and filecmp.cmp(src_path, dst_path):
# Check if font already exists and proceed with copy font
# process if needed or skip it
if os.path.isfile(dst_path):
continue
shutil.copy(src_path, user_fonts_dir)
shutil.copy(src_path, dst_path)

# Further process the font file (`.ttf`)
if os.path.splitext(name)[-1] == '.ttf':
if os.path.splitext(filename)[-1] == '.ttf':
# Load the font in the current session
if not gdi32.AddFontResourceW(dst_path):
os.remove(dst_path)
raise WindowsError(
f'AddFontResource failed to load "{src_path}"')
try:
os.remove(dst_path)
except OSError:
# Possible permission error when trying to remove
# a font which potentially is already in use
# See spyder-ide/qtawesome#236
continue

# Store the fontname/filename in the registry
filename = os.path.basename(dst_path)
fontname = os.path.splitext(filename)[0]

# Try to get the font's real name
Expand Down
20 changes: 6 additions & 14 deletions qtawesome/tests/test_qtawesome.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,17 @@ def test_bundled_font_installation():
"""
qta._instance()
fonts_expected = [
("codicon", "codicon.ttf"),
("elusiveicons-webfont", "elusiveicons-webfont.ttf"),
("fontawesome4.7-webfont", "fontawesome4.7-webfont.ttf"),
("fontawesome5-brands-webfont", "fontawesome5-brands-webfont.ttf"),
("fontawesome5-regular-webfont", "fontawesome5-regular-webfont.ttf"),
("fontawesome5-solid-webfont", "fontawesome5-solid-webfont.ttf"),
("materialdesignicons5-webfont", "materialdesignicons5-webfont.ttf"),
("materialdesignicons6-webfont ", "materialdesignicons6-webfont.ttf"),
("phosphor", "phosphor.ttf"),
("remixicon", "remixicon.ttf")
font_filename
for _prefix, font_filename, _charmap_filename in qta._BUNDLED_FONTS
]
fonts_command = [
"powershell.exe",
r'Get-ItemProperty "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"'
]
fonts_result = subprocess.run(fonts_command, capture_output=True, check=True, text=True).stdout

for font_name, font_filename in fonts_expected:
assert font_name in fonts_result
fonts_result = subprocess.run(
fonts_command, capture_output=True, check=True, text=True
).stdout
for font_filename in fonts_expected:
assert font_filename in fonts_result


Expand Down
55 changes: 40 additions & 15 deletions setupbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,18 @@ class UpdateFA5Command(setuptools.Command):

# Update these below if the FontAwesome changes their structure:
FA_STYLES = ('regular', 'solid', 'brands')
CHARMAP_PATH_TEMPLATE = os.path.join(HERE, 'qtawesome', 'fonts', 'fontawesome5-{style}-webfont-charmap.json')
TTF_PATH_TEMPLATE = os.path.join(HERE, 'qtawesome', 'fonts', 'fontawesome5-{style}-webfont.ttf')
CHARMAP_PATH_TEMPLATE = os.path.join(
HERE,
"qtawesome",
"fonts",
"fontawesome5-{style}-webfont-charmap-{version}.json",
)
TTF_PATH_TEMPLATE = os.path.join(
HERE,
"qtawesome",
"fonts",
"fontawesome5-{style}-webfont-{version}.ttf"
)
URL_TEMPLATE = 'https://github.com/FortAwesome/Font-Awesome/' \
'releases/download/{version}/fontawesome-free-{version}-web.zip'

Expand All @@ -108,11 +118,15 @@ def __print(self, msg):

def __get_charmap_path(self, style):
"""Get the project FA charmap path for a given style."""
return self.CHARMAP_PATH_TEMPLATE.format(style=style)
return self.CHARMAP_PATH_TEMPLATE.format(
style=style, version=self.fa_version
)

def __get_ttf_path(self, style):
"""Get the project FA font path for a given style."""
return self.TTF_PATH_TEMPLATE.format(style=style)
return self.TTF_PATH_TEMPLATE.format(
style=style, version=self.fa_version
)

@property
def __release_url(self):
Expand Down Expand Up @@ -218,7 +232,10 @@ def run(self):
# We read it in full, then use regex substitution:
for style, md5 in hashes.items():
self.__print('New "%s" hash is: %s' % (style, md5))
regex = r"('fontawesome5-%s-webfont.ttf':\s+)'(\w+)'" % style
regex = r"('fontawesome5-%s-webfont-%s.ttf':\s+)'(\w+)'" % (
style,
self.fa_version
)
subst = r"\g<1>'" + md5 + "'"
contents = re.sub(regex, subst, contents, 1)
# and finally overwrite with the modified file:
Expand All @@ -238,12 +255,16 @@ class UpdateCodiconCommand(setuptools.Command):
description = 'Try to update the Codicon font data in the project.'
user_options = []

CHARMAP_PATH = os.path.join(HERE, 'qtawesome', 'fonts', 'codicon-charmap.json')
TTF_PATH = os.path.join(HERE, 'qtawesome', 'fonts', 'codicon.ttf')
DOWNLOAD_URL_TTF = 'https://raw.githubusercontent.com/microsoft/vscode-codicons/master/dist/codicon.ttf'
DOWNLOAD_URL_CSV = 'https://raw.githubusercontent.com/microsoft/vscode-codicons/master/dist/codicon.csv'
CHARMAP_PATH = os.path.join(
HERE, "qtawesome", "fonts", "codicon-charmap-{version}.json"
)
TTF_PATH = os.path.join(
HERE, "qtawesome", "fonts", "codicon-{version}.ttf"
)
DOWNLOAD_URL_TTF = 'https://raw.githubusercontent.com/microsoft/vscode-codicons/main/dist/codicon.ttf'
DOWNLOAD_URL_CSV = 'https://raw.githubusercontent.com/microsoft/vscode-codicons/main/dist/codicon.csv'
# At the time of writing this comment, vscode-codicons repo does not use git tags, but you can get the version from package.json:
DOWNLOAD_URL_JSON = 'https://raw.githubusercontent.com/microsoft/vscode-codicons/master/package.json'
DOWNLOAD_URL_JSON = 'https://raw.githubusercontent.com/microsoft/vscode-codicons/main/package.json'

def initialize_options(self):
"""Required by setuptools."""
Expand Down Expand Up @@ -283,13 +304,17 @@ def run(self):
os.remove(tempCSV.name)

# Dump a .json charmap file the way we like it:
self.__print('Dumping updated charmap: %s' % self.CHARMAP_PATH)
with open(self.CHARMAP_PATH, 'w+') as f:
charmap_path = self.CHARMAP_PATH.format(version=package_version)
self.__print('Dumping updated charmap: %s' % charmap_path)
with open(charmap_path, 'w+') as f:
json.dump(charmap, f, indent=4, sort_keys=True)

# Dump a .ttf font file:
with open(self.TTF_PATH, 'wb+') as ttfFile:
self.__print('Downloading %s --> %s' % (self.DOWNLOAD_URL_TTF, self.TTF_PATH))
ttf_path = self.TTF_PATH.format(version=package_version)
with open(ttf_path, 'wb+') as ttfFile:
self.__print(
"Downloading %s --> %s" % (self.DOWNLOAD_URL_TTF, ttf_path)
)
response = urlopen(self.DOWNLOAD_URL_TTF)
data = response.read()
ttfFile.write(data)
Expand All @@ -300,7 +325,7 @@ def run(self):
self.__print('Patching new MD5 hashes in: %s' % INIT_PY_PATH)
with open(INIT_PY_PATH, 'r') as init_file:
contents = init_file.read()
regex = r"('codicon.ttf':\s+)'(\w+)'"
regex = r"('codicon-%s.ttf':\s+)'(\w+)'" % package_version
subst = r"\g<1>'" + md5 + "'"
contents = re.sub(regex, subst, contents, 1)
self.__print('Dumping updated file: %s' % INIT_PY_PATH)
Expand Down

0 comments on commit 43bcbb5

Please sign in to comment.