OBS: Migration needed(objects, scripts, players). This resolves issue 136 by allowing database objects to be nested in lists and dictionaries as

attributes on objects. Behind the scenes, only the DBREF is stored since storing dbobjects cannot be pickled. One used to be able to store single objects this way, but objects hidden in nested iterable structures were not found. Note that ONLY lists and dictionaries are supported to store on attributes - custom iterables will be stored and retrieved as a generic list instead - this is a tradeoff to be able to store database objects.

To migrate, give the following commands from game/:
 migrate.py migrate objects
 migrate.py migrate scripts
 migrate.py migrate players
This commit is contained in:
Griatch 2011-04-05 23:28:40 +00:00
parent 02775398c4
commit 6eff51de20
6 changed files with 435 additions and 106 deletions

View file

@ -90,7 +90,7 @@ class RedButton(Object):
# scripts that depend on the lid to be closed.
self.scripts.validate()
# now add new scripts that define the open-lid state
self.obj.scripts.add(scriptexamples.OpenLidState)
self.scripts.add(scriptexamples.OpenLidState)
# we also add a scripted event that will close the lid after a while.
# (this one cleans itself after being called once)
self.scripts.add(scriptexamples.CloseLidEvent)
@ -125,7 +125,7 @@ class RedButton(Object):
"""
self.db.lamp_works = False
self.obj.db.desc = "The big red button has stopped blinking for the time being."
self.db.desc = "The big red button has stopped blinking for the time being."
if feedback and self.location:
string = "The lamp flickers, the button going dark."

View file

@ -0,0 +1,127 @@
# encoding: 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):
# Deleting field 'ObjAttribute.db_mode'
from src.objects.models import ObjAttribute
from src.typeclasses.models import PackedDBobject
for attr in ObjAttribute.objects.all():
# resave attributes
db_mode = attr.db_mode
if db_mode and db_mode != 'pickle':
# an object. We need to resave this.
if db_mode == 'object':
val = PackedDBobject(attr.db_value, "objectdb")
elif db_mode == 'player':
val = PackedDBobject(attr.db_value, "playerdb")
elif db_mode == 'script':
val = PackedDBobject(attr.db_value, "scriptdb")
elif db_mode == 'help':
val = PackedDBobject(attr.db_value, "helpentry")
else:
val = PackedDBobject(attr.db_value, db_mode) # channel, msg
attr.value = val
db.delete_column('objects_objattribute', 'db_mode')
def backwards(self, orm):
# Adding field 'ObjAttribute.db_mode'
db.add_column('objects_objattribute', 'db_mode', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True), keep_default=False)
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'})
},
'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.alias': {
'Meta': {'object_name': 'Alias'},
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'objects.nick': {
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'Nick'},
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
'db_real': ('django.db.models.fields.TextField', [], {}),
'db_type': ('django.db.models.fields.CharField', [], {'default': "'inputline'", 'max_length': '16', 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'objects.objattribute': {
'Meta': {'object_name': 'ObjAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'objects.objectdb': {
'Meta': {'object_name': 'ObjectDB'},
'db_cmdset_storage': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'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_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.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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 = ['objects']

View file

@ -5,7 +5,7 @@ The managers for the custom Player object and permissions.
import datetime
from django.db import models
from django.contrib.auth.models import User
from src.typeclasses.managers import returns_typeclass_list, returns_typeclass
from src.typeclasses.managers import returns_typeclass_list, returns_typeclass, TypedObjectManager
from src.utils import logger
#
@ -59,7 +59,7 @@ def returns_player(method):
return None
return func
class PlayerManager(models.Manager):
class PlayerManager(TypedObjectManager):
"""
Custom manager for the player profile model. We use this
to wrap users in general in evennia, and supply some useful

View file

