Ran black on sources

This commit is contained in:
Griatch 2022-09-18 23:58:32 +02:00
parent 6fa68745ba
commit 43378b4c41
30 changed files with 473 additions and 275 deletions

View file

@ -234,7 +234,9 @@ class EventCharacter(DefaultCharacter):
if not string:
return
super().announce_move_from(destination, msg=string, move_type=move_type, mapping=mapping, **kwargs)
super().announce_move_from(
destination, msg=string, move_type=move_type, mapping=mapping, **kwargs
)
def announce_move_to(self, source_location, msg=None, move_type="move", mapping=None, **kwargs):
"""
@ -292,7 +294,9 @@ class EventCharacter(DefaultCharacter):
if not string:
return
super().announce_move_to(source_location, msg=string, move_type=move_type, mapping=mapping, **kwargs)
super().announce_move_to(
source_location, msg=string, move_type=move_type, mapping=mapping, **kwargs
)
def at_pre_move(self, destination, move_type="move", **kwargs):
"""

View file

@ -236,7 +236,9 @@ class CmdGiveUp(CmdEvscapeRoom):
# manually call move hooks
self.room.msg_room(self.caller, f"|r{self.caller.key} gave up and was whisked away!|n")
self.room.at_object_leave(self.caller, self.caller.home)
self.caller.move_to(self.caller.home, quiet=True, move_hooks=False, move_type="teleport")
self.caller.move_to(
self.caller.home, quiet=True, move_hooks=False, move_type="teleport"
)
# back to menu
run_evscaperoom_menu(self.caller)

View file

@ -236,6 +236,7 @@ class RecogError(Exception):
class LanguageError(Exception):
pass
def _get_case_ref(string):
"""
Helper function which parses capitalization and
@ -257,6 +258,7 @@ def _get_case_ref(string):
return case
# emoting mechanisms
def parse_language(speaker, emote):
"""
@ -405,7 +407,7 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
match_index = marker_match.start()
# split the emote string at the reference marker, to process everything after it
head = string[:match_index]
tail = string[match_index + 1:]
tail = string[match_index + 1 :]
if search_mode:
# match the candidates against the whole search string after the marker
@ -451,7 +453,7 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False, case_
# save search string
matched_text = "".join(tail[1:iend])
# recombine remainder of emote back into a string
tail = "".join(tail[iend + 1:])
tail = "".join(tail[iend + 1 :])
nmatches = len(bestmatches)
@ -1275,19 +1277,19 @@ class ContribRPObject(DefaultObject):
self.sdesc.add("Something")
def search(
self,
searchdata,
global_search=False,
use_nicks=True,
typeclass=None,
location=None,
attribute_name=None,
quiet=False,
exact=False,
candidates=None,
nofound_string=None,
multimatch_string=None,
use_dbref=None,
self,
searchdata,
global_search=False,
use_nicks=True,
typeclass=None,
location=None,
attribute_name=None,
quiet=False,
exact=False,
candidates=None,
nofound_string=None,
multimatch_string=None,
use_dbref=None,
):
"""
Returns an Object matching a search string/condition, taking
@ -1371,10 +1373,10 @@ class ContribRPObject(DefaultObject):
)
if global_search or (
is_string
and searchdata.startswith("#")
and len(searchdata) > 1
and searchdata[1:].isdigit()
is_string
and searchdata.startswith("#")
and len(searchdata) > 1
and searchdata[1:].isdigit()
):
# only allow exact matching if searching the entire database
# or unique #dbrefs

View file

@ -151,7 +151,13 @@ class TestRPSystem(BaseEvenniaTest):
id2 = f"#{self.receiver2.id}"
candidates = (self.receiver1, self.receiver2)
result = (
'With a flair, {'+id0+'} looks at {'+id1+'} and {'+id2+'}. She says "This is a test."',
"With a flair, {"
+ id0
+ "} looks at {"
+ id1
+ "} and {"
+ id2
+ '}. She says "This is a test."',
{
id2: self.receiver2,
id1: self.receiver1,
@ -178,7 +184,7 @@ class TestRPSystem(BaseEvenniaTest):
id2 = f"#{self.receiver2.id}"
candidates = (self.receiver1, self.receiver2)
result = (
"{"+id0+"} frowns at {"+id1+"} for trying to steal {"+id0+"}'s test.",
"{" + id0 + "} frowns at {" + id1 + "} for trying to steal {" + id0 + "}'s test.",
{
id1: self.receiver1,
id0: speaker,

View file

@ -332,11 +332,9 @@ class EvAdventureRollEngine:
setattr(character, abi, current_abi)
character.msg(
"~" * 78
+ "\n|yYou survive your brush with death, "
"~" * 78 + "\n|yYou survive your brush with death, "
f"but are |r{result.upper()}|y and permanently |rlose {loss} {abi}|y.|n\n"
f"|GYou recover |g{new_hp}|G health|.\n"
+ "~" * 78
f"|GYou recover |g{new_hp}|G health|.\n" + "~" * 78
)

View file

@ -76,48 +76,121 @@ from evennia.utils.utils import is_iter
# Load name data from Behind the Name lists
dirpath = path.dirname(path.abspath(__file__))
_FIRSTNAME_LIST = []
with open(path.join(dirpath, "btn_givennames.txt"),'r', encoding='utf-8') as file:
_FIRSTNAME_LIST = [ line.strip().rsplit(" ") for line in file if line and not line.startswith("#") ]
with open(path.join(dirpath, "btn_givennames.txt"), "r", encoding="utf-8") as file:
_FIRSTNAME_LIST = [
line.strip().rsplit(" ") for line in file if line and not line.startswith("#")
]
_SURNAME_LIST = []
with open(path.join(dirpath, "btn_surnames.txt"),'r', encoding='utf-8') as file:
_SURNAME_LIST = [ line.strip() for line in file if line and not line.startswith("#") ]
with open(path.join(dirpath, "btn_surnames.txt"), "r", encoding="utf-8") as file:
_SURNAME_LIST = [line.strip() for line in file if line and not line.startswith("#")]
_REQUIRED_KEYS = { "syllable", "consonants", "vowels", "length" }
_REQUIRED_KEYS = {"syllable", "consonants", "vowels", "length"}
# Define phoneme structure for built-in fantasy name generators.
_FANTASY_NAME_STRUCTURES = {
"harsh": {
"syllable": "CV(C)",
"consonants": [ "k", "k", "k", "z", "zh", "g", "v", "t", "th", "w", "n", "d", "d", ],
"start": ["dh", "kh", "kh", "kh", "vh", ],
"end": ["n", "x", ],
"vowels": [ "o", "o", "o", "a", "y", "u", "u", "u", "ä", "ö", "e", "i", "i", ],
"length": (1,3),
"syllable": "CV(C)",
"consonants": [
"k",
"k",
"k",
"z",
"zh",
"g",
"v",
"t",
"th",
"w",
"n",
"d",
"d",
],
"start": [
"dh",
"kh",
"kh",
"kh",
"vh",
],
"end": [
"n",
"x",
],
"vowels": [
"o",
"o",
"o",
"a",
"y",
"u",
"u",
"u",
"ä",
"ö",
"e",
"i",
"i",
],
"length": (1, 3),
},
"fluid": {
"syllable": "V(C)",
"consonants": [ 'r','r','l','l','l','l','s','s','s','sh','m','n','n','f','v','w','th' ],
"start": [],
"end": [],
"vowels": [ "a","a","a","a","a","e","i","i","i","y","u","o", ],
"length": (3,5),
"syllable": "V(C)",
"consonants": [
"r",
"r",
"l",
"l",
"l",
"l",
"s",
"s",
"s",
"sh",
"m",
"n",
"n",
"f",
"v",
"w",
"th",
],
"start": [],
"end": [],
"vowels": [
"a",
"a",
"a",
"a",
"a",
"e",
"i",
"i",
"i",
"y",
"u",
"o",
],
"length": (3, 5),
},
"alien": {
"syllable": "C(C(V))(')(C)",
"consonants": [ 'q','q','x','z','v','w','k','h','b' ],
"start": ['x',],
"end": [],
"vowels": [ 'y','w','o','y' ],
"length": (1,5),
"syllable": "C(C(V))(')(C)",
"consonants": ["q", "q", "x", "z", "v", "w", "k", "h", "b"],
"start": [
"x",
],
"end": [],
"vowels": ["y", "w", "o", "y"],
"length": (1, 5),
},
}
}
_RE_DOUBLES = re.compile(r'(\w)\1{2,}')
_RE_DOUBLES = re.compile(r"(\w)\1{2,}")
# Load in optional settings
custom_first_names = settings.NAMEGEN_FIRST_NAMES if hasattr(settings, "NAMEGEN_FIRST_NAMES") else []
custom_first_names = (
settings.NAMEGEN_FIRST_NAMES if hasattr(settings, "NAMEGEN_FIRST_NAMES") else []
)
custom_last_names = settings.NAMEGEN_LAST_NAMES if hasattr(settings, "NAMEGEN_LAST_NAMES") else []
if hasattr(settings, "NAMEGEN_FANTASY_RULES"):
@ -132,7 +205,6 @@ else:
_SURNAME_LIST += custom_last_names
def fantasy_name(num=1, style="harsh", return_list=False):
"""
Generate made-up names in one of a number of "styles".
@ -143,28 +215,34 @@ def fantasy_name(num=1, style="harsh", return_list=False):
return_list (bool) - Whether to always return a list. `False` by default,
which returns a string if there is only one value and a list if more.
"""
def _validate(style_name):
if style_name not in _FANTASY_NAME_STRUCTURES:
raise ValueError(f"Invalid style name: '{style_name}'. Available style names: {' '.join(_FANTASY_NAME_STRUCTURES.keys())}")
raise ValueError(
f"Invalid style name: '{style_name}'. Available style names: {' '.join(_FANTASY_NAME_STRUCTURES.keys())}"
)
style_dict = _FANTASY_NAME_STRUCTURES[style_name]
if type(style_dict) is not dict:
raise ValueError(f"Style {style_name} must be a dictionary.")
keys = set(style_dict.keys())
missing_keys = _REQUIRED_KEYS - keys
if len(missing_keys):
raise KeyError(f"Style dictionary {style_name} is missing required keys: {' '.join(missing_keys)}")
if not (type(style_dict['consonants']) is list and type(style_dict['vowels']) is list):
raise KeyError(
f"Style dictionary {style_name} is missing required keys: {' '.join(missing_keys)}"
)
if not (type(style_dict["consonants"]) is list and type(style_dict["vowels"]) is list):
raise TypeError(f"'consonants' and 'vowels' for style {style_name} must be lists.")
if not (is_iter(style_dict['length']) and len(style_dict['length']) == 2):
raise ValueError(f"'length' key for {style_name} must have a minimum and maximum number of syllables.")
if not (is_iter(style_dict["length"]) and len(style_dict["length"]) == 2):
raise ValueError(
f"'length' key for {style_name} must have a minimum and maximum number of syllables."
)
return style_dict
# validate num first
num = int(num)
if num < 1:
@ -178,9 +256,9 @@ def fantasy_name(num=1, style="harsh", return_list=False):
for key in style_dict["syllable"]:
# parentheses mean optional - allow nested parens
if key == "(":
weight = weight/2
weight = weight / 2
elif key == ")":
weight = weight*2
weight = weight * 2
else:
if key == "C":
sound_type = "consonants"
@ -189,23 +267,23 @@ def fantasy_name(num=1, style="harsh", return_list=False):
else:
sound_type = key
# append the sound type and weight
syllable.append( (sound_type, int(weight)) )
syllable.append((sound_type, int(weight)))
name_list = []
# time to generate a name!
for n in range(num):
# build a list of syllables
length = random.randint(*style_dict['length'])
length = random.randint(*style_dict["length"])
name = ""
for i in range(length):
# build the syllable itself
syll = ""
for sound, weight in syllable:
# random chance to skip this key; lower weights mean less likely
if random.randint(0,8) > weight:
if random.randint(0, 8) > weight:
continue
if sound not in style_dict:
# extra character, like apostrophes
syll += sound
@ -217,33 +295,38 @@ def fantasy_name(num=1, style="harsh", return_list=False):
if sound == "consonants":
# if it's a starting consonant, add starting-sounds to the options
if not len(syll):
choices += style_dict.get('start',[])
choices += style_dict.get("start", [])
# if it's an ending consonant, add ending-sounds to the options
elif i+1 == length:
choices += style_dict.get('end',[])
elif i + 1 == length:
choices += style_dict.get("end", [])
syll += random.choice(choices)
name += syll
# condense repeating letters down to a maximum of 2
name = _RE_DOUBLES.sub(lambda m: m.group(1)*2, name)
name = _RE_DOUBLES.sub(lambda m: m.group(1) * 2, name)
# capitalize the first letter
name = name[0].upper() + name[1:] if len(name) > 1 else name.upper()
name_list.append(name)
if len(name_list) == 1 and not return_list:
return name_list[0]
return name_list
def first_name(num=1, gender=None, return_list=False, ):
def first_name(
num=1,
gender=None,
return_list=False,
):
"""
Generate first names, also known as personal names.
Keyword args:
num (int) - How many names to return.
gender (str) - Restrict names by gender association. `None` by default, which selects from
all possible names. Set to "m" for masculine, "f" for feminine, "mf" for androgynous
all possible names. Set to "m" for masculine, "f" for feminine, "mf" for androgynous
return_list (bool) - Whether to always return a list. `False` by default,
which returns a string if there is only one value and a list if more.
"""
@ -251,29 +334,33 @@ def first_name(num=1, gender=None, return_list=False, ):
num = int(num)
if num < 1:
raise ValueError("Number of names to generate must be positive.")
if gender:
# filter the options by gender
name_options = [ name_data[0] for name_data in _FIRSTNAME_LIST if all([gender_key in gender for gender_key in name_data[1]])]
name_options = [
name_data[0]
for name_data in _FIRSTNAME_LIST
if all([gender_key in gender for gender_key in name_data[1]])
]
if not len(name_options):
raise ValueError(f"Invalid gender '{gender}'.")
else:
name_options = [ name_data[0] for name_data in _FIRSTNAME_LIST ]
name_options = [name_data[0] for name_data in _FIRSTNAME_LIST]
# take a random selection of `num` names, without repeats
results = random.sample(name_options,num)
results = random.sample(name_options, num)
if len(results) == 1 and not return_list:
# return single value as a string
return results[0]
return results
def last_name(num=1, return_list=False):
"""
Generate family names, also known as surnames or last names.
Keyword args:
num (int) - How many names to return.
return_list (bool) - Whether to always return a list. `False` by default,
@ -285,7 +372,7 @@ def last_name(num=1, return_list=False):
raise ValueError("Number of names to generate must be positive.")
# take a random selection of `num` names, without repeats
results = random.sample(_SURNAME_LIST,num)
results = random.sample(_SURNAME_LIST, num)
if len(results) == 1 and not return_list:
# return single value as a string
@ -293,15 +380,16 @@ def last_name(num=1, return_list=False):
return results
def full_name(num=1, parts=2, gender=None, return_list=False, surname_first=False):
"""
Generate complete names with a personal name, family name, and optionally middle names.
Keyword args:
num (int) - How many names to return.
parts (int) - How many parts the name should have. By default two: first and last.
gender (str) - Restrict names by gender association. `None` by default, which selects from
all possible names. Set to "m" for masculine, "f" for feminine, "mf" for androgynous
all possible names. Set to "m" for masculine, "f" for feminine, "mf" for androgynous
return_list (bool) - Whether to always return a list. `False` by default,
which returns a string if there is only one value and a list if more.
surname_first (bool) - Default `False`. Set to `True` if you want the family name to be
@ -318,26 +406,26 @@ def full_name(num=1, parts=2, gender=None, return_list=False, surname_first=Fals
name_lists = []
middle = parts-2
middle = parts - 2
if middle:
# calculate "middle" names.
# we want them to be an intelligent mix of personal names and family names
# first, split the total number of middle-name parts into "personal" and "family" at a random point
total_mids = middle*num
personals = random.randint(1,total_mids)
total_mids = middle * num
personals = random.randint(1, total_mids)
familys = total_mids - personals
# then get the names for each
personal_mids = first_name(num=personals, gender=gender, return_list=True)
family_mids = last_name(num=familys, return_list=True) if familys else []
# splice them together according to surname_first....
middle_names = family_mids+personal_mids if surname_first else personal_mids+family_mids
middle_names = family_mids + personal_mids if surname_first else personal_mids + family_mids
# ...and then split into `num`-length lists to be used for the final names
name_lists = [ middle_names[num*i:num*(i+1)] for i in range(0,middle) ]
name_lists = [middle_names[num * i : num * (i + 1)] for i in range(0, middle)]
# get personal and family names
personal_names = first_name(num=num, gender=gender, return_list=True)
last_names = last_name(num=num, return_list=True)
# attach personal/family names to the list of name lists, according to surname_first
if surname_first:
name_lists = [last_names] + name_lists + [personal_names]
@ -346,7 +434,7 @@ def full_name(num=1, parts=2, gender=None, return_list=False, surname_first=Fals
# lastly, zip them all up and join them together
names = list(zip(*name_lists))
names = [ " ".join(name) for name in names ]
names = [" ".join(name) for name in names]
if len(names) == 1 and not return_list:
# return single value as a string

View file

@ -1,4 +1,3 @@
"""
Tests for the Random Name Generator
"""
@ -8,35 +7,36 @@ from evennia.contrib.utils.name_generator import namegen
_INVALID_STYLES = {
"missing_keys": {
"consonants": ['c','d'],
"length": (1,2),
"consonants": ["c", "d"],
"length": (1, 2),
},
"invalid_vowels": {
"syllable": "CVC",
"consonants": ['c','d'],
"consonants": ["c", "d"],
"vowels": "aeiou",
"length": (1,2),
"length": (1, 2),
},
"invalid_length": {
"syllable": "CVC",
"consonants": ['c','d'],
"vowels": ['a','e'],
"consonants": ["c", "d"],
"vowels": ["a", "e"],
"length": 2,
},
}
namegen._FANTASY_NAME_STRUCTURES |= _INVALID_STYLES
class TestNameGenerator(BaseEvenniaTest):
def test_fantasy_name(self):
"""
Verify output types and lengths.
fantasy_name() - str
fantasy_name(style="fluid") - str
fantasy_name(num=3) - list of length 3
fantasy_name(return_list=True) - list of length 1
raises KeyError on missing style or ValueError on num
"""
single_name = namegen.fantasy_name()
@ -55,27 +55,27 @@ class TestNameGenerator(BaseEvenniaTest):
with self.assertRaises(ValueError):
namegen.fantasy_name(num=-1)
with self.assertRaises(ValueError):
namegen.fantasy_name(style="dummy")
def test_structure_validation(self):
"""
Verify that validation raises the correct errors for invalid inputs.
"""
with self.assertRaises(KeyError):
namegen.fantasy_name(style="missing_keys")
namegen.fantasy_name(style="missing_keys")
with self.assertRaises(TypeError):
namegen.fantasy_name(style="invalid_vowels")
namegen.fantasy_name(style="invalid_vowels")
with self.assertRaises(ValueError):
namegen.fantasy_name(style="invalid_length")
namegen.fantasy_name(style="invalid_length")
def test_first_name(self):
"""
Verify output types and lengths.
first_name() - str
first_name(num=3) - list of length 3
first_name(gender='f') - str
@ -88,7 +88,7 @@ class TestNameGenerator(BaseEvenniaTest):
self.assertEqual(type(three_names), list)
self.assertEqual(len(three_names), 3)
gendered_name = namegen.first_name(gender='f')
gendered_name = namegen.first_name(gender="f")
self.assertEqual(type(gendered_name), str)
single_list = namegen.first_name(return_list=True)
@ -96,7 +96,7 @@ class TestNameGenerator(BaseEvenniaTest):
self.assertEqual(len(single_list), 1)
with self.assertRaises(ValueError):
namegen.first_name(gender='x')
namegen.first_name(gender="x")
with self.assertRaises(ValueError):
namegen.first_name(num=-1)
@ -104,7 +104,7 @@ class TestNameGenerator(BaseEvenniaTest):
def test_last_name(self):
"""
Verify output types and lengths.
last_name() - str
last_name(num=3) - list of length 3
last_name(return_list=True) - list of length 1
@ -126,7 +126,7 @@ class TestNameGenerator(BaseEvenniaTest):
def test_full_name(self):
"""
Verify output types and lengths.
full_name() - str
full_name(num=3) - list of length 3
full_name(gender='f') - str
@ -139,7 +139,7 @@ class TestNameGenerator(BaseEvenniaTest):
self.assertEqual(type(three_names), list)
self.assertEqual(len(three_names), 3)
gendered_name = namegen.full_name(gender='f')
gendered_name = namegen.full_name(gender="f")
self.assertEqual(type(gendered_name), str)
single_list = namegen.full_name(return_list=True)