Skip to content

Formatting

coola.formatting

Contain functions that turn values into text for messages, repr and reports.

The package exports nothing: import a function from its module.

  • coola.formatting.structure: str_* and repr_* of sequences and mappings, and indentation.
  • coola.formatting.quantity: human-readable byte sizes and durations, and make_bar.
  • coola.formatting.text: count_lines, remove_empty_lines, slugify, truncate_str and char_diff_summary.
  • coola.formatting.secret: mask_secret.
  • coola.formatting.diff: unified_diff.

The functions are pure: the same input gives the same string.

coola.formatting.diff

Provide utilities to display differences between two texts.

coola.formatting.diff.unified_diff

unified_diff(
    text_a: str,
    text_b: str,
    label_a: str = "previous",
    label_b: str = "latest",
    context_lines: int = 3,
) -> str

Compute a unified diff between two texts, similar to git diff.

Parameters:

Name Type Description Default
text_a str

The original text (baseline).

required
text_b str

The updated text to compare against text_a.

required
label_a str

Label shown in the diff header for text_a. Defaults to "previous".

'previous'
label_b str

Label shown in the diff header for text_b. Defaults to "latest".

'latest'
context_lines int

Number of unchanged lines to show around each change for context. Must be non-negative. Defaults to 3.

3

Returns:

Type Description
str

A unified diff string, or an empty string if the two texts are

str

identical. A last line without a trailing newline is followed

str

by \\ No newline at end of file, as in git diff.

Raises:

Type Description
ValueError

If context_lines is negative.

Example
>>> from coola.formatting.diff import unified_diff
>>> print(unified_diff("hello\nworld\n", "hello\nearth\n"))
--- previous
+++ latest
@@ -1,2 +1,2 @@
 hello
-world
+earth
<BLANKLINE>

coola.formatting.quantity

Implement some utility functions to compute string representations of quantities (byte sizes, durations, ratios).

coola.formatting.quantity.find_best_byte_unit

find_best_byte_unit(size: int) -> str

Return the best byte unit given the byte size.

Parameters:

Name Type Description Default
size int

The size in bytes.

required

Returns:

Type Description
str

The best unit. The supported units are: 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB'.

Raises:

Type Description
ValueError

if size is negative.

Example
>>> from coola.formatting.quantity import find_best_byte_unit
>>> find_best_byte_unit(2)
'B'
>>> find_best_byte_unit(2048)
'KB'
>>> find_best_byte_unit(2097152)
'MB'

coola.formatting.quantity.make_bar

make_bar(value: float, length: int = 10) -> str

Create a progress bar string for a given value between 0 and 1.

Parameters:

Name Type Description Default
value float

A float between 0 and 1 representing the metric value.

required
length int

The length of the progress bar. Must be a positive integer.

10

Returns:

Type Description
str

A string representing the progress bar.

Raises:

Type Description
ValueError

If value is not in [0, 1], or length is not positive.

Example
>>> from coola.formatting.quantity import make_bar
>>> make_bar(0.6)
'[██████░░░░]'
>>> make_bar(0.1)
'[█░░░░░░░░░]'
>>> make_bar(1.0)
'[██████████]'
>>> make_bar(0.0)
'[░░░░░░░░░░]'

coola.formatting.quantity.str_human_byte_size

str_human_byte_size(
    size: int, unit: str | None = None
) -> str

Get a human-readable representation of the byte size.

Parameters:

Name Type Description Default
size int

The size in bytes.

required
unit str | None

The unit to use to show the byte size. If None, the best unit is found automatically. The supported units are: 'B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB' (units of 1024 bytes).

None

Returns:

Type Description
str

The byte size in a human-readable format.

Raises:

Type Description
ValueError

if size is negative or unit is not supported.

Example
>>> from coola.formatting.quantity import str_human_byte_size
>>> str_human_byte_size(2)
'2.00 B'
>>> str_human_byte_size(2048)
'2.00 KB'
>>> str_human_byte_size(2097152)
'2.00 MB'
>>> str_human_byte_size(2048, unit="B")
'2,048.00 B'
>>> str_human_byte_size(2**50)
'1.00 PB'

coola.formatting.quantity.str_time_human

str_time_human(seconds: float) -> str

Return a number of seconds in an easier format to read hh:mm:ss.

If the number of seconds is bigger than 1 day, this representation also encodes the number of days.

Parameters:

Name Type Description Default
seconds float

The number of seconds.

required

Returns:

Type Description
str

The number of seconds in a string format (hh:mm:ss). A negative duration is prefixed with -.

Raises:

Type Description
ValueError

if seconds is not finite or too large.

Example
>>> from coola.formatting.quantity import str_time_human
>>> str_time_human(1.2)
'0:00:01.200000'
>>> str_time_human(61.2)
'0:01:01.200000'
>>> str_time_human(3661.2)
'1:01:01.200000'
>>> str_time_human(-5)
'-0:00:05'

coola.formatting.secret

Define utility functions for secrets.

coola.formatting.secret.mask_secret

mask_secret(
    secret: str, show_first: int = 3, show_last: int = 4
) -> str

Mask the content of the secret with *.

Note

This is for display/logging only, not encryption: the shown characters are leaked, and the length of the secret is preserved.

Parameters:

Name Type Description Default
secret str

The secret to mask.

required
show_first int

The number of first values to show.

3
show_last int

The number of last values to show.

4

Returns:

Type Description
str

The masked secret.

Raises:

Type Description
ValueError

If show_first or show_last is negative.

Example
>>> from coola.formatting.secret import mask_secret
>>> secret = "abcdefghijklmnopqrstuvwxyz"
>>> mask_secret(secret)
'abc*******************wxyz'
>>> mask_secret(secret, show_first=0)
'**********************wxyz'
>>> mask_secret(secret, show_last=0)
'abc***********************'
>>> mask_secret(secret, show_first=0, show_last=0)
'**************************'

coola.formatting.structure

Implement some utility functions to compute string representations of sequences and mappings.

coola.formatting.structure.repr_indent

repr_indent(
    original: object, *, num_spaces: int = 2
) -> str

Add indentations if the original string is a multi-lines string.

Parameters:

Name Type Description Default
original object

The original string. If the input is not a string, it will be converted to a string with the function repr.

required
num_spaces int

The number of spaces used for the indentation.

2

Returns:

Type Description
str

The indented string.

Raises:

Type Description
ValueError

if num_spaces is negative.

Example
>>> from coola.formatting.structure import repr_indent
>>> print(repr_indent("string1\nstring2\n  string3", num_spaces=4))
string1
    string2
      string3

coola.formatting.structure.repr_mapping

repr_mapping(
    mapping: Mapping[Any, Any],
    *,
    sorted_keys: bool = False,
    num_spaces: int = 2,
) -> str

Compute a string representation of a mapping.

This function was designed for flat dictionary. If you have a nested dictionary, you may consider other functions. Note that this function works for nested dict but the output may not be nice.

Parameters:

Name Type Description Default
mapping Mapping[Any, Any]

The mapping.

required
sorted_keys bool

If True, the keys in the mapping are sorted before to compute the string representation.

False
num_spaces int

The number of spaces used for the indentation.

2

Returns:

Type Description
str

The string representation of the mapping.

Example
>>> from coola.formatting.structure import repr_mapping
>>> print(repr_mapping({"key1": "abc", "key2": "something\nelse"}))
(key1): abc
(key2): something
  else

coola.formatting.structure.repr_mapping_line

repr_mapping_line(
    mapping: Mapping[Any, Any],
    *,
    sorted_keys: bool = False,
    separator: str = ", ",
) -> str

Compute a single line string representation of the given mapping.

This function is designed for flat dictionary. If you have a nested dictionary, you may consider other functions. Note that this function works for nested dict but the output may not be nice.

Parameters:

Name Type Description Default
mapping Mapping[Any, Any]

The mapping.

required
sorted_keys bool

If True, the keys in the mapping are sorted before to compute the string representation.

False
separator str

The separator to use between each key-value pair.

', '

Returns:

Type Description
str

The string representation of the mapping.

Example
>>> from coola.formatting.structure import repr_mapping_line
>>> print(repr_mapping_line({"key1": "abc", "key2": "meow", "key3": 42}))
key1='abc', key2='meow', key3=42

coola.formatting.structure.repr_sequence

repr_sequence(
    sequence: Sequence[Any], *, num_spaces: int = 2
) -> str

Compute a string representation of a sequence.

Parameters:

Name Type Description Default
sequence Sequence[Any]

The sequence.

required
num_spaces int

The number of spaces used for the indentation.

2

Returns:

Type Description
str

The string representation of the sequence.

Example
>>> from coola.formatting.structure import repr_indent
>>> print(repr_sequence(["abc", "something\nelse"]))
(0): abc
(1): something
  else

coola.formatting.structure.repr_sequence_line

repr_sequence_line(
    sequence: Sequence[Any], *, separator: str = ", "
) -> str

Compute a single line string representation of a sequence.

Parameters:

Name Type Description Default
sequence Sequence[Any]

The sequence.

required
separator str

The separator to use between each item.

', '

Returns:

Type Description
str

The string representation of the sequence.

Example
>>> from coola.formatting.structure import repr_sequence_line
>>> print(repr_sequence_line(["abc", "meow", 42]))
'abc', 'meow', 42

coola.formatting.structure.str_indent

str_indent(original: object, *, num_spaces: int = 2) -> str

Add indentations if the original string is a multi-lines string.

Parameters:

Name Type Description Default
original object

The original string. If the input is not a string, it will be converted to a string with the function str.

required
num_spaces int

The number of spaces used for the indentation.

2

Returns:

Type Description
str

The indented string.

Raises:

Type Description
ValueError

if num_spaces is negative.

Example
>>> from coola.formatting.structure import str_indent
>>> print(str_indent("string1\nstring2\n  string3", num_spaces=4))
string1
    string2
      string3

coola.formatting.structure.str_mapping

str_mapping(
    mapping: Mapping[Any, Any],
    *,
    sorted_keys: bool = False,
    num_spaces: int = 2,
) -> str

Compute a string representation of a mapping.

This function was designed for flat dictionary. If you have a nested dictionary, you may consider other functions. Note that this function works for nested dict but the output may not be nice.

Parameters:

Name Type Description Default
mapping Mapping[Any, Any]

The mapping.

required
sorted_keys bool

If True, the keys in the mapping are sorted before to compute the string representation.

False
num_spaces int

The number of spaces used for the indentation.

2

Returns:

Type Description
str

The string representation of the mapping.

Example
>>> from coola.formatting.structure import str_mapping
>>> print(str_mapping({"key1": "abc", "key2": "something\nelse"}))
(key1): abc
(key2): something
  else

coola.formatting.structure.str_mapping_line

str_mapping_line(
    mapping: Mapping[Any, Any],
    *,
    sorted_keys: bool = False,
    separator: str = ", ",
) -> str

Compute a single line string representation of the given mapping.

This function is designed for flat dictionary. If you have a nested dictionary, you may consider other functions. Note that this function works for nested dict but the output may not be nice.

Parameters:

Name Type Description Default
mapping Mapping[Any, Any]

The mapping.

required
sorted_keys bool

If True, the keys in the mapping are sorted before to compute the string representation.

False
separator str

The separator to use between each key-value pair.

', '

Returns:

Type Description
str

The string representation of the mapping.

Example
>>> from coola.formatting.structure import str_mapping_line
>>> print(str_mapping_line({"key1": "abc", "key2": "meow", "key3": 42}))
key1=abc, key2=meow, key3=42

coola.formatting.structure.str_sequence

str_sequence(
    sequence: Sequence[Any], *, num_spaces: int = 2
) -> str

Compute a string representation of a sequence.

Parameters:

Name Type Description Default
sequence Sequence[Any]

The sequence.

required
num_spaces int

The number of spaces used for the indentation.

2

Returns:

Type Description
str

The string representation of the sequence.

Example
>>> from coola.formatting.structure import str_sequence
>>> print(str_sequence(["abc", "something\nelse"]))
(0): abc
(1): something
  else

coola.formatting.structure.str_sequence_line

str_sequence_line(
    sequence: Sequence[Any], *, separator: str = ", "
) -> str

Compute a single line string representation of a sequence.

Parameters:

Name Type Description Default
sequence Sequence[Any]

The sequence.

required
separator str

The separator to use between each item.

', '

Returns:

Type Description
str

The string representation of the sequence.

Example
>>> from coola.formatting.structure import str_sequence_line
>>> print(str_sequence_line(["abc", "meow", 42]))
abc, meow, 42

coola.formatting.text

Contain utility functions to process strings.

coola.formatting.text.char_diff_summary

char_diff_summary(before: str, after: str) -> str

Compute a human-readable character count difference string.

Returns a formatted string describing the character counts before and after a text transformation, including the signed difference and percentage change relative to the original length.

The sign of the diff reflects whether the transformation grew or shrank the text: negative means fewer characters, positive means more. Handles empty input gracefully: the percentage is 0.0% if both texts are empty, and n/a if the text grew from an empty text (the change relative to zero is undefined).

Parameters:

Name Type Description Default
before str

The text before transformation.

required
after str

The text after transformation.

required

Returns:

Type Description
str

A formatted string with the character count difference.

Example
>>> from coola.formatting.text import char_diff_summary
>>> char_diff_summary("<p>Hello</p>", "Hello")
'12 -> 5 chars (-7 chars, -58.3%).'
>>> char_diff_summary("", "abc")
'0 -> 3 chars (+3 chars, n/a).'

coola.formatting.text.count_lines

count_lines(text: str) -> int

Count the number of lines in a string.

Parameters:

Name Type Description Default
text str

The input string to count lines in.

required

Returns:

Type Description
int

The number of lines in the input string.

Example
>>> from coola.formatting.text import count_lines
>>> count_lines("Hello\nWorld")
2
>>> count_lines("Hello\nWorld\nFoo")
3

coola.formatting.text.remove_empty_lines

remove_empty_lines(text: str) -> str

Remove empty lines from a string.

Parameters:

Name Type Description Default
text str

The input string from which empty lines will be removed.

required

Returns:

Type Description
str

A new string with all empty or whitespace-only lines removed.

Example
>>> from coola.formatting.text import remove_empty_lines
>>> remove_empty_lines("Hello\n\nWorld\n\n\nFoo")
'Hello\nWorld\nFoo'
>>> remove_empty_lines("\n\nOnly empty lines\n\n")
'Only empty lines'

coola.formatting.text.slugify

slugify(text: str) -> str

Convert arbitrary text into a URL/filesystem-safe slug.

Lowercases the text, strips accents, replaces any run of characters that aren't alphanumerics with a single hyphen, and trims leading or trailing hyphens. Works on any string -- titles, names, tags, filenames, model names, etc. -- not just a specific kind of text.

Parameters:

Name Type Description Default
text str

The raw text to slugify (e.g. an article title, a tag, a file name, or a model name).

required

Returns:

Type Description
str

A lowercase, hyphen-separated slug safe to use as a filename, URL path segment, or dict key. If the text has letters, digits or other non-ASCII characters (e.g. an emoji) but none can be written in ASCII (e.g. "日本語"), the slug is a short hash of the text instead of an empty string. Text that only has whitespace and ASCII punctuation gives an empty string.

Example
>>> from coola.formatting.text import slugify
>>> slugify("Hello, World!")
'hello-world'
>>> slugify("Claude Sonnet 4.6")
'claude-sonnet-4-6'
>>> slugify("meta-llama/Llama-3.1-8B-Instruct")
'meta-llama-llama-3-1-8b-instruct'
>>> slugify("  Café con Leche  ")
'cafe-con-leche'

coola.formatting.text.truncate_str

truncate_str(
    s: str, max_len: int = 100, suffix: str = "..."
) -> str

Return a truncated string if the string exceeds the maximum length.

Parameters:

Name Type Description Default
s str

The string to truncate.

required
max_len int

The maximum number of characters. Must be greater than or equal to the length of suffix.

100
suffix str

The suffix to append when truncation occurs. Defaults to "...".

'...'

Returns:

Type Description
str

The original string if it is within max_len characters, otherwise a truncated string ending with suffix.

Raises:

Type Description
ValueError

If max_len is less than the length of suffix.

Example
>>> from coola.formatting.text import truncate_str
>>> truncate_str("hello world")
'hello world'
>>> truncate_str("hello world", max_len=8)
'hello...'
>>> truncate_str("hello world", max_len=8, suffix="…")
'hello w…'