Skip to content
Merged
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
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Pseudomatic is a Python-based tool for generating pseudonyms based on a seed str
- Ukrainian (`ua`)
- Generates pseudonyms in the format: `Adjective Noun` (e.g., "Brave Fox" or "Хоробрий Лис").
- Deterministic output: the same seed and language will always produce the same pseudonym.
- Supports random pseudonym generation when no seed is provided.

## Installation

Expand Down Expand Up @@ -46,6 +47,14 @@ print(pseudonym_en) # Example: "Brave Fox"
pseudonym_ua = pseudonym("JohnDoe", language="ua")
print(pseudonym_ua) # Example: "Хоробрий Лис"

# Generate a random pseudonym (no seed provided)
random_pseudonym = pseudonym(language="en")
print(random_pseudonym) # Example: "Curious Elephant"

# Generate a random pseudonym in Ukrainian
random_pseudonym_ua = pseudonym(language="ua")
print(random_pseudonym_ua) # Example: "Цікавий Слон"

# Use different themes
business_pseudonym = pseudonym("JohnDoe", language="en", theme="business")
market_pseudonym = pseudonym("JohnDoe", language="ua", theme="market")
Expand Down
11 changes: 8 additions & 3 deletions pseudomatic/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import hashlib
import uuid

from . import names

Expand All @@ -17,12 +18,13 @@
}
}

def pseudonym(seed: str, language: str = "en", theme: str = 'default') -> str:
def pseudonym(seed: str = None, language: str = "en", theme: str = 'default') -> str:
"""
Generate a pseudonym based on a seed string and language.
If seed is None or empty, a random seed will be generated.

Args:
seed (str): The input seed string.
seed (str, optional): The input seed string. If None or empty, a random seed will be generated.
language (str): The language code ("en" for English, "ua" for Ukrainian).
theme (str): The theme for the pseudonym ("default", "business", or "market").

Expand All @@ -34,6 +36,10 @@ def pseudonym(seed: str, language: str = "en", theme: str = 'default') -> str:

adjectives, nouns, gender = LANGUAGES[theme][language]

# Generate a random seed if none is provided
if seed is None or seed == "":
seed = str(uuid.uuid4())

# Hash the seed using SHA-256
hash_bytes = hashlib.sha256(seed.encode('utf-8')).digest()
number = int.from_bytes(hash_bytes, byteorder="big")
Expand All @@ -49,4 +55,3 @@ def pseudonym(seed: str, language: str = "en", theme: str = 'default') -> str:

# Combine into a pseudonym
return f"{adjective} {noun}"

46 changes: 38 additions & 8 deletions tests/test_pseudomatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,76 @@ def test_pseudonym_generation(self):
result1 = pseudonym(seed)
result2 = pseudonym(seed)
self.assertEqual(result1, result2)

def test_different_seeds(self):
# Test that different seeds produce different pseudonyms
seed1 = "test-seed-1"
seed2 = "test-seed-2"
result1 = pseudonym(seed1)
result2 = pseudonym(seed2)
self.assertNotEqual(result1, result2)

def test_language_support(self):
# Test English language
seed = "test-seed"
en_result = pseudonym(seed, language="en")
self.assertIsInstance(en_result, str)
self.assertTrue(len(en_result) > 0)

# Test Ukrainian language
ua_result = pseudonym(seed, language="ua")
self.assertIsInstance(ua_result, str)
self.assertTrue(len(ua_result) > 0)

# Test that different languages produce different results
self.assertNotEqual(en_result, ua_result)

def test_theme_support(self):
# Test different themes
seed = "test-seed"
default_result = pseudonym(seed, theme="default")
business_result = pseudonym(seed, theme="business")
market_result = pseudonym(seed, theme="market")

# Test that different themes produce different results
self.assertNotEqual(default_result, business_result)
self.assertNotEqual(default_result, market_result)
self.assertNotEqual(business_result, market_result)

def test_invalid_language(self):
# Test that an invalid language raises a ValueError
with self.assertRaises(ValueError):
pseudonym("test-seed", language="invalid")

def test_no_seed_provided(self):
# Test that calling pseudonym() without a seed returns a non-empty string
result = pseudonym()
self.assertIsInstance(result, str)
self.assertTrue(len(result) > 0)

# Test that calling pseudonym() with an empty string also generates a pseudonym
result_empty = pseudonym("")
self.assertIsInstance(result_empty, str)
self.assertTrue(len(result_empty) > 0)

def test_random_pseudonyms_are_different(self):
# Test that calling pseudonym() multiple times returns different pseudonyms
result1 = pseudonym()
result2 = pseudonym()
self.assertNotEqual(result1, result2)

# Test with different languages
en_result = pseudonym(language="en")
ua_result = pseudonym(language="ua")
self.assertNotEqual(en_result, ua_result)

# Test with different themes
default_result = pseudonym(theme="default")
business_result = pseudonym(theme="business")
market_result = pseudonym(theme="market")
self.assertNotEqual(default_result, business_result)
self.assertNotEqual(default_result, market_result)
self.assertNotEqual(business_result, market_result)

if __name__ == "__main__":
unittest.main()
unittest.main()