Merge branch 'master' into develop

This commit is contained in:
Griatch 2017-09-30 12:00:54 +02:00
commit cfec925bd2
13 changed files with 75 additions and 51 deletions

View file

@ -67,7 +67,7 @@ Welcome!
[homepage]: http://www.evennia.com [homepage]: http://www.evennia.com
[gettingstarted]: http://github.com/evennia/evennia/wiki/Getting-Started [gettingstarted]: http://github.com/evennia/evennia/wiki/Getting-Started
[wiki]: https://github.com/evennia/evennia/wiki [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 [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 [travisimg]: https://travis-ci.org/evennia/evennia.svg?branch=master
[travislink]: https://travis-ci.org/evennia/evennia [travislink]: https://travis-ci.org/evennia/evennia

View file

@ -173,7 +173,6 @@ def rename_in_tree(path, in_list, out_list, excl_list, fileend_list, is_interact
if new_root != root: if new_root != root:
inp = raw_input(_green("Dir Rename %s\n -> %s\n Y/[N]? > " % (root, new_root))) inp = raw_input(_green("Dir Rename %s\n -> %s\n Y/[N]? > " % (root, new_root)))
if inp.upper() == 'Y': if inp.upper() == 'Y':
new_full_path = os.path.join(root, new_file)
try: try:
os.rename(root, new_root) os.rename(root, new_root)
except OSError as err: except OSError as err:

View file

@ -649,8 +649,8 @@ def cmdhandler(called_by, raw_string, _testing=False, callertype="session", sess
args = raw_string args = raw_string
unformatted_raw_string = "%s%s" % (cmdname, args) unformatted_raw_string = "%s%s" % (cmdname, args)
cmdset = None cmdset = None
session = session # session = session
account = account # account = account
else: else:
# no explicit cmdobject given, figure it out # 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]) sysarg = yield _SEARCH_AT_RESULT([match[2] for match in matches], caller, query=matches[0][0])
raise ExecSystemCommand(syscmd, sysarg) raise ExecSystemCommand(syscmd, sysarg)
cmdname, args, cmd = "", "", None cmdname, args, cmd, raw_cmdname = "", "", None, ""
if len(matches) == 1: if len(matches) == 1:
# We have a unique command match. But it may still be invalid. # We have a unique command match. But it may still be invalid.
match = matches[0] match = matches[0]

View file

@ -543,7 +543,7 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
describe an object or the current room. describe an object or the current room.
Usage: Usage:
@setdesc [<obj> =] <description> @desc [<obj> =] <description>
Switches: Switches:
edit - Open up a line editor for more advanced editing. 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, Sets the "desc" attribute on an object. If an object is not given,
describe the current room. describe the current room.
""" """
key = "@setdesc" key = "@desc"
aliases = "@describe" aliases = "@describe"
locks = "cmd:perm(desc) or perm(Builder)" locks = "cmd:perm(desc) or perm(Builder)"
help_category = "Building" help_category = "Building"
@ -647,29 +647,32 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS):
def delobj(obj): def delobj(obj):
# helper function for deleting a single object # helper function for deleting a single object
string = "" string = ""
objname = obj.name if not obj.pk:
if not (obj.access(caller, "control") or obj.access(caller, 'delete')): string = "\nObject %s was already deleted." % obj.db_key
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: else:
string += "\n%s was destroyed." % objname objname = obj.name
if had_exits: if not (obj.access(caller, "control") or obj.access(caller, 'delete')):
string += " Exits to and from %s were destroyed as well." % objname return "\nYou don't have permission to delete %s." % objname
if had_objs: if obj.account and 'override' not in self.switches:
string += " Objects inside %s were moved to their homes." % objname 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 return string
objs = [] objs = []
@ -706,10 +709,10 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS):
else: else:
confirm += ", ".join(["#{}".format(obj.id) for obj in objs]) confirm += ", ".join(["#{}".format(obj.id) for obj in objs])
confirm += " [yes]/no?" if self.default_confirm == 'yes' else " yes/[no]" confirm += " [yes]/no?" if self.default_confirm == 'yes' else " yes/[no]"
answer = yield(confirm) answer = ""
answer = self.default_confirm if answer == '' else answer
while answer.strip().lower() not in ("y", "yes", "n", "no"): while answer.strip().lower() not in ("y", "yes", "n", "no"):
answer = yield(confirm) answer = yield(confirm)
answer = self.default_confirm if answer == '' else answer
if answer.strip().lower() in ("n", "no"): if answer.strip().lower() in ("n", "no"):
caller.msg("Cancelled: no object was destroyed.") caller.msg("Cancelled: no object was destroyed.")

View file

@ -108,7 +108,7 @@ def to_object(inp, objtype='account'):
return _AccountDB.objects.get(user_username__iexact=obj) return _AccountDB.objects.get(user_username__iexact=obj)
if typ == 'dbref': if typ == 'dbref':
return _AccountDB.objects.get(id=obj) 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() raise CommError()
elif objtype == 'object': elif objtype == 'object':
if typ == 'account': if typ == 'account':
@ -117,14 +117,14 @@ def to_object(inp, objtype='account'):
return _ObjectDB.objects.get(db_key__iexact=obj) return _ObjectDB.objects.get(db_key__iexact=obj)
if typ == 'dbref': if typ == 'dbref':
return _ObjectDB.objects.get(id=obj) 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() raise CommError()
elif objtype == 'channel': elif objtype == 'channel':
if typ == 'string': if typ == 'string':
return _ChannelDB.objects.get(db_key__iexact=obj) return _ChannelDB.objects.get(db_key__iexact=obj)
if typ == 'dbref': if typ == 'dbref':
return _ChannelDB.objects.get(id=obj) 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() raise CommError()
# an unknown # an unknown
return None return None

View file

@ -116,7 +116,6 @@ class Msg(SharedMemoryModel):
# these can be used to filter/hide a given message from supplied objects/accounts/channels # 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_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_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) db_hide_from_channels = models.ManyToManyField("ChannelDB", related_name='hide_from_channels_set', blank=True)

View file

@ -830,8 +830,6 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
new_key = new_key or find_clone_key() new_key = new_key or find_clone_key()
return ObjectDB.objects.copy_object(self, new_key=new_key) return ObjectDB.objects.copy_object(self, new_key=new_key)
delete_iter = 0
def delete(self): def delete(self):
""" """
Deletes this object. Before deletion, this method makes sure Deletes this object. Before deletion, this method makes sure
@ -847,20 +845,11 @@ class DefaultObject(with_metaclass(TypeclassBase, ObjectDB)):
if not _ScriptDB: if not _ScriptDB:
from evennia.scripts.models import ScriptDB as _ScriptDB from evennia.scripts.models import ScriptDB as _ScriptDB
if self.delete_iter > 0: if not self.pk or not self.at_object_delete():
# make sure to only call delete once on this object # This object has already been deleted,
# (avoid recursive loops) # or the pre-delete check return False
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. # See if we need to kick the account off.
for session in self.sessions.all(): for session in self.sessions.all():

View file

@ -433,6 +433,12 @@ class ServerSession(Session):
except AttributeError: except AttributeError:
return False return False
def __ne__(self, other):
try:
return self.address != other.address
except AttributeError:
return True
def __str__(self): def __str__(self):
""" """
String representation of the user session class. We use String representation of the user session class. We use

View file

@ -494,7 +494,7 @@ class TypeclassManager(TypedObjectManager):
""" """
# shlex splits by spaces unless escaped by quotes # 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 = [], [], [], [], [] queries, plustags, plusattrs, negtags, negattrs = [], [], [], [], []
for ipart, part in enumerate(querysplit): for ipart, part in enumerate(querysplit):
key, rest = part, "" key, rest = part, ""

View file

@ -215,6 +215,9 @@ class _SaverMutable(object):
def __eq__(self, other): def __eq__(self, other):
return self._data == other return self._data == other
def __ne__(self, other):
return self._data != other
@_save @_save
def __setitem__(self, key, value): def __setitem__(self, key, value):
self._data.__setitem__(key, self._convert_mutables(value)) self._data.__setitem__(key, self._convert_mutables(value))
@ -248,6 +251,13 @@ class _SaverList(_SaverMutable, MutableSequence):
except TypeError: except TypeError:
return False return False
def __ne__(self, other):
try:
return list(self._data) != list(other)
except TypeError:
return True
def index(self, value, *args): def index(self, value, *args):
return self._data.index(value, *args) return self._data.index(value, *args)

View file

@ -246,7 +246,7 @@ class EvMore(object):
else: else:
self._pos += 1 self._pos += 1
self.display() 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() self.page_quit()
def page_back(self): def page_back(self):

View file

@ -230,6 +230,13 @@ class ParseStack(list):
# indicates if the top of the stack is a string or not # indicates if the top of the stack is a string or not
self._string_last = True 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): def append(self, item):
""" """
The stack will merge strings, add other things as normal The stack will merge strings, add other things as normal

View file

@ -1831,6 +1831,17 @@ class LimitedSizeOrderedDict(OrderedDict):
self.filo = not kwargs.get("fifo", True) # FIFO inverse of FILO self.filo = not kwargs.get("fifo", True) # FIFO inverse of FILO
self._check_size() 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): def _check_size(self):
filo = self.filo filo = self.filo
if self.size_limit is not None: if self.size_limit is not None: