Skip to content
68 changes: 68 additions & 0 deletions src/briefcase/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import textwrap


def format_message_to_asterisk_box(
message: str,
title: str = "",
width=80,
border_char="*",
padding=2,
) -> str:
"""Format a message to an asterisk box.

Args:
message (str): The message to format.
title (str, optional): The title of the box. Defaults to None.
width (int, optional): The width of the box. Defaults to 80.
border_char (str, optional): The character to use for the border.
Defaults to "*".
padding (int, optional): The number of spaces to pad the border.
Defaults to 2.

Returns:
str: The formatted message.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use the Sphinx docstring format; check any other source file for examples of use.

Copy link
Author

@otekraden otekraden Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it!
I applied this format.

"""

if not message:
return ""

# Create border line
border_line = border_char * width
# create lines array with opening line of the box
lines = [border_line]

# if title exists, format title in the box
if title:
# Wrap the title to lines to fit the width of the box
wrapped_title_lines = textwrap.wrap(
title.strip(),
width=width - (padding * 2) - 4,
)

# width of title line inside the box
inner_width = width - (padding * 2)

for line in wrapped_title_lines:
# Center each line within the available space
padded_line = line.center(inner_width)
# add line to the box
lines.append(f"**{padded_line}**")

# closing line of title in the box
lines.append(border_line)

# split the message into paragraphs
paragraphs = message.split("\n")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably use textwrap.dedent() here as a convenience as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but in my current understanding of the logic of my function, I don't see how to use the textwrap.dedent() method. Could you please show me how to integrate it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I'm suggesting is that being able to call:

        console.warning_banner(
            "Some banner title"
            """\
                This is the content that I want to display. It is long
                but I don't want to have to manually word wrap\n
                \n
                But manual line breaks should be preserved.
            """
        )

We could do this by requiring the user to wrap the """ string in textwrap.dedent()... or we could do that automatically on every usage.

for paragraph in paragraphs:
if paragraph.strip(): # Non-empty paragraph
# Wrap paragraph to lines to fit the width of the box
wrapped_lines = textwrap.wrap(paragraph, width=width)
lines.extend(wrapped_lines)
else: # Empty paragraph (preserve blank lines)
lines.append("")

# closing line of message
lines.append(border_line)

# merge lines into a single string and return
return "\n".join(lines)
83 changes: 83 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
from briefcase.utils import format_message_to_asterisk_box

name = "Anton"
issue_idx = 2559

source_msg = (
f"Hi there! My name is {name}, and I'm a Python developer.\n\n"
"This is my very first experience in open source development. "
"I like your project, and I'm excited to contribute to it."
)
source_title = (
f"INFO: I TRIED TO SOLVE THIS ISSUE #{issue_idx}. "
"IT SEEMED TO ME RATHER SIMPLE, "
"BUT I GOT VERY GOOD EXPERIENCE"
)


def test_format_message_to_asterisk_box_empty_string_title():
# Test with empty message and title
msg = format_message_to_asterisk_box("")

assert msg == ""


def test_format_message_to_asterisk_box_width_80_default():
# Test with width 80: default
msg = format_message_to_asterisk_box(
source_msg,
title=source_title,
)
output_msg_width_80_default = (
"*" * 79
+ """*
** INFO: I TRIED TO SOLVE THIS ISSUE #2559. IT SEEMED TO ME RATHER SIMPLE, **
** BUT I GOT VERY GOOD EXPERIENCE **
********************************************************************************
Hi there! My name is Anton, and I'm a Python developer.

This is my very first experience in open source development. I like your
project, and I'm excited to contribute to it.
********************************************************************************"""
)
assert msg == output_msg_width_80_default


def test_format_message_to_asterisk_box_width_40_default():
# Test with width 40: very narrow
msg = format_message_to_asterisk_box(
source_msg,
title=source_title,
width=40,
)
output_msg_width_40 = """****************************************
** INFO: I TRIED TO SOLVE THIS **
** ISSUE #2559. IT SEEMED TO ME **
** RATHER SIMPLE, BUT I GOT VERY **
** GOOD EXPERIENCE **
****************************************
Hi there! My name is Anton, and I'm a
Python developer.

This is my very first experience in open
source development. I like your project,
and I'm excited to contribute to it.
****************************************"""
assert msg == output_msg_width_40


def test_format_message_to_asterisk_box_empty_title():
# Test with width 80: default
msg = format_message_to_asterisk_box(
source_msg,
)
output_msg_width_80_default = (
"*" * 79
+ """*
Hi there! My name is Anton, and I'm a Python developer.

This is my very first experience in open source development. I like your
project, and I'm excited to contribute to it.
********************************************************************************"""
)
assert msg == output_msg_width_80_default
Loading