Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
167 changes: 0 additions & 167 deletions src/imsosorry/uwuification.py

This file was deleted.

7 changes: 7 additions & 0 deletions src/imsosorry/uwuification/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"""UwU-ification of text."""

from .uwuifier import uwuify

__all__ = [
"uwuify",
]
69 changes: 69 additions & 0 deletions src/imsosorry/uwuification/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Regex and map constants for uwuification."""

import re

REGEX_WORD_REPLACE = re.compile(r"(?<!w)[lr](?!w)")
"""A regex that to detect certain characters to change to "w"s."""
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Grammatical error: 'A regex that to detect' should be 'A regex to detect' (remove 'that').

Copilot uses AI. Check for mistakes.

REGEX_PUNCTUATION = re.compile(r"[.!?\r\n\t]")
"""A regex to detect certain punctuation characters to emotify /(^•ω•^)"""

REGEX_TILDE = re.compile(r"(?![^ ])(?<!\B)")
"""A regex to find places to add tildes (~) to."""

REGEX_STUTTER = re.compile(r"(\s)([a-zA-Z])")
"""A regex to find words to stutter."""

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."""
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate word 'to' in documentation.

Suggested change
"""A regex to to nyaify words."""
"""A regex to nyaify words."""

Copilot uses AI. Check for mistakes.

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."""
1 change: 1 addition & 0 deletions src/imsosorry/uwuification/replacers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Replacers."""
29 changes: 29 additions & 0 deletions src/imsosorry/uwuification/replacers/regex.py
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +9 to +10
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The re module is imported only under TYPE_CHECKING, but it's used at runtime on line 29 with pattern.sub(). Move import re outside the TYPE_CHECKING block to avoid runtime errors.

Suggested change
if TYPE_CHECKING:
import re
import re
if TYPE_CHECKING:

Copilot uses AI. Check for mistakes.
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)
107 changes: 107 additions & 0 deletions src/imsosorry/uwuification/uwuifier.py
Original file line number Diff line number Diff line change
@@ -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."""
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring incorrectly states 'Repeat the last character in a string' but the function returns a tilde (~). Update to 'Return a tilde character.'

Suggested change
"""Repeat the last character in a string."""
"""Return a tilde character."""

Copilot uses AI. Check for mistakes.
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:
Comment on lines +76 to +81
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected spelling of 'minimun' to 'minimum'.

Suggested change
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:
minimum_processable_length: int = 2,
) -> str:
"""Uwuify a string."""
contains_alpha = any(char.isalpha() for char in text)
if len(text) < minimum_processable_length and not contains_alpha:

Copilot uses AI. Check for mistakes.
return random.choice(EMOJIS)

text = text.lower()
original_text = copy(text)

transforms = [
word_replace,
nyaify,
char_replace,
stutter,
Copy link

Copilot AI Jan 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The stutter function appears twice in the transforms list. Line 91 calls stutter without the required strength parameter, which will cause a TypeError. Remove line 91 to avoid the error and duplicate transformation.

Suggested change
stutter,

Copilot uses AI. Check for mistakes.
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
Loading