CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-prettyprinter

Syntax-highlighting, declarative and composable pretty printer for Python 3.5+

Pending
Overview
Eval results
Files

registration.mddocs/

Pretty Printer Registration

System for registering custom pretty printers for user-defined types and creating formatted function call representations. This enables extending prettyprinter to handle custom classes and data structures with specialized formatting logic.

Capabilities

Type Registration

Register custom pretty printers for specific types or predicate-based matching, enabling specialized formatting for user-defined classes and data structures.

def register_pretty(type=None, predicate=None):
    """
    Decorator that registers a function as the pretty printer for a type.
    
    Parameters:
    - type: Type to register for, or string 'module.ClassName' for deferred registration
    - predicate: Function taking one argument returning bool for predicate-based matching
    
    Notes:
    - Exactly one of 'type' or 'predicate' must be provided
    - Decorated function must accept (value, ctx) parameters
    - Returns the original function unchanged
    
    Usage:
        @register_pretty(MyClass)
        def pretty_my_class(value, ctx):
            return pretty_call(ctx, MyClass, value.attr1, value.attr2)
    """

Registration Status

Check whether a type has a registered pretty printer, useful for conditional formatting logic and debugging registration issues.

def is_registered(type, *, check_superclasses=False, check_deferred=True, 
                 register_deferred=True) -> bool:
    """
    Check if a type has a registered pretty printer.
    
    Parameters:
    - type: Type to check for registration
    - check_superclasses (bool): Check superclass types (default: False)
    - check_deferred (bool): Check deferred registrations (default: True)
    - register_deferred (bool): Register deferred printers when found (default: True)
    
    Returns:
    - bool: True if type has registered pretty printer
    
    Raises:
    - ValueError: If register_deferred=True when check_deferred=False
    """

Function Call Formatting (Python 3.6+)

Create formatted function call representations with automatic argument handling and keyword argument preservation.

def pretty_call(ctx, fn, *args, **kwargs):
    """
    Create a Doc representing a function call with arguments.
    
    Parameters:
    - ctx (PrettyContext): Current pretty printing context
    - fn: Callable to represent in the call
    - args: Positional arguments for the call
    - kwargs: Keyword arguments for the call
    
    Returns:
    - Doc: Document representing the formatted function call
    
    Notes:
    - Requires Python 3.6+ for keyword argument order preservation
    - Automatically handles syntax highlighting and layout
    - For Python 3.5 compatibility, use pretty_call_alt instead
    """

Function Call Formatting (All Python Versions)

Create formatted function call representations with explicit argument specification, compatible with all Python versions.

def pretty_call_alt(ctx, fn, args=(), kwargs=()):
    """
    Create a Doc representing a function call with explicit arguments.
    
    Parameters:
    - ctx (PrettyContext): Current pretty printing context
    - fn: Callable to represent in the call
    - args (tuple): Tuple of positional arguments
    - kwargs: OrderedDict, dict, or iterable of (key, value) pairs for keyword arguments
    
    Returns:
    - Doc: Document representing the formatted function call
    
    Notes:
    - Works on all Python versions including 3.5
    - For consistent results on Python 3.5, use OrderedDict or list of tuples for kwargs
    """

Usage Examples

Basic Type Registration

from prettyprinter import register_pretty, pretty_call
from collections import namedtuple

# Custom class example
class Person:
    def __init__(self, name, age, email):
        self.name = name
        self.age = age
        self.email = email

@register_pretty(Person)
def pretty_person(person, ctx):
    return pretty_call(ctx, Person, person.name, person.age, person.email)

# Now Person instances are pretty printed as constructor calls
person = Person("Alice", 30, "alice@example.com")
pprint(person)
# Output: Person('Alice', 30, 'alice@example.com')

Advanced Registration with Custom Logic

from prettyprinter import register_pretty, pretty_call, comment
import datetime

class Task:
    def __init__(self, title, priority=1, due_date=None, completed=False):
        self.title = title
        self.priority = priority
        self.due_date = due_date
        self.completed = completed

@register_pretty(Task)
def pretty_task(task, ctx):
    # Show different representation based on completion status
    if task.completed:
        return comment(
            pretty_call(ctx, Task, task.title, 
                       priority=task.priority, 
                       due_date=task.due_date, 
                       completed=task.completed),
            'COMPLETED'
        )
    else:
        return pretty_call(ctx, Task, task.title,
                          priority=task.priority,
                          due_date=task.due_date)

# Usage
task1 = Task("Write documentation", priority=2, 
            due_date=datetime.date(2024, 1, 15))
task2 = Task("Review code", completed=True)

pprint([task1, task2])

Predicate-Based Registration

from prettyprinter import register_pretty
from collections.abc import Mapping

# Register pretty printer for all custom mapping types
@register_pretty(predicate=lambda obj: isinstance(obj, Mapping) and 
                                      type(obj).__name__.endswith('Dict'))
def pretty_custom_dicts(mapping, ctx):
    return pretty_call(ctx, type(mapping), dict(mapping))

# This will handle CustomDict, OrderedDict, etc.
class CustomDict(dict):
    pass

custom = CustomDict([('a', 1), ('b', 2)])
pprint(custom)  # CustomDict({'a': 1, 'b': 2})

Deferred Registration

from prettyprinter import register_pretty

# Register for a type that might not be imported yet
@register_pretty('numpy.ndarray')
def pretty_numpy_array(arr, ctx):
    # This registration is deferred until numpy.ndarray is actually encountered
    return pretty_call(ctx, type(arr), arr.tolist())

# The registration becomes active when numpy arrays are first encountered
import numpy as np
arr = np.array([1, 2, 3, 4, 5])
pprint(arr)  # Triggers registration and uses custom formatter

Complex Object Hierarchies

from prettyprinter import register_pretty, pretty_call

class Database:
    def __init__(self, name, tables=None):
        self.name = name
        self.tables = tables or []

class Table:
    def __init__(self, name, columns=None, rows=0):
        self.name = name
        self.columns = columns or []
        self.rows = rows

@register_pretty(Database)
def pretty_database(db, ctx):
    return pretty_call(ctx, Database, db.name, tables=db.tables)

@register_pretty(Table)  
def pretty_table(table, ctx):
    return pretty_call(ctx, Table, table.name, 
                      columns=table.columns, rows=table.rows)

# Nested objects are automatically handled
db = Database("myapp", [
    Table("users", ["id", "name", "email"], 1000),
    Table("posts", ["id", "title", "content"], 5000)
])

pprint(db)
# Output shows nested structure with custom formatting for both types

Checking Registration Status

from prettyprinter import is_registered, register_pretty

class MyClass:
    pass

# Check if registered
print(is_registered(MyClass))  # False

@register_pretty(MyClass)
def pretty_my_class(obj, ctx):
    return "MyClass()"

# Now it's registered
print(is_registered(MyClass))  # True

# Check superclasses too
class MySubClass(MyClass):
    pass

print(is_registered(MySubClass))  # False
print(is_registered(MySubClass, check_superclasses=True))  # True

Using pretty_call_alt for Python 3.5 Compatibility

from prettyprinter import register_pretty, pretty_call_alt
from collections import OrderedDict

@register_pretty(Person)
def pretty_person_alt(person, ctx):
    # Use explicit args and kwargs for Python 3.5 compatibility
    return pretty_call_alt(
        ctx, 
        Person,
        args=(person.name,),
        kwargs=OrderedDict([
            ('age', person.age),
            ('email', person.email)
        ])
    )

Install with Tessl CLI

npx tessl i tessl/pypi-prettyprinter

docs

comments.md

configuration.md

core-printing.md

document-system.md

extras.md

index.md

registration.md

tile.json