Skip to content

Commit d7d8be9

Browse files
authored
Allow for a one-line representation in mf_pformat_dict() (#1667)
This PR enables small objects with a short string representation to be formatted on one line.
1 parent d91ef7e commit d7d8be9

File tree

3 files changed

+53
-15
lines changed

3 files changed

+53
-15
lines changed

metricflow-semantics/metricflow_semantics/mf_logging/pretty_print.py

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pprint
55
from dataclasses import fields, is_dataclass
66
from enum import Enum
7-
from typing import Any, List, Mapping, Optional, Sized, Tuple, Union
7+
from typing import Any, Dict, List, Mapping, Optional, Sized, Tuple, Union
88

99
from metricflow_semantics.mf_logging.formatting import indent
1010
from metricflow_semantics.mf_logging.pretty_formattable import MetricFlowPrettyFormattable
@@ -454,6 +454,8 @@ def mf_pformat_dict( # type: ignore
454454
description_lines: List[str] = [description] if description is not None else []
455455
obj_dict = obj_dict or {}
456456
item_sections = []
457+
458+
str_converted_dict: Dict[str, str] = {}
457459
for key, value in obj_dict.items():
458460
if preserve_raw_strings and isinstance(value, str):
459461
value_str = value
@@ -466,10 +468,10 @@ def mf_pformat_dict( # type: ignore
466468
include_none_object_fields=include_none_object_fields,
467469
include_empty_object_fields=include_empty_object_fields,
468470
)
471+
str_converted_dict[str(key)] = value_str
469472

470-
lines_in_value_str = len(value_str.split("\n"))
471473
item_section_lines: Tuple[str, ...]
472-
if lines_in_value_str > 1:
474+
if "\n" in value_str:
473475
item_section_lines = (
474476
f"{key}:",
475477
indent(
@@ -486,7 +488,37 @@ def mf_pformat_dict( # type: ignore
486488
else:
487489
item_sections.append(indent(item_section))
488490

491+
result_as_one_line = _as_one_line(
492+
description=description, str_converted_dict=str_converted_dict, max_line_length=max_line_length
493+
)
494+
if result_as_one_line is not None:
495+
return result_as_one_line
496+
489497
if pad_items_with_newlines:
490498
return "\n\n".join(description_lines + item_sections)
491499
else:
492500
return "\n".join(description_lines + item_sections)
501+
502+
503+
def _as_one_line(description: Optional[str], str_converted_dict: Dict[str, str], max_line_length: int) -> Optional[str]:
504+
"""See if the result can be returned in a compact, one-line representation.
505+
506+
e.g. for:
507+
mf_pformat_dict("Example output", {"a": 1, "b": 2})
508+
509+
Compact output:
510+
Example output (a=1, b=2)
511+
512+
Normal output:
513+
Example output
514+
a: 1
515+
b: 2
516+
"""
517+
items = tuple(f"{key_str}={value_str}" for key_str, value_str in str_converted_dict.items())
518+
value_in_parenthesis = ", ".join(items)
519+
result = f"{description}" + (f" ({value_in_parenthesis})" if len(value_in_parenthesis) > 0 else "")
520+
521+
if "\n" in result or len(result) > max_line_length:
522+
return None
523+
524+
return result

metricflow-semantics/tests_metricflow_semantics/mf_logging/test_lazy_format.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import logging
44

5-
from metricflow_semantics.formatting.formatting_helpers import mf_dedent
65
from metricflow_semantics.mf_logging.lazy_formattable import LazyFormat
76
from typing_extensions import override
87

@@ -19,12 +18,8 @@ def test_log_kwargs() -> None:
1918
recorded_logger.debug(
2019
LazyFormat("Found candidates.", matches=[1, 2, 3], parameters={"field_0": "value_0", "field_1": "value_1"})
2120
)
22-
assert handler.get_last_message() == mf_dedent(
23-
"""
24-
Found candidates.
25-
matches: [1, 2, 3]
26-
parameters: {'field_0': 'value_0', 'field_1': 'value_1'}
27-
"""
21+
assert handler.get_last_message() == (
22+
"Found candidates. (matches=[1, 2, 3], parameters={'field_0': 'value_0', 'field_1': 'value_1'})"
2823
)
2924

3025

metricflow-semantics/tests_metricflow_semantics/mf_logging/test_pformat_dict.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010

1111

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

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

2628

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

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

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

4751
assert (
4852
mf_dedent(
@@ -57,7 +61,9 @@ def test_pformat_dict_with_empty_message() -> None:
5761

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

6268
assert (
6369
mf_dedent(
@@ -72,7 +78,7 @@ def test_pformat_dict_with_pad_sections_with_newline() -> None:
7278

7379

7480
def test_pformat_many_with_strings() -> None: # noqa: D103
75-
result = mf_pformat_dict("Example description:", obj_dict={"object_0": "foo\nbar"})
81+
result = mf_pformat_dict("Example description:", obj_dict={"object_0": "foo\nbar"}, max_line_length=30)
7682
assert (
7783
textwrap.dedent(
7884
"""\
@@ -92,3 +98,8 @@ def test_minimal_length() -> None:
9298
foo: 'bar'
9399
"""
94100
)
101+
102+
103+
def test_one_line() -> None:
104+
"""Test formatting as a one-line string if possible."""
105+
assert mf_pformat_dict("Example output", {"a": 1, "b": 2}, max_line_length=80) == "Example output (a=1, b=2)"

0 commit comments

Comments
 (0)