Handle going from location=None to unset and back in prototype, as per #2005

This commit is contained in:
Griatch 2020-03-28 20:34:56 +01:00
parent bea61b289e
commit 8c44766c0a
5 changed files with 59 additions and 34 deletions

View file

@ -54,7 +54,8 @@ without arguments starts a full interactive Python console.
bugfixes. bugfixes.
- Remove `dummy@example.com` as a default account email when unset, a string is no longer - Remove `dummy@example.com` as a default account email when unset, a string is no longer
required by Django. required by Django.
- Fixes to `spawn`, make updating an existing prototype/object work better. - Fixes to `spawn`, make updating an existing prototype/object work better. Add `/raw` switch
to `spawn` command to extract the raw prototype dict for manual editing.
## Evennia 0.9 (2018-2019) ## Evennia 0.9 (2018-2019)

View file

@ -13,7 +13,8 @@ from evennia.utils.utils import (
class_from_module, class_from_module,
get_all_typeclasses, get_all_typeclasses,
variable_from_module, variable_from_module,
dbref, interactive dbref, interactive,
list_to_string
) )
from evennia.utils.eveditor import EvEditor from evennia.utils.eveditor import EvEditor
from evennia.utils.evmore import EvMore from evennia.utils.evmore import EvMore
@ -3253,6 +3254,7 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
search - search prototype by name or tags. search - search prototype by name or tags.
list - list available prototypes, optionally limit by tags. list - list available prototypes, optionally limit by tags.
show, examine - inspect prototype by key. If not given, acts like list. show, examine - inspect prototype by key. If not given, acts like list.
raw - show the raw dict of the prototype as a one-line string for manual editing.
save - save a prototype to the database. It will be listable by /list. save - save a prototype to the database. It will be listable by /list.
delete - remove a prototype from database, if allowed to. delete - remove a prototype from database, if allowed to.
update - find existing objects with the same prototype_key and update update - find existing objects with the same prototype_key and update
@ -3301,6 +3303,7 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
"search", "search",
"list", "list",
"show", "show",
"raw",
"examine", "examine",
"save", "save",
"delete", "delete",
@ -3433,9 +3436,12 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
def _list_prototypes(self, key=None, tags=None): 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. """
table = protlib.list_prototypes(self.caller, key=key, tags=tags)
if not table:
return True
EvMore( EvMore(
self.caller, self.caller,
str(protlib.list_prototypes(self.caller, key=key, tags=tags)), str(table),
exit_on_lastpage=True, exit_on_lastpage=True,
justify_kwargs=False, justify_kwargs=False,
) )
@ -3492,8 +3498,8 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
Parse ;-separated input list. Parse ;-separated input list.
""" """
key, desc, tags = "", "", [] key, desc, tags = "", "", []
if ";" in self.args: if ";" in argstring:
parts = (part.strip().lower() for part in self.args.split(";")) parts = [part.strip().lower() for part in argstring.split(";")]
if len(parts) > 1 and desc: if len(parts) > 1 and desc:
key = parts[0] key = parts[0]
desc = parts[1] desc = parts[1]
@ -3537,10 +3543,20 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
return return
# search for key;tag combinations # search for key;tag combinations
key, _, tags = self._parse_key_desc_tags(self.args, desc=False) key, _, tags = self._parse_key_desc_tags(self.args, desc=False)
self._list_prototypes(key, tags) self._list_prototypes(key, tags)
return return
if "raw" in self.switches:
# query for key match and return the prototype as a safe one-liner string.
if not self.args:
caller.msg("You need to specify a prototype-key to get the raw data for.")
prototype = self._search_prototype(self.args)
if not prototype:
return
caller.msg(str(prototype))
return
if "show" in self.switches or "examine" in self.switches: if "show" in self.switches or "examine" in self.switches:
# show a specific prot detail. The argument is a search query or empty. # show a specific prot detail. The argument is a search query or empty.
if not self.args: if not self.args:
@ -3556,7 +3572,11 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
if "list" in self.switches: if "list" in self.switches:
# for list, all optional arguments are tags. # for list, all optional arguments are tags.
self._list_prototypes(tags=self.lhslist) tags = self.lhslist
err = self._list_prototypes(tags=tags)
if err:
caller.msg("No prototypes found with prototype-tag(s): {}".format(
list_to_string(tags, "or")))
return return
if "save" in self.switches: if "save" in self.switches:

View file

@ -2294,7 +2294,8 @@ def node_apply_diff(caller, **kwargs):
if not custom_location: if not custom_location:
diff.pop("location", None) diff.pop("location", None)
txt, options = _format_diff_text_and_options(diff, objects=update_objects, base_obj=base_obj) txt, options = _format_diff_text_and_options(diff, objects=update_objects,
base_obj=base_obj, prototype=prototype)
if options: if options:
text = [ text = [

View file

@ -272,10 +272,10 @@ def save_prototype(prototype):
stored_prototype = create_script( stored_prototype = create_script(
DbPrototype, DbPrototype,
key=prototype_key, key=prototype_key,
desc=prototype["prototype_desc"], desc=in_prototype["prototype_desc"],
persistent=True, persistent=True,
locks=prototype_locks, locks=prototype_locks,
tags=prototype["prototype_tags"], tags=in_prototype["prototype_tags"],
attributes=[("prototype", in_prototype)], attributes=[("prototype", in_prototype)],
) )
return stored_prototype.prototype return stored_prototype.prototype
@ -724,15 +724,15 @@ def prototype_to_str(prototype):
prototype_desc=prototype.get("prototype_desc", "|wNone|n"), prototype_desc=prototype.get("prototype_desc", "|wNone|n"),
prototype_parent=prototype.get("prototype_parent", "|wNone|n"), prototype_parent=prototype.get("prototype_parent", "|wNone|n"),
) )
key = aliases = attrs = tags = locks = permissions = location = home = destination = ""
key = prototype.get("key", "") if "key" in prototype:
if key: key = prototype["key"]
key = "|ckey:|n {key}".format(key=key) key = "|ckey:|n {key}".format(key=key)
aliases = prototype.get("aliases", "") if "aliases" in prototype:
if aliases: aliases = prototype["aliases"]
aliases = "|caliases:|n {aliases}".format(aliases=", ".join(aliases)) aliases = "|caliases:|n {aliases}".format(aliases=", ".join(aliases))
attrs = prototype.get("attrs", "") if "attrs" in prototype:
if attrs: attrs = prototype["attrs"]
out = [] out = []
for (attrkey, value, category, locks) in attrs: for (attrkey, value, category, locks) in attrs:
locks = ", ".join(lock for lock in locks if lock) locks = ", ".join(lock for lock in locks if lock)
@ -751,8 +751,8 @@ def prototype_to_str(prototype):
) )
) )
attrs = "|cattrs:|n\n {attrs}".format(attrs="\n ".join(out)) attrs = "|cattrs:|n\n {attrs}".format(attrs="\n ".join(out))
tags = prototype.get("tags", "") if "tags" in prototype:
if tags: tags = prototype['tags']
out = [] out = []
for (tagkey, category, data) in tags: for (tagkey, category, data) in tags:
out.append( out.append(
@ -761,20 +761,20 @@ def prototype_to_str(prototype):
) )
) )
tags = "|ctags:|n\n {tags}".format(tags=", ".join(out)) tags = "|ctags:|n\n {tags}".format(tags=", ".join(out))
locks = prototype.get("locks", "") if "locks" in prototype:
if locks: locks = prototype["locks"]
locks = "|clocks:|n\n {locks}".format(locks=locks) locks = "|clocks:|n\n {locks}".format(locks=locks)
permissions = prototype.get("permissions", "") if "permissions" in prototype:
if permissions: permissions = prototype["permissions"]
permissions = "|cpermissions:|n {perms}".format(perms=", ".join(permissions)) permissions = "|cpermissions:|n {perms}".format(perms=", ".join(permissions))
location = prototype.get("location", "") if "location" in prototype:
if location: location = prototype["location"]
location = "|clocation:|n {location}".format(location=location) location = "|clocation:|n {location}".format(location=location)
home = prototype.get("home", "") if "home" in prototype:
if home: home = prototype["home"]
home = "|chome:|n {home}".format(home=home) home = "|chome:|n {home}".format(home=home)
destination = prototype.get("destination", "") if "destination" in prototype:
if destination: destination = prototype["destination"]
destination = "|cdestination:|n {destination}".format(destination=destination) destination = "|cdestination:|n {destination}".format(destination=destination)
body = "\n".join( body = "\n".join(

View file

@ -354,6 +354,9 @@ def prototype_diff(prototype1, prototype2, maxdepth=2, homogenize=False, implici
class Unset: class Unset:
def __bool__(self): def __bool__(self):
return False return False
def __str__(self):
return "<Unset>"
_unset = Unset() _unset = Unset()
def _recursive_diff(old, new, depth=0): def _recursive_diff(old, new, depth=0):
@ -361,10 +364,10 @@ def prototype_diff(prototype1, prototype2, maxdepth=2, homogenize=False, implici
old_type = type(old) old_type = type(old)
new_type = type(new) new_type = type(new)
if old_type == new_type and not (old and new): if old_type == new_type and not (old or new):
# both old and new are unset, like [] or None # both old and new are unset, like [] or None
return (old, new, "KEEP") return (None, None, "KEEP")
elif old_type != new_type: if old_type != new_type:
if old and not new: if old and not new:
if depth < maxdepth and old_type == dict: if depth < maxdepth and old_type == dict:
return {key: (part, None, "REMOVE") for key, part in old.items()} return {key: (part, None, "REMOVE") for key, part in old.items()}
@ -388,7 +391,7 @@ def prototype_diff(prototype1, prototype2, maxdepth=2, homogenize=False, implici
elif depth < maxdepth and new_type == dict: elif depth < maxdepth and new_type == dict:
all_keys = set(list(old.keys()) + list(new.keys())) all_keys = set(list(old.keys()) + list(new.keys()))
return { return {
key: _recursive_diff(old.get(key), new.get(key, _unset), depth=depth + 1) key: _recursive_diff(old.get(key, _unset), new.get(key, _unset), depth=depth + 1)
for key in all_keys for key in all_keys
} }
elif depth < maxdepth and is_iter(new): elif depth < maxdepth and is_iter(new):
@ -396,7 +399,7 @@ def prototype_diff(prototype1, prototype2, maxdepth=2, homogenize=False, implici
new_map = {part[0] if is_iter(part) else part: part for part in new} new_map = {part[0] if is_iter(part) else part: part for part in new}
all_keys = set(list(old_map.keys()) + list(new_map.keys())) all_keys = set(list(old_map.keys()) + list(new_map.keys()))
return { return {
key: _recursive_diff(old_map.get(key), new_map.get(key, _unset), depth=depth + 1) key: _recursive_diff(old_map.get(key, _unset), new_map.get(key, _unset), depth=depth + 1)
for key in all_keys for key in all_keys
} }
elif old != new: elif old != new: