Module clingox.pprint

This module is a replacement for Python`s pprint module for pretty printing clingo objects.

Expand source code
"""
This module is a replacement for Python`s pprint module for pretty printing
clingo objects.
"""

# pylint: disable=protected-access

import pprint as _pp
from typing import IO, Any, Dict, Optional, Sequence, Tuple

from clingo.ast import AST, ASTSequence, Location, Position
from clingo.symbol import Symbol, SymbolType

__all__ = [
    "PrettyPrinter",
    "isreadable",
    "isrecursive",
    "pformat",
    "pp",
    "pprint",
    "saferepr",
]


def pprint(
    obj: Any,
    stream: Optional[IO[str]] = None,
    indent: int = 1,
    width: int = 80,
    depth: Optional[int] = None,
    **kwargs
):
    """Pretty-print a Python object to a stream [default is sys.stdout]."""
    printer = PrettyPrinter(
        stream=stream, indent=indent, width=width, depth=depth, **kwargs
    )
    printer.pprint(obj)


def pformat(
    obj: Any, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs
) -> str:
    """Format a Python object into a pretty-printed representation."""
    return PrettyPrinter(
        stream=None, indent=indent, width=width, depth=depth, **kwargs
    ).pformat(obj)


def pp(obj: Any, *args, sort_dicts: bool = False, **kwargs):
    """Pretty-print a Python object."""
    # pylint: disable=invalid-name
    pprint(obj, *args, sort_dicts=sort_dicts, **kwargs)  # nocoverage


def saferepr(obj: Any) -> str:
    """Version of repr() which can handle recursive data structures."""
    if hasattr(PrettyPrinter, "_safe_repr"):
        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[0]  # type: ignore
    return _pp.saferepr(obj)  # nocoverage


def isreadable(obj: Any) -> bool:
    """Determine if saferepr(object) is readable by eval()."""
    if hasattr(PrettyPrinter, "_safe_repr"):
        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[1]  # type: ignore
    return _pp.isreadable(obj)  # nocoverage


def isrecursive(obj: Any) -> bool:
    """Determine if object requires a recursive representation."""
    if hasattr(PrettyPrinter, "_safe_repr"):
        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[2]  # type: ignore
    return _pp.isrecursive(obj)  # nocoverage


class _DummyLoc:
    def __repr__(self):
        return "LOC"


class PrettyPrinter(_pp.PrettyPrinter):
    """
    A pretty printer extending the standard `PrettyPrinter` class with
    functions to format `clingo.ast.AST` objects.
    """

    _hide_location: bool

    def __init__(self, *args, **kwargs):
        hide_location = kwargs.pop("hide_location", False)
        super().__init__(*args, **kwargs)
        self._hide_location = hide_location

    if _pp.PrettyPrinter.__init__.__doc__ is not None:
        __init__.__doc__ = (
            _pp.PrettyPrinter.__init__.__doc__
            + """hide_location
            Replace locations in `clingo.ast.AST` objects by placeholder LOC.
        """
        )

    def _pprint_namedtuple(
        self,
        obj: Any,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        # Note: adjusted _pprint_dataclass from python 3.10
        cls_name = obj.__class__.__name__
        indent += len(cls_name) + 1
        stream.write(cls_name + "(")
        self._format_kwargs_items(
            obj._asdict().items(), stream, indent, allowance, context, level
        )
        stream.write(")")

    def _format_kwargs_items(
        self,
        items: Sequence[Tuple[str, Any]],
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        # Note: copied _pprint_namespace_items from python 3.10
        write = stream.write
        delimnl = ",\n" + " " * indent
        last_index = len(items) - 1
        for i, (key, ent) in enumerate(items):
            last = i == last_index
            write(key)
            write("=")
            if id(ent) in context:
                write("...")  # nocoverage
            else:
                self._format(  # type: ignore
                    ent,
                    stream,
                    indent + len(key) + 1,
                    allowance if last else 1,
                    context,
                    level,
                )
            if not last:
                write(delimnl)

    def _format_args_items(
        self,
        items: Sequence[Any],
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        write = stream.write
        delimnl = ",\n" + " " * indent
        last_index = len(items) - 1
        for i, ent in enumerate(items):
            last = i == last_index
            if id(ent) in context:
                write("...")  # nocoverage
            else:
                self._format(  # type: ignore
                    ent,
                    stream,
                    indent,
                    allowance if last else 1,
                    context,
                    level,
                )
            if not last:
                write(delimnl)

    _dispatch = _pp.PrettyPrinter._dispatch.copy()  # type: ignore

    def _pprint_pos(
        self,
        obj: Position,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)

    _dispatch[Position.__repr__] = _pprint_pos

    def _pprint_loc(
        self,
        obj: Location,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)

    _dispatch[Location.__repr__] = _pprint_loc

    def _pprint_ast(
        self,
        obj: AST,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        name = str(obj.ast_type).replace("ASTType", "ast")
        indent += len(name) + 1
        items = [
            (key, _DummyLoc() if self._hide_location and key == "location" else val)
            for key, val in obj.items()
        ]
        stream.write(name + "(")
        self._format_kwargs_items(items, stream, indent, allowance, context, level)
        stream.write(")")

    _dispatch[AST.__repr__] = _pprint_ast
    _dispatch[ASTSequence.__repr__] = _pp.PrettyPrinter._pprint_list  # type: ignore

    def _pprint_sym(
        self,
        obj: Symbol,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        if obj.type == SymbolType.Function:
            indent += 9
            items = [obj.name, obj.arguments, obj.positive]

            stream.write("Function(")
            self._format_args_items(items, stream, indent, allowance, context, level)
            stream.write(")")
        else:
            stream.write(repr(obj))

    _dispatch[Symbol.__repr__] = _pprint_sym

Functions

def isreadable(obj: Any) ‑> bool

Determine if saferepr(object) is readable by eval().

Expand source code
def isreadable(obj: Any) -> bool:
    """Determine if saferepr(object) is readable by eval()."""
    if hasattr(PrettyPrinter, "_safe_repr"):
        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[1]  # type: ignore
    return _pp.isreadable(obj)  # nocoverage
def isrecursive(obj: Any) ‑> bool

Determine if object requires a recursive representation.

Expand source code
def isrecursive(obj: Any) -> bool:
    """Determine if object requires a recursive representation."""
    if hasattr(PrettyPrinter, "_safe_repr"):
        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[2]  # type: ignore
    return _pp.isrecursive(obj)  # nocoverage
def pformat(obj: Any, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs) ‑> str

Format a Python object into a pretty-printed representation.

Expand source code
def pformat(
    obj: Any, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs
) -> str:
    """Format a Python object into a pretty-printed representation."""
    return PrettyPrinter(
        stream=None, indent=indent, width=width, depth=depth, **kwargs
    ).pformat(obj)
def pp(obj: Any, *args, sort_dicts: bool = False, **kwargs)

Pretty-print a Python object.

Expand source code
def pp(obj: Any, *args, sort_dicts: bool = False, **kwargs):
    """Pretty-print a Python object."""
    # pylint: disable=invalid-name
    pprint(obj, *args, sort_dicts=sort_dicts, **kwargs)  # nocoverage
def pprint(obj: Any, stream: Optional[IO[str]] = None, indent: int = 1, width: int = 80, depth: Optional[int] = None, **kwargs)

Pretty-print a Python object to a stream [default is sys.stdout].

Expand source code
def pprint(
    obj: Any,
    stream: Optional[IO[str]] = None,
    indent: int = 1,
    width: int = 80,
    depth: Optional[int] = None,
    **kwargs
):
    """Pretty-print a Python object to a stream [default is sys.stdout]."""
    printer = PrettyPrinter(
        stream=stream, indent=indent, width=width, depth=depth, **kwargs
    )
    printer.pprint(obj)
def saferepr(obj: Any) ‑> str

Version of repr() which can handle recursive data structures.

Expand source code
def saferepr(obj: Any) -> str:
    """Version of repr() which can handle recursive data structures."""
    if hasattr(PrettyPrinter, "_safe_repr"):
        return PrettyPrinter()._safe_repr(obj, {}, None, 0)[0]  # type: ignore
    return _pp.saferepr(obj)  # nocoverage

Classes

class PrettyPrinter (*args, **kwargs)

A pretty printer extending the standard PrettyPrinter class with functions to format AST objects.

Handle pretty printing operations onto a stream using a set of configured parameters.

indent Number of spaces to indent for each level of nesting.

width Attempted maximum number of columns in the output.

depth The maximum depth to print out nested structures.

stream The desired output stream. If omitted (or false), the standard output stream available at construction will be used.

compact If true, several items will be combined in one line.

sort_dicts If true, dict keys are sorted.

hide_location Replace locations in AST objects by placeholder LOC.

Expand source code
class PrettyPrinter(_pp.PrettyPrinter):
    """
    A pretty printer extending the standard `PrettyPrinter` class with
    functions to format `clingo.ast.AST` objects.
    """

    _hide_location: bool

    def __init__(self, *args, **kwargs):
        hide_location = kwargs.pop("hide_location", False)
        super().__init__(*args, **kwargs)
        self._hide_location = hide_location

    if _pp.PrettyPrinter.__init__.__doc__ is not None:
        __init__.__doc__ = (
            _pp.PrettyPrinter.__init__.__doc__
            + """hide_location
            Replace locations in `clingo.ast.AST` objects by placeholder LOC.
        """
        )

    def _pprint_namedtuple(
        self,
        obj: Any,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        # Note: adjusted _pprint_dataclass from python 3.10
        cls_name = obj.__class__.__name__
        indent += len(cls_name) + 1
        stream.write(cls_name + "(")
        self._format_kwargs_items(
            obj._asdict().items(), stream, indent, allowance, context, level
        )
        stream.write(")")

    def _format_kwargs_items(
        self,
        items: Sequence[Tuple[str, Any]],
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        # Note: copied _pprint_namespace_items from python 3.10
        write = stream.write
        delimnl = ",\n" + " " * indent
        last_index = len(items) - 1
        for i, (key, ent) in enumerate(items):
            last = i == last_index
            write(key)
            write("=")
            if id(ent) in context:
                write("...")  # nocoverage
            else:
                self._format(  # type: ignore
                    ent,
                    stream,
                    indent + len(key) + 1,
                    allowance if last else 1,
                    context,
                    level,
                )
            if not last:
                write(delimnl)

    def _format_args_items(
        self,
        items: Sequence[Any],
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        write = stream.write
        delimnl = ",\n" + " " * indent
        last_index = len(items) - 1
        for i, ent in enumerate(items):
            last = i == last_index
            if id(ent) in context:
                write("...")  # nocoverage
            else:
                self._format(  # type: ignore
                    ent,
                    stream,
                    indent,
                    allowance if last else 1,
                    context,
                    level,
                )
            if not last:
                write(delimnl)

    _dispatch = _pp.PrettyPrinter._dispatch.copy()  # type: ignore

    def _pprint_pos(
        self,
        obj: Position,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)

    _dispatch[Position.__repr__] = _pprint_pos

    def _pprint_loc(
        self,
        obj: Location,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        self._pprint_namedtuple(obj, stream, indent, allowance, context, level)

    _dispatch[Location.__repr__] = _pprint_loc

    def _pprint_ast(
        self,
        obj: AST,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        name = str(obj.ast_type).replace("ASTType", "ast")
        indent += len(name) + 1
        items = [
            (key, _DummyLoc() if self._hide_location and key == "location" else val)
            for key, val in obj.items()
        ]
        stream.write(name + "(")
        self._format_kwargs_items(items, stream, indent, allowance, context, level)
        stream.write(")")

    _dispatch[AST.__repr__] = _pprint_ast
    _dispatch[ASTSequence.__repr__] = _pp.PrettyPrinter._pprint_list  # type: ignore

    def _pprint_sym(
        self,
        obj: Symbol,
        stream: IO[str],
        indent: int,
        allowance: int,
        context: Dict[int, Any],
        level: int,
    ):
        if obj.type == SymbolType.Function:
            indent += 9
            items = [obj.name, obj.arguments, obj.positive]

            stream.write("Function(")
            self._format_args_items(items, stream, indent, allowance, context, level)
            stream.write(")")
        else:
            stream.write(repr(obj))

    _dispatch[Symbol.__repr__] = _pprint_sym

Ancestors

  • pprint.PrettyPrinter