Cross-platform font discovery and resolution library for Python
Project description
JustMyType
A precise, lightweight, and extensible font discovery library for Python. JustMyType provides a robust "Font Atlas" for the Python ecosystem—a definitive map of every font available to an application, whether installed on the system or bundled in a Python package.
Features
- Cross-platform: Unified API across macOS, Linux, and Windows
- Extensible: Font packs can be added via standard Python EntryPoints mechanism
- Efficient: Lazy discovery with in-memory caching
- Flexible: Supports font matching by family, weight, style, and width with intelligent fallback
- W3C Compliant: Implements CSS Fonts Level 4 matching algorithm for browser-like behavior
- Precise: Uses
fonttoolsto parse binary font tables—never guesses from filenames
Installation
pip install justmytype
For Pillow support (optional, for loading fonts):
pip install justmytype[pillow]
Quick Start
from justmytype import FontRegistry, get_default_registry
# Get default registry
registry = get_default_registry()
# Find a font (lazy discovery happens automatically)
font_info = registry.find_font("Arial", weight=700, style="normal")
if font_info:
# Load as PIL ImageFont (requires Pillow)
font = font_info.load(size=16)
# Or use the path directly
print(f"Found font at: {font_info.path}")
Basic Usage
Finding Fonts
from justmytype import FontRegistry
registry = FontRegistry()
# Find by family name
font_info = registry.find_font("Roboto", weight=400)
# Find with style
font_info = registry.find_font("Open Sans", weight=700, style="italic")
# Find with width
font_info = registry.find_font("Arial", width="condensed")
# List all available families
for family in registry.list_families():
print(family)
Loading Fonts with Pillow
from justmytype import get_default_registry
from PIL import Image, ImageDraw, ImageFont
registry = get_default_registry()
font_info = registry.find_font("Arial", weight=700)
if font_info:
# Load as PIL ImageFont
font = font_info.load(size=24)
# Use with PIL
img = Image.new("RGB", (200, 100), "white")
draw = ImageDraw.Draw(img)
draw.text((10, 10), "Hello", font=font, fill="black")
img.save("output.png")
Blocking Font Packs
# Block system fonts
registry = FontRegistry(blocklist={"system-fonts"})
# Block via environment variable
# FONT_DISCOVERY_BLOCKLIST="system-fonts,broken-pack" python app.py
Creating Font Packs
Font packs can be registered via Python EntryPoints. This allows applications to bundle fonts or third-party packages to provide fonts.
First-Party Font Pack (Application's Own Fonts)
# myapp/fonts.py
from pathlib import Path
from importlib.resources import files
def get_font_directories():
"""Entry point factory for application's bundled fonts."""
package = files("myapp.fonts")
return [Path(str(package))]
# pyproject.toml
[project.entry-points."fontpacks"]
"myapp-fonts" = "myapp.fonts:get_font_directories"
Third-Party Font Pack
# my_font_pack/__init__.py
from pathlib import Path
from importlib.resources import files
def get_font_directories():
"""Entry point factory for font pack."""
package = files("my_font_pack.fonts")
return [Path(str(package))]
Architecture
JustMyType follows a unified "Font Pack" architecture where all font sources (system fonts, bundled fonts, third-party fonts) implement the same FontPack protocol. This ensures:
- Consistency: All fonts are discovered and resolved the same way
- Extensibility: New font sources can be added via EntryPoints
- Priority: Font packs (priority 100) override system fonts (priority 0)
See docs/architecture.md for detailed architecture documentation.
Development
Setup
# Clone the repository
git clone https://github.com/yourusername/justmytype.git
cd justmytype
# Install with development dependencies
pip install -e ".[pillow]"
pip install -e ".[dev]" # If dev dependencies are configured
Running Tests
# Run tests with coverage
pytest
# Run with coverage report
pytest --cov=justmytype --cov-report=html
Code Quality
# Format code
ruff format .
# Lint code
ruff check .
# Type checking
mypy src/
Requirements
- Python 3.10+
fonttools(required)Pillow(optional, forFontInfo.load())
License
MIT License - see LICENSE file for details.
Contributing
Contributions are welcome! Please read the architecture documentation in docs/architecture.md and follow the project philosophy outlined in AGENTS.md.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file justmytype-0.1.0.tar.gz.
File metadata
- Download URL: justmytype-0.1.0.tar.gz
- Upload date:
- Size: 13.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.2 CPython/3.10.6 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1594d226ab766004b599cd4ecb81d9a8f24973b1493da1eb0ea067544e31c61
|
|
| MD5 |
237533629218d6db432225b4adcac4ec
|
|
| BLAKE2b-256 |
37b376ca51db77de69d5e63d83f56b51262c7e03136586f6dee5adb6d403d2d1
|
File details
Details for the file justmytype-0.1.0-py3-none-any.whl.
File metadata
- Download URL: justmytype-0.1.0-py3-none-any.whl
- Upload date:
- Size: 15.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.1.2 CPython/3.10.6 Darwin/24.6.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c7f4cc6711b7dd4f9d204fb1ffa1dbc541ebea840e47038de6b35d5a3ef0af1
|
|
| MD5 |
410cb346a008306941887d1d193a326a
|
|
| BLAKE2b-256 |
d3693bef4a0110f6dbbf1611f4c43b2759537cb1ce3ed4baf0e4291ecbb4022e
|