Skip to content

Commit

Permalink
Allow for a one-line representation in mf_pformat_dict() (#1667)
Browse files Browse the repository at this point in the history
This PR enables small objects with a short string representation to be
formatted on one line.
  • Loading branch information
plypaul authored Feb 10, 2025
1 parent d91ef7e commit d7d8be9
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import pprint
from dataclasses import fields, is_dataclass
from enum import Enum
from typing import Any, List, Mapping, Optional, Sized, Tuple, Union
from typing import Any, Dict, List, Mapping, Optional, Sized, Tuple, Union

from metricflow_semantics.mf_logging.formatting import indent
from metricflow_semantics.mf_logging.pretty_formattable import MetricFlowPrettyFormattable
Expand Down Expand Up @@ -454,6 +454,8 @@ def mf_pformat_dict( # type: ignore
description_lines: List[str] = [description] if description is not None else []
obj_dict = obj_dict or {}
item_sections = []

str_converted_dict: Dict[str, str] = {}
for key, value in obj_dict.items():
if preserve_raw_strings and isinstance(value, str):
value_str = value
Expand All @@ -466,10 +468,10 @@ def mf_pformat_dict( # type: ignore
include_none_object_fields=include_none_object_fields,
include_empty_object_fields=include_empty_object_fields,
)
str_converted_dict[str(key)] = value_str

lines_in_value_str = len(value_str.split("\n"))
item_section_lines: Tuple[str, ...]
if lines_in_value_str > 1:
if "\n" in value_str:
item_section_lines = (
f"{key}:",
indent(
Expand All @@ -486,7 +488,37 @@ def mf_pformat_dict( # type: ignore
else:
item_sections.append(indent(item_section))

result_as_one_line = _as_one_line(
description=description, str_converted_dict=str_converted_dict, max_line_length=max_line_length
)
if result_as_one_line is not None:
return result_as_one_line

if pad_items_with_newlines:
return "\n\n".join(description_lines + item_sections)
else:
return "\n".join(description_lines + item_sections)


def _as_one_line(description: Optional[str], str_converted_dict: Dict[str, str], max_line_length: int) -> Optional[str]:
"""See if the result can be returned in a compact, one-line representation.
e.g. for:
mf_pformat_dict("Example output", {"a": 1, "b": 2})
Compact output:
Example output (a=1, b=2)
Normal output:
Example output
a: 1
b: 2
"""
items = tuple(f"{key_str}={value_str}" for key_str, value_str in str_converted_dict.items())
value_in_parenthesis = ", ".join(items)
result = f"{description}" + (f" ({value_in_parenthesis})" if len(value_in_parenthesis) > 0 else "")

if "\n" in result or len(result) > max_line_length:
return None

return result
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import logging

from metricflow_semantics.formatting.formatting_helpers import mf_dedent
from metricflow_semantics.mf_logging.lazy_formattable import LazyFormat
from typing_extensions import override

Expand All @@ -19,12 +18,8 @@ def test_log_kwargs() -> None:
recorded_logger.debug(
LazyFormat("Found candidates.", matches=[1, 2, 3], parameters={"field_0": "value_0", "field_1": "value_1"})
)
assert handler.get_last_message() == mf_dedent(
"""
Found candidates.
matches: [1, 2, 3]
parameters: {'field_0': 'value_0', 'field_1': 'value_1'}
"""
assert handler.get_last_message() == (
"Found candidates. (matches=[1, 2, 3], parameters={'field_0': 'value_0', 'field_1': 'value_1'})"
)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@


def test_pformat_many() -> None: # noqa: D103
result = mf_pformat_dict("Example description:", obj_dict={"object_0": (1, 2, 3), "object_1": {4: 5}})
result = mf_pformat_dict(
"Example description:", obj_dict={"object_0": (1, 2, 3), "object_1": {4: 5}}, max_line_length=30
)

assert (
textwrap.dedent(
Expand All @@ -25,7 +27,9 @@ def test_pformat_many() -> None: # noqa: D103


def test_pformat_many_with_raw_strings() -> None: # noqa: D103
result = mf_pformat_dict("Example description:", obj_dict={"object_0": "foo\nbar"}, preserve_raw_strings=True)
result = mf_pformat_dict(
"Example description:", obj_dict={"object_0": "foo\nbar"}, preserve_raw_strings=True, max_line_length=30
)

assert (
textwrap.dedent(
Expand All @@ -42,7 +46,7 @@ def test_pformat_many_with_raw_strings() -> None: # noqa: D103

def test_pformat_dict_with_empty_message() -> None:
"""Test `mf_pformat_dict` without a description."""
result = mf_pformat_dict(obj_dict={"object_0": (1, 2, 3), "object_1": {4: 5}})
result = mf_pformat_dict(obj_dict={"object_0": (1, 2, 3), "object_1": {4: 5}}, max_line_length=30)

assert (
mf_dedent(
Expand All @@ -57,7 +61,9 @@ def test_pformat_dict_with_empty_message() -> None:

def test_pformat_dict_with_pad_sections_with_newline() -> None:
"""Test `mf_pformat_dict` with new lines between sections."""
result = mf_pformat_dict(obj_dict={"object_0": (1, 2, 3), "object_1": {4: 5}}, pad_items_with_newlines=True)
result = mf_pformat_dict(
obj_dict={"object_0": (1, 2, 3), "object_1": {4: 5}}, pad_items_with_newlines=True, max_line_length=30
)

assert (
mf_dedent(
Expand All @@ -72,7 +78,7 @@ def test_pformat_dict_with_pad_sections_with_newline() -> None:


def test_pformat_many_with_strings() -> None: # noqa: D103
result = mf_pformat_dict("Example description:", obj_dict={"object_0": "foo\nbar"})
result = mf_pformat_dict("Example description:", obj_dict={"object_0": "foo\nbar"}, max_line_length=30)
assert (
textwrap.dedent(
"""\
Expand All @@ -92,3 +98,8 @@ def test_minimal_length() -> None:
foo: 'bar'
"""
)


def test_one_line() -> None:
"""Test formatting as a one-line string if possible."""
assert mf_pformat_dict("Example output", {"a": 1, "b": 2}, max_line_length=80) == "Example output (a=1, b=2)"

0 comments on commit d7d8be9

Please sign in to comment.