Skip to main content

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 fonttools to 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

Command-Line Interface

JustMyType includes a CLI for discovering and inspecting fonts from the command line.

List All Fonts

# List all available font families
justmytype list

# Sort by number of variants
justmytype list --sort count

# Output as JSON
justmytype list --json

Find a Font

# Find a font by family name
justmytype find "Roboto"

# Find with specific weight and style
justmytype find "Roboto" --weight 400 --style normal
justmytype find "Inter" --weight 700 --style italic

# Output as JSON
justmytype find "Roboto" --json

Show Font Information

# Show information about a font family
justmytype info "Roboto"

# Show all variants of a font
justmytype info "Roboto" --all-variants

# Output as JSON
justmytype info "Roboto" --json

List Font Packs

# List registered font packs
justmytype packs

# Show detailed pack information
justmytype packs --verbose

# Output as JSON
justmytype packs --json

Blocking Font Packs (CLI)

# Block specific font packs
justmytype list --blocklist "system-fonts"
justmytype find "Roboto" --blocklist "system-fonts,broken-pack"

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."justmytype.packs"]
"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, for FontInfo.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

justmytype-0.2.0.tar.gz (16.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

justmytype-0.2.0-py3-none-any.whl (19.5 kB view details)

Uploaded Python 3

File details

Details for the file justmytype-0.2.0.tar.gz.

File metadata

  • Download URL: justmytype-0.2.0.tar.gz
  • Upload date:
  • Size: 16.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.10.6 Darwin/24.6.0

File hashes

Hashes for justmytype-0.2.0.tar.gz
Algorithm Hash digest
SHA256 278c2a43de97b62f4de52c20f5e0dd35ff4763146feb5047fa19b9578ef65f1a
MD5 168297f64095f0849aa4db2bd5b3ad2b
BLAKE2b-256 3e2551c9d7f3b9e32630d46cb31188762bab2b2454926ddb86c8a75d20f9541c

See more details on using hashes here.

File details

Details for the file justmytype-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: justmytype-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 19.5 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

Hashes for justmytype-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7ba0c0dde84a5f107f5a69e0faa9d7c25d9df1fafe5abf63ab6f2250a5b63354
MD5 e7b4a75927096e54fcbda63bfaad64ea
BLAKE2b-256 5d50a0e074c3dd2fb4c742d076481aa53dcd4429ec9792527a0408cc78173b2b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page