169 lines
5.1 KiB
Python
169 lines
5.1 KiB
Python
"""
|
|
Test font utilities for ensuring consistent font usage across tests.
|
|
|
|
This module provides utilities to guarantee that all tests use the same bundled font,
|
|
preventing inconsistencies that can arise from different system fonts.
|
|
"""
|
|
|
|
import os
|
|
from typing import Optional
|
|
from PIL import ImageFont
|
|
|
|
from pyWebLayout.style.fonts import Font, FontWeight, FontStyle, TextDecoration
|
|
|
|
|
|
def get_bundled_font_path() -> Optional[str]:
|
|
"""
|
|
Get the path to the bundled DejaVuSans.ttf font.
|
|
|
|
This function works from test directories by finding the font relative to the
|
|
test file locations.
|
|
|
|
Returns:
|
|
str: Path to the bundled font file, or None if not found
|
|
"""
|
|
# Get the directory containing this test utility file
|
|
current_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
# Navigate up to the project root (tests/utils -> tests -> root)
|
|
project_root = os.path.dirname(os.path.dirname(current_dir))
|
|
|
|
# Path to the bundled font
|
|
bundled_font_path = os.path.join(
|
|
project_root,
|
|
'pyWebLayout',
|
|
'assets',
|
|
'fonts',
|
|
'DejaVuSans.ttf')
|
|
|
|
if os.path.exists(bundled_font_path):
|
|
return bundled_font_path
|
|
|
|
# Alternative: try to find it relative to the pyWebLayout module
|
|
try:
|
|
import pyWebLayout
|
|
module_dir = os.path.dirname(pyWebLayout.__file__)
|
|
alt_font_path = os.path.join(module_dir, 'assets', 'fonts', 'DejaVuSans.ttf')
|
|
if os.path.exists(alt_font_path):
|
|
return alt_font_path
|
|
except ImportError:
|
|
pass
|
|
|
|
return None
|
|
|
|
|
|
def verify_bundled_font_available() -> bool:
|
|
"""
|
|
Verify that the bundled font is available and can be loaded.
|
|
|
|
Returns:
|
|
bool: True if the bundled font is available and loadable
|
|
"""
|
|
font_path = get_bundled_font_path()
|
|
if not font_path:
|
|
return False
|
|
|
|
try:
|
|
# Try to load the font with PIL to verify it's valid
|
|
ImageFont.truetype(font_path, 16)
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def create_test_font(font_size: int = 16,
|
|
colour: tuple = (0, 0, 0),
|
|
weight: FontWeight = FontWeight.NORMAL,
|
|
style: FontStyle = FontStyle.NORMAL,
|
|
decoration: TextDecoration = TextDecoration.NONE,
|
|
background: Optional[tuple] = None,
|
|
language: str = "en_EN",
|
|
min_hyphenation_width: Optional[int] = None) -> Font:
|
|
"""
|
|
Create a Font object that uses the bundled font for consistent testing.
|
|
|
|
This function ensures all tests use the same font file, preventing
|
|
cross-system inconsistencies in text measurements and layout.
|
|
|
|
Args:
|
|
font_size: Size of the font in points
|
|
colour: RGB color tuple for the text
|
|
weight: Font weight (normal or bold)
|
|
style: Font style (normal or italic)
|
|
decoration: Text decoration (none, underline, or strikethrough)
|
|
background: RGBA background color for the text
|
|
language: Language code for hyphenation and text processing
|
|
min_hyphenation_width: Minimum width in pixels for hyphenation
|
|
|
|
Returns:
|
|
Font: A Font object guaranteed to use the bundled font
|
|
|
|
Raises:
|
|
RuntimeError: If the bundled font cannot be found or loaded
|
|
"""
|
|
font_path = get_bundled_font_path()
|
|
if not font_path:
|
|
raise RuntimeError(
|
|
"Bundled font (DejaVuSans.ttf) not found. "
|
|
"Ensure the font exists in pyWebLayout/assets/fonts/"
|
|
)
|
|
|
|
if not verify_bundled_font_available():
|
|
raise RuntimeError(
|
|
f"Bundled font at {font_path} cannot be loaded. "
|
|
"Font file may be corrupted or invalid."
|
|
)
|
|
|
|
return Font(
|
|
font_path=font_path,
|
|
font_size=font_size,
|
|
colour=colour,
|
|
weight=weight,
|
|
style=style,
|
|
decoration=decoration,
|
|
background=background,
|
|
language=language,
|
|
min_hyphenation_width=min_hyphenation_width
|
|
)
|
|
|
|
|
|
def create_default_test_font() -> Font:
|
|
"""
|
|
Create a default Font object for testing with the bundled font.
|
|
|
|
This is equivalent to Font() but guarantees the bundled font is used.
|
|
|
|
Returns:
|
|
Font: A default Font object using the bundled font
|
|
"""
|
|
return create_test_font()
|
|
|
|
|
|
def ensure_consistent_font_in_tests():
|
|
"""
|
|
Ensure that tests are using consistent fonts by checking availability.
|
|
|
|
This function can be called in test setup to verify the font environment
|
|
is properly configured.
|
|
|
|
Raises:
|
|
RuntimeError: If the bundled font is not available
|
|
"""
|
|
if not verify_bundled_font_available():
|
|
font_path = get_bundled_font_path()
|
|
if font_path:
|
|
raise RuntimeError(
|
|
f"Bundled font found at {font_path} but cannot be loaded. "
|
|
"Font file may be corrupted."
|
|
)
|
|
else:
|
|
raise RuntimeError(
|
|
"Bundled font (DejaVuSans.ttf) not found. "
|
|
"Ensure the font exists in pyWebLayout/assets/fonts/"
|
|
)
|
|
|
|
|
|
# Convenience aliases
|
|
get_test_font = create_default_test_font
|
|
font_factory = create_test_font
|