mirror of
https://github.com/evennia/evennia.git
synced 2026-03-31 21:17:17 +02:00
Ran black on sources
This commit is contained in:
parent
6fa68745ba
commit
43378b4c41
30 changed files with 473 additions and 275 deletions
|
|
@ -7,13 +7,13 @@ import evennia.accounts.manager
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0009_auto_20191025_0831'),
|
||||
("accounts", "0009_auto_20191025_0831"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='accountdb',
|
||||
name='first_name',
|
||||
field=models.CharField(blank=True, max_length=150, verbose_name='first name'),
|
||||
model_name="accountdb",
|
||||
name="first_name",
|
||||
field=models.CharField(blank=True, max_length=150, verbose_name="first name"),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ PATH_REMAP_PREFIX = {
|
|||
"auditing": "evennia.contrib.utils",
|
||||
"fieldfill": "evennia.contrib.utils",
|
||||
"random_string_generator": "evennia.contrib.utils",
|
||||
"tree_select": "evennia.contrib.utils"
|
||||
"tree_select": "evennia.contrib.utils",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -52,43 +52,45 @@ def convert_contrib_typeclass_paths(apps, schema_editor):
|
|||
try:
|
||||
package_path = obj.db_typeclass_path.split(".")[2:]
|
||||
package_name = package_path[0]
|
||||
if package_path[0] == 'security':
|
||||
if package_path[0] == "security":
|
||||
# renamed package and changed path
|
||||
package_name = 'auditing'
|
||||
package_name = "auditing"
|
||||
package_path.pop(0) # no longer security/auditing
|
||||
if package_path[-1] == ".Clothing":
|
||||
# renamed Clothing class to ContribClothing
|
||||
package_path[-1] = "ContribClothing"
|
||||
package_path = '.'.join(package_path)
|
||||
package_path = ".".join(package_path)
|
||||
|
||||
except IndexError:
|
||||
print(f"obj.db_typeclass_path={obj.db_typeclass_path} could not be parsed "
|
||||
"for converting to the new contrib location.")
|
||||
print(
|
||||
f"obj.db_typeclass_path={obj.db_typeclass_path} could not be parsed "
|
||||
"for converting to the new contrib location."
|
||||
)
|
||||
continue
|
||||
if package_name in PATH_REMAP_PREFIX:
|
||||
obj.db_typeclass_path = f"{PATH_REMAP_PREFIX[package_name]}.{package_path}"
|
||||
obj.save(update_fields=['db_typeclass_path'])
|
||||
obj.save(update_fields=["db_typeclass_path"])
|
||||
|
||||
for obj in AccountDB.objects.filter(db_cmdset_storage__startswith="evennia.contrib."):
|
||||
try:
|
||||
package_path = obj.db_cmdset_storage.split(".")[2:]
|
||||
package_name = package_path[0]
|
||||
package_path = '.'.join(package_path)
|
||||
package_path = ".".join(package_path)
|
||||
except IndexError:
|
||||
print(f"obj.db_cmdset_storage={obj.db_cmdset_storage} could not be parsed "
|
||||
"for converting to the new contrib location.")
|
||||
print(
|
||||
f"obj.db_cmdset_storage={obj.db_cmdset_storage} could not be parsed "
|
||||
"for converting to the new contrib location."
|
||||
)
|
||||
continue
|
||||
if package_name in PATH_REMAP_PREFIX:
|
||||
obj.db_cmdset_storage = f"{PATH_REMAP_PREFIX[package_name]}.{package_path}"
|
||||
obj.save(update_fields=['db_cmdset_storage'])
|
||||
obj.save(update_fields=["db_cmdset_storage"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0010_auto_20210520_2137'),
|
||||
("accounts", "0010_auto_20210520_2137"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(convert_contrib_typeclass_paths, migrations.RunPython.noop)
|
||||
]
|
||||
operations = [migrations.RunPython(convert_contrib_typeclass_paths, migrations.RunPython.noop)]
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ def build_matches(raw_string, cmdset, include_prefixes=False):
|
|||
try:
|
||||
orig_string = raw_string
|
||||
if not include_prefixes and len(raw_string) > 1:
|
||||
raw_string = raw_string.lstrip(_CMD_IGNORE_PREFIXES)
|
||||
raw_string = raw_string.lstrip(_CMD_IGNORE_PREFIXES)
|
||||
search_string = raw_string.lower()
|
||||
for cmd in cmdset:
|
||||
cmdname, raw_cmdname = cmd.match(search_string, include_prefixes=include_prefixes)
|
||||
|
|
|
|||
|
|
@ -359,11 +359,15 @@ class Command(metaclass=CommandMeta):
|
|||
"""
|
||||
if include_prefixes:
|
||||
for cmd_key in self._keyaliases:
|
||||
if cmdname.startswith(cmd_key) and (not self.arg_regex or self.arg_regex.match(cmdname[len(cmd_key) :])):
|
||||
if cmdname.startswith(cmd_key) and (
|
||||
not self.arg_regex or self.arg_regex.match(cmdname[len(cmd_key) :])
|
||||
):
|
||||
return cmd_key, cmd_key
|
||||
else:
|
||||
for k, v in self._noprefix_aliases.items():
|
||||
if cmdname.startswith(k) and (not self.arg_regex or self.arg_regex.match(cmdname[len(k) :])):
|
||||
if cmdname.startswith(k) and (
|
||||
not self.arg_regex or self.arg_regex.match(cmdname[len(k) :])
|
||||
):
|
||||
return k, v
|
||||
return None, None
|
||||
|
||||
|
|
|
|||
|
|
@ -1950,7 +1950,12 @@ class CmdSetAttribute(ObjManipCommand):
|
|||
if self.rhs is None:
|
||||
# no = means we inspect the attribute(s)
|
||||
if not attrs:
|
||||
attrs = [attr.key for attr in obj.attributes.get(category=None, return_obj=True, return_list=True)]
|
||||
attrs = [
|
||||
attr.key
|
||||
for attr in obj.attributes.get(
|
||||
category=None, return_obj=True, return_list=True
|
||||
)
|
||||
]
|
||||
for attr in attrs:
|
||||
if not self.check_attr(obj, attr, category):
|
||||
continue
|
||||
|
|
@ -2001,7 +2006,9 @@ class CmdSetAttribute(ObjManipCommand):
|
|||
result.append(self.set_attr(obj, attr, value, category))
|
||||
# check if anything was done
|
||||
if not result:
|
||||
caller.msg("No valid attributes were found. Usage: set obj/attr[:category] = value. Use empty value to clear.")
|
||||
caller.msg(
|
||||
"No valid attributes were found. Usage: set obj/attr[:category] = value. Use empty value to clear."
|
||||
)
|
||||
else:
|
||||
# send feedback
|
||||
caller.msg("".join(result).strip("\n"))
|
||||
|
|
@ -3732,7 +3739,7 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
|
|||
quiet="quiet" in self.switches,
|
||||
emit_to_obj=caller,
|
||||
use_destination="intoexit" not in self.switches,
|
||||
move_type="teleport"
|
||||
move_type="teleport",
|
||||
):
|
||||
|
||||
if obj_to_teleport == caller:
|
||||
|
|
|
|||
|
|
@ -1584,8 +1584,9 @@ class TestBuilding(BaseEvenniaCommandTest):
|
|||
self.call(
|
||||
building.CmdTeleport(),
|
||||
"Obj = Room2",
|
||||
"Obj(#{}) is leaving Room(#{}), heading for Room2(#{}).|Teleported Obj -> Room2."
|
||||
.format(oid, rid, rid2),
|
||||
"Obj(#{}) is leaving Room(#{}), heading for Room2(#{}).|Teleported Obj -> Room2.".format(
|
||||
oid, rid, rid2
|
||||
),
|
||||
)
|
||||
self.call(building.CmdTeleport(), "NotFound = Room", "Could not find 'NotFound'.")
|
||||
self.call(
|
||||
|
|
@ -1701,8 +1702,7 @@ class TestBuilding(BaseEvenniaCommandTest):
|
|||
self.call(
|
||||
building.CmdSpawn(),
|
||||
"{'prototype_key':'GOBLIN', 'typeclass':'evennia.objects.objects.DefaultCharacter', "
|
||||
"'key':'goblin', 'location':'%s'}"
|
||||
% spawnLoc.dbref,
|
||||
"'key':'goblin', 'location':'%s'}" % spawnLoc.dbref,
|
||||
"Spawned goblin",
|
||||
)
|
||||
goblin = get_object(self, "goblin")
|
||||
|
|
@ -1750,8 +1750,7 @@ class TestBuilding(BaseEvenniaCommandTest):
|
|||
self.call(
|
||||
building.CmdSpawn(),
|
||||
"/noloc {'prototype_parent':'TESTBALL', 'key': 'Ball', 'prototype_key': 'foo',"
|
||||
" 'location':'%s'}"
|
||||
% spawnLoc.dbref,
|
||||
" 'location':'%s'}" % spawnLoc.dbref,
|
||||
"Spawned Ball",
|
||||
)
|
||||
ball = get_object(self, "Ball")
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ def migrate_channel_aliases(apps, schema_editor):
|
|||
|
||||
"""
|
||||
from evennia.comms.models import ChannelDB
|
||||
|
||||
# ChannelDB = apps.get_model("comms", "ChannelDB")
|
||||
|
||||
for channel in ChannelDB.objects.all():
|
||||
|
|
@ -20,8 +21,12 @@ def migrate_channel_aliases(apps, schema_editor):
|
|||
chan_key = channel.db_key.lower()
|
||||
channel_aliases = [chan_key] + [alias.lower() for alias in channel.aliases.all()]
|
||||
for subscriber in channel.subscriptions.all():
|
||||
nicktuples = subscriber.nicks.get(category="channel", return_tuple=True, return_list=True)
|
||||
all_aliases = channel_aliases + [tup[2] for tup in nicktuples if tup[3].lower() == chan_key]
|
||||
nicktuples = subscriber.nicks.get(
|
||||
category="channel", return_tuple=True, return_list=True
|
||||
)
|
||||
all_aliases = channel_aliases + [
|
||||
tup[2] for tup in nicktuples if tup[3].lower() == chan_key
|
||||
]
|
||||
for key_or_alias in all_aliases:
|
||||
channel.add_user_channel_alias(subscriber, key_or_alias)
|
||||
except Exception as err:
|
||||
|
|
@ -33,9 +38,7 @@ def migrate_channel_aliases(apps, schema_editor):
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('comms', '0018_auto_20191025_0831'),
|
||||
("comms", "0018_auto_20191025_0831"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(migrate_channel_aliases)
|
||||
]
|
||||
operations = [migrations.RunPython(migrate_channel_aliases)]
|
||||
|
|
|
|||
|
|
@ -6,21 +6,28 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('comms', '0019_auto_20210514_2032'),
|
||||
("comms", "0019_auto_20210514_2032"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='msg',
|
||||
name='db_hide_from_channels',
|
||||
model_name="msg",
|
||||
name="db_hide_from_channels",
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='msg',
|
||||
name='db_receivers_channels',
|
||||
model_name="msg",
|
||||
name="db_receivers_channels",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='msg',
|
||||
name='db_receiver_external',
|
||||
field=models.CharField(blank=True, db_index=True, help_text='identifier for single external receiver, for use with receivers without a database existence.', max_length=1024, null=True, verbose_name='external receiver'),
|
||||
model_name="msg",
|
||||
name="db_receiver_external",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="identifier for single external receiver, for use with receivers without a database existence.",
|
||||
max_length=1024,
|
||||
null=True,
|
||||
verbose_name="external receiver",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,51 +7,101 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('scripts', '0014_auto_20210520_2137'),
|
||||
("scripts", "0014_auto_20210520_2137"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('objects', '0011_auto_20191025_0831'),
|
||||
('comms', '0020_auto_20210514_2210'),
|
||||
("objects", "0011_auto_20191025_0831"),
|
||||
("comms", "0020_auto_20210514_2210"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_receiver_external',
|
||||
field=models.CharField(blank=True, db_index=True, help_text='Identifier for single external receiver, for use with recievers not represented by a regular database model.', max_length=1024, null=True, verbose_name='external receiver'),
|
||||
model_name="msg",
|
||||
name="db_receiver_external",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="Identifier for single external receiver, for use with recievers not represented by a regular database model.",
|
||||
max_length=1024,
|
||||
null=True,
|
||||
verbose_name="external receiver",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_receivers_accounts',
|
||||
field=models.ManyToManyField(blank=True, help_text='account receivers', related_name='receiver_account_set', to=settings.AUTH_USER_MODEL, verbose_name='Receivers (Accounts)'),
|
||||
model_name="msg",
|
||||
name="db_receivers_accounts",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="account receivers",
|
||||
related_name="receiver_account_set",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="Receivers (Accounts)",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_receivers_objects',
|
||||
field=models.ManyToManyField(blank=True, help_text='object receivers', related_name='receiver_object_set', to='objects.ObjectDB', verbose_name='Receivers (Objects)'),
|
||||
model_name="msg",
|
||||
name="db_receivers_objects",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="object receivers",
|
||||
related_name="receiver_object_set",
|
||||
to="objects.ObjectDB",
|
||||
verbose_name="Receivers (Objects)",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_receivers_scripts',
|
||||
field=models.ManyToManyField(blank=True, help_text='script_receivers', related_name='receiver_script_set', to='scripts.ScriptDB', verbose_name='Receivers (Scripts)'),
|
||||
model_name="msg",
|
||||
name="db_receivers_scripts",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
help_text="script_receivers",
|
||||
related_name="receiver_script_set",
|
||||
to="scripts.ScriptDB",
|
||||
verbose_name="Receivers (Scripts)",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_sender_accounts',
|
||||
field=models.ManyToManyField(blank=True, db_index=True, related_name='sender_account_set', to=settings.AUTH_USER_MODEL, verbose_name='Senders (Accounts)'),
|
||||
model_name="msg",
|
||||
name="db_sender_accounts",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
related_name="sender_account_set",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
verbose_name="Senders (Accounts)",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_sender_external',
|
||||
field=models.CharField(blank=True, db_index=True, help_text='Identifier for single external sender, for use with senders not represented by a regular database model.', max_length=255, null=True, verbose_name='external sender'),
|
||||
model_name="msg",
|
||||
name="db_sender_external",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="Identifier for single external sender, for use with senders not represented by a regular database model.",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="external sender",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_sender_objects',
|
||||
field=models.ManyToManyField(blank=True, db_index=True, related_name='sender_object_set', to='objects.ObjectDB', verbose_name='Senders (Objects)'),
|
||||
model_name="msg",
|
||||
name="db_sender_objects",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
related_name="sender_object_set",
|
||||
to="objects.ObjectDB",
|
||||
verbose_name="Senders (Objects)",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='msg',
|
||||
name='db_sender_scripts',
|
||||
field=models.ManyToManyField(blank=True, db_index=True, related_name='sender_script_set', to='scripts.ScriptDB', verbose_name='Senders (Scripts)'),
|
||||
model_name="msg",
|
||||
name="db_sender_scripts",
|
||||
field=models.ManyToManyField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
related_name="sender_script_set",
|
||||
to="scripts.ScriptDB",
|
||||
verbose_name="Senders (Scripts)",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -17,12 +17,14 @@ at_server_cold_stop()
|
|||
|
||||
"""
|
||||
|
||||
|
||||
def at_server_init():
|
||||
"""
|
||||
This is called first as the server is starting up, regardless of how.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def at_server_start():
|
||||
"""
|
||||
This is called every time the server starts up, regardless of
|
||||
|
|
|
|||
|
|
@ -6,17 +6,17 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('help', '0003_auto_20190128_1820'),
|
||||
("help", "0003_auto_20190128_1820"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='helpentry',
|
||||
name='db_staff_only',
|
||||
model_name="helpentry",
|
||||
name="db_staff_only",
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='helpentry',
|
||||
name='db_date_created',
|
||||
field=models.DateTimeField(auto_now=True, verbose_name='creation date'),
|
||||
model_name="helpentry",
|
||||
name="db_date_created",
|
||||
field=models.DateTimeField(auto_now=True, verbose_name="creation date"),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def update_help_entries(apps, schema_editor):
|
||||
"""
|
||||
Change all help-entry files that use view: locks to read: locks
|
||||
|
|
@ -11,8 +12,10 @@ def update_help_entries(apps, schema_editor):
|
|||
HelpEntry = apps.get_model("help", "HelpEntry")
|
||||
for help_entry in HelpEntry.objects.all():
|
||||
lock_storage = help_entry.db_lock_storage
|
||||
lock_storage = dict(lstring.split(":", 1) if ":" in lstring else (lstring, "")
|
||||
for lstring in str(lock_storage).split(";"))
|
||||
lock_storage = dict(
|
||||
lstring.split(":", 1) if ":" in lstring else (lstring, "")
|
||||
for lstring in str(lock_storage).split(";")
|
||||
)
|
||||
if "read" in lock_storage:
|
||||
# already in place - skip
|
||||
continue
|
||||
|
|
@ -26,9 +29,7 @@ def update_help_entries(apps, schema_editor):
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('help', '0004_auto_20210520_2137'),
|
||||
("help", "0004_auto_20210520_2137"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_help_entries)
|
||||
]
|
||||
operations = [migrations.RunPython(update_help_entries)]
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ PATH_REMAP_PREFIX = {
|
|||
"auditing": "evennia.contrib.utils",
|
||||
"fieldfill": "evennia.contrib.utils",
|
||||
"random_string_generator": "evennia.contrib.utils",
|
||||
"tree_select": "evennia.contrib.utils"
|
||||
"tree_select": "evennia.contrib.utils",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -52,43 +52,45 @@ def convert_contrib_typeclass_paths(apps, schema_editor):
|
|||
try:
|
||||
package_path = obj.db_typeclass_path.split(".")[2:]
|
||||
package_name = package_path[0]
|
||||
if package_path[0] == 'security':
|
||||
if package_path[0] == "security":
|
||||
# renamed package and changed path
|
||||
package_name = 'auditing'
|
||||
package_name = "auditing"
|
||||
package_path.pop(0) # no longer security/auditing
|
||||
if package_path[-1] == ".Clothing":
|
||||
# renamed Clothing class to ContribClothing
|
||||
package_path[-1] = "ContribClothing"
|
||||
package_path = '.'.join(package_path)
|
||||
package_path = ".".join(package_path)
|
||||
|
||||
except IndexError:
|
||||
print(f"obj.db_typeclass_path={obj.db_typeclass_path} could not be parsed "
|
||||
"for converting to the new contrib location.")
|
||||
print(
|
||||
f"obj.db_typeclass_path={obj.db_typeclass_path} could not be parsed "
|
||||
"for converting to the new contrib location."
|
||||
)
|
||||
continue
|
||||
if package_name in PATH_REMAP_PREFIX:
|
||||
obj.db_typeclass_path = f"{PATH_REMAP_PREFIX[package_name]}.{package_path}"
|
||||
obj.save(update_fields=['db_typeclass_path'])
|
||||
obj.save(update_fields=["db_typeclass_path"])
|
||||
|
||||
for obj in ObjectDB.objects.filter(db_cmdset_storage__startswith="evennia.contrib."):
|
||||
try:
|
||||
package_path = obj.db_cmdset_storage.split(".")[2:]
|
||||
package_name = package_path[0]
|
||||
package_path = '.'.join(package_path)
|
||||
package_path = ".".join(package_path)
|
||||
except IndexError:
|
||||
print(f"obj.db_cmdset_storage={obj.db_cmdset_storage} could not be parsed "
|
||||
"for converting to the new contrib location.")
|
||||
print(
|
||||
f"obj.db_cmdset_storage={obj.db_cmdset_storage} could not be parsed "
|
||||
"for converting to the new contrib location."
|
||||
)
|
||||
continue
|
||||
if package_name in PATH_REMAP_PREFIX:
|
||||
obj.db_cmdset_storage = f"{PATH_REMAP_PREFIX[package_name]}.{package_path}"
|
||||
obj.save(update_fields=['db_cmdset_storage'])
|
||||
obj.save(update_fields=["db_cmdset_storage"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('objects', '0011_auto_20191025_0831'),
|
||||
("objects", "0011_auto_20191025_0831"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(convert_contrib_typeclass_paths, migrations.RunPython.noop)
|
||||
]
|
||||
operations = [migrations.RunPython(convert_contrib_typeclass_paths, migrations.RunPython.noop)]
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@ from evennia import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom
|
|||
from evennia.objects.models import ObjectDB
|
||||
from evennia.objects.objects import DefaultObject
|
||||
from evennia.typeclasses.attributes import AttributeProperty
|
||||
from evennia.typeclasses.tags import (AliasProperty, PermissionProperty,
|
||||
TagProperty)
|
||||
from evennia.typeclasses.tags import AliasProperty, PermissionProperty, TagProperty
|
||||
from evennia.utils import create
|
||||
from evennia.utils.test_resources import BaseEvenniaTest, EvenniaTestCase
|
||||
|
||||
|
|
@ -240,14 +239,16 @@ class SubAttributeProperty(AttributeProperty):
|
|||
class SubTagProperty(TagProperty):
|
||||
pass
|
||||
|
||||
|
||||
class CustomizedProperty(AttributeProperty):
|
||||
def at_set(self, value, obj):
|
||||
obj.settest = value
|
||||
return value
|
||||
|
||||
|
||||
def at_get(self, value, obj):
|
||||
return value + obj.awaretest
|
||||
|
||||
|
||||
class TestObjectPropertiesClass(DefaultObject):
|
||||
attr1 = AttributeProperty(default="attr1")
|
||||
attr2 = AttributeProperty(default="attr2", category="attrcategory")
|
||||
|
|
@ -266,6 +267,7 @@ class TestObjectPropertiesClass(DefaultObject):
|
|||
def base_property(self):
|
||||
self.property_initialized = True
|
||||
|
||||
|
||||
class TestProperties(EvenniaTestCase):
|
||||
"""
|
||||
Test Properties.
|
||||
|
|
@ -273,7 +275,9 @@ class TestProperties(EvenniaTestCase):
|
|||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.obj: TestObjectPropertiesClass = create.create_object(TestObjectPropertiesClass, key="testobj")
|
||||
self.obj: TestObjectPropertiesClass = create.create_object(
|
||||
TestObjectPropertiesClass, key="testobj"
|
||||
)
|
||||
|
||||
def tearDown(self):
|
||||
self.obj.delete()
|
||||
|
|
@ -317,7 +321,7 @@ class TestProperties(EvenniaTestCase):
|
|||
self.assertFalse(hasattr(obj, "property_initialized"))
|
||||
|
||||
def test_object_awareness(self):
|
||||
'''Test the "object-awareness" of customized AttributeProperty getter/setters'''
|
||||
"""Test the "object-awareness" of customized AttributeProperty getter/setters"""
|
||||
obj = self.obj
|
||||
|
||||
# attribute properties receive on obj ref in the getter/setter that can customize return
|
||||
|
|
|
|||
|
|
@ -6,18 +6,22 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('scripts', '0013_auto_20191025_0831'),
|
||||
("scripts", "0013_auto_20191025_0831"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='scriptdb',
|
||||
name='db_interval',
|
||||
field=models.IntegerField(default=-1, help_text='how often to repeat script, in seconds. <= 0 means off.', verbose_name='interval'),
|
||||
model_name="scriptdb",
|
||||
name="db_interval",
|
||||
field=models.IntegerField(
|
||||
default=-1,
|
||||
help_text="how often to repeat script, in seconds. <= 0 means off.",
|
||||
verbose_name="interval",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='scriptdb',
|
||||
name='db_persistent',
|
||||
field=models.BooleanField(default=True, verbose_name='survive server reboot'),
|
||||
model_name="scriptdb",
|
||||
name="db_persistent",
|
||||
field=models.BooleanField(default=True, verbose_name="survive server reboot"),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ PATH_REMAP_PREFIX = {
|
|||
"auditing": "evennia.contrib.utils",
|
||||
"fieldfill": "evennia.contrib.utils",
|
||||
"random_string_generator": "evennia.contrib.utils",
|
||||
"tree_select": "evennia.contrib.utils"
|
||||
"tree_select": "evennia.contrib.utils",
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -52,30 +52,30 @@ def convert_contrib_typeclass_paths(apps, schema_editor):
|
|||
try:
|
||||
package_path = obj.db_typeclass_path.split(".")[2:]
|
||||
package_name = package_path[0]
|
||||
if package_path[0] == 'security':
|
||||
if package_path[0] == "security":
|
||||
# renamed package and changed path
|
||||
package_name = 'auditing'
|
||||
package_name = "auditing"
|
||||
package_path.pop(0) # no longer security/auditing
|
||||
if package_path[-1] == ".Clothing":
|
||||
# renamed Clothing class to ContribClothing
|
||||
package_path[-1] = "ContribClothing"
|
||||
package_path = '.'.join(package_path)
|
||||
package_path = ".".join(package_path)
|
||||
|
||||
except IndexError:
|
||||
print(f"obj.db_typeclass_path={obj.db_typeclass_path} could not be parsed "
|
||||
"for converting to the new contrib location.")
|
||||
print(
|
||||
f"obj.db_typeclass_path={obj.db_typeclass_path} could not be parsed "
|
||||
"for converting to the new contrib location."
|
||||
)
|
||||
continue
|
||||
if package_name in PATH_REMAP_PREFIX:
|
||||
obj.db_typeclass_path = f"{PATH_REMAP_PREFIX[package_name]}.{package_path}"
|
||||
obj.save(update_fields=['db_typeclass_path'])
|
||||
obj.save(update_fields=["db_typeclass_path"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('scripts', '0014_auto_20210520_2137'),
|
||||
("scripts", "0014_auto_20210520_2137"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(convert_contrib_typeclass_paths, migrations.RunPython.noop)
|
||||
]
|
||||
operations = [migrations.RunPython(convert_contrib_typeclass_paths, migrations.RunPython.noop)]
|
||||
|
|
|
|||
|
|
@ -47,8 +47,11 @@ _SA = object.__setattr__
|
|||
SERVER_RESTART = os.path.join(settings.GAME_DIR, "server", "server.restart")
|
||||
|
||||
# modules containing hook methods called during start_stop
|
||||
SERVER_STARTSTOP_MODULES = [mod_import(mod) for mod in make_iter(settings.AT_SERVER_STARTSTOP_MODULE)
|
||||
if isinstance(mod, str)]
|
||||
SERVER_STARTSTOP_MODULES = [
|
||||
mod_import(mod)
|
||||
for mod in make_iter(settings.AT_SERVER_STARTSTOP_MODULE)
|
||||
if isinstance(mod, str)
|
||||
]
|
||||
|
||||
# modules containing plugin services
|
||||
SERVER_SERVICES_PLUGIN_MODULES = make_iter(settings.SERVER_SERVICES_PLUGIN_MODULES)
|
||||
|
|
|
|||
|
|
@ -202,18 +202,18 @@ class AttributeProperty:
|
|||
self._lockstring = lockstring
|
||||
self._autocreate = autocreate
|
||||
self._key = ""
|
||||
|
||||
|
||||
@property
|
||||
def _default(self):
|
||||
"""
|
||||
Tries returning a new instance of default if callable.
|
||||
|
||||
|
||||
"""
|
||||
if callable(self.__default):
|
||||
return self.__default()
|
||||
|
||||
|
||||
return self.__default
|
||||
|
||||
|
||||
@_default.setter
|
||||
def _default(self, value):
|
||||
self.__default = value
|
||||
|
|
@ -233,13 +233,16 @@ class AttributeProperty:
|
|||
"""
|
||||
value = self._default
|
||||
try:
|
||||
value = self.at_get(getattr(instance, self.attrhandler_name).get(
|
||||
key=self._key,
|
||||
default=self._default,
|
||||
category=self._category,
|
||||
strattr=self._strattr,
|
||||
raise_exception=self._autocreate,
|
||||
), instance)
|
||||
value = self.at_get(
|
||||
getattr(instance, self.attrhandler_name).get(
|
||||
key=self._key,
|
||||
default=self._default,
|
||||
category=self._category,
|
||||
strattr=self._strattr,
|
||||
raise_exception=self._autocreate,
|
||||
),
|
||||
instance,
|
||||
)
|
||||
except AttributeError:
|
||||
if self._autocreate:
|
||||
# attribute didn't exist and autocreate is set
|
||||
|
|
|
|||
|
|
@ -6,13 +6,20 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0013_auto_20191015_1922'),
|
||||
("typeclasses", "0013_auto_20191015_1922"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='db_category',
|
||||
field=models.CharField(blank=True, db_index=True, help_text='tag category', max_length=64, null=True, verbose_name='category'),
|
||||
model_name="tag",
|
||||
name="db_category",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="tag category",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="category",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ from django.db import migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0014_alter_tag_db_category'),
|
||||
("typeclasses", "0014_alter_tag_db_category"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='attribute',
|
||||
options={'verbose_name': 'Attribute'},
|
||||
name="attribute",
|
||||
options={"verbose_name": "Attribute"},
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ from evennia.scripts.scripts import DefaultScript
|
|||
from evennia.utils.test_resources import EvenniaTest
|
||||
from evennia.utils.search import search_script_attribute, search_script_tag, search_script
|
||||
|
||||
class TestSearch(EvenniaTest):
|
||||
|
||||
class TestSearch(EvenniaTest):
|
||||
def test_search_script_tag(self):
|
||||
"""Check that a script can be found by its tag."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
|
|
@ -19,21 +19,21 @@ class TestSearch(EvenniaTest):
|
|||
found = search_script_tag("a-tag", category="a-category")
|
||||
self.assertEqual(len(found), 1, errors)
|
||||
self.assertEqual(script.key, found[0].key, errors)
|
||||
|
||||
|
||||
def test_search_script_tag_wrong_category(self):
|
||||
"""Check that a script cannot be found by the wrong category."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
script.tags.add("a-tag", category="a-category")
|
||||
found = search_script_tag("a-tag", category="wrong-category")
|
||||
self.assertEqual(len(found), 0, errors)
|
||||
|
||||
|
||||
def test_search_script_tag_wrong(self):
|
||||
"""Check that a script cannot be found by the wrong tag."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
script.tags.add("a-tag", category="a-category")
|
||||
found = search_script_tag("wrong-tag", category="a-category")
|
||||
self.assertEqual(len(found), 0, errors)
|
||||
|
||||
|
||||
def test_search_script_attribute(self):
|
||||
"""Check that a script can be found by its attributes."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
|
|
@ -41,24 +41,23 @@ class TestSearch(EvenniaTest):
|
|||
found = search_script_attribute(key="an_attribute", value="some value")
|
||||
self.assertEqual(len(found), 1, errors)
|
||||
self.assertEqual(script.key, found[0].key, errors)
|
||||
|
||||
|
||||
def test_search_script_attribute_wrong(self):
|
||||
"""Check that a script cannot be found by wrong value of its attributes."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
script.db.an_attribute = "some value"
|
||||
found = search_script_attribute(key="an_attribute", value="wrong value")
|
||||
self.assertEqual(len(found), 0, errors)
|
||||
|
||||
|
||||
def test_search_script_key(self):
|
||||
"""Check that a script can be found by its key value."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
found = search_script("a-script")
|
||||
self.assertEqual(len(found), 1, errors)
|
||||
self.assertEqual(script.key, found[0].key, errors)
|
||||
|
||||
|
||||
def test_search_script_wrong_key(self):
|
||||
"""Check that a script cannot be found by a wrong key value."""
|
||||
script, errors = DefaultScript.create("a-script")
|
||||
found = search_script("wrong_key")
|
||||
self.assertEqual(len(found), 0, errors)
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,9 @@ class TestListToString(TestCase):
|
|||
self.assertEqual("1, 2 and 3", utils.list_to_string([1, 2, 3], endsep="and"))
|
||||
self.assertEqual("1, 2 3", utils.list_to_string([1, 2, 3], endsep=""))
|
||||
self.assertEqual("1; 2; 3", utils.list_to_string([1, 2, 3], sep=";", endsep=";"))
|
||||
self.assertEqual('"1", "2", "3"', utils.list_to_string([1, 2, 3], endsep=",", addquote=True))
|
||||
self.assertEqual(
|
||||
'"1", "2", "3"', utils.list_to_string([1, 2, 3], endsep=",", addquote=True)
|
||||
)
|
||||
self.assertEqual(
|
||||
'"1", "2" and "3"', utils.list_to_string([1, 2, 3], endsep="and", addquote=True)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -275,8 +275,7 @@ class CharacterPuppetView(EvenniaWebTest):
|
|||
self.assertTrue(
|
||||
response.status_code >= 400,
|
||||
"Invalid access should return a 4xx code-- either obj not found or permission denied!"
|
||||
" (Returned %s)"
|
||||
% response.status_code,
|
||||
" (Returned %s)" % response.status_code,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue