mirror of
https://github.com/evennia/evennia.git
synced 2026-03-23 08:16:30 +01:00
OBS- need to run migrations! Refactored attributes to use a slightly different internal storage format for faster access. Also set up caching of all attribute data, so subsequent reads of an attribute will not hit the database anymore, and writes will re-cache.
This commit is contained in:
parent
8b5f3628ab
commit
a32aebaa0e
12 changed files with 560 additions and 152 deletions
|
|
@ -224,8 +224,8 @@ start
|
|||
@create/drop The sea (in the distance);sea;ocean
|
||||
#
|
||||
@desc sea =
|
||||
The grey sea stretches as far as the eye can se to the east, and far below you its waves crash
|
||||
against the foot of the cliff. The vast inland moors meets the ocean along a high and uninviting
|
||||
The grey sea stretches as far as the eye can see to the east. Far below you its waves crash
|
||||
against the foot of the cliff. The vast inland moor meets the ocean along a high and uninviting
|
||||
coastline of ragged vertical stone.
|
||||
|
||||
Once this part of the world might have been beautiful, but now the eternal winds and storms have
|
||||
|
|
@ -287,16 +287,15 @@ north
|
|||
: tutorial_world.rooms.TutorialRoom
|
||||
= enter;in,leave;out
|
||||
#
|
||||
@desc The Evennia Inn consist mainly of one large room filled with tables. The bardisk extends
|
||||
@desc The Evennia Inn consists of one large room filled with tables. The bardisk extends
|
||||
along the east wall, where multiple barrels and bottles line the shelves. The barkeep seems busy
|
||||
handing out ale and chatting with the patrons, which are a rowdy and cheerful lot, keeping the sound
|
||||
level only just below thunderous.
|
||||
level only just below thunderous. This is a rare spot of warmth and mirth on this dread moor.
|
||||
|
||||
|
||||
Soon you have a beer in hand and is chatting with the locals. Your eye fall on a {wbarrel{n in a corner with a few
|
||||
old rusty weapons sticking out. There is a sign next to it: {wFree to take{n.
|
||||
|
||||
A patron tells you cheerfully that it's the leftovers from those foolish adventurers that challenged the old ruin before you ...
|
||||
old rusty weapons sticking out. There is a sign next to it: {wFree to take{n. A patron tells you cheerfully that
|
||||
it's the leftovers from those foolish adventurers that challenged the old ruin before you ...
|
||||
#
|
||||
@set here/tutorial_info =
|
||||
Nothing special about this room, only a bonus place to go for chatting
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ class Msg(SharedMemoryModel):
|
|||
logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
|
||||
lock_storage = property(lock_storage_get, lock_storage_set, lock_storage_del)
|
||||
|
||||
db_model_name = "msg" # used by attributes to safely store objects
|
||||
|
||||
#
|
||||
# Msg class methods
|
||||
|
|
@ -513,6 +514,8 @@ class Channel(SharedMemoryModel):
|
|||
logger.log_errmsg("Lock_Storage (on %s) cannot be deleted. Use obj.lock.delete() instead." % self)
|
||||
lock_storage = property(lock_storage_get, lock_storage_set, lock_storage_del)
|
||||
|
||||
db_model_name = "channel" # used by attributes to safely store objects
|
||||
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
verbose_name = "Channel"
|
||||
|
|
|
|||
112
src/objects/migrations/0009_converting_attributes.py
Normal file
112
src/objects/migrations/0009_converting_attributes.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
from src.utils.utils import to_str, to_unicode
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
"Write your forwards methods here."
|
||||
for attr in orm.ObjAttribute.objects.all():
|
||||
attr.value = pickle.loads(to_str(attr.db_value))
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
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'})
|
||||
},
|
||||
'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_index': 'True'}),
|
||||
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['objects.ObjectDB']"}),
|
||||
'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_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']"}),
|
||||
'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.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'})
|
||||
},
|
||||
'objects.objectnick': {
|
||||
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'ObjectNick'},
|
||||
'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'})
|
||||
},
|
||||
'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_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 = ['objects']
|
||||
|
|
@ -425,6 +425,7 @@ class ObjectDB(TypedObject):
|
|||
#attribute_model_name = "ObjAttribute"
|
||||
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
||||
attribute_class = ObjAttribute
|
||||
db_model_name = "objectdb" # used by attributes to safely store objects
|
||||
|
||||
# this is used by all typedobjects as a fallback
|
||||
try:
|
||||
|
|
|
|||
106
src/players/migrations/0008_converting_attributes.py
Normal file
106
src/players/migrations/0008_converting_attributes.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
from src.utils.utils import to_str, to_unicode
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
"Write your forwards methods here."
|
||||
for attr in orb.PlayerAttribute.objects.all():
|
||||
attr.value = pickle.loads(to_str(attr.db_value))
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
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'})
|
||||
},
|
||||
'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.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_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['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_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_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'})
|
||||
},
|
||||
'players.playernick': {
|
||||
'Meta': {'unique_together': "(('db_nick', 'db_type', 'db_obj'),)", 'object_name': 'PlayerNick'},
|
||||
'db_nick': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['players.PlayerDB']"}),
|
||||
'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'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['players']
|
||||
|
|
@ -269,6 +269,7 @@ class PlayerDB(TypedObject):
|
|||
#attribute_model_name = "PlayerAttribute"
|
||||
typeclass_paths = settings.PLAYER_TYPECLASS_PATHS
|
||||
attribute_class = PlayerAttribute
|
||||
db_model_name = "playerdb" # used by attributes to safely store objects
|
||||
|
||||
# name property (wraps self.user.username)
|
||||
#@property
|
||||
|
|
|
|||
114
src/scripts/migrations/0005_converting_attributes.py
Normal file
114
src/scripts/migrations/0005_converting_attributes.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
# encoding: utf-8
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
try:
|
||||
import cPickle as pickle
|
||||
except ImportError:
|
||||
import pickle
|
||||
from src.utils.utils import to_str, to_unicode
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
def forwards(self, orm):
|
||||
"Write your forwards methods here."
|
||||
for attr in orm.ScriptAttribute.objects.all():
|
||||
attr.value = pickle.loads(to_str(attr.db_value))
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
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'})
|
||||
},
|
||||
'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_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'})
|
||||
},
|
||||
'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_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['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_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_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']
|
||||
|
|
@ -249,6 +249,7 @@ class ScriptDB(TypedObject):
|
|||
#attribute_model_name = "ScriptAttribute"
|
||||
typeclass_paths = settings.SCRIPT_TYPECLASS_PATHS
|
||||
attribute_class = ScriptAttribute
|
||||
db_model_name = "scriptdb" # used by attributes to safely store objects
|
||||
|
||||
# this is used by all typedobjects as a fallback
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ import and inherit from these classes.
|
|||
|
||||
Attributes are database objects stored on other objects. The implementing
|
||||
class needs to supply a ForeignKey field attr_object pointing to the kind
|
||||
of object being mapped.
|
||||
of object being mapped. Attributes storing iterables actually store special
|
||||
types of iterables named PackedList/PackedDict respectively. These make
|
||||
sure to save changes to them to database - this is criticial in order to
|
||||
allow for obj.db.mylist[2] = data. Also, all dbobjects are saved as
|
||||
dbrefs but are also aggressively cached.
|
||||
|
||||
TypedObjects are objects 'decorated' with a typeclass - that is, the typeclass
|
||||
(which is a normal Python class implementing some special tricks with its
|
||||
|
|
@ -37,7 +41,7 @@ from src.server.models import ServerConfig
|
|||
from src.typeclasses import managers
|
||||
from src.locks.lockhandler import LockHandler
|
||||
from src.utils import logger, utils
|
||||
from src.utils.utils import is_iter, has_parent
|
||||
from src.utils.utils import is_iter, has_parent, to_unicode, to_str
|
||||
|
||||
PERMISSION_HIERARCHY = [p.lower() for p in settings.PERMISSION_HIERARCHY]
|
||||
|
||||
|
|
@ -45,17 +49,20 @@ CTYPEGET = ContentType.objects.get
|
|||
GA = object.__getattribute__
|
||||
SA = object.__setattr__
|
||||
DA = object.__delattr__
|
||||
PLOADS = pickle.loads
|
||||
PDUMPS = pickle.dumps
|
||||
|
||||
# used by Attribute to efficiently identify stored object types.
|
||||
# Note that these have to be updated if directory structure changes.
|
||||
PARENTS = {
|
||||
"typeclass":"src.typeclasses.typeclass.TypeClass",
|
||||
"objectdb":"src.objects.models.ObjectDB",
|
||||
"playerdb":"src.players.models.PlayerDB",
|
||||
"scriptdb":"src.scripts.models.ScriptDB",
|
||||
"msg":"src.comms.models.Msg",
|
||||
"channel":"src.comms.models.Channel",
|
||||
"helpentry":"src.help.models.HelpEntry"}
|
||||
|
||||
# # used by Attribute to efficiently identify stored object types.
|
||||
# # Note that these have to be updated if directory structure changes.
|
||||
# PARENTS = {
|
||||
# "typeclass":"src.typeclasses.typeclass.TypeClass",
|
||||
# "objectdb":"src.objects.models.ObjectDB",
|
||||
# "playerdb":"src.players.models.PlayerDB",
|
||||
# "scriptdb":"src.scripts.models.ScriptDB",
|
||||
# "msg":"src.comms.models.Msg",
|
||||
# "channel":"src.comms.models.Channel",
|
||||
# "helpentry":"src.help.models.HelpEntry"}
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
|
|
@ -63,15 +70,20 @@ PARENTS = {
|
|||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class PackedDBobject(object):
|
||||
class PackedDBobject(dict):
|
||||
"""
|
||||
Attribute helper class.
|
||||
A container for storing and easily identifying database objects in
|
||||
the database (which doesn't suppport storing db_objects directly).
|
||||
"""
|
||||
def __init__(self, ID, db_model):
|
||||
self.id = ID
|
||||
self.db_model = db_model
|
||||
def __init__(self, ID, db_model, db_key):
|
||||
self['id'] = ID
|
||||
self['db_model'] = db_model
|
||||
self['key'] = db_key
|
||||
def __str__(self):
|
||||
return "%s(#%s)" % (self['key'], self['id'])
|
||||
def __unicode__(self):
|
||||
return u"%s(#%s)" % (self['key'], self['id'])
|
||||
|
||||
class PackedDict(dict):
|
||||
"""
|
||||
|
|
@ -87,37 +99,32 @@ class PackedDict(dict):
|
|||
order to allow custom updates to the dict.
|
||||
|
||||
db_obj - the Attribute object storing this dict.
|
||||
|
||||
|
||||
"""
|
||||
self.db_obj = db_obj
|
||||
self.db_store = False
|
||||
super(PackedDict, self).__init__(*args, **kwargs)
|
||||
def db_save(self):
|
||||
"save data to Attribute, if db_store is active"
|
||||
if self.db_store:
|
||||
self.db_obj.value = self
|
||||
def __str__(self):
|
||||
return "{%s}" % ", ".join("%s:%s" % (key, str(val)) for key, val in self.items())
|
||||
def __setitem__(self, *args, **kwargs):
|
||||
"Custom setitem that stores changed dict to database."
|
||||
"assign item to this dict"
|
||||
super(PackedDict, self).__setitem__(*args, **kwargs)
|
||||
self.db_save()
|
||||
def __getitem__(self, *args, **kwargs):
|
||||
return super(PackedDict, self).__getitem__(*args, **kwargs)
|
||||
self.db_obj.value = self
|
||||
def clear(self, *args, **kwargs):
|
||||
"Custom clear"
|
||||
super(PackedDict, self).clear(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def pop(self, *args, **kwargs):
|
||||
"Custom pop"
|
||||
super(PackedDict, self).pop(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def popitem(self, *args, **kwargs):
|
||||
"Custom popitem"
|
||||
super(PackedDict, self).popitem(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def update(self, *args, **kwargs):
|
||||
"Custom update"
|
||||
super(PackedDict, self).update(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
|
||||
class PackedList(list):
|
||||
"""
|
||||
|
|
@ -128,54 +135,45 @@ class PackedList(list):
|
|||
"""
|
||||
def __init__(self, db_obj, *args, **kwargs):
|
||||
"""
|
||||
Sets up the packing list. The db_store variable
|
||||
is set by Attribute.validate_data() when returned in
|
||||
order to allow custom updates to the list.
|
||||
|
||||
Sets up the packing list.
|
||||
db_obj - the Attribute object storing this dict.
|
||||
|
||||
"""
|
||||
self.db_obj = db_obj
|
||||
self.db_store = False
|
||||
super(PackedList, self).__init__(*args, **kwargs)
|
||||
def db_save(self):
|
||||
"save data to Attribute, if db_store is active"
|
||||
if self.db_store:
|
||||
self.db_obj.value = self
|
||||
def __str__(self):
|
||||
return "[%s]" % ", ".join(str(val) for val in self)
|
||||
def __setitem__(self, *args, **kwargs):
|
||||
"Custom setitem that stores changed dict to database."
|
||||
super(PackedList, self).__setitem__(*args, **kwargs)
|
||||
self.db_save()
|
||||
"Custom setitem that stores changed list to database."
|
||||
super(PackedList, self).__setitem__(*args, **kwargs)
|
||||
self.db_obj.value = self
|
||||
def append(self, *args, **kwargs):
|
||||
"Custom append"
|
||||
super(PackedList, self).append(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def extend(self, *args, **kwargs):
|
||||
"Custom extend"
|
||||
super(PackedList, self).extend(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def insert(self, *args, **kwargs):
|
||||
"Custom insert"
|
||||
super(PackedList, self).insert(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def remove(self, *args, **kwargs):
|
||||
"Custom remove"
|
||||
super(PackedList, self).remove(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def pop(self, *args, **kwargs):
|
||||
"Custom pop"
|
||||
super(PackedList, self).pop(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def reverse(self, *args, **kwargs):
|
||||
"Custom reverse"
|
||||
super(PackedList, self).reverse(*args, **kwargs)
|
||||
self.db_save()
|
||||
self.db_obj.value = self
|
||||
def sort(self, *args, **kwargs):
|
||||
"Custom sort"
|
||||
super(PackedList, self).sort(*args, **kwargs)
|
||||
self.db_save()
|
||||
|
||||
|
||||
self.db_obj.value = self
|
||||
|
||||
class Attribute(SharedMemoryModel):
|
||||
"""
|
||||
|
|
@ -195,7 +193,15 @@ class Attribute(SharedMemoryModel):
|
|||
obj - which object the attribute is defined on
|
||||
date_created - when the attribute was created
|
||||
value - the data stored in the attribute
|
||||
what is actually stored in the field is a dict
|
||||
|
||||
{type : nodb|dbobj|dbiter,
|
||||
data : <data>}
|
||||
|
||||
where type is info for the loader, telling it if holds a single
|
||||
dbobject (dbobj), have to do a full scan for dbrefs (dbiter) or
|
||||
if it is a normal Python structure without any dbobjs inside it
|
||||
and can thus return it without further action (nodb).
|
||||
"""
|
||||
|
||||
#
|
||||
|
|
@ -214,7 +220,7 @@ class Attribute(SharedMemoryModel):
|
|||
# by each child class to this abstact class)
|
||||
db_obj = None # models.ForeignKey("RefencedObject")
|
||||
# time stamp
|
||||
db_date_created = models.DateTimeField('date_created',editable=False, auto_now_add=True)
|
||||
db_date_created = models.DateTimeField('date_created', editable=False, auto_now_add=True)
|
||||
|
||||
# Database manager
|
||||
objects = managers.AttributeManager()
|
||||
|
|
@ -224,13 +230,14 @@ class Attribute(SharedMemoryModel):
|
|||
"Initializes the parent first -important!"
|
||||
SharedMemoryModel.__init__(self, *args, **kwargs)
|
||||
self.locks = LockHandler(self)
|
||||
self.value_cache = None
|
||||
|
||||
self.no_cache = True
|
||||
self.cached_value = None
|
||||
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
abstract = True
|
||||
verbose_name = "Evennia Attribute"
|
||||
|
||||
verbose_name = "Evennia Attribute"
|
||||
|
||||
# Wrapper properties to easily set database fields. These are
|
||||
# @property decorators that allows to access these fields using
|
||||
# normal python operations (without having to remember to save()
|
||||
|
|
@ -291,17 +298,30 @@ class Attribute(SharedMemoryModel):
|
|||
#@property
|
||||
def value_get(self):
|
||||
"""
|
||||
Getter. Allows for value = self.value.
|
||||
"""
|
||||
try:
|
||||
return utils.to_unicode(self.validate_data(pickle.loads(utils.to_str(self.db_value))))
|
||||
except pickle.UnpicklingError:
|
||||
return self.db_value
|
||||
Getter. Allows for value = self.value. Reads from cache if possible.
|
||||
"""
|
||||
if self.no_cache:
|
||||
# re-create data from database and cache it
|
||||
try:
|
||||
value = self.from_attr(PLOADS(to_str(self.db_value)))
|
||||
except pickle.UnpicklingError:
|
||||
value = self.db_value
|
||||
self.cached_value = value
|
||||
self.no_cache = False
|
||||
return value
|
||||
else:
|
||||
# normally the memory cache holds the latest data so no db access is needed.
|
||||
return self.cached_value
|
||||
|
||||
#@value.setter
|
||||
def value_set(self, new_value):
|
||||
"Setter. Allows for self.value = value"
|
||||
self.db_value = utils.to_unicode(pickle.dumps(utils.to_str(self.validate_data(new_value, setmode=True))))
|
||||
#self.db_value = utils.to_unicode(pickle.dumps(utils.to_str(self.validate_data(new_value))))
|
||||
"""
|
||||
Setter. Allows for self.value = value. We make sure to cache everything.
|
||||
"""
|
||||
new_value = self.to_attr(new_value)
|
||||
self.cached_value = self.from_attr(new_value)
|
||||
self.no_cache = False
|
||||
self.db_value = to_unicode(PDUMPS(to_str(new_value)))
|
||||
self.save()
|
||||
#@value.deleter
|
||||
def value_del(self):
|
||||
|
|
@ -338,8 +358,12 @@ class Attribute(SharedMemoryModel):
|
|||
def __unicode__(self):
|
||||
return u"%s(%s)" % (self.key, self.id)
|
||||
|
||||
def validate_data(self, item, niter=0, setmode=False):
|
||||
# operators on various data
|
||||
|
||||
def to_attr(self, data):
|
||||
"""
|
||||
Convert data to proper attr data format before saving
|
||||
|
||||
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
|
||||
|
|
@ -351,75 +375,120 @@ class Attribute(SharedMemoryModel):
|
|||
(and any nested combination of them) this way, all other
|
||||
iterables are stored and returned as lists.
|
||||
|
||||
setmode - used for iterables; when first assigning, this settings makes
|
||||
sure that it's a normal built-in python object that is stored in the db,
|
||||
not the custom one. This will then just be updated later, assuring the
|
||||
pickling works as it should.
|
||||
niter - iteration counter for recursive iterable search.
|
||||
"""
|
||||
if isinstance(item, basestring):
|
||||
# a string is unmodified
|
||||
ret = item
|
||||
elif type(item) == PackedDBobject:
|
||||
# unpack a previously packed db_object
|
||||
try:
|
||||
#print "unpack:", item.id, item.db_model
|
||||
mclass = CTYPEGET(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) == tuple:
|
||||
# handle tuples
|
||||
ret = []
|
||||
for it in item:
|
||||
ret.append(self.validate_data(it))
|
||||
ret = tuple(ret)
|
||||
elif type(item) == dict or type(item) == PackedDict:
|
||||
# handle dictionaries
|
||||
if setmode:
|
||||
ret = {}
|
||||
for key, it in item.items():
|
||||
ret[key] = self.validate_data(it, niter=niter+1, setmode=True)
|
||||
data storage format:
|
||||
(simple|dbobj|iter, <data>)
|
||||
where
|
||||
simple - a single non-db object, like a string or number
|
||||
dbobj - a single dbobj
|
||||
iter - any iterable object - will be looped over recursively
|
||||
to convert dbobj->id.
|
||||
|
||||
"""
|
||||
|
||||
def iter_db2id(item):
|
||||
"""
|
||||
recursively looping through stored iterables, replacing objects with ids.
|
||||
(Python only builds nested functions once, so there is no overhead for nesting)
|
||||
"""
|
||||
dtype = type(item)
|
||||
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||
return item
|
||||
elif hasattr(item, "id") and hasattr(item, "db_model_name") and hasattr(item, "db_key"):
|
||||
db_model_name = item.db_model_name
|
||||
if db_model_name == "typeclass":
|
||||
db_model_name = GA(item.dbobj, "db_model_name")
|
||||
return PackedDBobject(item.id, db_model_name, item.db_key)
|
||||
elif dtype == tuple:
|
||||
return tuple(iter_db2id(val) for val in item)
|
||||
elif dtype in (dict, PackedDict):
|
||||
return dict((key, iter_db2id(val)) for key, val in item.items())
|
||||
elif hasattr(item, '__iter__'):
|
||||
return list(iter_db2id(val) for val in item)
|
||||
else:
|
||||
ret = PackedDict(self)
|
||||
for key, it in item.items():
|
||||
ret[key] = self.validate_data(it, niter=niter+1)
|
||||
if niter == 0:
|
||||
ret.db_store = True
|
||||
elif is_iter(item):
|
||||
# Note: ALL other iterables except dicts and tuples are stored&retrieved as lists!
|
||||
if setmode:
|
||||
ret = []
|
||||
for it in item:
|
||||
ret.append(self.validate_data(it, niter=niter+1,setmode=True))
|
||||
else:
|
||||
ret = PackedList(self)
|
||||
for it in item:
|
||||
ret.append(self.validate_data(it, niter=niter+1))
|
||||
if niter == 0:
|
||||
ret.db_store = True
|
||||
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)]
|
||||
#print "db_model", db_model
|
||||
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)]
|
||||
#print "db_model2", db_model
|
||||
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
|
||||
return item
|
||||
|
||||
dtype = type(data)
|
||||
|
||||
if dtype in (basestring, int, float):
|
||||
return ("simple",data)
|
||||
elif hasattr(data, "id") and hasattr(data, "db_model_name") and hasattr(data, 'db_key'):
|
||||
# all django models (objectdb,scriptdb,playerdb,channel,msg,typeclass)
|
||||
# have the protected property db_model_name hardcoded on themselves for speed.
|
||||
db_model_name = data.db_model_name
|
||||
if db_model_name == "typeclass":
|
||||
# typeclass cannot help us, we want the actual child object model name
|
||||
db_model_name = GA(data.dbobj, "db_model_name")
|
||||
return ("dbobj", PackedDBobject(data.id, db_model_name, data.db_key))
|
||||
elif hasattr(data, "__iter__"):
|
||||
return ("iter", iter_db2id(data))
|
||||
else:
|
||||
ret = item
|
||||
return ret
|
||||
return ("simple", data)
|
||||
|
||||
|
||||
def from_attr(self, datatuple):
|
||||
"""
|
||||
Retrieve data from a previously stored attribute. This
|
||||
is always a dict with keys type and data.
|
||||
|
||||
datatuple comes from the database storage and has
|
||||
the following format:
|
||||
(simple|dbobj|iter, <data>)
|
||||
where
|
||||
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.
|
||||
iter - an iterable. This is traversed iteratively, converting all found
|
||||
dbobj-ids back to objects. Also, all lists and dictionaries are
|
||||
returned as their PackedList/PackedDict counterparts in order to
|
||||
allow in-place assignment such as obj.db.mylist[3] = val. Mylist
|
||||
is then a PackedList that saves the data on the fly.
|
||||
"""
|
||||
# nested functions
|
||||
def id2db(data):
|
||||
"""
|
||||
Convert db-stored dbref back to object
|
||||
"""
|
||||
mclass = CTYPEGET(model=data["db_model"]).model_class()
|
||||
try:
|
||||
return mclass.objects.dbref_search(data['id'])
|
||||
except AttributeError:
|
||||
try:
|
||||
return mclass.objects.get(id=data['id'])
|
||||
except mclass.DoesNotExist: # could happen if object was deleted in the interim.
|
||||
return None
|
||||
|
||||
def iter_id2db(item):
|
||||
"""
|
||||
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
|
||||
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.
|
||||
"""
|
||||
dtype = type(item)
|
||||
if dtype in (basestring, int, float): # check the most common types first, for speed
|
||||
return item
|
||||
elif dtype == PackedDBobject:
|
||||
return id2db(item)
|
||||
elif dtype == tuple:
|
||||
return tuple([iter_id2db(val) for val in item])
|
||||
elif dtype in (dict, PackedDict):
|
||||
return PackedDict(self, dict(zip([key for key in item.keys()],
|
||||
[iter_id2db(val) for val in item.values()])))
|
||||
elif hasattr(item, '__iter__'):
|
||||
return PackedList(self, list(iter_id2db(val) for val in item))
|
||||
else:
|
||||
return item
|
||||
|
||||
typ, data = datatuple
|
||||
|
||||
if typ == 'simple':
|
||||
# single non-db objects
|
||||
return data
|
||||
elif typ == 'dbobj':
|
||||
# a single stored dbobj
|
||||
return id2db(data)
|
||||
elif typ == 'iter':
|
||||
# all types of iterables
|
||||
return iter_id2db(data)
|
||||
|
||||
def access(self, accessing_obj, access_type='read', default=False):
|
||||
"""
|
||||
|
|
@ -706,7 +775,8 @@ class TypedObject(SharedMemoryModel):
|
|||
#attribute_model_path = "src.typeclasses.models"
|
||||
#attribute_model_name = "Attribute"
|
||||
typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
||||
attribute_class = Attribute # replaced by relevant attribute class for child
|
||||
attribute_class = Attribute # replaced by relevant attribute class for child
|
||||
db_model_name = "typeclass" # used by attributes to safely store objects
|
||||
|
||||
def __eq__(self, other):
|
||||
return other and hasattr(other, 'id') and self.id == other.id
|
||||
|
|
@ -870,7 +940,7 @@ class TypedObject(SharedMemoryModel):
|
|||
# no mudinfo channel is found. Log instead.
|
||||
cmessage = "\n".join(["[NO MUDINFO CHANNEL]: %s" % line for line in message.split('\n')])
|
||||
logger.log_errmsg(cmessage)
|
||||
except Exception, e:
|
||||
except Exception:
|
||||
if ServerConfig.objects.conf("server_starting_mode"):
|
||||
print cmessage
|
||||
else:
|
||||
|
|
@ -1054,15 +1124,14 @@ class TypedObject(SharedMemoryModel):
|
|||
attrib_obj = None
|
||||
attrclass = self.attribute_class
|
||||
try:
|
||||
# use old attribute
|
||||
attrib_obj = attrclass.objects.filter(
|
||||
db_obj=self).filter(db_key__iexact=attribute_name)[0]
|
||||
except IndexError:
|
||||
# no match; create new attribute
|
||||
new_attrib = attrclass(db_key=attribute_name, db_obj=self)
|
||||
new_attrib.value = new_value
|
||||
return
|
||||
attrib_obj = attrclass(db_key=attribute_name, db_obj=self)
|
||||
# re-set an old attribute value
|
||||
attrib_obj.value = new_value
|
||||
attrib_obj.value = new_value
|
||||
|
||||
def get_attribute(self, attribute_name, default=None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -25,7 +25,8 @@ DA = object.__delattr__
|
|||
# full access anyway), so no protection against changing
|
||||
# e.g. 'locks' or 'permissions' should go here.
|
||||
PROTECTED = ('id', 'dbobj', 'db', 'ndb', 'objects', 'typeclass',
|
||||
'attr', 'save', 'delete')
|
||||
'attr', 'save', 'delete', 'db_model_name','attribute_class',
|
||||
'typeclass_paths')
|
||||
|
||||
# If this is true, all non-protected property assignments
|
||||
# are directly stored to a database attribute
|
||||
|
|
@ -207,3 +208,5 @@ class TypeClass(object):
|
|||
def __str__(self):
|
||||
"represent the object"
|
||||
return self.key
|
||||
def __unicode__(self):
|
||||
return u"%s" % self.key
|
||||
|
|
|
|||
|
|
@ -399,7 +399,7 @@ def create_player(name, email, password,
|
|||
|
||||
from src.players.models import PlayerDB
|
||||
from src.players.player import Player
|
||||
|
||||
|
||||
if not email:
|
||||
email = "dummy@dummy.com"
|
||||
if user:
|
||||
|
|
@ -410,7 +410,6 @@ def create_player(name, email, password,
|
|||
new_user = User.objects.create_superuser(name, email, password)
|
||||
else:
|
||||
new_user = User.objects.create_user(name, email, password)
|
||||
|
||||
try:
|
||||
if not typeclass:
|
||||
typeclass = settings.BASE_PLAYER_TYPECLASS
|
||||
|
|
@ -464,7 +463,7 @@ def create_player(name, email, password,
|
|||
player=new_player)
|
||||
return new_character
|
||||
return new_player
|
||||
except Exception:
|
||||
except Exception,e:
|
||||
# a failure in creating the character
|
||||
if not user:
|
||||
# in there was a failure we clean up everything we can
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class GameTime(Script):
|
|||
self.persistent = True
|
||||
self.start_delay = True
|
||||
self.attr("game_time", 0.0) #IC time
|
||||
self.attr("run_time", 0.0) #OOC time
|
||||
self.attr("run_time", 0.0) #OOC time
|
||||
self.attr("up_time", 0.0) #OOC time
|
||||
|
||||
def at_repeat(self):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue