Files
unshackle/tests/core/test_windows_fonts.py
imSp4rky a28c99b811 fix(fonts): find per-user Windows fonts by their family name
Read the per-user font registry as well as the machine one, and list each font under the family name in its file. Skip missing files, bitmap fonts and values that are not text.
2026-11-11 10:46:47 -07:00

93 lines
3.1 KiB
Python

"""get_windows_fonts reads the fonts installed for all users and for the current user."""
from __future__ import annotations
import sys
import types
from pathlib import Path, PureWindowsPath
import pytest
from unshackle.core import utilities
HKLM, HKCU = "HKLM", "HKCU"
class Key(list):
def __enter__(self) -> Key:
return self
def __exit__(self, *exc: object) -> None:
return None
@pytest.fixture
def registry(monkeypatch, tmp_path):
"""Install a fake winreg whose hives are the returned dict, with the machine font folder in tmp_path."""
hives: dict[str, list[tuple[str, object]]] = {}
def open_key(hive: str, *_: object) -> Key:
if hive not in hives:
raise FileNotFoundError(hive)
return Key(hives[hive])
winreg = types.SimpleNamespace(
HKEY_LOCAL_MACHINE=HKLM,
HKEY_CURRENT_USER=HKCU,
KEY_READ=0,
OpenKey=open_key,
QueryInfoKey=lambda key: (0, len(key), 0),
EnumValue=lambda key, n: (*key[n], 1),
)
monkeypatch.setitem(sys.modules, "winreg", winreg)
monkeypatch.setattr(sys, "platform", "win32")
(tmp_path / "machine").mkdir()
monkeypatch.setattr(utilities, "WINDOWS_FONTS_DIR", tmp_path / "machine")
monkeypatch.setattr(utilities, "extract_font_family", lambda path: None)
return hives
def font(path: Path) -> Path:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_bytes(b"")
return path
def test_per_user_fonts_are_found(registry, tmp_path):
machine = font(tmp_path / "machine/arial.ttf")
user = font(tmp_path / "user/MyFont-Bold.ttf")
registry[HKLM] = [("Arial (TrueType)", "arial.ttf")]
registry[HKCU] = [("My Font Bold (TrueType)", str(user)), ("Arial (TrueType)", str(user))]
fonts = utilities.get_windows_fonts()
assert fonts == {"Arial": machine, "My Font Bold": user}
assert utilities.find_font_with_fallbacks("My Font", fonts) == user
def test_a_font_is_found_by_the_family_name_in_its_file(registry, tmp_path, monkeypatch):
user = font(tmp_path / "user/My Font - Bold.ttf")
registry[HKCU] = [("MyFont-Bold (TrueType)", str(user))]
monkeypatch.setattr(utilities, "extract_font_family", lambda path: "My Font")
fonts = utilities.get_windows_fonts()
assert fonts == {"MyFont-Bold": user, "My Font": user}
assert utilities.find_font_with_fallbacks("My Font", fonts) == user
def test_an_absolute_registry_value_replaces_the_font_folder():
user = r"C:\Users\x\AppData\Local\Microsoft\Windows\Fonts\MyFont-Bold.ttf"
assert PureWindowsPath(r"C:\Windows\Fonts", user) == PureWindowsPath(user)
def test_missing_files_bitmap_fonts_and_odd_values_are_skipped(registry, tmp_path):
font(tmp_path / "machine/modern.fon")
collection = font(tmp_path / "machine/msgothic.ttc")
registry[HKLM] = [
("Modern (All res)", "modern.fon"),
("MS Gothic & MS UI Gothic (TrueType)", "msgothic.ttc"),
("Gone (TrueType)", "gone.ttf"),
("Binary (TrueType)", b"x.ttf"),
]
registry[HKCU] = [("Deleted (TrueType)", str(tmp_path / "user/Deleted.ttf"))]
assert utilities.get_windows_fonts() == {"MS Gothic & MS UI Gothic": collection}