From f25ea99b83dff018144461b5cd5a81780c01c26f Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 17 Jan 2015 23:42:40 +0100 Subject: [PATCH] Fixed how Msgs identify senders, using __dbclass__ rather than the old system using path-lookups. Resolves #639. --- evennia/comms/managers.py | 28 +++----- evennia/comms/models.py | 145 ++++++++++++++++++++------------------ 2 files changed, 88 insertions(+), 85 deletions(-) diff --git a/evennia/comms/managers.py b/evennia/comms/managers.py index e37c020b53..12ffe35865 100644 --- a/evennia/comms/managers.py +++ b/evennia/comms/managers.py @@ -45,28 +45,20 @@ def dbref(dbref, reqhash=True): def identify_object(inp): "identify if an object is a player or an object; return its database model" - # load global stores - global _PlayerDB, _ObjectDB, _ChannelDB - if not _PlayerDB: - from evennia.players.models import PlayerDB as _PlayerDB - if not _ObjectDB: - from evennia.objects.models import ObjectDB as _ObjectDB - if not _ChannelDB: - from evennia.comms.models import ChannelDB as _ChannelDB - - if not inp: - return inp, None + if hasattr(inp, "__dbclass__"): + clsname = inp.__dbclass__.__name__ + if clsname == "PlayerDB": + return "player" + elif clsname == "ObjectDB": + return "object" + elif clsname == "ChannelDB": + return "channel" if isinstance(inp, basestring): return inp, "string" - elif inp.is_typeclass(_PlayerDB, exact=False): - return inp, "player" - elif inp.is_typeclass(_ObjectDB, exact=False): - return inp, "object" - elif inp.is_typeclass(_ChannelDB, exact=False): - return inp, "channel" elif dbref(inp): return dbref(inp), "dbref" - return inp, None # something else + else: + return inp, None def to_object(inp, objtype='player'): diff --git a/evennia/comms/models.py b/evennia/comms/models.py index 67922efa9a..6e0abb469d 100644 --- a/evennia/comms/models.py +++ b/evennia/comms/models.py @@ -25,7 +25,6 @@ from django.db import models from evennia.typeclasses.models import TypedObject from evennia.utils.idmapper.models import SharedMemoryModel from evennia.comms import managers -from evennia.comms.managers import identify_object from evennia.locks.lockhandler import LockHandler from evennia.utils.utils import crop, make_iter, lazy_property @@ -70,16 +69,22 @@ class Msg(SharedMemoryModel): # Sender is either a player, an object or an external sender, like # an IRC channel; normally there is only one, but if co-modification of # a message is allowed, there may be more than one "author" - db_sender_players = models.ManyToManyField("players.PlayerDB", related_name='sender_player_set', null=True, verbose_name='sender(player)', db_index=True) - db_sender_objects = models.ManyToManyField("objects.ObjectDB", related_name='sender_object_set', null=True, verbose_name='sender(object)', db_index=True) + db_sender_players = models.ManyToManyField("players.PlayerDB", related_name='sender_player_set', + null=True, verbose_name='sender(player)', db_index=True) + db_sender_objects = models.ManyToManyField("objects.ObjectDB", related_name='sender_object_set', + null=True, verbose_name='sender(object)', db_index=True) db_sender_external = models.CharField('external sender', max_length=255, null=True, db_index=True, - help_text="identifier for external sender, for example a sender over an IRC connection (i.e. someone who doesn't have an exixtence in-game).") + help_text="identifier for external sender, for example a sender over an " + "IRC connection (i.e. someone who doesn't have an exixtence in-game).") # The destination objects of this message. Stored as a # comma-separated string of object dbrefs. Can be defined along # with channels below. - db_receivers_players = models.ManyToManyField('players.PlayerDB', related_name='receiver_player_set', null=True, help_text="player receivers") - db_receivers_objects = models.ManyToManyField('objects.ObjectDB', related_name='receiver_object_set', null=True, help_text="object receivers") - db_receivers_channels = models.ManyToManyField("ChannelDB", related_name='channel_set', null=True, help_text="channel recievers") + db_receivers_players = models.ManyToManyField('players.PlayerDB', related_name='receiver_player_set', + null=True, help_text="player receivers") + db_receivers_objects = models.ManyToManyField('objects.ObjectDB', related_name='receiver_object_set', + null=True, help_text="object receivers") + db_receivers_channels = models.ManyToManyField("ChannelDB", related_name='channel_set', + null=True, help_text="channel recievers") # header could be used for meta-info about the message if your system needs # it, or as a separate store for the mail subject line maybe. @@ -126,21 +131,23 @@ class Msg(SharedMemoryModel): self.extra_senders #@sender.setter - def __senders_set(self, value): + def __senders_set(self, senders): "Setter. Allows for self.sender = value" - for val in (v for v in make_iter(value) if v): - obj, typ = identify_object(val) - if typ == 'player': - self.db_sender_players.add(obj) - elif typ == 'object': - self.db_sender_objects.add(obj) - elif isinstance(typ, basestring): - self.db_sender_external = obj - elif not obj: - return - else: - raise ValueError(obj) - self.save() + for sender in make_iter(senders): + if not sender: + continue + if isinstance(sender, basestring): + self.db_sender_external = sender + self.extra_senders.append(sender) + self.save(update_fields=["db_sender_external"]) + continue + if not hasattr(sender, "__dbclass__"): + raise ValueError("This is a not a typeclassed object!") + clsname = sender.__dbclass__.__name__ + if clsname == "ObjectDB": + self.db_sender_objects.add(sender) + elif clsname == "PlayerDB": + self.db_sender_players.add(sender) #@sender.deleter def __senders_del(self): @@ -152,19 +159,21 @@ class Msg(SharedMemoryModel): self.save() senders = property(__senders_get, __senders_set, __senders_del) - def remove_sender(self, value): + def remove_sender(self, senders): "Remove a single sender or a list of senders" - for val in make_iter(value): - obj, typ = identify_object(val) - if typ == 'player': - self.db_sender_players.remove(obj) - elif typ == 'object': - self.db_sender_objects.remove(obj) - elif isinstance(obj, basestring): - self.db_sender_external = obj - else: - raise ValueError(obj) - self.save() + for sender in make_iter(senders): + if not sender: + continue + if isinstance(sender, basestring): + self.db_sender_external = "" + self.save(update_fields=["db_sender_external"]) + if not hasattr(sender, "__dbclass__"): + raise ValueError("This is a not a typeclassed object!") + clsname = sender.__dbclass__.__name__ + if clsname == "ObjectDB": + self.db_sender_objects.remove(sender) + elif clsname == "PlayerDB": + self.db_sender_players.remove(sender) # receivers property #@property @@ -176,42 +185,42 @@ class Msg(SharedMemoryModel): return list(self.db_receivers_players.all()) + list(self.db_receivers_objects.all()) #@receivers.setter - def __receivers_set(self, value): + def __receivers_set(self, receivers): """ Setter. Allows for self.receivers = value. This appends a new receiver to the message. """ - for val in (v for v in make_iter(value) if v): - obj, typ = identify_object(val) - if typ == 'player': - self.db_receivers_players.add(obj) - elif typ == 'object': - self.db_receivers_objects.add(obj) - elif not obj: - return - else: - raise ValueError - self.save() + for receiver in make_iter(receivers): + if not receiver: + continue + if not hasattr(receiver, "__dbclass__"): + raise ValueError("This is a not a typeclassed object!") + clsname = receiver.__dbclass__.__name__ + if clsname == "ObjectDB": + self.db_receiver_objects.add(receiver) + elif clsname == "PlayerDB": + self.db_receiver_players.add(receiver) #@receivers.deleter def __receivers_del(self): "Deleter. Clears all receivers" self.db_receivers_players.clear() self.db_receivers_objects.clear() - self.extra_senders = [] self.save() receivers = property(__receivers_get, __receivers_set, __receivers_del) - def remove_receiver(self, obj): - "Remove a single recevier" - obj, typ = identify_object(obj) - if typ == 'player': - self.db_receivers_players.remove(obj) - elif typ == 'object': - self.db_receivers_objects.remove(obj) - else: - raise ValueError - self.save() + def remove_receiver(self, receivers): + "Remove a single receiver or a list of receivers" + for receiver in make_iter(receivers): + if not receiver: + continue + if not hasattr(receiver, "__dbclass__"): + raise ValueError("This is a not a typeclassed object!") + clsname = receiver.__dbclass__.__name__ + if clsname == "ObjectDB": + self.db_receiver_objects.remove(receiver) + elif clsname == "PlayerDB": + self.db_receiver_players.remove(receiver) # channels property #@property @@ -243,18 +252,20 @@ class Msg(SharedMemoryModel): return self.db_hide_from_players.all(), self.db_hide_from_objects.all(), self.db_hide_from_channels.all() #@hide_from_sender.setter - def __hide_from_set(self, value): + def __hide_from_set(self, hiders): "Setter. Allows for self.hide_from = value. Will append to hiders" - obj, typ = identify_object(value) - if typ == "player": - self.db_hide_from_players.add(obj) - elif typ == "object": - self.db_hide_from_objects.add(obj) - elif typ == "channel": - self.db_hide_from_channels.add(obj) - else: - raise ValueError - self.save() + for hider in make_iter(hiders): + if not hider: + continue + if not hasattr(hider, "__dbclass__"): + raise ValueError("This is a not a typeclassed object!") + clsname = hider.__dbclass__.__name__ + if clsname == "PlayerDB": + self.db_hide_from_players.add(hider.__dbclass__) + elif clsname == "ObjectDB": + self.db_hide_from_objects.add(hider.__dbclass__) + elif clsname == "ChannelDB": + self.db_hide_from_channels.add(hider.__dbclass__) #@hide_from_sender.deleter def __hide_from_del(self):