import math import re from typing import Optional __all__ = ["abbreviate", "leading", "pluralize", "re_find_all", "re_replace_with_list", "get_edu_year_name"] def abbreviate(text: str, max_length: int) -> str: """Abbreviate a string to a maximum length If the string is longer, add an ellipsis (...) at the end """ if len(text) <= max_length: return text # Strip to avoid ending on random double newlines return text[: max_length - 1].strip() + "…" def leading(character: str, string: str, target_length: Optional[int] = 2) -> str: """Add a leading [character] to [string] to make it length [target_length] Pass None to target length to always do it (once), no matter the length """ # Cast to string just in case string = str(string) # Add no matter what if target_length is None: return character + string # String is already long enough if len(string) >= target_length: return string frequency = math.ceil((target_length - len(string)) / len(character)) return (frequency * character) + string def pluralize(word: str, amount: int, plural_form: Optional[str] = None) -> str: """Turn a word into plural""" if amount == 1: return word return plural_form or (word + "s") def re_find_all(pattern: str, string: str, flags: re.RegexFlag = 0) -> list[str]: """Find all matches of a regex in a string""" matches = [] while True: match = re.search(pattern, string, flags=flags) if not match: break matches.append(match.group(0)) string = string[match.end() :] return matches def re_replace_with_list(pattern: str, string: str, replacements: list[str]) -> str: """Replace all matches of a pattern one by one using a list of replacements""" for replacement in replacements: string = re.sub(pattern, replacement, string, count=1) return string def get_edu_year_name(year: int) -> str: # pragma: no cover """Get the string representation of a university year""" years = ["1st Bachelor", "2nd Bachelor", "3rd Bachelor", "1st Master", "2nd Master"] return years[year]