2022-07-01 15:46:56 +02:00
|
|
|
import math
|
2022-11-21 22:46:19 +01:00
|
|
|
import random
|
2022-09-19 15:59:12 +02:00
|
|
|
import re
|
2022-09-19 18:15:10 +02:00
|
|
|
from typing import Optional, Union
|
2022-06-21 18:44:47 +02:00
|
|
|
|
2022-11-21 22:46:19 +01:00
|
|
|
__all__ = ["abbreviate", "leading", "mock", "pluralize", "re_find_all", "re_replace_with_list", "get_edu_year_name"]
|
2022-07-14 20:28:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
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() + "…"
|
2022-07-11 22:23:38 +02:00
|
|
|
|
2022-06-21 18:44:47 +02:00
|
|
|
|
|
|
|
def leading(character: str, string: str, target_length: Optional[int] = 2) -> str:
|
|
|
|
"""Add a leading [character] to [string] to make it length [target_length]
|
2022-07-13 22:54:16 +02:00
|
|
|
|
2022-07-01 15:46:56 +02:00
|
|
|
Pass None to target length to always do it (once), no matter the length
|
2022-06-21 18:44:47 +02:00
|
|
|
"""
|
|
|
|
# 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
|
|
|
|
|
2022-07-01 15:46:56 +02:00
|
|
|
frequency = math.ceil((target_length - len(string)) / len(character))
|
2022-06-21 18:44:47 +02:00
|
|
|
|
|
|
|
return (frequency * character) + string
|
2022-06-30 21:17:48 +02:00
|
|
|
|
|
|
|
|
2022-11-21 22:46:19 +01:00
|
|
|
def mock(string: str) -> str:
|
|
|
|
"""Mock an input string
|
|
|
|
|
|
|
|
The result of this is comparable to the Mocking Spongebob memes
|
|
|
|
"""
|
|
|
|
replacements = {"a": "4", "b": "8", "e": "3", "i": "1", "o": "0", "s": "5"}
|
|
|
|
result_string = ""
|
|
|
|
|
|
|
|
for letter in string.lower():
|
|
|
|
# Letter should be mocked
|
|
|
|
if letter.isalpha() and random.random() < 0.5:
|
|
|
|
# Use replacement if it exists
|
|
|
|
if letter in replacements and random.random() < 0.5:
|
|
|
|
result_string += replacements[letter]
|
|
|
|
else:
|
|
|
|
result_string += letter.upper()
|
|
|
|
else:
|
|
|
|
result_string += letter
|
|
|
|
|
|
|
|
return result_string
|
|
|
|
|
|
|
|
|
2022-06-30 21:17:48 +02:00
|
|
|
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")
|
2022-08-13 00:07:48 +02:00
|
|
|
|
|
|
|
|
2022-09-19 18:15:10 +02:00
|
|
|
def re_find_all(pattern: str, string: str, flags: Union[int, re.RegexFlag] = 0) -> list[str]:
|
2022-09-19 15:59:12 +02:00
|
|
|
"""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
|
|
|
|
|
|
|
|
|
2022-09-03 01:26:32 +02:00
|
|
|
def get_edu_year_name(year: int) -> str: # pragma: no cover
|
2022-08-13 00:07:48 +02:00
|
|
|
"""Get the string representation of a university year"""
|
|
|
|
years = ["1st Bachelor", "2nd Bachelor", "3rd Bachelor", "1st Master", "2nd Master"]
|
|
|
|
|
|
|
|
return years[year]
|