OBS:Run migrations! Changed the comms.Msg.db_title field to db_header to better reflect its use.

This commit is contained in:
Griatch 2012-11-04 15:37:06 +01:00
parent a4a50fdb87
commit f3b50a20a8
5 changed files with 206 additions and 65 deletions

View file

@ -231,7 +231,7 @@ class MsgManager(models.Manager):
receiver_restrict = Q() receiver_restrict = Q()
# filter by full text # filter by full text
if freetext: if freetext:
fulltext_restrict = Q(db_title__icontains=freetext) | Q(db_message__icontains=freetext) fulltext_restrict = Q(db_header__icontains=freetext) | Q(db_message__icontains=freetext)
else: else:
fulltext_restrict = Q() fulltext_restrict = Q()
# execute the query # execute the query

View file

@ -7,13 +7,13 @@ from django.db import models
class Migration(SchemaMigration): class Migration(SchemaMigration):
def forwards(self, orm): def forwards(self, orm):
# Adding index on 'Channel', fields ['db_key'] # Adding index on 'Channel', fields ['db_key']
db.create_index('comms_channel', ['db_key']) db.create_index('comms_channel', ['db_key'])
def backwards(self, orm): def backwards(self, orm):
# Removing index on 'Channel', fields ['db_key'] # Removing index on 'Channel', fields ['db_key']
db.delete_index('comms_channel', ['db_key']) db.delete_index('comms_channel', ['db_key'])

View file

@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Msg.db_header'
db.add_column('comms_msg', 'db_header',
self.gf('django.db.models.fields.CharField')(db_index=True, max_length=128, null=True, blank=True),
keep_default=False)
if not db.dry_run:
for msg in orm.Msg.objects.all():
msg.db_header = msg.db_title
msg.save()
# Deleting field 'Msg.db_title'
db.delete_column('comms_msg', 'db_title')
def backwards(self, orm):
# Adding field 'Msg.db_title'
raise RuntimeError
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'comms.channel': {
'Meta': {'object_name': 'Channel'},
'db_aliases': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '80', 'null': 'True', 'blank': 'True'}),
'db_keep_log': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'comms.externalchannelconnection': {
'Meta': {'object_name': 'ExternalChannelConnection'},
'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['comms.Channel']"}),
'db_external_config': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_external_key': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'db_external_send_code': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_is_enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'comms.msg': {
'Meta': {'object_name': 'Msg'},
'db_date_sent': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
'db_header': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '128', 'null': 'True', 'blank': 'True'}),
'db_hide_from_channles': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_channels_set'", 'null': 'True', 'to': "orm['comms.Channel']"}),
'db_hide_from_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_objects_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_hide_from_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'hide_from_players_set'", 'null': 'True', 'to': "orm['players.PlayerDB']"}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_message': ('django.db.models.fields.TextField', [], {}),
'db_receivers_channels': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'channel_set'", 'null': 'True', 'to': "orm['comms.Channel']"}),
'db_receivers_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'receiver_object_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_receivers_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'receiver_player_set'", 'null': 'True', 'to': "orm['players.PlayerDB']"}),
'db_sender_external': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'db_index': 'True'}),
'db_sender_objects': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'sender_object_set'", 'null': 'True', 'db_index': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_sender_players': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'related_name': "'sender_player_set'", 'null': 'True', 'db_index': 'True', 'to': "orm['players.PlayerDB']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'comms.playerchannelconnection': {
'Meta': {'object_name': 'PlayerChannelConnection'},
'db_channel': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['comms.Channel']"}),
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'objects.objectdb': {
'Meta': {'object_name': 'ObjectDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True', 'blank': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destinations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': "orm['objects.ObjectDB']"}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_cmdset_storage': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_is_connected': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_lock_storage': ('django.db.models.fields.CharField', [], {'max_length': '512', 'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True', 'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'unique': 'True'})
}
}
complete_apps = ['comms']

View file

@ -75,11 +75,12 @@ class Msg(SharedMemoryModel):
db_receivers_objects = models.ManyToManyField('objects.ObjectDB', related_name='receiver_object_set', null=True, help_text="object receivers") db_receivers_objects = models.ManyToManyField('objects.ObjectDB', related_name='receiver_object_set', null=True, help_text="object receivers")
db_receivers_channels = models.ManyToManyField("Channel", related_name='channel_set', null=True, help_text="channel recievers") db_receivers_channels = models.ManyToManyField("Channel", 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
# The actual message and a timestamp. The message field # store for the mail subject line maybe.
# should itself handle eventual headers etc. db_header = models.CharField('header', max_length=128, null=True, blank=True, db_index=True)
db_title = models.CharField('title', max_length=512, null=True, blank=True, db_index=True) # the message body itself
db_message = models.TextField('messsage') db_message = models.TextField('messsage')
# send date
db_date_sent = models.DateTimeField('date sent', editable=False, auto_now_add=True, db_index=True) db_date_sent = models.DateTimeField('date sent', editable=False, auto_now_add=True, db_index=True)
# lock storage # lock storage
db_lock_storage = models.CharField('locks', max_length=512, blank=True, db_lock_storage = models.CharField('locks', max_length=512, blank=True,
@ -209,23 +210,23 @@ class Msg(SharedMemoryModel):
self.save() self.save()
channels = property(__channels_get, __channels_set, __channels_del) channels = property(__channels_get, __channels_set, __channels_del)
# title property (wraps db_title) # header property (wraps db_header)
#@property #@property
def __title_get(self): def __header_get(self):
"Getter. Allows for value = self.message" "Getter. Allows for value = self.message"
return self.db_title return self.db_header
#@message.setter #@message.setter
def __title_set(self, value): def __header_set(self, value):
"Setter. Allows for self.message = value" "Setter. Allows for self.message = value"
if value: if value:
self.db_title = value self.db_header = value
self.save() self.save()
#@message.deleter #@message.deleter
def __title_del(self): def __header_del(self):
"Deleter. Allows for del self.message" "Deleter. Allows for del self.message"
self.db_title = "" self.db_header = ""
self.save() self.save()
title = property(__title_get, __title_set, __title_del) header = property(__header_get, __header_set, __header_del)
# message property (wraps db_message) # message property (wraps db_message)
#@property #@property
@ -338,11 +339,12 @@ class TempMsg(object):
sender to be given. sender to be given.
""" """
def __init__(self, senders=None, receivers=None, channels=None, message="", title="", lockstring="", hide_from=None): def __init__(self, senders=None, receivers=None, channels=None, message="", header="", type="", lockstring="", hide_from=None):
self.senders = senders and make_iter(senders) or [] self.senders = senders and make_iter(senders) or []
self.receivers = receivers and make_iter(receivers) or [] self.receivers = receivers and make_iter(receivers) or []
self.channels = channels and make_iter(channels) or [] self.channels = channels and make_iter(channels) or []
self.title = title self.type = type
self.header, header
self.message = message self.message = message
self.lock_storage = lockstring self.lock_storage = lockstring
self.locks = LockHandler(self) self.locks = LockHandler(self)
@ -544,7 +546,7 @@ class Channel(SharedMemoryModel):
""" """
return PlayerChannelConnection.objects.has_player_connection(player, self) return PlayerChannelConnection.objects.has_player_connection(player, self)
def msg(self, msgobj, title=None, senders=None, persistent=True): def msg(self, msgobj, header=None, senders=None, persistent=True):
""" """
Send the given message to all players connected to channel. Note that Send the given message to all players connected to channel. Note that
no permission-checking is done here; it is assumed to have been no permission-checking is done here; it is assumed to have been
@ -568,7 +570,7 @@ class Channel(SharedMemoryModel):
msg = TempMsg() msg = TempMsg()
if senders: if senders:
msg.senders = make_iter(senders) msg.senders = make_iter(senders)
msg.title = title msg.header = header
msg.message = msgobj msg.message = msgobj
msg.channels = [self] # add this channel msg.channels = [self] # add this channel
else: else:
@ -586,11 +588,11 @@ class Channel(SharedMemoryModel):
logger.log_trace("Cannot send msg to connection '%s'" % conn) logger.log_trace("Cannot send msg to connection '%s'" % conn)
return True return True
def tempmsg(self, message, title=None, senders=None): def tempmsg(self, message, header=None, senders=None):
""" """
A wrapper for sending non-persistent messages. A wrapper for sending non-persistent messages.
""" """
self.msg(message, senders=senders, title=title, persistent=False) self.msg(message, senders=senders, header=header, persistent=False)
def connect_to(self, player): def connect_to(self, player):
"Connect the user to this channel" "Connect the user to this channel"

View file

@ -20,63 +20,63 @@ DA = object.__delattr__
class PackedDict(dict): class PackedDict(dict):
""" """
Attribute helper class. Attribute helper class.
A variant of dict that stores itself to the database when A variant of dict that stores itself to the database when
updating one of its keys. This is called and handled by updating one of its keys. This is called and handled by
Attribute.validate_data(). Attribute.validate_data().
""" """
def __init__(self, db_obj, *args, **kwargs): def __init__(self, db_obj, *args, **kwargs):
""" """
Sets up the packing dict. The db_store variable Sets up the packing dict. The db_store variable
is set by Attribute.validate_data() when returned in is set by Attribute.validate_data() when returned in
order to allow custom updates to the dict. order to allow custom updates to the dict.
db_obj - the Attribute object storing this dict. db_obj - the Attribute object storing this dict.
""" """
self.db_obj = db_obj self.db_obj = db_obj
super(PackedDict, self).__init__(*args, **kwargs) super(PackedDict, self).__init__(*args, **kwargs)
def __str__(self): def __str__(self):
return "{%s}" % ", ".join("%s:%s" % (key, str(val)) for key, val in self.items()) return "{%s}" % ", ".join("%s:%s" % (key, str(val)) for key, val in self.items())
def __setitem__(self, *args, **kwargs): def __setitem__(self, *args, **kwargs):
"assign item to this dict" "assign item to this dict"
super(PackedDict, self).__setitem__(*args, **kwargs) super(PackedDict, self).__setitem__(*args, **kwargs)
self.db_obj.value = self self.db_obj.value = self
def clear(self, *args, **kwargs): def clear(self, *args, **kwargs):
"Custom clear" "Custom clear"
super(PackedDict, self).clear(*args, **kwargs) super(PackedDict, self).clear(*args, **kwargs)
self.db_obj.value = self self.db_obj.value = self
def pop(self, *args, **kwargs): def pop(self, *args, **kwargs):
"Custom pop" "Custom pop"
super(PackedDict, self).pop(*args, **kwargs) super(PackedDict, self).pop(*args, **kwargs)
self.db_obj.value = self self.db_obj.value = self
def popitem(self, *args, **kwargs): def popitem(self, *args, **kwargs):
"Custom popitem" "Custom popitem"
super(PackedDict, self).popitem(*args, **kwargs) super(PackedDict, self).popitem(*args, **kwargs)
self.db_obj.value = self self.db_obj.value = self
def update(self, *args, **kwargs): def update(self, *args, **kwargs):
"Custom update" "Custom update"
super(PackedDict, self).update(*args, **kwargs) super(PackedDict, self).update(*args, **kwargs)
self.db_obj.value = self self.db_obj.value = self
class PackedList(list): class PackedList(list):
""" """
Attribute helper class. Attribute helper class.
A variant of list that stores itself to the database when A variant of list that stores itself to the database when
updating one of its keys. This is called and handled by updating one of its keys. This is called and handled by
Attribute.validate_data(). Attribute.validate_data().
""" """
def __init__(self, db_obj, *args, **kwargs): def __init__(self, db_obj, *args, **kwargs):
""" """
Sets up the packing list. Sets up the packing list.
db_obj - the Attribute object storing this dict. db_obj - the Attribute object storing this dict.
""" """
self.db_obj = db_obj self.db_obj = db_obj
super(PackedList, self).__init__(*args, **kwargs) super(PackedList, self).__init__(*args, **kwargs)
def __str__(self): def __str__(self):
return "[%s]" % ", ".join(str(val) for val in self) return "[%s]" % ", ".join(str(val) for val in self)
def __setitem__(self, *args, **kwargs): def __setitem__(self, *args, **kwargs):
"Custom setitem that stores changed list to database." "Custom setitem that stores changed list to database."
super(PackedList, self).__setitem__(*args, **kwargs) super(PackedList, self).__setitem__(*args, **kwargs)
self.db_obj.value = self self.db_obj.value = self
def append(self, *args, **kwargs): def append(self, *args, **kwargs):
"Custom append" "Custom append"
@ -123,13 +123,13 @@ def to_attr(data):
(and any nested combination of them) this way, all other (and any nested combination of them) this way, all other
iterables are stored and returned as lists. iterables are stored and returned as lists.
data storage format: data storage format:
(simple|dbobj|iter, <data>) (simple|dbobj|iter, <data>)
where where
simple - a single non-db object, like a string or number simple - a single non-db object, like a string or number
dbobj - a single dbobj dbobj - a single dbobj
iter - any iterable object - will be looped over recursively iter - any iterable object - will be looped over recursively
to convert dbobj->id. to convert dbobj->id.
""" """
@ -140,7 +140,7 @@ def to_attr(data):
""" """
dtype = type(item) dtype = type(item)
if dtype in (basestring, int, float): # check the most common types first, for speed if dtype in (basestring, int, float): # check the most common types first, for speed
return item return item
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"): elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"):
db_model_name = item.db_model_name db_model_name = item.db_model_name
if db_model_name == "typeclass": if db_model_name == "typeclass":
@ -166,8 +166,8 @@ def to_attr(data):
if db_model_name == "typeclass": if db_model_name == "typeclass":
# typeclass cannot help us, we want the actual child object model name # typeclass cannot help us, we want the actual child object model name
db_model_name = GA(data.dbobj, "db_model_name") db_model_name = GA(data.dbobj, "db_model_name")
return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key)) return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key))
elif hasattr(data, "__iter__"): elif hasattr(data, "__iter__"):
return ("iter", iter_db2id(data)) return ("iter", iter_db2id(data))
else: else:
return ("simple", data) return ("simple", data)
@ -175,21 +175,21 @@ def to_attr(data):
def from_attr(attr, datatuple): def from_attr(attr, datatuple):
""" """
Retrieve data from a previously stored attribute. This Retrieve data from a previously stored attribute. This
is always a dict with keys type and data. is always a dict with keys type and data.
datatuple comes from the database storage and has datatuple comes from the database storage and has
the following format: the following format:
(simple|dbobj|iter, <data>) (simple|dbobj|iter, <data>)
where where
simple - a single non-db object, like a string. is returned as-is. simple - a single non-db object, like a string. is returned as-is.
dbobj - a single dbobj-id. This id is retrieved back from the database. dbobj - a single dbobj-id. This id is retrieved back from the database.
iter - an iterable. This is traversed iteratively, converting all found iter - an iterable. This is traversed iteratively, converting all found
dbobj-ids back to objects. Also, all lists and dictionaries are dbobj-ids back to objects. Also, all lists and dictionaries are
returned as their PackedList/PackedDict counterparts in order to returned as their PackedList/PackedDict counterparts in order to
allow in-place assignment such as obj.db.mylist[3] = val. Mylist allow in-place assignment such as obj.db.mylist[3] = val. Mylist
is then a PackedList that saves the data on the fly. is then a PackedList that saves the data on the fly.
""" """
# nested functions # nested functions
def id2db(data): def id2db(data):
""" """
Convert db-stored dbref back to object Convert db-stored dbref back to object
@ -202,39 +202,39 @@ def from_attr(attr, datatuple):
try: try:
return mclass.objects.get(id=data.id) return mclass.objects.get(id=data.id)
except mclass.DoesNotExist: # could happen if object was deleted in the interim. except mclass.DoesNotExist: # could happen if object was deleted in the interim.
return None return None
def iter_id2db(item): def iter_id2db(item):
""" """
Recursively looping through stored iterables, replacing ids with actual objects. Recursively looping through stored iterables, replacing ids with actual objects.
We return PackedDict and PackedLists instead of normal lists; this is needed in order for We return PackedDict and PackedLists instead of normal lists; this is needed in order for
the user to do dynamic saving of nested in-place, such as obj.db.attrlist[2]=3. What is the user to do dynamic saving of nested in-place, such as obj.db.attrlist[2]=3. What is
stored in the database are however always normal python primitives. stored in the database are however always normal python primitives.
""" """
dtype = type(item) dtype = type(item)
if dtype in (basestring, int, float): # check the most common types first, for speed if dtype in (basestring, int, float): # check the most common types first, for speed
return item return item
elif dtype == PackedDBobject: elif dtype == PackedDBobject:
return id2db(item) return id2db(item)
elif dtype == tuple: elif dtype == tuple:
return tuple([iter_id2db(val) for val in item]) return tuple([iter_id2db(val) for val in item])
elif dtype in (dict, PackedDict): elif dtype in (dict, PackedDict):
return dict(zip([key for key in item.keys()], return dict(zip([key for key in item.keys()],
[iter_id2db(val) for val in item.values()])) [iter_id2db(val) for val in item.values()]))
elif hasattr(item, '__iter__'): elif hasattr(item, '__iter__'):
return list(iter_id2db(val) for val in item) return list(iter_id2db(val) for val in item)
else: else:
return item return item
typ, data = datatuple typ, data = datatuple
if typ == 'simple': if typ == 'simple':
# single non-db objects # single non-db objects
return data return data
elif typ == 'dbobj': elif typ == 'dbobj':
# a single stored dbobj # a single stored dbobj
return id2db(data) return id2db(data)
elif typ == 'iter': elif typ == 'iter':
# all types of iterables # all types of iterables
return iter_id2db(data) return iter_id2db(data)
@ -249,9 +249,9 @@ class Migration(DataMigration):
val = pickle.loads(to_str(attr.db_value)) val = pickle.loads(to_str(attr.db_value))
attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val))))) attr.db_value = to_unicode(pickle.dumps(to_str(to_attr(from_attr(attr, val)))))
attr.save() attr.save()
except TypeError, RuntimeError: except TypeError, RuntimeError:
pass pass
def backwards(self, orm): def backwards(self, orm):
"Write your backwards methods here." "Write your backwards methods here."
raise RuntimeError raise RuntimeError