Fixed how Msgs identify senders, using __dbclass__ rather than the old system using path-lookups. Resolves #639.

This commit is contained in:
Griatch 2015-01-17 23:42:40 +01:00
parent c654094536
commit f25ea99b83
2 changed files with 88 additions and 85 deletions

View file

@ -45,28 +45,20 @@ def dbref(dbref, reqhash=True):
def identify_object(inp): def identify_object(inp):
"identify if an object is a player or an object; return its database model" "identify if an object is a player or an object; return its database model"
# load global stores if hasattr(inp, "__dbclass__"):
global _PlayerDB, _ObjectDB, _ChannelDB clsname = inp.__dbclass__.__name__
if not _PlayerDB: if clsname == "PlayerDB":
from evennia.players.models import PlayerDB as _PlayerDB return "player"
if not _ObjectDB: elif clsname == "ObjectDB":
from evennia.objects.models import ObjectDB as _ObjectDB return "object"
if not _ChannelDB: elif clsname == "ChannelDB":
from evennia.comms.models import ChannelDB as _ChannelDB return "channel"
if not inp:
return inp, None
if isinstance(inp, basestring): if isinstance(inp, basestring):
return inp, "string" 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): elif dbref(inp):
return dbref(inp), "dbref" return dbref(inp), "dbref"
return inp, None # something else else:
return inp, None
def to_object(inp, objtype='player'): def to_object(inp, objtype='player'):

View file

@ -25,7 +25,6 @@ from django.db import models
from evennia.typeclasses.models import TypedObject from evennia.typeclasses.models import TypedObject
from evennia.utils.idmapper.models import SharedMemoryModel from evennia.utils.idmapper.models import SharedMemoryModel
from evennia.comms import managers from evennia.comms import managers
from evennia.comms.managers import identify_object
from evennia.locks.lockhandler import LockHandler from evennia.locks.lockhandler import LockHandler
from evennia.utils.utils import crop, make_iter, lazy_property 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 # 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 # an IRC channel; normally there is only one, but if co-modification of
# a message is allowed, there may be more than one "author" # 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_players = models.ManyToManyField("players.PlayerDB", related_name='sender_player_set',
db_sender_objects = models.ManyToManyField("objects.ObjectDB", related_name='sender_object_set', null=True, verbose_name='sender(object)', db_index=True) 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, 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 # The destination objects of this message. Stored as a
# comma-separated string of object dbrefs. Can be defined along # comma-separated string of object dbrefs. Can be defined along
# with channels below. # with channels below.
db_receivers_players = models.ManyToManyField('players.PlayerDB', related_name='receiver_player_set', null=True, help_text="player receivers") db_receivers_players = models.ManyToManyField('players.PlayerDB', related_name='receiver_player_set',
db_receivers_objects = models.ManyToManyField('objects.ObjectDB', related_name='receiver_object_set', null=True, help_text="object receivers") null=True, help_text="player receivers")
db_receivers_channels = models.ManyToManyField("ChannelDB", related_name='channel_set', null=True, help_text="channel recievers") 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 # 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. # it, or as a separate store for the mail subject line maybe.
@ -126,21 +131,23 @@ class Msg(SharedMemoryModel):
self.extra_senders self.extra_senders
#@sender.setter #@sender.setter
def __senders_set(self, value): def __senders_set(self, senders):
"Setter. Allows for self.sender = value" "Setter. Allows for self.sender = value"
for val in (v for v in make_iter(value) if v): for sender in make_iter(senders):
obj, typ = identify_object(val) if not sender:
if typ == 'player': continue
self.db_sender_players.add(obj) if isinstance(sender, basestring):
elif typ == 'object': self.db_sender_external = sender
self.db_sender_objects.add(obj) self.extra_senders.append(sender)
elif isinstance(typ, basestring): self.save(update_fields=["db_sender_external"])
self.db_sender_external = obj continue
elif not obj: if not hasattr(sender, "__dbclass__"):
return raise ValueError("This is a not a typeclassed object!")
else: clsname = sender.__dbclass__.__name__
raise ValueError(obj) if clsname == "ObjectDB":
self.save() self.db_sender_objects.add(sender)
elif clsname == "PlayerDB":
self.db_sender_players.add(sender)
#@sender.deleter #@sender.deleter
def __senders_del(self): def __senders_del(self):
@ -152,19 +159,21 @@ class Msg(SharedMemoryModel):
self.save() self.save()
senders = property(__senders_get, __senders_set, __senders_del) 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" "Remove a single sender or a list of senders"
for val in make_iter(value): for sender in make_iter(senders):
obj, typ = identify_object(val) if not sender:
if typ == 'player': continue
self.db_sender_players.remove(obj) if isinstance(sender, basestring):
elif typ == 'object': self.db_sender_external = ""
self.db_sender_objects.remove(obj) self.save(update_fields=["db_sender_external"])
elif isinstance(obj, basestring): if not hasattr(sender, "__dbclass__"):
self.db_sender_external = obj raise ValueError("This is a not a typeclassed object!")
else: clsname = sender.__dbclass__.__name__
raise ValueError(obj) if clsname == "ObjectDB":
self.save() self.db_sender_objects.remove(sender)
elif clsname == "PlayerDB":
self.db_sender_players.remove(sender)
# receivers property # receivers property
#@property #@property
@ -176,42 +185,42 @@ class Msg(SharedMemoryModel):
return list(self.db_receivers_players.all()) + list(self.db_receivers_objects.all()) return list(self.db_receivers_players.all()) + list(self.db_receivers_objects.all())
#@receivers.setter #@receivers.setter
def __receivers_set(self, value): def __receivers_set(self, receivers):
""" """
Setter. Allows for self.receivers = value. Setter. Allows for self.receivers = value.
This appends a new receiver to the message. This appends a new receiver to the message.
""" """
for val in (v for v in make_iter(value) if v): for receiver in make_iter(receivers):
obj, typ = identify_object(val) if not receiver:
if typ == 'player': continue
self.db_receivers_players.add(obj) if not hasattr(receiver, "__dbclass__"):
elif typ == 'object': raise ValueError("This is a not a typeclassed object!")
self.db_receivers_objects.add(obj) clsname = receiver.__dbclass__.__name__
elif not obj: if clsname == "ObjectDB":
return self.db_receiver_objects.add(receiver)
else: elif clsname == "PlayerDB":
raise ValueError self.db_receiver_players.add(receiver)
self.save()
#@receivers.deleter #@receivers.deleter
def __receivers_del(self): def __receivers_del(self):
"Deleter. Clears all receivers" "Deleter. Clears all receivers"
self.db_receivers_players.clear() self.db_receivers_players.clear()
self.db_receivers_objects.clear() self.db_receivers_objects.clear()
self.extra_senders = []
self.save() self.save()
receivers = property(__receivers_get, __receivers_set, __receivers_del) receivers = property(__receivers_get, __receivers_set, __receivers_del)
def remove_receiver(self, obj): def remove_receiver(self, receivers):
"Remove a single recevier" "Remove a single receiver or a list of receivers"
obj, typ = identify_object(obj) for receiver in make_iter(receivers):
if typ == 'player': if not receiver:
self.db_receivers_players.remove(obj) continue
elif typ == 'object': if not hasattr(receiver, "__dbclass__"):
self.db_receivers_objects.remove(obj) raise ValueError("This is a not a typeclassed object!")
else: clsname = receiver.__dbclass__.__name__
raise ValueError if clsname == "ObjectDB":
self.save() self.db_receiver_objects.remove(receiver)
elif clsname == "PlayerDB":
self.db_receiver_players.remove(receiver)
# channels property # channels property
#@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() return self.db_hide_from_players.all(), self.db_hide_from_objects.all(), self.db_hide_from_channels.all()
#@hide_from_sender.setter #@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" "Setter. Allows for self.hide_from = value. Will append to hiders"
obj, typ = identify_object(value) for hider in make_iter(hiders):
if typ == "player": if not hider:
self.db_hide_from_players.add(obj) continue
elif typ == "object": if not hasattr(hider, "__dbclass__"):
self.db_hide_from_objects.add(obj) raise ValueError("This is a not a typeclassed object!")
elif typ == "channel": clsname = hider.__dbclass__.__name__
self.db_hide_from_channels.add(obj) if clsname == "PlayerDB":
else: self.db_hide_from_players.add(hider.__dbclass__)
raise ValueError elif clsname == "ObjectDB":
self.save() self.db_hide_from_objects.add(hider.__dbclass__)
elif clsname == "ChannelDB":
self.db_hide_from_channels.add(hider.__dbclass__)
#@hide_from_sender.deleter #@hide_from_sender.deleter
def __hide_from_del(self): def __hide_from_del(self):