@ -0,0 +1,113 @@
# encoding: 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):
# Deleting field 'PlayerAttribute.db_mode'
from src.players.models import PlayerAttribute
from src.typeclasses.models import PackedDBobject
for attr in PlayerAttribute.objects.all():
# resave attributes
db_mode = attr.db_mode
if db_mode and db_mode != 'pickle':
# an object. We need to resave this.
if db_mode == 'object':
val = PackedDBobject(attr.db_value, "objectdb")
elif db_mode == 'player':
val = PackedDBobject(attr.db_value, "playerdb")
elif db_mode == 'script':
val = PackedDBobject(attr.db_value, "scriptdb")
elif db_mode == 'help':
val = PackedDBobject(attr.db_value, "helpentry")
else:
val = PackedDBobject(attr.db_value, db_mode) # channel, msg
attr.value = val
db.delete_column('players_playerattribute', 'db_mode')
def backwards(self, orm):
# Adding field 'PlayerAttribute.db_mode'
db.add_column('players_playerattribute', 'db_mode', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True), keep_default=False)
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'})
},
'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.TextField', [], {'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'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_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.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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.playerattribute': {
'Meta': {'object_name': 'PlayerAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'players.playerdb': {
'Meta': {'object_name': 'PlayerDB'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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 = ['players']

View file

@ -0,0 +1,129 @@
# encoding: 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):
# Deleting field 'ScriptAttribute.db_mode'
from src.scripts.models import ScriptAttribute
from src.typeclasses.models import PackedDBobject
for attr in ScriptAttribute.objects.all():
# resave attributes
db_mode = attr.db_mode
if db_mode and db_mode != 'pickle':
# an object. We need to resave this.
if db_mode == 'object':
val = PackedDBobject(attr.db_value, "objectdb")
elif db_mode == 'player':
val = PackedDBobject(attr.db_value, "playerdb")
elif db_mode == 'script':
val = PackedDBobject(attr.db_value, "scriptdb")
elif db_mode == 'help':
val = PackedDBobject(attr.db_value, "helpentry")
else:
val = PackedDBobject(attr.db_value, db_mode) # channel, msg
attr.value = val
db.delete_column('scripts_scriptattribute', 'db_mode')
def backwards(self, orm):
# Adding field 'ScriptAttribute.db_mode'
db.add_column('scripts_scriptattribute', 'db_mode', self.gf('django.db.models.fields.CharField')(max_length=20, null=True, blank=True), keep_default=False)
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'})
},
'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.TextField', [], {'null': 'True'}),
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'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_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.TextField', [], {'blank': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']", 'null': 'True'}),
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '512', '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'})
},
'scripts.scriptattribute': {
'Meta': {'object_name': 'ScriptAttribute'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['scripts.ScriptDB']"}),
'db_value': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'scripts.scriptdb': {
'Meta': {'object_name': 'ScriptDB'},
'db_date_created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'db_desc': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'db_interval': ('django.db.models.fields.IntegerField', [], {'default': '-1'}),
'db_is_active': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'db_lock_storage': ('django.db.models.fields.TextField', [], {'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': '512', 'blank': 'True'}),
'db_persistent': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_repeats': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'db_start_delay': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
}
}
complete_apps = ['scripts']

View file

@ -30,6 +30,7 @@ import traceback
from django.db import models
from django.conf import settings
from django.utils.encoding import smart_str
from django.contrib.contenttypes.models import ContentType
from src.utils.idmapper.models import SharedMemoryModel
from src.typeclasses import managers
from src.locks.lockhandler import LockHandler
@ -42,12 +43,12 @@ PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
# Note that these have to be updated if directory structure changes.
PARENTS = {
"typeclass":"src.typeclasses.typeclass.TypeClass",
"object":"src.objects.models.ObjectDB",
"player":"src.players.models.PlayerDB",
"script":"src.scripts.models.ScriptDB",
"objectdb":"src.objects.models.ObjectDB",
"layerdb":"src.players.models.PlayerDB",
"scriptdb":"src.scripts.models.ScriptDB",
"msg":"src.comms.models.Msg",
"channel":"src.comms.models.Channel",
"help":"src.help.models.HelpEntry"}
"helpentry":"src.help.models.HelpEntry"}
# cached typeclasses for all typed models
TYPECLASS_CACHE = {}
@ -63,6 +64,12 @@ def reset():
#
#------------------------------------------------------------
class PackedDBobject(object):
"Simple helper class for storing database object ids."
def __init__(self, ID, db_model):
self.id = ID
self.db_model = db_model
class Attribute(SharedMemoryModel):
"""
Abstract django model.
@ -94,8 +101,6 @@ class Attribute(SharedMemoryModel):
db_key = models.CharField(max_length=255)
# access through the value property
db_value = models.TextField(blank=True, null=True)
# tells us what type of data is stored in the attribute
db_mode = models.CharField(max_length=20, null=True, blank=True)
# Lock storage
db_lock_storage = models.TextField(blank=True)
# references the object the attribute is linked to (this is set
@ -106,7 +111,7 @@ class Attribute(SharedMemoryModel):
# Database manager
objects = managers.AttributeManager()
# Lock handler self.locks
def __init__(self, *args, **kwargs):
"Initializes the parent first -important!"
@ -143,23 +148,6 @@ class Attribute(SharedMemoryModel):
raise Exception("Cannot delete attribute key!")
key = property(key_get, key_set, key_del)
# mode property (wraps db_mode)
#@property
def mode_get(self):
"Getter. Allows for value = self.mode"
return self.db_mode
#@mode.setter
def mode_set(self, value):
"Setter. Allows for self.mode = value"
self.db_mode = value
self.save()
#@mode.deleter
def mode_del(self):
"Deleter. Allows for del self.mode"
self.db_mode = None
self.save()
mode = property(mode_get, mode_set, mode_del)
# obj property (wraps db_obj)
#@property
def obj_get(self):
@ -198,44 +186,14 @@ class Attribute(SharedMemoryModel):
"""
Getter. Allows for value = self.value.
"""
db_value = self.db_value
db_mode = self.db_mode
try:
if not db_mode:
# it's a string, just return plain db_value below
pass
elif db_mode == 'pickle':
db_value = pickle.loads(str(db_value))
elif db_mode == 'object':
from src.objects.models import ObjectDB
db_value = ObjectDB.objects.dbref_search(db_value)
elif db_mode == 'script':
from src.scripts.models import ScriptDB
db_value = ScriptDB.objects.dbref_search(db_value)
elif db_mode == 'player':
from src.players.models import PlayerDB
db_value = PlayerDB.objects.get(id=int(db_value))
elif db_mode == 'msg':
from src.comms.models import Msg
db_value = Msg.objects.objects.get(id=int(db_value))
elif db_mode == 'channel':
from src.comms.models import Channel
db_value = Channel.objects.get(id=int(db_value))
elif db_mode == 'help':
from src.help.models import HelpEntry
db_value = HelpEntry.objects.get(id=int(db_value))
except Exception:
logger.log_trace() #TODO: Remove when stable?
db_value = None
return db_value
return self.validate_data(pickle.loads(str(self.db_value)))
except pickle.UnpicklingError:
return self.db_value
#@value.setter
def value_set(self, new_value):
"Setter. Allows for self.value = value"
new_value, mode = self._convert_value(new_value)
if mode == "pickle":
new_value = pickle.dumps(new_value) #,pickle.HIGHEST_PROTOCOL)
self.db_value = new_value
self.db_mode = mode
self.db_value = pickle.dumps(self.validate_data(new_value))
self.save()
#@value.deleter
def value_del(self):
@ -272,52 +230,55 @@ class Attribute(SharedMemoryModel):
def __unicode__(self):
return u"%s(%s)" % (self.key, self.id)
def _convert_value(self, in_value):
def validate_data(self, item):
"""
We have to be careful as to what we store. Some things, such
as django model instances, cannot be directly stored/pickled
in an attribute, so we have to be clever about it. Types of
objects and how they are handled:
* str - stored directly in field
* django model object - store its dbref in field
* any other python structure - pickle in field
We have to make sure to not store database objects raw, since this will
crash the system. Instead we must store their IDs and make sure to convert
back when the attribute is read back later.
"""
if isinstance(in_value, basestring):
# (basestring matches both str and unicode)
# strings we just store directly.
return in_value, None
We handle only lists and dicts for iterables.
"""
if isinstance(item, basestring):
# a string is unmodified
ret = item
elif type(item) == PackedDBobject:
# unpack a previously packed object
try:
mclass = ContentType.objects.get(model=item.db_model).model_class()
try:
ret = mclass.objects.dbref_search(item.id)
except AttributeError:
ret = mclass.objects.get(id=item.id)
except Exception:
logger.log_trace("Attribute error: %s, %s" % (item.db_model, item.id)) #TODO: Remove when stable?
ret = None
elif type(item) == dict:
# handle dictionaries
ret = {}
for key, it in item.items():
ret[key] = self.validate_data(it)
elif is_iter(item):
# Note: ALL other iterables are considered to be lists!
ret = []
for it in item:
ret.append(self.validate_data(it))
elif has_parent('django.db.models.base.Model', item) or has_parent(PARENTS['typeclass'], item):
# db models must be stored as dbrefs
db_model = [parent for parent, path in PARENTS.items() if has_parent(path, item)]
if db_model and db_model[0] == 'typeclass':
# the typeclass alone can't help us, we have to know the db object.
db_model = [parent for parent, path in PARENTS.items()
if has_parent(path, item.dbobj)]
if db_model:
# store the object in an easily identifiable container
ret = PackedDBobject(str(item.id), db_model[0])
else:
# not a valid object - some third-party class or primitive?
ret = item
else:
ret = item
if is_iter(in_value):
# an iterable. This is normally something to pickle,
# but we have to be careful so as to not find
# django model instances nested in the iterable.
pass #TODO!
if not has_parent('django.db.models.base.Model', in_value) \
and not has_parent(PARENTS['typeclass'], in_value):
# non-django models that are not strings we pickle
#print "type identified: to_pickle"
#print "found a non-django parent."
return in_value, 'pickle'
# this is a db model. Try to determine what type of db object it is.
db_type = [parent for parent, path in PARENTS.items()
if has_parent(path, in_value)]
if db_type and db_type[0] == 'typeclass':
# the typeclass alone can't help us, we have to know the db object.
db_type = [parent for parent, path in PARENTS.items()
if has_parent(path, in_value.dbobj)]
if not db_type:
# no match; maybe it's a non-model from inside django(?).
return in_value, "pickle"
# it's a db model. Return its dbref as a string instead.
#print "type identified: %s" % db_type[0]
return str(in_value.id), db_type[0]
return ret
def access(self, accessing_obj, access_type='read', default=False):
"""
@ -329,7 +290,6 @@ class Attribute(SharedMemoryModel):
return self.locks.check(accessing_obj, access_type=access_type, default=default)
#------------------------------------------------------------
#
# Typed Objects