From cf0ec7b4039363491e1615e58f24cc37996140ad Mon Sep 17 00:00:00 2001 From: lda Date: Sun, 30 Aug 2026 01:53:53 +0700 Subject: [PATCH] Use wonderwords for shell names --- pyproject.toml | 1 + src/ipython_demo/app.py | 10 ++++++---- tests/test_app.py | 20 ++++++++++++++++++++ uv.lock | 11 +++++++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 82c20ec..2a96fc1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ dependencies = [ "matplotlib>=3.11.1", "matplotlib-inline>=0.1.7", "sympy>=1.14.0", + "wonderwords>=2.2.0", ] [project.scripts] diff --git a/src/ipython_demo/app.py b/src/ipython_demo/app.py index cb47515..7eac574 100644 --- a/src/ipython_demo/app.py +++ b/src/ipython_demo/app.py @@ -2,20 +2,22 @@ import contextlib import io import json from dataclasses import asdict -from random import choice from uuid import uuid4 +from wonderwords import RandomWord + from .models import CallResponse from .shell import Shell -_ADJECTIVES = ("bright", "calm", "curious", "quiet", "swift") -_NOUNS = ("otter", "comet", "raven", "panda", "badger") +_WORD_GENERATOR = RandomWord() def generate_good_names() -> str: """Generate a readable, collision-resistant shell name.""" - return f"{choice(_ADJECTIVES)}-{choice(_NOUNS)}-{uuid4().hex[:4]}" + adjective = _WORD_GENERATOR.word(include_parts_of_speech=["adjectives"]) + noun = _WORD_GENERATOR.word(include_parts_of_speech=["nouns"]) + return f"{adjective}-{noun}-{uuid4().hex[:4]}" class App: diff --git a/tests/test_app.py b/tests/test_app.py index ccdb21e..c441b0c 100644 --- a/tests/test_app.py +++ b/tests/test_app.py @@ -1,15 +1,35 @@ import contextlib +import importlib import io import json +import re import subprocess import sys import unittest +from unittest.mock import Mock, patch from ipython_demo.app import App from ipython_demo.models import CallResponse class AppTests(unittest.TestCase): + def test_generate_good_names_uses_readable_random_words(self): + app_module = importlib.import_module("ipython_demo.app") + generator = Mock() + generator.word.side_effect = ["luminous", "otter"] + + with patch.object( + app_module, + "_WORD_GENERATOR", + generator, + create=True, + ): + name = app_module.generate_good_names() + + self.assertRegex(name, re.compile(r"^[a-z]+-[a-z]+-[0-9a-f]{4}$")) + generator.word.assert_any_call(include_parts_of_speech=["adjectives"]) + generator.word.assert_any_call(include_parts_of_speech=["nouns"]) + def test_main_emits_one_json_payload(self): completed = subprocess.run( [sys.executable, "-c", "from ipython_demo.app import main; main()"], diff --git a/uv.lock b/uv.lock index 94555e1..bee2bcd 100644 --- a/uv.lock +++ b/uv.lock @@ -126,6 +126,7 @@ dependencies = [ { name = "matplotlib" }, { name = "matplotlib-inline" }, { name = "sympy" }, + { name = "wonderwords" }, ] [package.metadata] @@ -134,6 +135,7 @@ requires-dist = [ { name = "matplotlib", specifier = ">=3.11.1" }, { name = "matplotlib-inline", specifier = ">=0.1.7" }, { name = "sympy", specifier = ">=1.14.0" }, + { name = "wonderwords", specifier = ">=2.2.0" }, ] [[package]] @@ -553,3 +555,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/36/57/ed58088fafdf4c55a wheels = [ { url = "https://files.pythonhosted.org/packages/c4/0e/57f6bb3024a597b2e8ec4aee710ffe62ddc95af2e2bb1ee7a7abdc22c68c/wcwidth-0.8.3-py3-none-any.whl", hash = "sha256:d5b73dba6158a595ec9370350e7f2637bcac8d6c5e4fde34f30fcffb6103a5e4", size = 331669, upload-time = "2026-08-28T18:10:04.909Z" }, ] + +[[package]] +name = "wonderwords" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/23/e144fc3dfabb845dc1d94c45315d97b308cf75a664e3db3a89aeb1cb505d/wonderwords-3.0.1.tar.gz", hash = "sha256:5ee43ab6f13823a857a7c3d58c7b4db6a1350bd3aa5f914ed379ad49042a1c36", size = 73339, upload-time = "2025-10-30T17:30:44.231Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a4/75/855c2062d28b8e9247939f8262fb2f4ff3b12a49e4bab9fd1ba16cc5df82/wonderwords-3.0.1-py3-none-any.whl", hash = "sha256:4dd66deb6a76ca9e0b0422d1d3e111f9b910d7c16922d42de733ee8def98f8d0", size = 51658, upload-time = "2025-10-30T17:30:42.785Z" }, +]