diff --git a/src/imsosorry/uwuification.py b/src/imsosorry/uwuification.py deleted file mode 100644 index cf8a6d4..0000000 --- a/src/imsosorry/uwuification.py +++ /dev/null @@ -1,167 +0,0 @@ -"""The ancient arts of Uwuification.""" - -from __future__ import annotations - -import random -import re -from functools import partial - -WORD_REPLACE = { - "small": "smol", - "cute": "kawaii~", - "fluff": "floof", - "love": "luv", - "stupid": "baka", - "idiot": "baka", - "what": "nani", - "meow": "nya~", - "roar": "rawrr~", -} -"""A dict to match certain words for replacement words""" - -EMOJIS = [ - "rawr x3", - "OwO", - "UwU", - "o.O", - "-.-", - ">w<", - "(⑅˘꒳˘)", - "(ꈍᴗꈍ)", - "(˘ω˘)", - "(U ᵕ U❁)", - "σωσ", - "òωó", - "(///ˬ///✿)", - "(U ﹏ U)", # noqa: RUF001 - literally the point... - "( ͡o ω ͡o )", - "ʘwʘ", - ":3", - ":3", # important enough to have twice - "XD", - "nyaa~~", - "mya", - ">_<", - "😳", - "🥺", - "😳😳😳", - "rawr", - "^^", - "^^;;", - "(ˆ ﻌ ˆ)♡", # noqa: RUF001 - literally the point... - "^•ﻌ•^", - "/(^•ω•^)", - "(✿oωo)", -] -"""A list of emojis/emoticons to add.""" - -REGEX_WORD_REPLACE = re.compile(r"(?\g<2>-\g<2>" -"""A regex to add st-stuttering to strings.""" - -REGEX_NYA = re.compile(r"n([aeou][^aeiou])") -"""A regex to detect words with an n before a vowel to nyaify.""" -SUBSTITUTE_NYA = r"ny\1" -"""A regex to to nyaify words.""" - - -def word_replace(text: str) -> str: - """Replace words that are keys in the word replacement hash to the values specified.""" - for word, replacement in WORD_REPLACE.items(): - text = text.replace(word, replacement) - return text - - -def char_replace(text: str) -> str: - """Replace certain characters with 'w'.""" - return REGEX_WORD_REPLACE.sub("w", text) - - -def stutter_replace(match: re.Match[str], strength: float = 0.0) -> str: - """Replace a single character with a stuttered character.""" - match_string = match.group() - if random.random() < strength: - # Stutter the last character - return f"{match_string}-{match_string[-1]}" - return match_string - - -def stutter(text: str, strength: float) -> str: - """Add stuttering to a string.""" - return REGEX_STUTTER.sub(partial(stutter_replace, strength=strength), text, 0) - - -def nyaify(text: str) -> str: - """Nyaify a string by adding a 'y' between an 'n' and a vowel.""" - return REGEX_NYA.sub(SUBSTITUTE_NYA, text, 0) - - -def emoji_replace(match: re.Match[str], strength: float = 0.0) -> str: - """Replace a punctuation character with an emoticon.""" - match_string = match.group() - if random.random() < strength: - return f" {random.choice(EMOJIS)} " - return match_string - - -def emoji(text: str, strength: float) -> str: - """Replace some punctuation with emoticons.""" - return REGEX_PUNCTUATION.sub(partial(emoji_replace, strength=strength), text, 0) - - -def tildes(match: re.Match[str], strength: float = 0.0) -> str: - """Add some tildes to spaces.""" - match_string = match.group() - if random.random() < strength: - return "~" - return match_string - - -def tildify(text: str, strength: float) -> str: - """Add some tildes to spaces.""" - return REGEX_TILDE.sub(partial(tildes, strength=strength), text, 0) - - -def uwuify( - text: str, - *, - stutter_strength: float = 0.2, - emoji_strength: float = 0.1, - tilde_strength: float = 0.1, - max_emojifiable_len: int = 2, -) -> str: - """Take a string and returns an uwuified version of it.""" - alpha = any(char.isalpha() for char in text) - - if len(text) < max_emojifiable_len and not alpha: - return random.choice(EMOJIS) - - original_text = text.lower() - - text = text.lower() - text = word_replace(text) - text = nyaify(text) - text = char_replace(text) - text = stutter(text, stutter_strength) - text = emoji(text, emoji_strength) - text = tildify(text, tilde_strength) - - if text == original_text and alpha: - text = uwuify( - text, - stutter_strength=stutter_strength + 0.225, - emoji_strength=emoji_strength + 0.075, - tilde_strength=tilde_strength + 0.175, - ) - - return text diff --git a/src/imsosorry/uwuification/__init__.py b/src/imsosorry/uwuification/__init__.py new file mode 100644 index 0000000..abe5fc3 --- /dev/null +++ b/src/imsosorry/uwuification/__init__.py @@ -0,0 +1,7 @@ +"""UwU-ification of text.""" + +from .uwuifier import uwuify + +__all__ = [ + "uwuify", +] diff --git a/src/imsosorry/uwuification/constants.py b/src/imsosorry/uwuification/constants.py new file mode 100644 index 0000000..20a1d12 --- /dev/null +++ b/src/imsosorry/uwuification/constants.py @@ -0,0 +1,69 @@ +"""Regex and map constants for uwuification.""" + +import re + +REGEX_WORD_REPLACE = re.compile(r"(?w<", + "(⑅˘꒳˘)", + "(ꈍᴗꈍ)", + "(˘ω˘)", + "(U ᵕ U❁)", + "σωσ", + "òωó", + "(///ˬ///✿)", + "(U ﹏ U)", # noqa: RUF001 - literally the point... + "( ͡o ω ͡o )", + "ʘwʘ", + ":3", + ":3", # important enough to have twice + "XD", + "nyaa~~", + "mya", + ">_<", + "😳", + "🥺", + "😳😳😳", + "rawr", + "^^", + "^^;;", + "(ˆ ﻌ ˆ)♡", # noqa: RUF001 - literally the point... + "^•ﻌ•^", + "/(^•ω•^)", + "(✿oωo)", +] +"""A list of emojis/emoticons to add.""" diff --git a/src/imsosorry/uwuification/replacers/__init__.py b/src/imsosorry/uwuification/replacers/__init__.py new file mode 100644 index 0000000..d53b088 --- /dev/null +++ b/src/imsosorry/uwuification/replacers/__init__.py @@ -0,0 +1 @@ +"""Replacers.""" diff --git a/src/imsosorry/uwuification/replacers/regex.py b/src/imsosorry/uwuification/replacers/regex.py new file mode 100644 index 0000000..faa746f --- /dev/null +++ b/src/imsosorry/uwuification/replacers/regex.py @@ -0,0 +1,29 @@ +"""Regex replacers.""" + +from __future__ import annotations + +import random +from functools import partial +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + import re + from collections.abc import Callable + + +def re_sub_maybe( + text: str, + pattern: re.Pattern[str], + text_getter: Callable[[str], str], + strength: float = 0.0, +) -> str: + """Replace pattern in string randomly.""" + + def inner(match: re.Match[str], strength: float) -> str: + """Replace text randomly.""" + match_string = match.group() + if random.random() < strength: + return text_getter(match_string) + return match_string + + return pattern.sub(partial(inner, strength=strength), text) diff --git a/src/imsosorry/uwuification/uwuifier.py b/src/imsosorry/uwuification/uwuifier.py new file mode 100644 index 0000000..42d1af6 --- /dev/null +++ b/src/imsosorry/uwuification/uwuifier.py @@ -0,0 +1,107 @@ +"""Uwuification of text.""" + +from __future__ import annotations + +import random +from copy import copy +from functools import partial + +from imsosorry.uwuification.replacers.regex import re_sub_maybe + +from .constants import ( + EMOJIS, + REGEX_NYA, + REGEX_PUNCTUATION, + REGEX_STUTTER, + REGEX_TILDE, + REGEX_WORD_REPLACE, + SUBSTITUTE_NYA, + WORD_REPLACE, +) + + +def _stutter_string(text: str) -> str: + """Repeat the last character in a string.""" + return f"{text}-{text[-1]}" + + +def _emoji_string(_text: str) -> str: + """Return a random emoji.""" + return f" {random.choice(EMOJIS)} " + + +def _tildify_string(_text: str) -> str: + """Repeat the last character in a string.""" + return "~" + + +def word_replace(text: str) -> str: + """Replace words that are keys in the word replacement hash to the values specified.""" + for word, replacement in WORD_REPLACE.items(): + text = text.replace(word, replacement) + return text + + +def nyaify(text: str) -> str: + """Nyaify a string by adding a 'y' between an 'n' and a vowel.""" + return REGEX_NYA.sub(SUBSTITUTE_NYA, text) + + +def char_replace(text: str) -> str: + """Replace certain characters with 'w'.""" + return REGEX_WORD_REPLACE.sub("w", text) + + +def stutter(text: str, strength: float) -> str: + """Add stuttering to a string.""" + return re_sub_maybe(text=text, pattern=REGEX_STUTTER, text_getter=_stutter_string, strength=strength) + + +def emoji(text: str, strength: float) -> str: + """Replace some punctuation with emoticons.""" + return re_sub_maybe(text=text, pattern=REGEX_PUNCTUATION, text_getter=_emoji_string, strength=strength) + + +def tildify(text: str, strength: float) -> str: + """Add some tildes to spaces.""" + return re_sub_maybe(text=text, pattern=REGEX_TILDE, text_getter=_tildify_string, strength=strength) + + +def uwuify( + text: str, + *, + stutter_strength: float = 0.2, + emoji_strength: float = 0.1, + tilde_strength: float = 0.1, + minimun_processable_length: int = 2, +) -> str: + """Uwuify a string.""" + contains_alpha = any(char.isalpha() for char in text) + + if len(text) < minimun_processable_length and not contains_alpha: + return random.choice(EMOJIS) + + text = text.lower() + original_text = copy(text) + + transforms = [ + word_replace, + nyaify, + char_replace, + stutter, + partial(stutter, strength=stutter_strength), + partial(emoji, strength=emoji_strength), + partial(tildify, strength=tilde_strength), + ] + for transform in transforms: + text = transform(text) # type: ignore[operator] + + if text == original_text and contains_alpha: + return uwuify( + text, + stutter_strength=stutter_strength + 0.225, + emoji_strength=emoji_strength + 0.075, + tilde_strength=tilde_strength + 0.175, + ) + + return text diff --git a/tests/test_uwuification.py b/tests/test_uwuification.py index ebc5212..572beab 100644 --- a/tests/test_uwuification.py +++ b/tests/test_uwuification.py @@ -1,11 +1,11 @@ -"""Test the arts of Uwuification.""" +"""Test the uwuification.""" from __future__ import annotations import pytest -from imsosorry.uwuification import ( - EMOJIS, +from imsosorry.uwuification.constants import EMOJIS +from imsosorry.uwuification.uwuifier import ( char_replace, emoji, nyaify,