Run black reformatter on code

This commit is contained in:
Griatch 2022-02-08 13:03:52 +01:00
parent 4582eb4085
commit bd3e31bf3c
178 changed files with 4511 additions and 3385 deletions

View file

@ -80,47 +80,63 @@ _SEARCH_AT_RESULT = utils.variable_from_module(*settings.SEARCH_AT_RESULT.rsplit
# is the normal "production message to echo to the account.
_ERROR_UNTRAPPED = (
_("""
_(
"""
An untrapped error occurred.
"""),
_("""
"""
),
_(
"""
An untrapped error occurred. Please file a bug report detailing the steps to reproduce.
"""),
"""
),
)
_ERROR_CMDSETS = (
_("""
_(
"""
A cmdset merger-error occurred. This is often due to a syntax
error in one of the cmdsets to merge.
"""),
_("""
"""
),
_(
"""
A cmdset merger-error occurred. Please file a bug report detailing the
steps to reproduce.
"""),
"""
),
)
_ERROR_NOCMDSETS = (
_("""
_(
"""
No command sets found! This is a critical bug that can have
multiple causes.
"""),
_("""
"""
),
_(
"""
No command sets found! This is a sign of a critical bug. If
disconnecting/reconnecting doesn't" solve the problem, try to contact
the server admin through" some other means for assistance.
"""),
"""
),
)
_ERROR_CMDHANDLER = (
_("""
_(
"""
A command handler bug occurred. If this is not due to a local change,
please file a bug report with the Evennia project, including the
traceback and steps to reproduce.
"""),
_("""
"""
),
_(
"""
A command handler bug occurred. Please notify staff - they should
likely file a bug report with the Evennia project.
"""),
"""
),
)
_ERROR_RECURSION_LIMIT = _(

View file

@ -71,7 +71,7 @@ def build_matches(raw_string, cmdset, include_prefixes=False):
for cmdname in [cmd.key] + cmd.aliases
if cmdname
and l_raw_string.startswith(cmdname.lower())
and (not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname):]))
and (not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname) :]))
]
)
else:
@ -90,7 +90,7 @@ def build_matches(raw_string, cmdset, include_prefixes=False):
if (
cmdname
and l_raw_string.startswith(cmdname.lower())
and (not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname):]))
and (not cmd.arg_regex or cmd.arg_regex.match(l_raw_string[len(cmdname) :]))
):
matches.append(create_match(cmdname, raw_string, cmd, raw_cmdname))
except Exception:
@ -125,7 +125,10 @@ def try_num_differentiators(raw_string):
# the user might be trying to identify the command
# with a #num-command style syntax. We expect the regex to
# contain the groups "number" and "name".
mindex, new_raw_string = (num_ref_match.group("number"), num_ref_match.group("name") + num_ref_match.group("args"))
mindex, new_raw_string = (
num_ref_match.group("number"),
num_ref_match.group("name") + num_ref_match.group("args"),
)
return int(mindex), new_raw_string
else:
return None, None
@ -182,9 +185,7 @@ def cmdparser(raw_string, cmdset, caller, match_index=None):
if not matches and _CMD_IGNORE_PREFIXES:
# still no match. Try to strip prefixes
raw_string = (
raw_string.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_string) > 1 else raw_string
)
raw_string = raw_string.lstrip(_CMD_IGNORE_PREFIXES) if len(raw_string) > 1 else raw_string
matches = build_matches(raw_string, cmdset, include_prefixes=False)
# only select command matches we are actually allowed to call.

View file

@ -358,14 +358,18 @@ class CmdSet(object, metaclass=_CmdSetMeta):
"""
perm = "perm" if self.persistent else "non-perm"
options = ", ".join([
"{}:{}".format(opt, "T" if getattr(self, opt) else "F")
for opt in ("no_exits", "no_objs", "no_channels", "duplicates")
if getattr(self, opt) is not None
])
options = ", ".join(
[
"{}:{}".format(opt, "T" if getattr(self, opt) else "F")
for opt in ("no_exits", "no_objs", "no_channels", "duplicates")
if getattr(self, opt) is not None
]
)
options = (", " + options) if options else ""
return (f"<CmdSet {self.key}, {self.mergetype}, {perm}, prio {self.priority}{options}>: "
+ ", ".join([str(cmd) for cmd in sorted(self.commands, key=lambda o: o.key)]))
return (
f"<CmdSet {self.key}, {self.mergetype}, {perm}, prio {self.priority}{options}>: "
+ ", ".join([str(cmd) for cmd in sorted(self.commands, key=lambda o: o.key)])
)
def __iter__(self):
"""
@ -519,10 +523,12 @@ class CmdSet(object, metaclass=_CmdSetMeta):
try:
cmdset = self._instantiate(cmdset)
except RuntimeError:
err = ("Adding cmdset {cmdset} to {cls} lead to an "
"infinite loop. When adding a cmdset to another, "
"make sure they are not themself cyclically added to "
"the new cmdset somewhere in the chain.")
err = (
"Adding cmdset {cmdset} to {cls} lead to an "
"infinite loop. When adding a cmdset to another, "
"make sure they are not themself cyclically added to "
"the new cmdset somewhere in the chain."
)
raise RuntimeError(_(err.format(cmdset=cmdset, cls=self.__class__)))
cmds = cmdset.commands
elif is_iter(cmd):

View file

@ -423,8 +423,7 @@ class CmdSetHandler(object):
self.mergetype_stack.append(new_current.actual_mergetype)
self.current = new_current
def add(self, cmdset, emit_to_obj=None, persistent=False, default_cmdset=False,
**kwargs):
def add(self, cmdset, emit_to_obj=None, persistent=False, default_cmdset=False, **kwargs):
"""
Add a cmdset to the handler, on top of the old ones, unless it
is set as the default one (it will then end up at the bottom of the stack)
@ -451,9 +450,11 @@ class CmdSetHandler(object):
"""
if "permanent" in kwargs:
logger.log_dep("obj.cmdset.add() kwarg 'permanent' has changed name to "
"'persistent' and now defaults to True.")
persistent = kwargs['permanent'] if persistent is None else persistent
logger.log_dep(
"obj.cmdset.add() kwarg 'permanent' has changed name to "
"'persistent' and now defaults to True."
)
persistent = kwargs["permanent"] if persistent is None else persistent
if not (isinstance(cmdset, str) or utils.inherits_from(cmdset, CmdSet)):
string = _("Only CmdSets can be added to the cmdsethandler!")
@ -491,9 +492,10 @@ class CmdSetHandler(object):
"""
if "permanent" in kwargs:
logger.log_dep("obj.cmdset.add_default() kwarg 'permanent' has changed name to "
"'persistent'.")
persistent = kwargs['permanent'] if persistent is None else persistent
logger.log_dep(
"obj.cmdset.add_default() kwarg 'permanent' has changed name to 'persistent'."
)
persistent = kwargs["permanent"] if persistent is None else persistent
self.add(cmdset, emit_to_obj=emit_to_obj, persistent=persistent, default_cmdset=True)
def remove(self, cmdset=None, default_cmdset=False):

View file

@ -102,16 +102,16 @@ def _init_command(cls, **kwargs):
# pre-prepare a help index entry for quicker lookup
# strip the @- etc to allow help to be agnostic
stripped_key = cls.key[1:] if cls.key and cls.key[0] in CMD_IGNORE_PREFIXES else ""
stripped_aliases = (
" ".join(al[1:] if al and al[0] in CMD_IGNORE_PREFIXES else al
for al in cls.aliases))
stripped_aliases = " ".join(
al[1:] if al and al[0] in CMD_IGNORE_PREFIXES else al for al in cls.aliases
)
cls.search_index_entry = {
"key": cls.key,
"aliases": " ".join(cls.aliases),
"no_prefix": f"{stripped_key} {stripped_aliases}",
"category": cls.help_category,
"text": cls.__doc__,
"tags": ""
"tags": "",
}
@ -562,7 +562,7 @@ Command {self} has no defined `func()` - showing on-command variables:
"""
try:
return reverse(
'help-entry-detail',
"help-entry-detail",
kwargs={"category": slugify(self.help_category), "topic": slugify(self.key)},
)
except Exception as e:

View file

@ -217,7 +217,7 @@ class CmdBan(COMMAND_DEFAULT_CLASS):
ipregex = re.compile(r"%s" % ipregex)
bantup = ("", ban, ipregex, now, reason)
ret = yield(f"Are you sure you want to {typ}-ban '|w{ban}|n' [Y]/N?")
ret = yield (f"Are you sure you want to {typ}-ban '|w{ban}|n' [Y]/N?")
if str(ret).lower() in ("no", "n"):
self.caller.msg("Aborted.")
return
@ -273,7 +273,7 @@ class CmdUnban(COMMAND_DEFAULT_CLASS):
ban = banlist[num - 1]
value = (" ".join([s for s in ban[:2]])).strip()
ret = yield(f"Are you sure you want to unban {num}: '|w{value}|n' [Y]/N?")
ret = yield (f"Are you sure you want to unban {num}: '|w{value}|n' [Y]/N?")
if str(ret).lower() in ("n", "no"):
self.caller.msg("Aborted.")
return

View file

@ -17,7 +17,8 @@ from evennia.utils.utils import (
class_from_module,
get_all_typeclasses,
variable_from_module,
dbref, crop,
dbref,
crop,
interactive,
list_to_string,
display_len,
@ -1498,9 +1499,11 @@ class CmdOpen(ObjManipCommand):
super().parse()
self.location = self.caller.location
if not self.args or not self.rhs:
self.caller.msg("Usage: open <new exit>[;alias...][:typeclass]"
"[,<return exit>[;alias..][:typeclass]]] "
"= <destination>")
self.caller.msg(
"Usage: open <new exit>[;alias...][:typeclass]"
"[,<return exit>[;alias..][:typeclass]]] "
"= <destination>"
)
raise InterruptCommand
if not self.location:
self.caller.msg("You cannot create an exit from a None-location.")
@ -1519,8 +1522,9 @@ class CmdOpen(ObjManipCommand):
as well as the self.create_exit() method.
"""
# Create exit
ok = self.create_exit(self.exit_name, self.location, self.destination,
self.exit_aliases, self.exit_typeclass)
ok = self.create_exit(
self.exit_name, self.location, self.destination, self.exit_aliases, self.exit_typeclass
)
if not ok:
# an error; the exit was not created, so we quit.
return
@ -1529,8 +1533,13 @@ class CmdOpen(ObjManipCommand):
back_exit_name = self.lhs_objs[1]["name"]
back_exit_aliases = self.lhs_objs[1]["aliases"]
back_exit_typeclass = self.lhs_objs[1]["option"]
self.create_exit(back_exit_name, self.destination, self.location, back_exit_aliases,
back_exit_typeclass)
self.create_exit(
back_exit_name,
self.destination,
self.location,
back_exit_aliases,
back_exit_typeclass,
)
def _convert_from_string(cmd, strobj):
@ -1740,8 +1749,10 @@ class CmdSetAttribute(ObjManipCommand):
obj.attributes.remove(attr, category=category)
return f"\nDeleted attribute {obj.name}/|w{attr}|n [category:{category}]."
else:
return (f"\nNo attribute {obj.name}/|w{attr}|n [category: {category}] "
"was found to delete.")
return (
f"\nNo attribute {obj.name}/|w{attr}|n [category: {category}] "
"was found to delete."
)
error = f"\nNo attribute {obj.name}/|w{attr}|n [category: {category}] was found to delete."
if nested:
error += " (Nested lookups attempted)"
@ -1813,7 +1824,7 @@ class CmdSetAttribute(ObjManipCommand):
except AttributeError:
# we set empty buffer on nonexisting Attribute because otherwise
# we'd always have the string "None" in the buffer to start with
old_value = ''
old_value = ""
return str(old_value) # we already confirmed we are ok with this
def save(caller, buf):
@ -1825,11 +1836,12 @@ class CmdSetAttribute(ObjManipCommand):
try:
old_value = obj.attributes.get(attr, raise_exception=True)
if not isinstance(old_value, str):
answer = yield(
answer = yield (
f"|rWarning: Attribute |w{attr}|r is of type |w{type(old_value).__name__}|r. "
"\nTo continue editing, it must be converted to (and saved as) a string. "
"Continue? [Y]/N?")
if answer.lower() in ('n', 'no'):
"Continue? [Y]/N?"
)
if answer.lower() in ("n", "no"):
self.caller.msg("Aborted edit.")
return
except AttributeError:
@ -1903,9 +1915,11 @@ class CmdSetAttribute(ObjManipCommand):
caller.msg("The Line editor can only be applied " "to one attribute at a time.")
return
if not attrs:
caller.msg("Use `set/edit <objname>/<attr>` to define the Attribute to edit.\nTo "
"edit the current room description, use `set/edit here/desc` (or "
"use the `desc` command).")
caller.msg(
"Use `set/edit <objname>/<attr>` to define the Attribute to edit.\nTo "
"edit the current room description, use `set/edit here/desc` (or "
"use the `desc` command)."
)
return
self.edit_handler(obj, attrs[0], caller)
return
@ -1936,8 +1950,10 @@ class CmdSetAttribute(ObjManipCommand):
global _ATTRFUNCPARSER
if not _ATTRFUNCPARSER:
_ATTRFUNCPARSER = funcparser.FuncParser(
{"dbref": funcparser.funcparser_callable_search,
"search": funcparser.funcparser_callable_search}
{
"dbref": funcparser.funcparser_callable_search,
"search": funcparser.funcparser_callable_search,
}
)
if not (obj.access(self.caller, "control") or obj.access(self.caller, "edit")):
@ -1951,10 +1967,13 @@ class CmdSetAttribute(ObjManipCommand):
if hasattr(parsed_value, "access"):
# if this is an object we must have the right to read it, if so,
# we will not convert it to a string
if not (parsed_value.access(caller, "control")
or parsed_value.access(self.caller, "edit")):
caller.msg("You don't have permission to set "
f"object with identifier '{value}'.")
if not (
parsed_value.access(caller, "control")
or parsed_value.access(self.caller, "edit")
):
caller.msg(
"You don't have permission to set " f"object with identifier '{value}'."
)
continue
value = parsed_value
else:
@ -2038,7 +2057,7 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
obj = caller.search(query)
if not obj:
return
elif (self.account and self.account.__dbclass__ == dbclass):
elif self.account and self.account.__dbclass__ == dbclass:
# applying account while caller is object
caller.msg(f"Trying to search {new_typeclass} with query '{self.lhs}'.")
obj = self.account.search(query)
@ -2071,7 +2090,7 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
caller = self.caller
if "list" in self.switches or self.cmdname in ('typeclasses', '@typeclasses'):
if "list" in self.switches or self.cmdname in ("typeclasses", "@typeclasses"):
tclasses = get_all_typeclasses()
contribs = [key for key in sorted(tclasses) if key.startswith("evennia.contrib")] or [
"<None loaded>"
@ -2188,8 +2207,10 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
is_same = obj.is_typeclass(new_typeclass, exact=True)
if is_same and "force" not in self.switches:
string = (f"{obj.name} already has the typeclass '{new_typeclass}'. "
"Use /force to override.")
string = (
f"{obj.name} already has the typeclass '{new_typeclass}'. "
"Use /force to override."
)
else:
update = "update" in self.switches
reset = "reset" in self.switches
@ -2220,7 +2241,8 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
if "prototype" in self.switches:
modified = spawner.batch_update_objects_with_prototype(
prototype, objects=[obj], caller=self.caller)
prototype, objects=[obj], caller=self.caller
)
prototype_success = modified > 0
if not prototype_success:
caller.msg("Prototype %s failed to apply." % prototype["key"])
@ -2543,9 +2565,7 @@ class CmdExamine(ObjManipCommand):
def format_locks(self, obj):
locks = str(obj.locks)
if locks:
return utils.fill(
"; ".join([lock for lock in locks.split(";")]), indent=2
)
return utils.fill("; ".join([lock for lock in locks.split(";")]), indent=2)
return "Default"
def format_scripts(self, obj):
@ -2572,6 +2592,7 @@ class CmdExamine(ObjManipCommand):
if value:
return f"{string}: T"
return f"{string}: F"
txt = ", ".join(
_truefalse(opt, getattr(cmdset, opt))
for opt in ("no_exits", "no_objs", "no_channels", "duplicates")
@ -2607,13 +2628,18 @@ class CmdExamine(ObjManipCommand):
# we only show the first session's cmdset here (it is -in principle- possible
# that different sessions have different cmdsets but for admins who want such
# madness it is better that they overload with their own CmdExamine to handle it).
all_cmdsets.extend([(cmdset.key, cmdset)
for cmdset in obj.account.sessions.all()[0].cmdset.all()])
all_cmdsets.extend(
[(cmdset.key, cmdset) for cmdset in obj.account.sessions.all()[0].cmdset.all()]
)
else:
try:
# we have to protect this since many objects don't have sessions.
all_cmdsets.extend([(cmdset.key, cmdset)
for cmdset in obj.get_session(obj.sessions.get()).cmdset.all()])
all_cmdsets.extend(
[
(cmdset.key, cmdset)
for cmdset in obj.get_session(obj.sessions.get()).cmdset.all()
]
)
except (TypeError, AttributeError):
# an error means we are merging an object without a session
pass
@ -2659,8 +2685,10 @@ class CmdExamine(ObjManipCommand):
typ = f" |B[type: {typ}]|n" if typ else ""
value = utils.to_str(value)
value = _FUNCPARSER.parse(ansi_raw(value), escape=True)
return (f"Attribute {obj.name}/{self.header_color}{key}|n "
f"[category={category}]{typ}:\n\n{value}")
return (
f"Attribute {obj.name}/{self.header_color}{key}|n "
f"[category={category}]{typ}:\n\n{value}"
)
def format_single_attribute(self, attr):
global _FUNCPARSER
@ -2680,8 +2708,7 @@ class CmdExamine(ObjManipCommand):
def format_attributes(self, obj):
output = "\n " + "\n ".join(
sorted(self.format_single_attribute(attr)
for attr in obj.db_attributes.all())
sorted(self.format_single_attribute(attr) for attr in obj.db_attributes.all())
)
if output.strip():
# we don't want just an empty line
@ -2695,8 +2722,7 @@ class CmdExamine(ObjManipCommand):
if ndb_attr and ndb_attr[0]:
return "\n " + " \n".join(
sorted(self.format_single_attribute(attr)
for attr, value in ndb_attr)
sorted(self.format_single_attribute(attr) for attr, value in ndb_attr)
)
def format_exits(self, obj):
@ -2706,14 +2732,16 @@ class CmdExamine(ObjManipCommand):
def format_chars(self, obj):
if hasattr(obj, "contents"):
chars = ", ".join(f"{obj.name}({obj.dbref})" for obj in obj.contents
if obj.account)
chars = ", ".join(f"{obj.name}({obj.dbref})" for obj in obj.contents if obj.account)
return chars if chars else None
def format_things(self, obj):
if hasattr(obj, "contents"):
things = ", ".join(f"{obj.name}({obj.dbref})" for obj in obj.contents
if not obj.account and not obj.destination)
things = ", ".join(
f"{obj.name}({obj.dbref})"
for obj in obj.contents
if not obj.account and not obj.destination
)
return things if things else None
def format_script_desc(self, obj):
@ -2736,8 +2764,10 @@ class CmdExamine(ObjManipCommand):
remaining_repeats = obj.remaining_repeats()
remaining_repeats = 0 if remaining_repeats is None else remaining_repeats
repeats = f" - {remaining_repeats}/{obj.db_repeats} remain"
return (f"{active} - interval: {interval}s "
f"(next: {next_repeat}{repeats}, start_delay: {start_delay})")
return (
f"{active} - interval: {interval}s "
f"(next: {next_repeat}{repeats}, start_delay: {start_delay})"
)
def format_channel_sub_totals(self, obj):
if hasattr(obj, "db_account_subscriptions"):
@ -2752,14 +2782,16 @@ class CmdExamine(ObjManipCommand):
account_subs = obj.db_account_subscriptions.all()
if account_subs:
return "\n " + "\n ".join(
format_grid([sub.key for sub in account_subs], sep=' ', width=_DEFAULT_WIDTH))
format_grid([sub.key for sub in account_subs], sep=" ", width=_DEFAULT_WIDTH)
)
def format_channel_object_subs(self, obj):
if hasattr(obj, "db_object_subscriptions"):
object_subs = obj.db_object_subscriptions.all()
if object_subs:
return "\n " + "\n ".join(
format_grid([sub.key for sub in object_subs], sep=' ', width=_DEFAULT_WIDTH))
format_grid([sub.key for sub in object_subs], sep=" ", width=_DEFAULT_WIDTH)
)
def get_formatted_obj_data(self, obj, current_cmdset):
"""
@ -2781,13 +2813,14 @@ class CmdExamine(ObjManipCommand):
objdata["Destination"] = self.format_destination(obj)
objdata["Permissions"] = self.format_permissions(obj)
objdata["Locks"] = self.format_locks(obj)
if (current_cmdset
and not (len(obj.cmdset.all()) == 1
and obj.cmdset.current.key == "_EMPTY_CMDSET")):
if current_cmdset and not (
len(obj.cmdset.all()) == 1 and obj.cmdset.current.key == "_EMPTY_CMDSET"
):
objdata["Stored Cmdset(s)"] = self.format_stored_cmdsets(obj)
objdata["Merged Cmdset(s)"] = self.format_merged_cmdsets(obj, current_cmdset)
objdata[f"Commands vailable to {obj.key} (result of Merged Cmdset(s))"] = (
self.format_current_cmds(obj, current_cmdset))
objdata[
f"Commands vailable to {obj.key} (result of Merged Cmdset(s))"
] = self.format_current_cmds(obj, current_cmdset)
if self.object_type == "script":
objdata["Description"] = self.format_script_desc(obj)
objdata["Persistent"] = self.format_script_is_persistent(obj)
@ -2859,10 +2892,11 @@ class CmdExamine(ObjManipCommand):
obj = None
elif len(obj) > 1:
err = "Multiple {objtype} found with key {obj_name}:\n{matches}"
self.caller.msg(err.format(
obj_name=obj_name,
matches=", ".join(f"{ob.key}(#{ob.id})" for ob in obj)
))
self.caller.msg(
err.format(
obj_name=obj_name, matches=", ".join(f"{ob.key}(#{ob.id})" for ob in obj)
)
)
obj = None
else:
obj = obj[0]
@ -2887,13 +2921,16 @@ class CmdExamine(ObjManipCommand):
# is not so common anyway.
obj = None
obj_name = objdef["name"] # name
obj_name = objdef["name"] # name
obj_attrs = objdef["attrs"] # /attrs
# identify object type, in prio account - script - channel
object_type = "object"
if (utils.inherits_from(self.caller, "evennia.accounts.accounts.DefaultAccount")
or "account" in self.switches or obj_name.startswith("*")):
if (
utils.inherits_from(self.caller, "evennia.accounts.accounts.DefaultAccount")
or "account" in self.switches
or obj_name.startswith("*")
):
object_type = "account"
elif "script" in self.switches:
object_type = "script"
@ -3293,7 +3330,7 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
"start": "|gStarted|n",
"stop": "|RStopped|n",
"pause": "|Paused|n",
"delete": "|rDeleted|n"
"delete": "|rDeleted|n",
}
def _search_script(self, args):
@ -3307,7 +3344,7 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
return scripts
if "-" in args:
# may be a dbref-range
val1, val2 = (dbref(part.strip()) for part in args.split('-', 1))
val1, val2 = (dbref(part.strip()) for part in args.split("-", 1))
if val1 and val2:
scripts = ScriptDB.objects.filter(id__in=(range(val1, val2 + 1)))
if scripts:
@ -3348,11 +3385,14 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
if obj.scripts.add(self.rhs, autostart=True):
caller.msg(
f"Script |w{self.rhs}|n successfully added and "
f"started on {obj.get_display_name(caller)}.")
f"started on {obj.get_display_name(caller)}."
)
else:
caller.msg(f"Script {self.rhs} could not be added and/or started "
f"on {obj.get_display_name(caller)} (or it started and "
"immediately shut down).")
caller.msg(
f"Script {self.rhs} could not be added and/or started "
f"on {obj.get_display_name(caller)} (or it started and "
"immediately shut down)."
)
else:
# just show all scripts on object
scripts = ScriptDB.objects.filter(db_obj=obj)
@ -3374,12 +3414,15 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
new_script = None
if new_script:
caller.msg(f"Global Script Created - "
f"{new_script.key} ({new_script.typeclass_path})")
caller.msg(
f"Global Script Created - "
f"{new_script.key} ({new_script.typeclass_path})"
)
ScriptEvMore(caller, [new_script], session=self.session)
else:
caller.msg(f"Global Script |rNOT|n Created |r(see log)|n - "
f"arguments: {self.args}")
caller.msg(
f"Global Script |rNOT|n Created |r(see log)|n - " f"arguments: {self.args}"
)
elif scripts or obj:
# modification switches - must operate on existing scripts
@ -3388,9 +3431,11 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
scripts = ScriptDB.objects.filter(db_obj=obj)
if scripts.count() > 1:
ret = yield(f"Multiple scripts found: {scripts}. Are you sure you want to "
"operate on all of them? [Y]/N? ")
if ret.lower() in ('n', 'no'):
ret = yield (
f"Multiple scripts found: {scripts}. Are you sure you want to "
"operate on all of them? [Y]/N? "
)
if ret.lower() in ("n", "no"):
caller.msg("Aborted.")
return
@ -3406,11 +3451,14 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
getattr(script, switch)()
except Exception:
logger.log_trace()
msgs.append(f"{scripttype} |rNOT|n {verb} |r(see log)|n - "
f"{script_key} ({script_typeclass_path})|n")
msgs.append(
f"{scripttype} |rNOT|n {verb} |r(see log)|n - "
f"{script_key} ({script_typeclass_path})|n"
)
else:
msgs.append(f"{scripttype} {verb} - "
f"{script_key} ({script_typeclass_path})")
msgs.append(
f"{scripttype} {verb} - " f"{script_key} ({script_typeclass_path})"
)
caller.msg("\n".join(msgs))
if "delete" not in self.switches:
ScriptEvMore(caller, [script], session=self.session)
@ -3488,7 +3536,7 @@ class CmdObjects(COMMAND_DEFAULT_CLASS):
)
# last N table
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim): ]
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :]
latesttable = self.styled_table(
"|wcreated|n", "|wdbref|n", "|wname|n", "|wtypeclass|n", align="l", border="table"
)
@ -3620,14 +3668,18 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
# check any locks
if not (caller.permissions.check("Admin") or obj_to_teleport.access(caller, "teleport")):
caller.msg(f"{obj_to_teleport} 'teleport'-lock blocks you from teleporting "
"it anywhere.")
caller.msg(
f"{obj_to_teleport} 'teleport'-lock blocks you from teleporting " "it anywhere."
)
return
if not (caller.permissions.check("Admin")
or destination.access(obj_to_teleport, "teleport_here")):
caller.msg(f"{destination} 'teleport_here'-lock blocks {obj_to_teleport} from "
"moving there.")
if not (
caller.permissions.check("Admin")
or destination.access(obj_to_teleport, "teleport_here")
):
caller.msg(
f"{destination} 'teleport_here'-lock blocks {obj_to_teleport} from " "moving there."
)
return
# try the teleport
@ -3636,8 +3688,11 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
obj_to_teleport.location = destination
caller.msg(f"Teleported {obj_to_teleport} None -> {destination}")
elif obj_to_teleport.move_to(
destination, quiet="quiet" in self.switches,
emit_to_obj=caller, use_destination="intoexit" not in self.switches):
destination,
quiet="quiet" in self.switches,
emit_to_obj=caller,
use_destination="intoexit" not in self.switches,
):
if obj_to_teleport == caller:
caller.msg(f"Teleported to {destination}.")
@ -3995,7 +4050,7 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
self.caller.msg("No prototypes found.")
def _list_prototypes(self, key=None, tags=None):
"""Display prototypes as a list, optionally limited by key/tags. """
"""Display prototypes as a list, optionally limited by key/tags."""
protlib.list_prototypes(self.caller, key=key, tags=tags, session=self.session)
@interactive
@ -4039,7 +4094,9 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
return
try:
n_updated = spawner.batch_update_objects_with_prototype(
prototype, objects=existing_objects, caller=caller,
prototype,
objects=existing_objects,
caller=caller,
)
except Exception:
logger.log_trace()

View file

@ -20,16 +20,15 @@ from evennia.utils.evmenu import ask_yes_no
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
CHANNEL_DEFAULT_TYPECLASS = class_from_module(
settings.BASE_CHANNEL_TYPECLASS, fallback=settings.FALLBACK_CHANNEL_TYPECLASS)
settings.BASE_CHANNEL_TYPECLASS, fallback=settings.FALLBACK_CHANNEL_TYPECLASS
)
# limit symbol import for API
__all__ = (
"CmdChannel",
"CmdObjectChannel",
"CmdPage",
"CmdIRC2Chan",
"CmdIRCStatus",
"CmdRSS2Chan",
@ -207,6 +206,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
ban mychannel1,mychannel2= EvilUser : Was banned for spamming.
"""
key = "@channel"
aliases = ["@chan", "@channels"]
help_category = "Comms"
@ -215,8 +215,25 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
# the manage: lock controls access to /create/destroy/desc/lock/unlock switches
locks = "cmd:not pperm(channel_banned);admin:all();manage:all();changelocks:perm(Admin)"
switch_options = (
"list", "all", "history", "sub", "unsub", "mute", "unmute", "alias", "unalias",
"create", "destroy", "desc", "lock", "unlock", "boot", "ban", "unban", "who",)
"list",
"all",
"history",
"sub",
"unsub",
"mute",
"unmute",
"alias",
"unalias",
"create",
"destroy",
"desc",
"lock",
"unlock",
"boot",
"ban",
"unban",
"who",
)
# disable this in child command classes if wanting on-character channels
account_caller = True
@ -253,17 +270,24 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
channels = CHANNEL_DEFAULT_TYPECLASS.objects.channel_search(channelname, exact=exact)
# check permissions
channels = [channel for channel in channels
if channel.access(caller, 'listen') or channel.access(caller, 'control')]
channels = [
channel
for channel in channels
if channel.access(caller, "listen") or channel.access(caller, "control")
]
if handle_errors:
if not channels:
self.msg(f"No channel found matching '{channelname}' "
"(could also be due to missing access).")
self.msg(
f"No channel found matching '{channelname}' "
"(could also be due to missing access)."
)
return None
elif len(channels) > 1:
self.msg("Multiple possible channel matches/alias for "
"'{channelname}':\n" + ", ".join(chan.key for chan in channels))
self.msg(
"Multiple possible channel matches/alias for "
"'{channelname}':\n" + ", ".join(chan.key for chan in channels)
)
return None
return channels[0]
else:
@ -312,6 +336,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
return self.msg(
"".join(line.split("[-]", 1)[1] if "[-]" in line else line for line in lines)
)
# asynchronously tail the log file
tail_log_file(log_file, start_index, 20, callback=send_msg)
@ -491,7 +516,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
lockstring = "send:all();listen:all();control:id(%s)" % caller.id
new_chan = create.create_channel(
name, aliases=aliases, desc=description, locks=lockstring, typeclass=typeclass)
name, aliases=aliases, desc=description, locks=lockstring, typeclass=typeclass
)
self.sub_to_channel(new_chan)
return new_chan, ""
@ -514,14 +540,14 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
channel_key = channel.key
if message is None:
message = (f"|rChannel {channel_key} is being destroyed. "
"Make sure to clean any channel aliases.|n")
message = (
f"|rChannel {channel_key} is being destroyed. "
"Make sure to clean any channel aliases.|n"
)
if message:
channel.msg(message, senders=caller, bypass_mute=True)
channel.delete()
logger.log_sec(
"Channel {} was deleted by {}".format(channel_key, caller)
)
logger.log_sec("Channel {} was deleted by {}".format(channel_key, caller))
def set_lock(self, channel, lockstring):
"""
@ -610,8 +636,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
if not quiet:
channel.msg(f"{target.key} was booted from channel by {self.caller.key}.{reason}")
logger.log_sec(f"Channel Boot: {target} (Channel: {channel}, "
f"Reason: {reason.strip()}, Caller: {self.caller}")
logger.log_sec(
f"Channel Boot: {target} (Channel: {channel}, "
f"Reason: {reason.strip()}, Caller: {self.caller}"
)
return True, ""
def ban_user(self, channel, target, quiet=False, reason=""):
@ -684,7 +712,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
caller = self.caller
mute_list = list(channel.mutelist)
online_list = channel.subscriptions.online()
if channel.access(caller, 'control'):
if channel.access(caller, "control"):
# for those with channel control, show also offline users
all_subs = list(channel.subscriptions.all())
else:
@ -694,8 +722,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
who_list = []
for subscriber in all_subs:
name = subscriber.get_display_name(caller)
conditions = ("muting" if subscriber in mute_list else "",
"offline" if subscriber not in online_list else "")
conditions = (
"muting" if subscriber in mute_list else "",
"offline" if subscriber not in online_list else "",
)
conditions = [cond for cond in conditions if cond]
cond_text = "(" + ", ".join(conditions) + ")" if conditions else ""
who_list.append(f"{name}{cond_text}")
@ -743,7 +773,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
"locks",
"description",
align="l",
maxwidth=_DEFAULT_WIDTH
maxwidth=_DEFAULT_WIDTH,
)
for chan in subscribed:
@ -756,14 +786,14 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
my_aliases = ", ".join(self.get_channel_aliases(chan))
comtable.add_row(
*(
chanid,
"{key}{aliases}".format(
key=chan.key,
aliases=";"+ ";".join(chan.aliases.all()) if chan.aliases.all() else ""
),
my_aliases,
locks,
chan.db.desc
chanid,
"{key}{aliases}".format(
key=chan.key,
aliases=";" + ";".join(chan.aliases.all()) if chan.aliases.all() else "",
),
my_aliases,
locks,
chan.db.desc,
)
)
return comtable
@ -799,11 +829,14 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
substatus = "|gYes|n"
my_aliases = ", ".join(self.get_channel_aliases(chan))
comtable.add_row(
*(substatus,
chan.key,
",".join(chan.aliases.all()) if chan.aliases.all() else "",
my_aliases,
chan.db.desc))
*(
substatus,
chan.key,
",".join(chan.aliases.all()) if chan.aliases.all() else "",
my_aliases,
chan.db.desc,
)
)
comtable.reformat_column(0, width=8)
return comtable
@ -818,16 +851,17 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
switches = self.switches
channel_names = [name for name in self.lhslist if name]
#from evennia import set_trace;set_trace()
# from evennia import set_trace;set_trace()
if 'all' in switches:
if "all" in switches:
# show all available channels
subscribed, available = self.list_channels()
table = self.display_all_channels(subscribed, available)
self.msg(
"\n|wAvailable channels|n (use no argument to "
f"only show your subscriptions)\n{table}")
f"only show your subscriptions)\n{table}"
)
return
if not channel_names:
@ -835,15 +869,16 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
subscribed, _ = self.list_channels()
table = self.display_subbed_channels(subscribed)
self.msg("\n|wChannel subscriptions|n "
f"(use |w/all|n to see all available):\n{table}")
self.msg(
"\n|wChannel subscriptions|n " f"(use |w/all|n to see all available):\n{table}"
)
return
if not self.switches and not self.args:
self.msg("Usage[/switches]: channel [= message]")
return
if 'create' in switches:
if "create" in switches:
# create a new channel
if not self.access(caller, "manage"):
@ -865,7 +900,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(err)
return
if 'unalias' in switches:
if "unalias" in switches:
# remove a personal alias (no channel needed)
alias = self.args.strip()
if not alias:
@ -884,12 +919,11 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
# channels without a space in their name), we need to check if the
# first 'channel name' is in fact 'channelname text'
no_rhs_channel_name = self.args.split(" ", 1)[0]
possible_lhs_message = self.args[len(no_rhs_channel_name):]
if possible_lhs_message.strip() == '=':
possible_lhs_message = self.args[len(no_rhs_channel_name) :]
if possible_lhs_message.strip() == "=":
possible_lhs_message = ""
channel_names.append(no_rhs_channel_name)
channels = []
errors = []
for channel_name in channel_names:
@ -897,16 +931,20 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
# 'listen/control' perms.
found_channels = self.search_channel(channel_name, exact=False, handle_errors=False)
if not found_channels:
errors.append(f"No channel found matching '{channel_name}' "
"(could also be due to missing access).")
errors.append(
f"No channel found matching '{channel_name}' "
"(could also be due to missing access)."
)
elif len(found_channels) > 1:
errors.append("Multiple possible channel matches/alias for "
"'{channel_name}':\n" + ", ".join(chan.key for chan in found_channels))
errors.append(
"Multiple possible channel matches/alias for "
"'{channel_name}':\n" + ", ".join(chan.key for chan in found_channels)
)
else:
channels.append(found_channels[0])
if not channels:
self.msg('\n'.join(errors))
self.msg("\n".join(errors))
return
# we have at least one channel at this point
@ -925,30 +963,35 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
if channel in subscribed:
table = self.display_subbed_channels([channel])
header = f"Channel |w{channel.key}|n"
self.msg(f"{header}\n(use |w{channel.key} <msg>|n (or a channel-alias) "
f"to chat and the 'channel' command "
f"to customize)\n{table}")
self.msg(
f"{header}\n(use |w{channel.key} <msg>|n (or a channel-alias) "
f"to chat and the 'channel' command "
f"to customize)\n{table}"
)
elif channel in available:
table = self.display_all_channels([], [channel])
self.msg(
"\n|wNot subscribed to this channel|n (use /list to "
f"show all subscriptions)\n{table}")
f"show all subscriptions)\n{table}"
)
return
if 'history' in switches or 'hist' in switches:
if "history" in switches or "hist" in switches:
# view channel history
index = self.rhs or 0
try:
index = max(0, int(index))
except ValueError:
self.msg("The history index (describing how many lines to go back) "
"must be an integer >= 0.")
self.msg(
"The history index (describing how many lines to go back) "
"must be an integer >= 0."
)
return
self.get_channel_history(channel, start_index=index)
return
if 'sub' in switches:
if "sub" in switches:
# subscribe to a channel
aliases = []
if self.rhs:
@ -957,26 +1000,29 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
if success:
for alias in aliases:
self.add_alias(channel, alias)
alias_txt = ', '.join(aliases)
alias_txt = f" using alias(es) {alias_txt}" if aliases else ''
self.msg("You are now subscribed "
f"to the channel {channel.key}{alias_txt}. Use /alias to "
"add additional aliases for referring to the channel.")
alias_txt = ", ".join(aliases)
alias_txt = f" using alias(es) {alias_txt}" if aliases else ""
self.msg(
"You are now subscribed "
f"to the channel {channel.key}{alias_txt}. Use /alias to "
"add additional aliases for referring to the channel."
)
else:
self.msg(err)
return
if 'unsub' in switches:
if "unsub" in switches:
# un-subscribe from a channel
success, err = self.unsub_from_channel(channel)
if success:
self.msg(f"You un-subscribed from channel {channel.key}. "
"All aliases were cleared.")
self.msg(
f"You un-subscribed from channel {channel.key}. " "All aliases were cleared."
)
else:
self.msg(err)
return
if 'alias' in switches:
if "alias" in switches:
# create a new personal alias for a channel
alias = self.rhs
if not alias:
@ -986,7 +1032,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(f"Added/updated your alias '{alias}' for channel {channel.key}.")
return
if 'mute' in switches:
if "mute" in switches:
# mute a given channel
success, err = self.mute_channel(channel)
if success:
@ -995,7 +1041,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(err)
return
if 'unmute' in switches:
if "unmute" in switches:
# unmute a given channel
success, err = self.unmute_channel(channel)
if success:
@ -1004,7 +1050,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(err)
return
if 'destroy' in switches or 'delete' in switches:
if "destroy" in switches or "delete" in switches:
# destroy a channel we control
if not self.access(caller, "manage"):
@ -1028,10 +1074,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
"remove all users' aliases. {options}?",
yes_action=_perform_delete,
no_action="Aborted.",
default="N"
default="N",
)
if 'desc' in switches:
if "desc" in switches:
# set channel description
if not self.access(caller, "manage"):
@ -1051,7 +1097,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.set_desc(channel, desc)
self.msg("Updated channel description.")
if 'lock' in switches:
if "lock" in switches:
# add a lockstring to channel
if not self.access(caller, "changelocks"):
@ -1075,7 +1121,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(f"Could not add/update lock: {err}")
return
if 'unlock' in switches:
if "unlock" in switches:
# remove/update lockstring from channel
if not self.access(caller, "changelocks"):
@ -1099,7 +1145,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(f"Could not remove lock: {err}")
return
if 'boot' in switches:
if "boot" in switches:
# boot a user from channel(s)
if not self.access(caller, "admin"):
@ -1134,8 +1180,9 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(f"Cannot boot {target.key} from channel {chan.key}: {err}")
channames = ", ".join(chan.key for chan in channels)
reasonwarn = (". Also note that your reason will be echoed to the channel"
if reason else '')
reasonwarn = (
". Also note that your reason will be echoed to the channel" if reason else ""
)
ask_yes_no(
caller,
prompt=f"Are you sure you want to boot user {target.key} from "
@ -1143,11 +1190,11 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
"{options}?",
yes_action=_boot_user,
no_action="Aborted.",
default="Y"
default="Y",
)
return
if 'ban' in switches:
if "ban" in switches:
# ban a user from channel(s)
if not self.access(caller, "admin"):
@ -1161,8 +1208,10 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(f"You need 'control'-access to view bans on channel {channel.key}")
return
bans = ["Channel bans "
"(to ban, use channel/ban channel[,channel,...] = username [:reason]"]
bans = [
"Channel bans "
"(to ban, use channel/ban channel[,channel,...] = username [:reason]"
]
bans.extend(self.channel_list_bans(channel))
self.msg("\n".join(bans))
return
@ -1191,8 +1240,9 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
self.msg(f"Cannot boot {target.key} from channel {chan.key}: {err}")
channames = ", ".join(chan.key for chan in channels)
reasonwarn = (". Also note that your reason will be echoed to the channel"
if reason else '')
reasonwarn = (
". Also note that your reason will be echoed to the channel" if reason else ""
)
ask_yes_no(
caller,
f"Are you sure you want to ban user {target.key} from "
@ -1203,7 +1253,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
)
return
if 'unban' in switches:
if "unban" in switches:
# unban a previously banned user from channel
if not self.access(caller, "admin"):
@ -1414,7 +1464,6 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
receiver=receiver,
message=page.message,
)
)
lastpages = "\n ".join(listing)
@ -1465,6 +1514,7 @@ def _list_bots(cmd):
else:
return "No irc bots found."
class CmdIRC2Chan(COMMAND_DEFAULT_CLASS):
"""
Link an evennia channel to an external IRC channel

View file

@ -382,10 +382,13 @@ class CmdInventory(COMMAND_DEFAULT_CLASS):
string = "You are not carrying anything."
else:
from evennia.utils.ansi import raw as raw_ansi
table = self.styled_table(border="header")
for item in items:
table.add_row(f"|C{item.name}|n",
"{}|n".format(utils.crop(raw_ansi(item.db.desc or ""), width=50) or ""))
table.add_row(
f"|C{item.name}|n",
"{}|n".format(utils.crop(raw_ansi(item.db.desc or ""), width=50) or ""),
)
string = f"|wYou are carrying:\n{table}"
self.caller.msg(string)

View file

@ -19,11 +19,7 @@ from evennia.utils import create, evmore
from evennia.utils.ansi import ANSIString
from evennia.help.filehelp import FILE_HELP_ENTRIES
from evennia.utils.eveditor import EvEditor
from evennia.utils.utils import (
class_from_module,
inherits_from,
format_grid, pad
)
from evennia.utils.utils import class_from_module, inherits_from, format_grid, pad
from evennia.help.utils import help_search_with_index, parse_entry_for_subcategories
CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
@ -35,12 +31,14 @@ HELP_CLICKABLE_TOPICS = settings.HELP_CLICKABLE_TOPICS
# limit symbol import for API
__all__ = ("CmdHelp", "CmdSetHelp")
@dataclass
class HelpCategory:
"""
Mock 'help entry' to search categories with the same code.
"""
key: str
@property
@ -113,7 +111,10 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
if type(self).help_more:
usemore = True
if self.session and self.session.protocol_key in ("websocket", "ajax/comet",):
if self.session and self.session.protocol_key in (
"websocket",
"ajax/comet",
):
try:
options = self.account.db._saved_webclient_options
if options and options["helppopup"]:
@ -127,8 +128,15 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
self.msg(text=(text, {"type": "help"}))
def format_help_entry(self, topic="", help_text="", aliases=None, suggested=None,
subtopics=None, click_topics=True):
def format_help_entry(
self,
topic="",
help_text="",
aliases=None,
suggested=None,
subtopics=None,
click_topics=True,
):
"""This visually formats the help entry.
This method can be overriden to customize the way a help
entry is displayed.
@ -152,28 +160,24 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
title = f"|CHelp for |w{topic}|n" if topic else "|rNo help found|n"
if aliases:
aliases = (
" |C(aliases: {}|C)|n".format("|C,|n ".join(f"|w{ali}|n" for ali in aliases))
)
aliases = " |C(aliases: {}|C)|n".format("|C,|n ".join(f"|w{ali}|n" for ali in aliases))
else:
aliases = ''
aliases = ""
help_text = "\n" + dedent(help_text.strip('\n')) if help_text else ""
help_text = "\n" + dedent(help_text.strip("\n")) if help_text else ""
if subtopics:
if click_topics:
subtopics = [
f"|lchelp {topic}/{subtop}|lt|w{topic}/{subtop}|n|le"
for subtop in subtopics
]
f"|lchelp {topic}/{subtop}|lt|w{topic}/{subtop}|n|le" for subtop in subtopics
]
else:
subtopics = [f"|w{topic}/{subtop}|n" for subtop in subtopics]
subtopics = (
"\n|CSubtopics:|n\n {}".format(
"\n ".join(format_grid(subtopics, width=self.client_width())))
subtopics = "\n|CSubtopics:|n\n {}".format(
"\n ".join(format_grid(subtopics, width=self.client_width()))
)
else:
subtopics = ''
subtopics = ""
if suggested:
suggested = sorted(suggested)
@ -181,12 +185,11 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
suggested = [f"|lchelp {sug}|lt|w{sug}|n|le" for sug in suggested]
else:
suggested = [f"|w{sug}|n" for sug in suggested]
suggested = (
"\n|COther topic suggestions:|n\n{}".format(
"\n ".join(format_grid(suggested, width=self.client_width())))
suggested = "\n|COther topic suggestions:|n\n{}".format(
"\n ".join(format_grid(suggested, width=self.client_width()))
)
else:
suggested = ''
suggested = ""
end = start
@ -194,8 +197,9 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
return "\n".join(part.rstrip() for part in partorder if part)
def format_help_index(self, cmd_help_dict=None, db_help_dict=None, title_lone_category=False,
click_topics=True):
def format_help_index(
self, cmd_help_dict=None, db_help_dict=None, title_lone_category=False, click_topics=True
):
"""Output a category-ordered g for displaying the main help, grouped by
category.
@ -219,6 +223,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
commands and topics.
"""
def _group_by_category(help_dict):
grid = []
verbatim_elements = []
@ -231,9 +236,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# make the help topics clickable
if click_topics:
entries = [
f'|lchelp {entry}|lt{entry}|le' for entry in entries
]
entries = [f"|lchelp {entry}|lt{entry}|le" for entry in entries]
# add the entries to the grid
grid.extend(entries)
@ -243,7 +246,8 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
category_str = f"-- {category.title()} "
grid.append(
ANSIString(
self.index_category_clr + category_str
self.index_category_clr
+ category_str
+ "-" * (width - len(category_str))
+ self.index_topic_clr
)
@ -255,9 +259,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# make the help topics clickable
if click_topics:
entries = [
f'|lchelp {entry}|lt{entry}|le' for entry in entries
]
entries = [f"|lchelp {entry}|lt{entry}|le" for entry in entries]
# add the entries to the grid
grid.extend(entries)
@ -272,18 +274,22 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
if any(cmd_help_dict.values()):
# get the command-help entries by-category
sep1 = (self.index_type_separator_clr
+ pad("Commands", width=width, fillchar='-')
+ self.index_topic_clr)
sep1 = (
self.index_type_separator_clr
+ pad("Commands", width=width, fillchar="-")
+ self.index_topic_clr
)
grid, verbatim_elements = _group_by_category(cmd_help_dict)
gridrows = format_grid(grid, width, sep=" ", verbatim_elements=verbatim_elements)
cmd_grid = ANSIString("\n").join(gridrows) if gridrows else ""
if any(db_help_dict.values()):
# get db-based help entries by-category
sep2 = (self.index_type_separator_clr
+ pad("Game & World", width=width, fillchar='-')
+ self.index_topic_clr)
sep2 = (
self.index_type_separator_clr
+ pad("Game & World", width=width, fillchar="-")
+ self.index_topic_clr
)
grid, verbatim_elements = _group_by_category(db_help_dict)
gridrows = format_grid(grid, width, sep=" ", verbatim_elements=verbatim_elements)
db_grid = ANSIString("\n").join(gridrows) if gridrows else ""
@ -316,9 +322,9 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
"""
if inherits_from(cmd_or_topic, "evennia.commands.command.Command"):
return cmd_or_topic.auto_help and cmd_or_topic.access(caller, 'read', default=True)
return cmd_or_topic.auto_help and cmd_or_topic.access(caller, "read", default=True)
else:
return cmd_or_topic.access(caller, 'read', default=True)
return cmd_or_topic.access(caller, "read", default=True)
def can_list_topic(self, cmd_or_topic, caller):
"""
@ -355,12 +361,12 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
)
if has_view:
return cmd_or_topic.access(caller, 'view', default=True)
return cmd_or_topic.access(caller, "view", default=True)
else:
# no explicit 'view' lock - use the 'read' lock
return cmd_or_topic.access(caller, 'read', default=True)
return cmd_or_topic.access(caller, "read", default=True)
def collect_topics(self, caller, mode='list'):
def collect_topics(self, caller, mode="list"):
"""
Collect help topics from all sources (cmd/db/file).
@ -383,43 +389,45 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
cmdset.make_unique(caller)
# retrieve all available commands and database / file-help topics.
# also check the 'cmd:' lock here
cmd_help_topics = [cmd for cmd in cmdset if cmd and cmd.access(caller, 'cmd')]
cmd_help_topics = [cmd for cmd in cmdset if cmd and cmd.access(caller, "cmd")]
# get all file-based help entries, checking perms
file_help_topics = {
topic.key.lower().strip(): topic
for topic in FILE_HELP_ENTRIES.all()
}
file_help_topics = {topic.key.lower().strip(): topic for topic in FILE_HELP_ENTRIES.all()}
# get db-based help entries, checking perms
db_help_topics = {
topic.key.lower().strip(): topic
for topic in HelpEntry.objects.all()
}
if mode == 'list':
db_help_topics = {topic.key.lower().strip(): topic for topic in HelpEntry.objects.all()}
if mode == "list":
# check the view lock for all help entries/commands and determine key
cmd_help_topics = {
cmd.auto_help_display_key
if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
for cmd in cmd_help_topics if self.can_list_topic(cmd, caller)}
cmd.auto_help_display_key if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
for cmd in cmd_help_topics
if self.can_list_topic(cmd, caller)
}
db_help_topics = {
key: entry for key, entry in db_help_topics.items()
key: entry
for key, entry in db_help_topics.items()
if self.can_list_topic(entry, caller)
}
file_help_topics = {
key: entry for key, entry in file_help_topics.items()
if self.can_list_topic(entry, caller)}
key: entry
for key, entry in file_help_topics.items()
if self.can_list_topic(entry, caller)
}
else:
# query - check the read lock on entries
cmd_help_topics = {
cmd.auto_help_display_key
if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
for cmd in cmd_help_topics if self.can_read_topic(cmd, caller)}
cmd.auto_help_display_key if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
for cmd in cmd_help_topics
if self.can_read_topic(cmd, caller)
}
db_help_topics = {
key: entry for key, entry in db_help_topics.items()
key: entry
for key, entry in db_help_topics.items()
if self.can_read_topic(entry, caller)
}
file_help_topics = {
key: entry for key, entry in file_help_topics.items()
if self.can_read_topic(entry, caller)}
key: entry
for key, entry in file_help_topics.items()
if self.can_read_topic(entry, caller)
}
return cmd_help_topics, db_help_topics, file_help_topics
@ -452,9 +460,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# return of this will either be a HelpCategory, a Command or a
# HelpEntry/FileHelpEntry.
matches, suggestions = help_search_with_index(
match_query, entries,
suggestion_maxnum=self.suggestion_maxnum,
fields=search_fields
match_query, entries, suggestion_maxnum=self.suggestion_maxnum, fields=search_fields
)
if matches:
match = matches[0]
@ -478,8 +484,9 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# parse the query
if self.args:
self.subtopics = [part.strip().lower()
for part in self.args.split(self.subtopic_separator_char)]
self.subtopics = [
part.strip().lower() for part in self.args.split(self.subtopic_separator_char)
]
self.topic = self.subtopics.pop(0)
else:
self.topic = ""
@ -505,7 +512,6 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
return key[1:]
return key
def func(self):
"""
Run the dynamic help entry creator.
@ -518,8 +524,9 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# list all available help entries, grouped by category. We want to
# build dictionaries {category: [topic, topic, ...], ...}
cmd_help_topics, db_help_topics, file_help_topics = \
self.collect_topics(caller, mode='list')
cmd_help_topics, db_help_topics, file_help_topics = self.collect_topics(
caller, mode="list"
)
# db-topics override file-based ones
file_db_help_topics = {**file_help_topics, **db_help_topics}
@ -538,21 +545,21 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
file_db_help_by_category[entry.help_category].append(key)
# generate the index and display
output = self.format_help_index(cmd_help_by_category,
file_db_help_by_category,
click_topics=clickable_topics)
output = self.format_help_index(
cmd_help_by_category, file_db_help_by_category, click_topics=clickable_topics
)
self.msg_help(output)
return
# search for a specific entry. We need to check for 'read' access here before
# building the set of possibilities.
cmd_help_topics, db_help_topics, file_help_topics = \
self.collect_topics(caller, mode='query')
cmd_help_topics, db_help_topics, file_help_topics = self.collect_topics(
caller, mode="query"
)
# get a collection of all keys + aliases to be able to strip prefixes like @
key_and_aliases = set(
chain(*(cmd._keyaliases for cmd in cmd_help_topics.values())))
key_and_aliases = set(chain(*(cmd._keyaliases for cmd in cmd_help_topics.values())))
# db-help topics takes priority over file-help
file_db_help_topics = {**file_help_topics, **db_help_topics}
@ -561,8 +568,9 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
all_topics = {**file_db_help_topics, **cmd_help_topics}
# get all categories
all_categories = list(set(
HelpCategory(topic.help_category) for topic in all_topics.values()))
all_categories = list(
set(HelpCategory(topic.help_category) for topic in all_topics.values())
)
# all available help options - will be searched in order. We also check # the
# read-permission here.
@ -586,23 +594,26 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
for match_query in [query, f"{query}*", f"*{query}"]:
_, suggestions = help_search_with_index(
match_query, entries,
match_query,
entries,
suggestion_maxnum=self.suggestion_maxnum,
fields=search_fields
fields=search_fields,
)
if suggestions:
help_text += (
"\n... But matches where found within the help "
"texts of the suggestions below.")
suggestions = [self.strip_cmd_prefix(sugg, key_and_aliases)
for sugg in suggestions]
"texts of the suggestions below."
)
suggestions = [
self.strip_cmd_prefix(sugg, key_and_aliases) for sugg in suggestions
]
break
output = self.format_help_entry(
topic=None, # this will give a no-match style title
help_text=help_text,
suggested=suggestions,
click_topics=clickable_topics
click_topics=clickable_topics,
)
self.msg_help(output)
@ -612,14 +623,20 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# no subtopics for categories - these are just lists of topics
category = match.key
category_lower = category.lower()
cmds_in_category = [key for key, cmd in cmd_help_topics.items()
if category_lower == cmd.help_category]
topics_in_category = [key for key, topic in file_db_help_topics.items()
if category_lower == topic.help_category]
output = self.format_help_index({category: cmds_in_category},
{category: topics_in_category},
title_lone_category=True,
click_topics=clickable_topics)
cmds_in_category = [
key for key, cmd in cmd_help_topics.items() if category_lower == cmd.help_category
]
topics_in_category = [
key
for key, topic in file_db_help_topics.items()
if category_lower == topic.help_category
]
output = self.format_help_index(
{category: cmds_in_category},
{category: topics_in_category},
title_lone_category=True,
click_topics=clickable_topics,
)
self.msg_help(output)
return
@ -674,7 +691,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
topic=topic,
help_text=f"No help entry found for '{checked_topic}'",
subtopics=subtopic_index,
click_topics=clickable_topics
click_topics=clickable_topics,
)
self.msg_help(output)
return
@ -702,7 +719,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
aliases=aliases,
subtopics=subtopic_index,
suggested=suggested,
click_topics=clickable_topics
click_topics=clickable_topics,
)
self.msg_help(output)
@ -829,15 +846,17 @@ class CmdSetHelp(CmdHelp):
# check if we have an old entry with the same name
cmd_help_topics, db_help_topics, file_help_topics = \
self.collect_topics(self.caller, mode='query')
cmd_help_topics, db_help_topics, file_help_topics = self.collect_topics(
self.caller, mode="query"
)
# db-help topics takes priority over file-help
file_db_help_topics = {**file_help_topics, **db_help_topics}
# commands take priority over the other types
all_topics = {**file_db_help_topics, **cmd_help_topics}
# get all categories
all_categories = list(set(
HelpCategory(topic.help_category) for topic in all_topics.values()))
all_categories = list(
set(HelpCategory(topic.help_category) for topic in all_topics.values())
)
# all available help options - will be searched in order. We also check # the
# read-permission here.
entries = list(all_topics.values()) + all_categories
@ -853,29 +872,35 @@ class CmdSetHelp(CmdHelp):
if match:
warning = None
if isinstance(match, HelpCategory):
warning = (f"'{querystr}' matches (or partially matches) the name of "
"help-category '{match.key}'. If you continue, your help entry will "
"take precedence and the category (or part of its name) *may* not "
"be usable for grouping help entries anymore.")
warning = (
f"'{querystr}' matches (or partially matches) the name of "
"help-category '{match.key}'. If you continue, your help entry will "
"take precedence and the category (or part of its name) *may* not "
"be usable for grouping help entries anymore."
)
elif inherits_from(match, "evennia.commands.command.Command"):
warning = (f"'{querystr}' matches (or partially matches) the key/alias of "
"Command '{match.key}'. Command-help take precedence over other "
"help entries so your help *may* be impossible to reach for those "
"with access to that command.")
warning = (
f"'{querystr}' matches (or partially matches) the key/alias of "
"Command '{match.key}'. Command-help take precedence over other "
"help entries so your help *may* be impossible to reach for those "
"with access to that command."
)
elif inherits_from(match, "evennia.help.filehelp.FileHelpEntry"):
warning = (f"'{querystr}' matches (or partially matches) the name/alias of the "
f"file-based help topic '{match.key}'. File-help entries cannot be "
"modified from in-game (they are files on-disk). If you continue, "
"your help entry may shadow the file-based one's name partly or "
"completely.")
warning = (
f"'{querystr}' matches (or partially matches) the name/alias of the "
f"file-based help topic '{match.key}'. File-help entries cannot be "
"modified from in-game (they are files on-disk). If you continue, "
"your help entry may shadow the file-based one's name partly or "
"completely."
)
if warning:
# show a warning for a clashing help-entry type. Even if user accepts this
# we don't break here since we may need to show warnings for other inputs.
# We don't count this as an old-entry hit because we can't edit these
# types of entries.
self.msg(f"|rWarning:\n|r{warning}|n")
repl = yield("|wDo you still want to continue? Y/[N]?|n")
if repl.lower() not in ('y', 'yes'):
repl = yield ("|wDo you still want to continue? Y/[N]?|n")
if repl.lower() not in ("y", "yes"):
self.msg("Aborted.")
return
else:
@ -897,7 +922,11 @@ class CmdSetHelp(CmdHelp):
helpentry = old_entry
else:
helpentry = create.create_help_entry(
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases,
topicstr,
self.rhs,
category=category,
locks=lockstring,
aliases=aliases,
)
self.caller.db._editing_help = helpentry
@ -976,6 +1005,4 @@ class CmdSetHelp(CmdHelp):
)
return
else:
self.msg(
f"Error when creating topic '{topicstr}'{aliastxt}! Contact an admin."
)
self.msg(f"Error when creating topic '{topicstr}'{aliastxt}! Contact an admin.")

View file

@ -593,13 +593,15 @@ class CmdService(COMMAND_DEFAULT_CLASS):
if delmode:
caller.msg("You cannot remove a core Evennia service (named 'Evennia*').")
return
string = ("|RYou seem to be shutting down a core Evennia "
"service (named 'Evennia*').\nNote that stopping "
"some TCP port services will *not* disconnect users "
"*already* connected on those ports, but *may* "
"instead cause spurious errors for them.\nTo safely "
"and permanently remove ports, change settings file "
"and restart the server.|n\n")
string = (
"|RYou seem to be shutting down a core Evennia "
"service (named 'Evennia*').\nNote that stopping "
"some TCP port services will *not* disconnect users "
"*already* connected on those ports, but *may* "
"instead cause spurious errors for them.\nTo safely "
"and permanently remove ports, change settings file "
"and restart the server.|n\n"
)
caller.msg(string)
if delmode:
@ -611,9 +613,11 @@ class CmdService(COMMAND_DEFAULT_CLASS):
try:
service.stopService()
except Exception as err:
caller.msg(f"|rErrors were reported when stopping this service{err}.\n"
"If there are remaining problems, try reloading "
"or rebooting the server.")
caller.msg(
f"|rErrors were reported when stopping this service{err}.\n"
"If there are remaining problems, try reloading "
"or rebooting the server."
)
caller.msg("|g... Stopped service '%s'.|n" % self.args)
return
@ -626,9 +630,11 @@ class CmdService(COMMAND_DEFAULT_CLASS):
try:
service.startService()
except Exception as err:
caller.msg(f"|rErrors were reported when starting this service{err}.\n"
"If there are remaining problems, try reloading the server, changing the "
"settings if it's a non-standard service.|n")
caller.msg(
f"|rErrors were reported when starting this service{err}.\n"
"If there are remaining problems, try reloading the server, changing the "
"settings if it's a non-standard service.|n"
)
caller.msg("|gService started.|n")
@ -973,8 +979,8 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
@staticmethod
def coll_date_func(task):
"""Replace regex characters in date string and collect deferred function name."""
t_comp_date = str(task[0]).replace('-', '/')
t_func_name = str(task[1]).split(' ')
t_comp_date = str(task[0]).replace("-", "/")
t_func_name = str(task[1]).split(" ")
t_func_mem_ref = t_func_name[3] if len(t_func_name) >= 4 else None
return t_comp_date, t_func_mem_ref
@ -994,19 +1000,19 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
# verify manipulating the correct task
task_args = _TASK_HANDLER.tasks.get(task_id, False)
if not task_args: # check if the task is still active
self.msg('Task completed while waiting for input.')
self.msg("Task completed while waiting for input.")
return
else:
# make certain a task with matching IDs has not been created
t_comp_date, t_func_mem_ref = self.coll_date_func(task_args)
if self.t_comp_date != t_comp_date or self.t_func_mem_ref != t_func_mem_ref:
self.msg('Task completed while waiting for input.')
self.msg("Task completed while waiting for input.")
return
# Do the action requested by command caller
action_return = self.task_action()
self.msg(f'{self.action_request} request completed.')
self.msg(f'The task function {self.action_request} returned: {action_return}')
self.msg(f"{self.action_request} request completed.")
self.msg(f"The task function {self.action_request} returned: {action_return}")
def func(self):
# get a reference of the global task handler
@ -1015,9 +1021,9 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
from evennia.scripts.taskhandler import TASK_HANDLER as _TASK_HANDLER
# handle no tasks active.
if not _TASK_HANDLER.tasks:
self.msg('There are no active tasks.')
self.msg("There are no active tasks.")
if self.switches or self.args:
self.msg('Likely the task has completed and been removed.')
self.msg("Likely the task has completed and been removed.")
return
# handle caller's request to manipulate a task(s)
@ -1033,8 +1039,8 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
# if the argument is a task id, proccess the action on a single task
if arg_is_id:
err_arg_msg = 'Switch and task ID are required when manipulating a task.'
task_comp_msg = 'Task completed while processing request.'
err_arg_msg = "Switch and task ID are required when manipulating a task."
task_comp_msg = "Task completed while processing request."
# handle missing arguments or switches
if not self.switches and self.lhs:
@ -1047,14 +1053,16 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
# handle task no longer existing
if not task.exists():
self.msg(f'Task {task_id} does not exist.')
self.msg(f"Task {task_id} does not exist.")
return
# get a reference of the function caller requested
switch_action = getattr(task, action_request, False)
if not switch_action:
self.msg(f'{self.switches[0]}, is not an acceptable task action or ' \
f'{task_comp_msg.lower()}')
self.msg(
f"{self.switches[0]}, is not an acceptable task action or "
f"{task_comp_msg.lower()}"
)
# verify manipulating the correct task
if task_id in _TASK_HANDLER.tasks:
@ -1064,25 +1072,29 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
return
else:
t_comp_date, t_func_mem_ref = self.coll_date_func(task_args)
t_func_name = str(task_args[1]).split(' ')
t_func_name = str(task_args[1]).split(" ")
t_func_name = t_func_name[1] if len(t_func_name) >= 2 else None
if task.exists(): # make certain the task has not been called yet.
prompt = (f'{action_request.capitalize()} task {task_id} with completion date '
f'{t_comp_date} ({t_func_name}) {{options}}?')
no_msg = f'No {action_request} processed.'
prompt = (
f"{action_request.capitalize()} task {task_id} with completion date "
f"{t_comp_date} ({t_func_name}) {{options}}?"
)
no_msg = f"No {action_request} processed."
# record variables for use in do_task_action method
self.task_id = task_id
self.t_comp_date = t_comp_date
self.t_func_mem_ref = t_func_mem_ref
self.task_action = switch_action
self.action_request = action_request
ask_yes_no(self.caller,
prompt=prompt,
yes_action=self.do_task_action,
no_action=no_msg,
default="Y",
allow_abort=True)
ask_yes_no(
self.caller,
prompt=prompt,
yes_action=self.do_task_action,
no_action=no_msg,
default="Y",
allow_abort=True,
)
return True
else:
self.msg(task_comp_msg)
@ -1102,7 +1114,7 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
# call requested action on all tasks with the function name
for task_id, task_args in current_tasks.items():
t_func_name = str(task_args[1]).split(' ')
t_func_name = str(task_args[1]).split(" ")
t_func_name = t_func_name[1] if len(t_func_name) >= 2 else None
# skip this task if it is not for the function desired
if arg_func_name != t_func_name:
@ -1112,33 +1124,39 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
switch_action = getattr(task, action_request, False)
if switch_action:
action_return = switch_action()
self.msg(f'Task action {action_request} completed on task ID {task_id}.')
self.msg(f'The task function {action_request} returned: {action_return}')
self.msg(f"Task action {action_request} completed on task ID {task_id}.")
self.msg(f"The task function {action_request} returned: {action_return}")
# provide a message if not tasks of the function name was found
if not name_match_found:
self.msg(f'No tasks deferring function name {arg_func_name} found.')
self.msg(f"No tasks deferring function name {arg_func_name} found.")
return
return True
# check if an maleformed request was created
elif self.switches or self.lhs:
self.msg('Task command misformed.')
self.msg('Proper format tasks[/switch] [function name or task id]')
self.msg("Task command misformed.")
self.msg("Proper format tasks[/switch] [function name or task id]")
return
# No task manupilation requested, build a table of tasks and display it
# get the width of screen in characters
width = self.client_width()
# create table header and list to hold tasks data and actions
tasks_header = ('Task ID', 'Completion Date', 'Function', 'Arguments', 'KWARGS',
'persistent')
tasks_header = (
"Task ID",
"Completion Date",
"Function",
"Arguments",
"KWARGS",
"persistent",
)
# empty list of lists, the size of the header
tasks_list = [list() for i in range(len(tasks_header))]
for task_id, task in _TASK_HANDLER.tasks.items():
# collect data from the task
t_comp_date, t_func_mem_ref = self.coll_date_func(task)
t_func_name = str(task[1]).split(' ')
t_func_name = str(task[1]).split(" ")
t_func_name = t_func_name[1] if len(t_func_name) >= 2 else None
t_args = str(task[2])
t_kwargs = str(task[3])
@ -1148,8 +1166,9 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
for i in range(len(tasks_header)):
tasks_list[i].append(task_data[i])
# create and display the table
tasks_table = EvTable(*tasks_header, table=tasks_list, maxwidth=width, border='cells',
align='center')
actions = (f'/{switch}' for switch in self.switch_options)
tasks_table = EvTable(
*tasks_header, table=tasks_list, maxwidth=width, border="cells", align="center"
)
actions = (f"/{switch}" for switch in self.switch_options)
helptxt = f"\nActions: {iter_to_str(actions)}"
self.msg(str(tasks_table) + helptxt)

File diff suppressed because it is too large Load diff

View file

@ -201,13 +201,17 @@ class CmdUnconnectedCreate(COMMAND_DEFAULT_CLASS):
non_normalized_username = username
username = Account.normalize_username(username)
if non_normalized_username != username:
session.msg("Note: your username was normalized to strip spaces and remove characters "
"that could be visually confusing.")
session.msg(
"Note: your username was normalized to strip spaces and remove characters "
"that could be visually confusing."
)
# have the user verify their new account was what they intended
answer = yield(f"You want to create an account '{username}' with password '{password}'."
"\nIs this what you intended? [Y]/N?")
if answer.lower() in ('n', 'no'):
answer = yield (
f"You want to create an account '{username}' with password '{password}'."
"\nIs this what you intended? [Y]/N?"
)
if answer.lower() in ("n", "no"):
session.msg("Aborted. If your user name contains spaces, surround it by quotes.")
return
@ -344,7 +348,7 @@ class CmdUnconnectedEncoding(COMMAND_DEFAULT_CLASS):
If you don't submit an encoding, the current encoding will be displayed
instead.
"""
"""
key = "encoding"
aliases = "encode"

View file

@ -339,7 +339,7 @@ class TestOptionTransferTrue(TestCase):
b.no_objs = False
d.duplicates = False
# higher-prio sets will change the option up the chain
cmdset_f = d + c + b + a # reverse, high prio
cmdset_f = d + c + b + a # reverse, high prio
self.assertTrue(cmdset_f.no_exits)
self.assertTrue(cmdset_f.no_objs)
self.assertTrue(cmdset_f.no_channels)
@ -407,7 +407,7 @@ class TestOptionTransferTrue(TestCase):
c.priority = 1
d.priority = 2
c.no_exits = False
c.no_channels = None # passthrough
c.no_channels = None # passthrough
b.no_objs = False
d.duplicates = False
# higher-prio sets will change the option up the chain
@ -639,7 +639,7 @@ class TestOptionTransferFalse(TestCase):
b.no_objs = True
d.duplicates = True
# higher-prio sets will change the option up the chain
cmdset_f = d + c + b + a # reverse, high prio
cmdset_f = d + c + b + a # reverse, high prio
self.assertFalse(cmdset_f.no_exits)
self.assertFalse(cmdset_f.no_objs)
self.assertFalse(cmdset_f.no_channels)
@ -663,7 +663,7 @@ class TestOptionTransferFalse(TestCase):
b.no_objs = True
d.duplicates = True
# higher-prio sets will change the option up the chain
cmdset_f = a + b + c + d # forward, high prio, never happens
cmdset_f = a + b + c + d # forward, high prio, never happens
self.assertFalse(cmdset_f.no_exits)
self.assertFalse(cmdset_f.no_objs)
self.assertFalse(cmdset_f.no_channels)
@ -707,7 +707,7 @@ class TestOptionTransferFalse(TestCase):
c.priority = 1
d.priority = 2
c.no_exits = True
c.no_channels = None # passthrough
c.no_channels = None # passthrough
b.no_objs = True
d.duplicates = True
# higher-prio sets will change the option up the chain
@ -908,6 +908,7 @@ class TestOptionTransferReplace(TestCase):
"""
Test option transfer through more complex merge types.
"""
def setUp(self):
super().setUp()
self.cmdset_a = _CmdSetA()
@ -1182,7 +1183,6 @@ class TestCmdSetNesting(BaseEvenniaTest):
"""
def test_nest(self):
class CmdA(Command):
key = "a"