Skip to content

String Tools

Functions for manipulating strings.


condense_str

condense_str(
    value,
    max_length,
    delimiter="-",
    hash_length=DEFAULT_CONDENSE_HASH_LENGTH,
)

Shorten a string to a maximum length while keeping it unique and readable.

For names that must fit a downstream length limit -- generated AWS resource names being the motivating case -- where plain truncation would risk collisions.

A value that already fits is returned unchanged. That matters: condensing has to be a no-op for names already within budget, or adopting this helper somewhere would silently rename every existing resource.

A value that does not fit keeps as much of its readable prefix as possible and is suffixed with delimiter plus a hash of the whole original value. Hashing the original rather than the discarded tail means two values sharing a long common prefix still condense to different results.

The result is deterministic: the same input always condenses to the same output. Callers depend on that -- a name that changed between runs would, for example, register a new AWS Batch job definition revision every time.

Parameters:

Name Type Description Default
value str

The string to condense.

required
max_length int

Maximum length of the result. Must leave room for the hash suffix plus at least one character of prefix.

required
delimiter str

Separator placed between the truncated prefix and the hash suffix.

'-'
hash_length int

Number of hex characters of hash to append.

DEFAULT_CONDENSE_HASH_LENGTH

Returns:

Type Description
str

value if it already fits within max_length, otherwise

str

<prefix><delimiter><hash>, of exactly max_length characters.

Raises:

Type Description
ValueError

If hash_length is not positive, or if max_length is too small to fit the suffix plus at least one prefix character. Truncating without a hash would silently invite collisions, so this is an error rather than a quiet fallback.

Examples:

>>> condense_str("short-name", max_length=24)
'short-name'
>>> condense_str("a" * 40, max_length=24)
'aaaaaaaaaaaaaaa-e4bcc900'
Source code in src/aibs_informatics_core/utils/tools/strtools.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
def condense_str(
    value: str,
    max_length: int,
    delimiter: str = "-",
    hash_length: int = DEFAULT_CONDENSE_HASH_LENGTH,
) -> str:
    """Shorten a string to a maximum length while keeping it unique and readable.

    For names that must fit a downstream length limit -- generated AWS resource names
    being the motivating case -- where plain truncation would risk collisions.

    A value that already fits is returned **unchanged**. That matters: condensing has
    to be a no-op for names already within budget, or adopting this helper somewhere
    would silently rename every existing resource.

    A value that does not fit keeps as much of its readable prefix as possible and is
    suffixed with ``delimiter`` plus a hash of the **whole original value**. Hashing
    the original rather than the discarded tail means two values sharing a long common
    prefix still condense to different results.

    The result is deterministic: the same input always condenses to the same output.
    Callers depend on that -- a name that changed between runs would, for example,
    register a new AWS Batch job definition revision every time.

    Args:
        value: The string to condense.
        max_length: Maximum length of the result. Must leave room for the hash suffix
            plus at least one character of prefix.
        delimiter: Separator placed between the truncated prefix and the hash suffix.
        hash_length: Number of hex characters of hash to append.

    Returns:
        ``value`` if it already fits within ``max_length``, otherwise
        ``<prefix><delimiter><hash>``, of exactly ``max_length`` characters.

    Raises:
        ValueError: If ``hash_length`` is not positive, or if ``max_length`` is too
            small to fit the suffix plus at least one prefix character. Truncating
            without a hash would silently invite collisions, so this is an error
            rather than a quiet fallback.

    Examples:
        >>> condense_str("short-name", max_length=24)
        'short-name'
        >>> condense_str("a" * 40, max_length=24)
        'aaaaaaaaaaaaaaa-e4bcc900'
    """
    if hash_length <= 0:
        raise ValueError(f"hash_length must be positive, got {hash_length}")

    if len(value) <= max_length:
        return value

    suffix_length = len(delimiter) + hash_length
    if max_length <= suffix_length:
        raise ValueError(
            f"Cannot condense to max_length={max_length}: the {suffix_length} character "
            f"suffix (delimiter {delimiter!r} + {hash_length} hash chars) leaves no room "
            f"for a prefix. Raise max_length or lower hash_length."
        )

    prefix = value[: max_length - suffix_length]
    return f"{prefix}{delimiter}{sha256_hexdigest(value)[:hash_length]}"

is_prefixed

is_prefixed(value, prefix)

Check whether a string starts with the given prefix.

Parameters:

Name Type Description Default
value str

The string to check.

required
prefix str

The prefix to look for.

required

Returns:

Type Description
bool

True if value starts with prefix.

Source code in src/aibs_informatics_core/utils/tools/strtools.py
89
90
91
92
93
94
95
96
97
98
99
def is_prefixed(value: str, prefix: str) -> bool:
    """Check whether a string starts with the given prefix.

    Args:
        value: The string to check.
        prefix: The prefix to look for.

    Returns:
        True if ``value`` starts with ``prefix``.
    """
    return value.startswith(prefix)

is_suffixed

is_suffixed(value, suffix)

Check whether a string ends with the given suffix.

Parameters:

Name Type Description Default
value str

The string to check.

required
suffix str

The suffix to look for.

required

Returns:

Type Description
bool

True if value ends with suffix.

Source code in src/aibs_informatics_core/utils/tools/strtools.py
102
103
104
105
106
107
108
109
110
111
112
def is_suffixed(value: str, suffix: str) -> bool:
    """Check whether a string ends with the given suffix.

    Args:
        value: The string to check.
        suffix: The suffix to look for.

    Returns:
        True if ``value`` ends with ``suffix``.
    """
    return value.endswith(suffix)

lowercase

lowercase(value)

Convert a string to lowercase.

Parameters:

Name Type Description Default
value str

The string to convert.

required

Returns:

Type Description
str

The lowercased string.

Source code in src/aibs_informatics_core/utils/tools/strtools.py
147
148
149
150
151
152
153
154
155
156
def lowercase(value: str) -> str:
    """Convert a string to lowercase.

    Args:
        value: The string to convert.

    Returns:
        The lowercased string.
    """
    return value.lower()

removeprefix

removeprefix(value, prefix)

Remove the given prefix from the beginning of a string.

Parameters:

Name Type Description Default
value str

The original string.

required
prefix str

The prefix to remove.

required

Returns:

Type Description
str

The string with the prefix removed, or the original string if not prefixed.

Source code in src/aibs_informatics_core/utils/tools/strtools.py
115
116
117
118
119
120
121
122
123
124
125
def removeprefix(value: str, prefix: str) -> str:
    """Remove the given prefix from the beginning of a string.

    Args:
        value: The original string.
        prefix: The prefix to remove.

    Returns:
        The string with the prefix removed, or the original string if not prefixed.
    """
    return value.removeprefix(prefix)

removesuffix

removesuffix(value, suffix)

Remove the given suffix from the end of a string.

Parameters:

Name Type Description Default
value str

The original string.

required
suffix str

The suffix to remove.

required

Returns:

Type Description
str

The string with the suffix removed, or the original string if not suffixed.

Source code in src/aibs_informatics_core/utils/tools/strtools.py
128
129
130
131
132
133
134
135
136
137
138
def removesuffix(value: str, suffix: str) -> str:
    """Remove the given suffix from the end of a string.

    Args:
        value: The original string.
        suffix: The suffix to remove.

    Returns:
        The string with the suffix removed, or the original string if not suffixed.
    """
    return value.removesuffix(suffix)

uppercase

uppercase(value)

Convert a string to uppercase.

Parameters:

Name Type Description Default
value str

The string to convert.

required

Returns:

Type Description
str

The uppercased string.

Source code in src/aibs_informatics_core/utils/tools/strtools.py
159
160
161
162
163
164
165
166
167
168
def uppercase(value: str) -> str:
    """Convert a string to uppercase.

    Args:
        value: The string to convert.

    Returns:
        The uppercased string.
    """
    return value.upper()