From dfe6e61babf62ab59940c8e93066c2ef65f7bd81 Mon Sep 17 00:00:00 2001 From: Gonzalo Pena-Castellanos Date: Wed, 8 Jan 2020 22:47:01 -0500 Subject: [PATCH] Update font registry on windows --- .github/workflows/ci.yml | 14 +++++++-- colosseum/fonts.py | 56 ++++++++++++++++++++++++--------- tests/utils.py | 68 ++++++++++++++++++++++++++-------------- 3 files changed, 98 insertions(+), 40 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3c07fddb..b9cfa6109 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,6 +39,9 @@ jobs: sudo apt-get install -y python3-gi python3-gi-cairo gir1.2-gtk-3.0 python3-dev libgirepository1.0-dev libcairo2-dev pkg-config pip install --upgrade pip setuptools pytest-tldr pip install -e . + - name: Install fonts + run: | + xvfb-run -a -s '-screen 0 2048x1536x24' python tests/utils.py - name: Test run: | xvfb-run -a -s '-screen 0 2048x1536x24' python setup.py test @@ -62,6 +65,9 @@ jobs: sudo apt-get install -y python3-gi python3-gi-cairo gir1.2-gtk-3.0 python3-dev libgirepository1.0-dev libcairo2-dev pkg-config pip install --upgrade pip setuptools pip install -e . + - name: Install fonts + run: | + xvfb-run -a -s '-screen 0 2048x1536x24' python tests/utils.py - name: Test run: | xvfb-run -a -s '-screen 0 2048x1536x24' python setup.py test @@ -80,9 +86,11 @@ jobs: run: | pip install --upgrade pip setuptools pip install -e . - - name: Test + - name: Install fonts run: | python tests/utils.py + - name: Test + run: | python setup.py test macOS: @@ -99,7 +107,9 @@ jobs: run: | pip install --upgrade pip setuptools pip install -e . - - name: Test + - name: Install fonts run: | python tests/utils.py + - name: Test + run: | python setup.py test diff --git a/colosseum/fonts.py b/colosseum/fonts.py index 47784ef65..a7752e560 100644 --- a/colosseum/fonts.py +++ b/colosseum/fonts.py @@ -28,6 +28,31 @@ def validate_font_family(cls, value): raise ValidationError('Font family "{value}" not found on system!'.format(value=value)) + @staticmethod + def fonts_path(system=False): + """Return the path for cross platform user fonts.""" + if os.name == 'nt': + import winreg + if system: + fonts_dir = os.path.join(winreg.ExpandEnvironmentStrings(r'%windir%'), 'Fonts') + else: + fonts_dir = os.path.join(winreg.ExpandEnvironmentStrings(r'%LocalAppData%'), + 'Microsoft', 'Windows', 'Fonts') + elif sys.platform == 'darwin': + if system: + fonts_dir = os.path.expanduser('/Library/Fonts') + else: + fonts_dir = os.path.expanduser('~/Library/Fonts') + elif sys.platform.startswith('linux'): + if system: + fonts_dir = os.path.expanduser('/usr/local/share/fonts') + else: + fonts_dir = os.path.expanduser('~/.local/share/fonts/') + else: + raise NotImplementedError('System not supported!') + + return fonts_dir + def _check_font_family_mac(value): """List available font family names on mac.""" @@ -58,9 +83,11 @@ class Window(Gtk.Window): def check_system_font(self, value): """Check if font family exists on system.""" context = self.create_pango_context() - for fam in context.list_families(): - if fam.get_name() == value: + for font_family in context.list_families(): + font_name = font_family.get_name() + if font_name == value: return True + return False global _GTK_WINDOW # noqa @@ -72,16 +99,17 @@ def check_system_font(self, value): def _check_font_family_win(value): """List available font family names on windows.""" - import winreg - key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, - r"Software\Microsoft\Windows NT\CurrentVersion\Fonts", - 0, - winreg.KEY_READ) - for idx in range(0, winreg.QueryInfoKey(key)[1]): - font_name = winreg.EnumValue(key, idx)[0] - font_name = font_name.replace(' (TrueType)', '') - if font_name == value: - return True + import winreg # noqa + for base in [winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER]: + key = winreg.OpenKey(base, + r"Software\Microsoft\Windows NT\CurrentVersion\Fonts", + 0, + winreg.KEY_READ) + for idx in range(0, winreg.QueryInfoKey(key)[1]): + font_name = winreg.EnumValue(key, idx)[0] + font_name = font_name.replace(' (TrueType)', '') + if font_name == value: + return True return False @@ -95,7 +123,7 @@ def check_font_family(value): elif os.name == 'nt': return _check_font_family_win(value) else: - raise NotImplementedError('Cannot request fonts on this system!') + raise NotImplementedError('Cannot check font existence on this system!') def get_system_font(keyword): @@ -103,7 +131,7 @@ def get_system_font(keyword): from .constants import SYSTEM_FONT_KEYWORDS # noqa if keyword in SYSTEM_FONT_KEYWORDS: - # Get the system font + # TODO: Get the system font that corresponds return 'Ahem' return None diff --git a/tests/utils.py b/tests/utils.py index adce6235a..a8028ff59 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -156,44 +156,60 @@ def output_layout(layout, depth=1): return (' ' * depth + "* '{text}'\n".format(text=layout['text'].strip())) -def fonts_path(system=False): - """Return the path for cross platform user fonts.""" - if os.name == 'nt': - import winreg - fonts_dir = os.path.join(winreg.ExpandEnvironmentStrings('%windir%'), 'fonts') - elif sys.platform == 'darwin': - if system: - fonts_dir = os.path.expanduser('/Library/Fonts') - else: - fonts_dir = os.path.expanduser('~/Library/Fonts') - elif sys.platform.startswith('linux'): - fonts_dir = os.path.expanduser('~/.local/share/fonts/') - else: - raise NotImplementedError('System not supported!') - - return fonts_dir - - def copy_fonts(system=False): """Copy needed files for running tests.""" - fonts_folder = fonts_path(system=system) + fonts_folder = FontDatabase.fonts_path(system=system) + if not os.path.isdir(fonts_folder): os.makedirs(fonts_folder) + fonts_data_path = os.path.join(HERE, 'data', 'fonts') font_files = sorted([item for item in os.listdir(fonts_data_path) if item.endswith('.ttf')]) for font_file in font_files: font_file_data_path = os.path.join(fonts_data_path, font_file) font_file_path = os.path.join(fonts_folder, font_file) + if not os.path.isfile(font_file_path): shutil.copyfile(font_file_data_path, font_file_path) + # Register font + + if os.name == 'nt': + import winreg # noqa + base_key = winreg.HKEY_LOCAL_MACHINE if system else winreg.HKEY_CURRENT_USER + key_path = r"Software\Microsoft\Windows NT\CurrentVersion\Fonts" + + if '_' in font_file: + font_name = font_file.split('_')[-1].split('.')[0] + else: + font_name = font_file.split('.')[0] + + # This font has a space in its system name + if font_name == 'WhiteSpace': + font_name = 'White Space' + + font_name = font_name + ' (TrueType)' + + with winreg.OpenKey(base_key, key_path, 0, winreg.KEY_ALL_ACCESS) as reg_key: + value = None + try: + # Query if it exists + value = winreg.QueryValueEx(reg_key, font_name) + except FileNotFoundError: + pass + + # If it does not exists, add value + if value != font_file_path: + winreg.SetValueEx(reg_key, font_name, 0, winreg.REG_SZ, font_file_path) class ColosseumTestCase(TestCase): """Install test fonts before running tests that use them.""" + _FONTS_ACTIVE = False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.copy_fonts() + if self._FONTS_ACTIVE is False: + self.copy_fonts() def copy_fonts(self): copy_fonts() @@ -204,6 +220,8 @@ def copy_fonts(self): raise Exception('\n\nTesting fonts (Ahem & Ahem Extra) are not active.\n' '\nPlease run the test suite one more time.\n') + ColosseumTestCase._FONTS_ACTIVE = True + class LayoutTestCase(ColosseumTestCase): def setUp(self): @@ -451,7 +469,9 @@ def test_method(self): if __name__ == '__main__': - print('Copying test fonts...') - print(fonts_path(system=True)) - copy_fonts(system=True) - print(list(sorted(os.listdir(fonts_path())))) + # On CI we use system font locations except for linux containers + system = bool(os.environ.get('GITHUB_WORKSPACE', None)) + if sys.platform.startswith('linux'): + system = False + print('Copying test fonts to "{path}"...'.format(path=FontDatabase.fonts_path(system=system))) + copy_fonts(system=system)