diff --git a/README.md b/README.md index 6439c8861e..0383c98034 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Welcome! [homepage]: http://www.evennia.com [gettingstarted]: http://github.com/evennia/evennia/wiki/Getting-Started [wiki]: https://github.com/evennia/evennia/wiki -[screenshot]: https://raw.githubusercontent.com/wiki/evennia/evennia/images/evennia_screenshot3.png +[screenshot]: https://user-images.githubusercontent.com/294267/30773728-ea45afb6-a076-11e7-8820-49be2168a6b8.png [logo]: https://github.com/evennia/evennia/blob/master/evennia/web/website/static/website/images/evennia_logo.png [travisimg]: https://travis-ci.org/evennia/evennia.svg?branch=master [travislink]: https://travis-ci.org/evennia/evennia diff --git a/bin/project_rename.py b/bin/project_rename.py index 75417d15b1..8f22d75f1c 100644 --- a/bin/project_rename.py +++ b/bin/project_rename.py @@ -173,7 +173,6 @@ def rename_in_tree(path, in_list, out_list, excl_list, fileend_list, is_interact if new_root != root: inp = raw_input(_green("Dir Rename %s\n -> %s\n Y/[N]? > " % (root, new_root))) if inp.upper() == 'Y': - new_full_path = os.path.join(root, new_file) try: os.rename(root, new_root) except OSError as err: diff --git a/evennia/commands/cmdhandler.py b/evennia/commands/cmdhandler.py index 016bbee09a..44304b4ea1 100644 --- a/evennia/commands/cmdhandler.py +++ b/evennia/commands/cmdhandler.py @@ -649,8 +649,8 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess args = raw_string unformatted_raw_string = "%s%s" % (cmdname, args) cmdset = None - session = session - account = account + # session = session + # account = account else: # no explicit cmdobject given, figure it out @@ -687,7 +687,7 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess sysarg = yield _SEARCH_AT_RESULT([match[2] for match in matches], caller, query=matches[0][0]) raise ExecSystemCommand(syscmd, sysarg) - cmdname, args, cmd = "", "", None + cmdname, args, cmd, raw_cmdname = "", "", None, "" if len(matches) == 1: # We have a unique command match. But it may still be invalid. match = matches[0] diff --git a/evennia/commands/default/building.py b/evennia/commands/default/building.py index d0839df349..61a46bde30 100644 --- a/evennia/commands/default/building.py +++ b/evennia/commands/default/building.py @@ -543,7 +543,7 @@ class CmdDesc(COMMAND_DEFAULT_CLASS): describe an object or the current room. Usage: - @setdesc [ =] + @desc [ =] Switches: edit - Open up a line editor for more advanced editing. @@ -551,7 +551,7 @@ class CmdDesc(COMMAND_DEFAULT_CLASS): Sets the "desc" attribute on an object. If an object is not given, describe the current room. """ - key = "@setdesc" + key = "@desc" aliases = "@describe" locks = "cmd:perm(desc) or perm(Builder)" help_category = "Building" @@ -647,29 +647,32 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS): def delobj(obj): # helper function for deleting a single object string = "" - objname = obj.name - if not (obj.access(caller, "control") or obj.access(caller, 'delete')): - return "\nYou don't have permission to delete %s." % objname - if obj.account and 'override' not in self.switches: - return "\nObject %s is controlled by an active account. Use /override to delete anyway." % objname - if obj.dbid == int(settings.DEFAULT_HOME.lstrip("#")): - return "\nYou are trying to delete |c%s|n, which is set as DEFAULT_HOME. " \ - "Re-point settings.DEFAULT_HOME to another " \ - "object before continuing." % objname - - had_exits = hasattr(obj, "exits") and obj.exits - had_objs = hasattr(obj, "contents") and any(obj for obj in obj.contents - if not (hasattr(obj, "exits") and obj not in obj.exits)) - # do the deletion - okay = obj.delete() - if not okay: - string += "\nERROR: %s not deleted, probably because delete() returned False." % objname + if not obj.pk: + string = "\nObject %s was already deleted." % obj.db_key else: - string += "\n%s was destroyed." % objname - if had_exits: - string += " Exits to and from %s were destroyed as well." % objname - if had_objs: - string += " Objects inside %s were moved to their homes." % objname + objname = obj.name + if not (obj.access(caller, "control") or obj.access(caller, 'delete')): + return "\nYou don't have permission to delete %s." % objname + if obj.account and 'override' not in self.switches: + return "\nObject %s is controlled by an active account. Use /override to delete anyway." % objname + if obj.dbid == int(settings.DEFAULT_HOME.lstrip("#")): + return "\nYou are trying to delete |c%s|n, which is set as DEFAULT_HOME. " \ + "Re-point settings.DEFAULT_HOME to another " \ + "object before continuing." % objname + + had_exits = hasattr(obj, "exits") and obj.exits + had_objs = hasattr(obj, "contents") and any(obj for obj in obj.contents + if not (hasattr(obj, "exits") and obj not in obj.exits)) + # do the deletion + okay = obj.delete() + if not okay: + string += "\nERROR: %s not deleted, probably because delete() returned False." % objname + else: + string += "\n%s was destroyed." % objname + if had_exits: + string += " Exits to and from %s were destroyed as well." % objname + if had_objs: + string += " Objects inside %s were moved to their homes." % objname return string objs = [] @@ -706,10 +709,10 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS): else: confirm += ", ".join(["#{}".format(obj.id) for obj in objs]) confirm += " [yes]/no?" if self.default_confirm == 'yes' else " yes/[no]" - answer = yield(confirm) - answer = self.default_confirm if answer == '' else answer + answer = "" while answer.strip().lower() not in ("y", "yes", "n", "no"): answer = yield(confirm) + answer = self.default_confirm if answer == '' else answer if answer.strip().lower() in ("n", "no"): caller.msg("Cancelled: no object was destroyed.") diff --git a/evennia/comms/managers.py b/evennia/comms/managers.py index 14a746fa77..f50d813123 100644 --- a/evennia/comms/managers.py +++ b/evennia/comms/managers.py @@ -108,7 +108,7 @@ def to_object(inp, objtype='account'): return _AccountDB.objects.get(user_username__iexact=obj) if typ == 'dbref': return _AccountDB.objects.get(id=obj) - logger.log_err("%s %s %s %s %s", objtype, inp, obj, typ, type(inp)) + logger.log_err("%s %s %s %s %s" % (objtype, inp, obj, typ, type(inp))) raise CommError() elif objtype == 'object': if typ == 'account': @@ -117,14 +117,14 @@ def to_object(inp, objtype='account'): return _ObjectDB.objects.get(db_key__iexact=obj) if typ == 'dbref': return _ObjectDB.objects.get(id=obj) - logger.log_err("%s %s %s %s %s", objtype, inp, obj, typ, type(inp)) + logger.log_err("%s %s %s %s %s" % (objtype, inp, obj, typ, type(inp))) raise CommError() elif objtype == 'channel': if typ == 'string': return _ChannelDB.objects.get(db_key__iexact=obj) if typ == 'dbref': return _ChannelDB.objects.get(id=obj) - logger.log_err("%s %s %s %s %s", objtype, inp, obj, typ, type(inp)) + logger.log_err("%s %s %s %s %s" % (objtype, inp, obj, typ, type(inp))) raise CommError() # an unknown return None diff --git a/evennia/comms/models.py b/evennia/comms/models.py index 700fcedbf7..b1a5a37ed9 100644 --- a/evennia/comms/models.py +++ b/evennia/comms/models.py @@ -116,7 +116,6 @@ class Msg(SharedMemoryModel): # these can be used to filter/hide a given message from supplied objects/accounts/channels db_hide_from_accounts = models.ManyToManyField("accounts.AccountDB", related_name='hide_from_accounts_set', blank=True) - db_hide_from_accounts = models.ManyToManyField("accounts.AccountDB", related_name='hide_from_accounts_set', blank=True) db_hide_from_objects = models.ManyToManyField("objects.ObjectDB", related_name='hide_from_objects_set', blank=True) db_hide_from_channels = models.ManyToManyField("ChannelDB", related_name='hide_from_channels_set', blank=True) diff --git a/evennia/objects/objects.py b/evennia/objects/objects.py index 6915c95d95..0181aef740 100644 --- a/evennia/objects/objects.py +++ b/evennia/objects/objects.py @@ -830,8 +830,6 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)): new_key = new_key or find_clone_key() return ObjectDB.objects.copy_object(self, new_key=new_key) - delete_iter = 0 - def delete(self): """ Deletes this object. Before deletion, this method makes sure @@ -847,20 +845,11 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)): if not _ScriptDB: from evennia.scripts.models import ScriptDB as _ScriptDB - if self.delete_iter > 0: - # make sure to only call delete once on this object - # (avoid recursive loops) + if not self.pk or not self.at_object_delete(): + # This object has already been deleted, + # or the pre-delete check return False return False - if not self.at_object_delete(): - # this is an extra pre-check - # run before deletion field-related properties - # is kicked into gear. - self.delete_iter = 0 - return False - - self.delete_iter += 1 - # See if we need to kick the account off. for session in self.sessions.all(): diff --git a/evennia/server/serversession.py b/evennia/server/serversession.py index 47591383cd..aaaeaaaedd 100644 --- a/evennia/server/serversession.py +++ b/evennia/server/serversession.py @@ -433,6 +433,12 @@ class ServerSession(Session): except AttributeError: return False + def __ne__(self, other): + try: + return self.address != other.address + except AttributeError: + return True + def __str__(self): """ String representation of the user session class. We use diff --git a/evennia/typeclasses/managers.py b/evennia/typeclasses/managers.py index 18379d5687..11a84f275a 100644 --- a/evennia/typeclasses/managers.py +++ b/evennia/typeclasses/managers.py @@ -494,7 +494,7 @@ class TypeclassManager(TypedObjectManager): """ # shlex splits by spaces unless escaped by quotes - querysplit = shlex.split(to_unicode(query, force=True)) + querysplit = shlex.split(to_unicode(query, force_string=True)) queries, plustags, plusattrs, negtags, negattrs = [], [], [], [], [] for ipart, part in enumerate(querysplit): key, rest = part, "" diff --git a/evennia/utils/dbserialize.py b/evennia/utils/dbserialize.py index 35fc59f761..80203923e8 100644 --- a/evennia/utils/dbserialize.py +++ b/evennia/utils/dbserialize.py @@ -215,6 +215,9 @@ class _SaverMutable(object): def __eq__(self, other): return self._data == other + def __ne__(self, other): + return self._data != other + @_save def __setitem__(self, key, value): self._data.__setitem__(key, self._convert_mutables(value)) @@ -248,6 +251,13 @@ class _SaverList(_SaverMutable, MutableSequence): except TypeError: return False + def __ne__(self, other): + try: + return list(self._data) != list(other) + except TypeError: + return True + + def index(self, value, *args): return self._data.index(value, *args) diff --git a/evennia/utils/evmore.py b/evennia/utils/evmore.py index 3dc936bd3e..4043025d6f 100644 --- a/evennia/utils/evmore.py +++ b/evennia/utils/evmore.py @@ -246,7 +246,7 @@ class EvMore(object): else: self._pos += 1 self.display() - if self.exit_on_lastpage and self._pos == self._pos >= self._npages - 1: + if self.exit_on_lastpage and self._pos >= self._npages - 1: self.page_quit() def page_back(self): diff --git a/evennia/utils/inlinefuncs.py b/evennia/utils/inlinefuncs.py index eba36a324c..8baa89cabc 100644 --- a/evennia/utils/inlinefuncs.py +++ b/evennia/utils/inlinefuncs.py @@ -230,6 +230,13 @@ class ParseStack(list): # indicates if the top of the stack is a string or not self._string_last = True + def __eq__(self, other): + return (super(ParseStack).__eq__(other) and + hasattr(other, "_string_last") and self._string_last == other._string_last) + + def __ne__(self, other): + return not self.__eq__(other) + def append(self, item): """ The stack will merge strings, add other things as normal diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index daa5379fbd..1a159991ba 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -1831,6 +1831,17 @@ class LimitedSizeOrderedDict(OrderedDict): self.filo = not kwargs.get("fifo", True) # FIFO inverse of FILO self._check_size() + def __eq__(self, other): + ret = super(LimitedSizeOrderedDict, self).__eq__(other) + if ret: + return (ret and + hasattr(other, 'size_limit') and self.size_limit == other.size_limit and + hasattr(other, 'fifo') and self.fifo == other.fifo) + return False + + def __ne__(self, other): + return not self.__eq__(other) + def _check_size(self): filo = self.filo if self.size_limit is not None: