mirror of
https://github.com/evennia/evennia.git
synced 2026-03-27 02:06:32 +01:00
Merge from DBenoy's branch.
This commit is contained in:
commit
b0bf60cda4
138 changed files with 5295 additions and 1803 deletions
|
|
@ -5,11 +5,13 @@ all Attributes and TypedObjects).
|
|||
"""
|
||||
from functools import update_wrapper
|
||||
from django.db import models
|
||||
from django.db.models import Q
|
||||
from src.utils import idmapper
|
||||
from src.utils.utils import make_iter
|
||||
from src.utils.dbserialize import to_pickle
|
||||
|
||||
__all__ = ("AttributeManager", "TypedObjectManager")
|
||||
_GA = object.__getattribute__
|
||||
|
||||
# Managers
|
||||
|
||||
|
|
@ -48,28 +50,168 @@ class AttributeManager(models.Manager):
|
|||
def exists(self,*args, **kwargs):
|
||||
return super(AttributeManager, self).exists(*args, **kwargs)
|
||||
|
||||
def attr_namesearch(self, searchstr, obj, exact_match=True):
|
||||
def get_attrs_on_obj(self, searchstr, obj, exact_match=True):
|
||||
"""
|
||||
Searches the object's attributes for name matches.
|
||||
Searches the object's attributes for attribute key matches.
|
||||
|
||||
searchstr: (str) A string to search for.
|
||||
"""
|
||||
# Retrieve the list of attributes for this object.
|
||||
if exact_match:
|
||||
return self.filter(db_obj=obj).filter(
|
||||
db_key__iexact=searchstr)
|
||||
else:
|
||||
return self.filter(db_obj=obj).filter(
|
||||
db_key__icontains=searchstr)
|
||||
|
||||
def attr_valuesearch(self, searchstr, obj=None):
|
||||
if exact_match:
|
||||
return _GA("obj", "db_attributes").filter(db_key__iexact=searchstr)
|
||||
else:
|
||||
return _GA("obj", "db_attributes").filter(db_key__icontains=searchstr)
|
||||
|
||||
def attr_namesearch(self, *args, **kwargs):
|
||||
"alias wrapper for backwards compatability"
|
||||
return self.get_attrs_on_obj(*args, **kwargs)
|
||||
|
||||
def get_attr_by_value(self, searchstr, obj=None):
|
||||
"""
|
||||
Searches for Attributes with a given value on obj
|
||||
Searches obj for Attributes with a given value.
|
||||
searchstr - value to search for. This may be any suitable object.
|
||||
obj - limit to a given object instance
|
||||
|
||||
If no restraint is given, all Attributes on all types of objects
|
||||
will be searched. It's highly recommended to at least
|
||||
supply the objclass argument (DBObject, DBScript or DBPlayer)
|
||||
to restrict this lookup.
|
||||
"""
|
||||
if obj:
|
||||
return self.filter(db_obj=obj, db_value=searchstr)
|
||||
return _GA(obj, "db_attributes").filter(db_value=searchstr)
|
||||
return self.filter(db_value=searchstr)
|
||||
|
||||
def attr_valuesearch(self, *args, **kwargs):
|
||||
"alias wrapper for backwards compatability"
|
||||
return self.get_attr_by_value(self, *args, **kwargs)
|
||||
|
||||
#
|
||||
# LiteAttributeManager
|
||||
#
|
||||
|
||||
class LiteAttributeManager(models.Manager):
|
||||
"""
|
||||
Manager methods for LiteAttributes
|
||||
"""
|
||||
def get_lattrs_on_obj(self, obj, search_key=None, category=None):
|
||||
"""
|
||||
Get all lattrs on obj, optionally limited by key and/or category
|
||||
"""
|
||||
if search_key or category:
|
||||
key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q()
|
||||
return _GA(obj, "db_liteattributes").filter(cat_cands & key_cands)
|
||||
else:
|
||||
return list(_GA(obj, "db_liteattributes").all())
|
||||
|
||||
def get_lattr(self, search_key=None, category=None):
|
||||
"""
|
||||
Search and return all liteattrs matching any combination of
|
||||
the search criteria.
|
||||
search_key (string) - the lattr identifier
|
||||
category (string) - the lattr category
|
||||
"""
|
||||
key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q()
|
||||
return list(self.filter(key_cands & cat_cands))
|
||||
|
||||
def get_lattr_data(self, obj=None, search_key=None, category=None):
|
||||
"""
|
||||
Retrieve data from found lattrs in an efficient way. Returns a list of data
|
||||
matching the search criterions
|
||||
"""
|
||||
key_cands = Q(db_key__iexact=search_key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if search_key!=None else Q()
|
||||
if obj:
|
||||
query = _GA(obj, "db_liteattributes").filter(key_cands & cat_cands).prefetch_related("db_data")
|
||||
else:
|
||||
query = self.filter(key_cands & cat_cands).prefetch_related("db_data")
|
||||
return [q.db_data for q in query]
|
||||
|
||||
def create_lattr(self, key, category=None, data=None, obj=None):
|
||||
"""
|
||||
Create a LiteAttribute. This makes sure the create case-insensitive keys.
|
||||
"""
|
||||
|
||||
lattr = self.objects.create(db_key=key.lower().strip(),
|
||||
db_category=category.lower().strip() if category!=None else None,
|
||||
db_data=str(data) if data!=None else None)
|
||||
lattr.save()
|
||||
if obj:
|
||||
obj.db_liteattributes.add(lattr)
|
||||
return lattr
|
||||
|
||||
#
|
||||
# TagManager
|
||||
#
|
||||
|
||||
class TagManager(models.Manager):
|
||||
"""
|
||||
Extra manager methods for Tags
|
||||
"""
|
||||
def get_tags_on_obj(self, obj, key=None, category=None):
|
||||
"""
|
||||
Get all tags on obj, optionally limited by key and/or category
|
||||
"""
|
||||
if key or category:
|
||||
key_cands = Q(db_key__iexact=key.lower().strip()) if key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower.strip()) if key!=None else Q()
|
||||
return _GA(obj, "db_tags").filter(cat_cands & key_cands)
|
||||
else:
|
||||
return list(_GA(obj, "db_tags").all())
|
||||
|
||||
def get_tag(self, key=None, category=None):
|
||||
"""
|
||||
Search and return all tags matching any combination of
|
||||
the search criteria.
|
||||
search_key (string) - the tag identifier
|
||||
category (string) - the tag category
|
||||
|
||||
Returns a single Tag (or None) if both key and category is given, otherwise
|
||||
it will return a list.
|
||||
"""
|
||||
key_cands = Q(db_key__iexact=key.lower().strip()) if key!=None else Q()
|
||||
cat_cands = Q(db_category__iexact=category.lower().strip()) if category!=None else Q()
|
||||
tags = self.filter(key_cands & cat_cands)
|
||||
if key and category:
|
||||
return tags[0] if tags else None
|
||||
else:
|
||||
return list(tags)
|
||||
|
||||
def get_objs_with_tag(self, objclass, key=None, category=None):
|
||||
"""
|
||||
Search and return all objects of objclass that has tags matching
|
||||
the given search criteria.
|
||||
objclass (dbmodel) - the object class to search
|
||||
key (string) - the tag identifier
|
||||
category (string) - the tag category
|
||||
"""
|
||||
key_cands = Q(db_tags__db_key__iexact=key.lower().strip()) if search_key!=None else Q()
|
||||
cat_cands = Q(db_tags__db_category__iexact=category.lower().strip()) if category!=None else Q()
|
||||
return objclass.objects.filter(key_cands & cat_cands)
|
||||
|
||||
def create_tag(self, key=None, category=None, data=None):
|
||||
"""
|
||||
Create a tag. This makes sure the create case-insensitive tags.
|
||||
Note that if the exact same tag configuration (key+category)
|
||||
exists, it will be re-used. A data keyword will overwrite existing
|
||||
data on a tag (it is not part of what makes the tag unique).
|
||||
|
||||
"""
|
||||
data = str(data) if data!=None else None
|
||||
|
||||
tag = self.get_tag(key=key, category=category)
|
||||
if tag and data != None:
|
||||
tag.db_data = data
|
||||
tag.save()
|
||||
elif not tag:
|
||||
tag = self.create(db_key=key.lower().strip() if key!=None else None,
|
||||
db_category=category.lower().strip() if key!=None else None,
|
||||
db_data=str(data) if data!=None else None)
|
||||
tag.save()
|
||||
return tag
|
||||
|
||||
#
|
||||
# helper functions for the TypedObjectManager.
|
||||
#
|
||||
|
|
|
|||
38
src/typeclasses/migrations/0001_initial.py
Normal file
38
src/typeclasses/migrations/0001_initial.py
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# -*- 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 model 'Attribute'
|
||||
db.create_table(u'typeclasses_attribute', (
|
||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, db_index=True)),
|
||||
('db_value', self.gf('src.utils.picklefield.PickledObjectField')(null=True)),
|
||||
('db_lock_storage', self.gf('django.db.models.fields.TextField')(blank=True)),
|
||||
('db_date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal(u'typeclasses', ['Attribute'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Deleting model 'Attribute'
|
||||
db.delete_table(u'typeclasses_attribute')
|
||||
|
||||
|
||||
models = {
|
||||
u'typeclasses.attribute': {
|
||||
'Meta': {'object_name': 'Attribute'},
|
||||
'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.TextField', [], {'blank': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['typeclasses']
|
||||
197
src/typeclasses/migrations/0002_resave_attrs.py
Normal file
197
src/typeclasses/migrations/0002_resave_attrs.py
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models
|
||||
|
||||
try:
|
||||
from django.contrib.auth import get_user_model
|
||||
except ImportError: # django < 1.5
|
||||
from django.contrib.auth.models import User
|
||||
else:
|
||||
User = get_user_model()
|
||||
|
||||
user_orm_label = '%s.%s' % (User._meta.app_label, User._meta.object_name)
|
||||
user_model_label = '%s.%s' % (User._meta.app_label, User._meta.module_name)
|
||||
user_ptr_name = '%s_ptr' % User._meta.object_name.lower()
|
||||
|
||||
class Migration(DataMigration):
|
||||
depends_on = (('server', '0004_store_all_attrs'),
|
||||
('objects', '0021_auto__del_objattribute'),
|
||||
('players', '0020_auto__del_playerattribute'),
|
||||
('scripts', '0013_auto__del_scriptattribute'))
|
||||
no_dry_run=True
|
||||
def forwards(self, orm):
|
||||
"Write your forwards methods here."
|
||||
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
|
||||
|
||||
for tmpattr in orm['server.TmpAttribute'].objects.all():
|
||||
typ = tmpattr.db_obj_type
|
||||
dbid = tmpattr.db_obj_id
|
||||
if typ == 'objectdb':
|
||||
try:
|
||||
dbobj = orm['objects.ObjectDB'].objects.get(id=dbid)
|
||||
except:
|
||||
print "could not find objid %i" % dbid
|
||||
continue
|
||||
elif typ == 'playerdb':
|
||||
try:
|
||||
dbobj = orm['players.PlayerDB'].objects.get(id=dbid)
|
||||
except:
|
||||
print "could not find objid %i" % dbid
|
||||
continue
|
||||
elif typ == 'scriptdb':
|
||||
try:
|
||||
dbobj = orm['scripts.ScriptDB'].objects.get(id=dbid)
|
||||
except:
|
||||
print "could not find objid %i" % dbid
|
||||
continue
|
||||
else:
|
||||
print "Wrong object type to store on: %s" % typ
|
||||
continue
|
||||
dbattr = orm['typeclasses.Attribute'](db_key=tmpattr.db_key,
|
||||
db_value=tmpattr.db_value,
|
||||
db_lock_storage=tmpattr.db_lock_storage,
|
||||
db_date_created=tmpattr.db_date_created)
|
||||
|
||||
dbattr.save()
|
||||
dbobj.db_attributes.add(dbattr)
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
raise RuntimeError("Cannot revert this migration.")
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
user_model_label: {
|
||||
'Meta': {'object_name': User.__name__, 'db_table': "'%s'" % User._meta.db_table},
|
||||
'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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'})
|
||||
},
|
||||
u'server.serverconfig': {
|
||||
'Meta': {'object_name': 'ServerConfig'},
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
|
||||
'db_value': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
'server.tmpattribute': {
|
||||
'Meta': {'object_name': 'TmpAttribute'},
|
||||
'db_date_created': ('django.db.models.fields.DateTimeField', [], {}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_obj_id': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
|
||||
'db_obj_type': ('django.db.models.fields.CharField', [], {'max_length': '10', 'null': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.attribute': {
|
||||
'Meta': {'object_name': 'Attribute'},
|
||||
'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.TextField', [], {'blank': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'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': u"orm['objects.ObjectDB']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'objects.objectdb': {
|
||||
'Meta': {'object_name': 'ObjectDB'},
|
||||
'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'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': u"orm['objects.ObjectDB']"}),
|
||||
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"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': u"orm['objects.ObjectDB']"}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
|
||||
'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
|
||||
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'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': u"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'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'players.playerdb': {
|
||||
'Meta': {'object_name': 'PlayerDB'},
|
||||
'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'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.TextField', [], {'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'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['%s']" % user_orm_label, 'unique': 'True'})
|
||||
},
|
||||
u'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': u"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'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'scripts.scriptdb': {
|
||||
'Meta': {'object_name': 'ScriptDB'},
|
||||
'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'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.TextField', [], {'blank': 'True'}),
|
||||
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['server', 'typeclasses', 'objects', 'scripts', 'players']
|
||||
symmetrical = True
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# -*- 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 model 'LiteAttribute'
|
||||
db.create_table(u'typeclasses_liteattribute', (
|
||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('db_key', self.gf('django.db.models.fields.CharField')(max_length=255)),
|
||||
('db_category', self.gf('django.db.models.fields.CharField')(max_length=64, null=True, blank=True)),
|
||||
('db_data', self.gf('django.db.models.fields.TextField')()),
|
||||
))
|
||||
db.send_create_signal(u'typeclasses', ['LiteAttribute'])
|
||||
|
||||
# Adding index on 'LiteAttribute', fields ['db_key', 'db_category']
|
||||
db.create_index(u'typeclasses_liteattribute', ['db_key', 'db_category'])
|
||||
|
||||
# Adding model 'Tag'
|
||||
db.create_table(u'typeclasses_tag', (
|
||||
(u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
|
||||
('db_key', self.gf('django.db.models.fields.CharField')(max_length=255, null=True)),
|
||||
('db_category', self.gf('django.db.models.fields.CharField')(max_length=64, null=True)),
|
||||
('db_data', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
|
||||
))
|
||||
db.send_create_signal(u'typeclasses', ['Tag'])
|
||||
|
||||
# Adding unique constraint on 'Tag', fields ['db_key', 'db_category']
|
||||
db.create_unique(u'typeclasses_tag', ['db_key', 'db_category'])
|
||||
|
||||
# Adding index on 'Tag', fields ['db_key', 'db_category']
|
||||
db.create_index(u'typeclasses_tag', ['db_key', 'db_category'])
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
# Removing index on 'Tag', fields ['db_key', 'db_category']
|
||||
db.delete_index(u'typeclasses_tag', ['db_key', 'db_category'])
|
||||
|
||||
# Removing unique constraint on 'Tag', fields ['db_key', 'db_category']
|
||||
db.delete_unique(u'typeclasses_tag', ['db_key', 'db_category'])
|
||||
|
||||
# Removing index on 'LiteAttribute', fields ['db_key', 'db_category']
|
||||
db.delete_index(u'typeclasses_liteattribute', ['db_key', 'db_category'])
|
||||
|
||||
# Deleting model 'LiteAttribute'
|
||||
db.delete_table(u'typeclasses_liteattribute')
|
||||
|
||||
# Deleting model 'Tag'
|
||||
db.delete_table(u'typeclasses_tag')
|
||||
|
||||
|
||||
models = {
|
||||
u'typeclasses.attribute': {
|
||||
'Meta': {'object_name': 'Attribute'},
|
||||
'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.TextField', [], {'blank': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.liteattribute': {
|
||||
'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.tag': {
|
||||
'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['typeclasses']
|
||||
|
|
@ -0,0 +1,177 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import datetime
|
||||
from south.db import db
|
||||
from south.v2 import DataMigration
|
||||
from django.db import models, IntegrityError
|
||||
|
||||
|
||||
class Migration(DataMigration):
|
||||
|
||||
depends_on = (("objects", "0022_add_db_liteattributes_db_tags"),
|
||||
("players", "0025_auto__add_db_liteattributes_db_tags"))
|
||||
|
||||
def forwards(self, orm):
|
||||
"Write your forwards methods here."
|
||||
# Note: Don't use "from appname.models import ModelName".
|
||||
# Use orm.ModelName to refer to models in this application,
|
||||
# and orm['appname.ModelName'] for models in other applications.
|
||||
|
||||
# Each alias and nick is its own case. By default, this function starts
|
||||
# in a transaction, so we'll close that and make our own transactions.
|
||||
|
||||
for alias in orm['objects.Alias'].objects.all():
|
||||
# convert all Aliases to tags
|
||||
try:
|
||||
tag = orm.Tag.objects.get(db_key=alias.db_key, db_category="object_alias")
|
||||
except orm.Tag.DoesNotExist:
|
||||
tag = orm.Tag(db_key=alias.db_key, db_category="object_alias", db_data=None)
|
||||
tag.save()
|
||||
obj = alias.db_obj
|
||||
obj.db_tags.add(tag)
|
||||
# convert all nicks to LiteAttrs
|
||||
for nick in orm['objects.ObjectNick'].objects.all():
|
||||
lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="object_nick_%s" % nick.db_type, db_data=nick.db_real)
|
||||
lattr.save()
|
||||
obj = nick.db_obj
|
||||
obj.db_liteattributes.add(lattr)
|
||||
for nick in orm['players.PlayerNick'].objects.all():
|
||||
lattr = orm.LiteAttribute(db_key=nick.db_nick, db_category="player_nick_%s" % nick.db_type, db_data=nick.db_real)
|
||||
lattr.save()
|
||||
obj = nick.db_obj
|
||||
obj.db_liteattributes.add(lattr)
|
||||
|
||||
def backwards(self, orm):
|
||||
"Write your backwards methods here."
|
||||
|
||||
models = {
|
||||
u'auth.group': {
|
||||
'Meta': {'object_name': 'Group'},
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
|
||||
},
|
||||
u'auth.permission': {
|
||||
'Meta': {'ordering': "(u'content_type__app_label', u'content_type__model', u'codename')", 'unique_together': "((u'content_type', u'codename'),)", 'object_name': 'Permission'},
|
||||
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['contenttypes.ContentType']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
|
||||
},
|
||||
u'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'}),
|
||||
u'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'})
|
||||
},
|
||||
u'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': u"orm['objects.ObjectDB']"}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'objects.objectdb': {
|
||||
'Meta': {'object_name': 'ObjectDB'},
|
||||
'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'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': u"orm['objects.ObjectDB']"}),
|
||||
'db_home': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'homes_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'}),
|
||||
'db_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'db_location': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'locations_set'", 'null': 'True', 'to': u"orm['objects.ObjectDB']"}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'db_player': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['players.PlayerDB']", 'null': 'True', 'blank': 'True'}),
|
||||
'db_sessid': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
|
||||
'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'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': u"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'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'players.playerdb': {
|
||||
'Meta': {'object_name': 'PlayerDB'},
|
||||
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
|
||||
'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'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_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_permissions': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
|
||||
'db_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
'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': u"orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
u'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': u"orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
|
||||
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
|
||||
},
|
||||
u'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': u"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'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'scripts.scriptdb': {
|
||||
'Meta': {'object_name': 'ScriptDB'},
|
||||
'db_attributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Attribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'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_liteattributes': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.LiteAttribute']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'db_lock_storage': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
|
||||
'db_obj': ('django.db.models.fields.related.ForeignKey', [], {'to': u"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_tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['typeclasses.Tag']", 'null': 'True', 'symmetrical': 'False'}),
|
||||
'db_typeclass_path': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.attribute': {
|
||||
'Meta': {'object_name': 'Attribute'},
|
||||
'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.TextField', [], {'blank': 'True'}),
|
||||
'db_value': ('src.utils.picklefield.PickledObjectField', [], {'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.liteattribute': {
|
||||
'Meta': {'object_name': 'LiteAttribute', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True', 'blank': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
},
|
||||
u'typeclasses.tag': {
|
||||
'Meta': {'unique_together': "(('db_key', 'db_category'),)", 'object_name': 'Tag', 'index_together': "(('db_key', 'db_category'),)"},
|
||||
'db_category': ('django.db.models.fields.CharField', [], {'max_length': '64', 'null': 'True'}),
|
||||
'db_data': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'db_key': ('django.db.models.fields.CharField', [], {'max_length': '255', 'null': 'True'}),
|
||||
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['objects', 'scripts', 'players', 'typeclasses']
|
||||
symmetrical = True
|
||||
0
src/typeclasses/migrations/__init__.py
Normal file
0
src/typeclasses/migrations/__init__.py
Normal file
|
|
@ -34,20 +34,24 @@ import sys
|
|||
import traceback
|
||||
#from collections import defaultdict
|
||||
|
||||
from django.db import models, IntegrityError
|
||||
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.server.caches import get_field_cache, set_field_cache, del_field_cache
|
||||
from src.server.caches import get_attr_cache, set_attr_cache, del_attr_cache
|
||||
from src.server.caches import get_prop_cache, set_prop_cache, del_prop_cache, flush_attr_cache
|
||||
from src.server.caches import call_ndb_hooks
|
||||
from src.server.caches import get_attr_cache, set_attr_cache
|
||||
from src.server.caches import get_prop_cache, set_prop_cache, flush_attr_cache
|
||||
|
||||
from django.db.models.signals import m2m_changed
|
||||
from src.server.caches import post_attr_update
|
||||
|
||||
#from src.server.caches import call_ndb_hooks
|
||||
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 make_iter, is_iter, to_unicode, to_str
|
||||
from src.utils.utils import make_iter, is_iter, to_str
|
||||
from src.utils.dbserialize import to_pickle, from_pickle
|
||||
from src.utils.picklefield import PickledObjectField
|
||||
|
||||
|
|
@ -59,8 +63,7 @@ _CTYPEGET = ContentType.objects.get
|
|||
_GA = object.__getattribute__
|
||||
_SA = object.__setattr__
|
||||
_DA = object.__delattr__
|
||||
#_PLOADS = pickle.loads
|
||||
#_PDUMPS = pickle.dumps
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
|
|
@ -68,7 +71,6 @@ _DA = object.__delattr__
|
|||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
|
||||
class Attribute(SharedMemoryModel):
|
||||
"""
|
||||
Abstract django model.
|
||||
|
|
@ -85,34 +87,22 @@ class Attribute(SharedMemoryModel):
|
|||
mode - which type of data is stored in attribute
|
||||
lock_storage - perm strings
|
||||
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
|
||||
date_created - when the attribute was created.
|
||||
value - the data stored in the attribute, in pickled form
|
||||
using wrappers to be able to store/retrieve models.
|
||||
|
||||
{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).
|
||||
"""
|
||||
|
||||
#
|
||||
# Attribute Database Model setup
|
||||
#
|
||||
#
|
||||
# These databse fields are all set using their corresponding properties,
|
||||
# These database fields are all set using their corresponding properties,
|
||||
# named same as the field, but withtout the db_* prefix.
|
||||
|
||||
db_key = models.CharField('key', max_length=255, db_index=True)
|
||||
# access through the value property
|
||||
db_value = PickledObjectField('value2', null=True)
|
||||
db_value = PickledObjectField('value', null=True)
|
||||
# Lock storage
|
||||
db_lock_storage = models.TextField('locks', blank=True)
|
||||
# references the object the attribute is linked to (this is set
|
||||
# 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)
|
||||
|
||||
|
|
@ -129,9 +119,9 @@ class Attribute(SharedMemoryModel):
|
|||
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
abstract = True
|
||||
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()
|
||||
|
|
@ -242,10 +232,10 @@ class Attribute(SharedMemoryModel):
|
|||
#
|
||||
|
||||
def __str__(self):
|
||||
return smart_str("%s(%s)" % (self.key, self.id))
|
||||
return smart_str("%s(%s)" % (_GA(self, "db_key", _GA(self, "id"))))
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s(%s)" % (self.key, self.id)
|
||||
return u"%s(%s)" % (_GA(self, "db_key", _GA(self, "id")))
|
||||
|
||||
def access(self, accessing_obj, access_type='read', default=False):
|
||||
"""
|
||||
|
|
@ -262,53 +252,208 @@ class Attribute(SharedMemoryModel):
|
|||
"""
|
||||
pass
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Nicks
|
||||
# LiteAttributes
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class TypeNick(SharedMemoryModel):
|
||||
"""
|
||||
This model holds whichever alternate names this object
|
||||
has for OTHER objects, but also for arbitrary strings,
|
||||
channels, players etc. Setting a nick does not affect
|
||||
the nicknamed object at all (as opposed to Aliases above),
|
||||
and only this object will be able to refer to the nicknamed
|
||||
object by the given nick.
|
||||
|
||||
The default nick types used by Evennia are:
|
||||
inputline (default) - match against all input
|
||||
player - match against player searches
|
||||
obj - match against object searches
|
||||
channel - used to store own names for channels
|
||||
class LiteAttribute(models.Model):
|
||||
|
||||
"""
|
||||
db_nick = models.CharField('nickname',max_length=255, db_index=True, help_text='the alias')
|
||||
db_real = models.TextField('realname', help_text='the original string to match and replace.')
|
||||
db_type = models.CharField('nick type',default="inputline", max_length=16, null=True, blank=True,
|
||||
help_text="the nick type describes when the engine tries to do nick-replacement. Common options are 'inputline','player','obj' and 'channel'. Inputline checks everything being inserted, whereas the other cases tries to replace in various searches or when posting to channels.")
|
||||
db_obj = None #models.ForeignKey("ObjectDB")
|
||||
This specialized model is a middle-road between a Tag
|
||||
and an Attribute. A LiteAttribute is smaller, less complex
|
||||
to search than an Attribute (its key is indexed together with its
|
||||
category) but can only hold strings in its db_value property whereas
|
||||
an Attribute can hold arbitrary data. A LiteAttribute is also not
|
||||
kept in memory in the same way as Attributes and has no inherent
|
||||
concept of access restrictions which makes it unsuitable for modification
|
||||
by untrusted users.
|
||||
|
||||
The difference between Liteattrs and Tags are that liteattrs are
|
||||
not shared/unique but are created separately for each object holding them.
|
||||
|
||||
LiteAttributes are accessed through the db_liteattributes many2many field on
|
||||
Typed Objects.
|
||||
|
||||
|
||||
The main default use of the LiteAttribute is to implement Nick replacement.
|
||||
In this case the category determines when the replacement is to be checked.
|
||||
The key value is the input to replace and the data value holds the replacement
|
||||
text.
|
||||
|
||||
The default nick category types used by Evennia are:
|
||||
nick_inputline (default) - match against all input
|
||||
nick_player - match against player searches
|
||||
nick_obj - match against object searches
|
||||
nick_channel - used to store own names for channels
|
||||
|
||||
"""
|
||||
db_key = models.CharField('key', max_length=255, help_text='name if liteattribute')
|
||||
db_category = models.CharField('category', max_length=64, null=True, blank=True, help_text="liteattribute category")
|
||||
db_data = models.TextField('data', help_text='holds string data')
|
||||
|
||||
objects = managers.LiteAttributeManager()
|
||||
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
abstract = True
|
||||
verbose_name = "Nickname"
|
||||
unique_together = ("db_nick", "db_type", "db_obj")
|
||||
verbose_name = "Lite Attribute"
|
||||
index_together = (("db_key", "db_category"),)
|
||||
def __unicode__(self):
|
||||
return u"%s" % self.db_key
|
||||
def __str__(self):
|
||||
return str(self.db_key)
|
||||
|
||||
class TypeNickHandler(object):
|
||||
#------------------------------------------------------------
|
||||
#
|
||||
# Tags
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
|
||||
class Tag(models.Model):
|
||||
"""
|
||||
Handles nick access and setting. Accessed through ObjectDB.nicks
|
||||
Tags are quick markers for objects in-game. An typeobject
|
||||
can have any number of tags, stored via its db_tags property.
|
||||
Tagging similar objects will make it easier to quickly locate the
|
||||
group later (such as when implementing zones). The main advantage
|
||||
of tagging as opposed to using Attributes is speed; a tag is very
|
||||
limited in what data it can hold, and the tag key+category is
|
||||
indexed for efficient lookup in the database. Tags are shared between
|
||||
objects - a new tag is only created if the key+category combination
|
||||
did not previously exist, making them unsuitable for storing
|
||||
object-related data (for this a LiteAttribute or a full Attribute
|
||||
should be used).
|
||||
The 'db_data' field is intended as a documentation
|
||||
field for the tag itself, such as to document what this tag+category
|
||||
stands for and display that in a web interface or similar.
|
||||
|
||||
The main default use for Tags is to implement Aliases for objects.
|
||||
this uses the 'aliases' tag category, which is also checked by the
|
||||
default search functions of Evennia to allow quick searches by alias.
|
||||
"""
|
||||
db_key = models.CharField('key', max_length=255, null=True, help_text="tag identifier")
|
||||
db_category = models.CharField('category', max_length=64, null=True, help_text="tag category")
|
||||
db_data = models.TextField('data', null=True, blank=True, help_text="optional data field with extra information. This is not searched for.")
|
||||
|
||||
NickClass = TypeNick
|
||||
objects = managers.TagManager()
|
||||
class Meta:
|
||||
"Define Django meta options"
|
||||
verbose_name = "Tag"
|
||||
unique_together =(('db_key', 'db_category'),)
|
||||
index_together = (('db_key', 'db_category'),)
|
||||
def __unicode__(self):
|
||||
return u"%s" % self.db_key
|
||||
def __str__(self):
|
||||
return str(self.db_key)
|
||||
|
||||
def __init__(self, obj):
|
||||
|
||||
#
|
||||
# Helper handlers
|
||||
#
|
||||
|
||||
class TagHandler(object):
|
||||
"""
|
||||
Generic tag-handler. Accessed via TypedObject.tags.
|
||||
"""
|
||||
def __init__(self, obj, category_prefix=""):
|
||||
"""
|
||||
This handler allows for accessing and setting nicks -
|
||||
on-the-fly replacements for various text input passing through
|
||||
this object (most often a Character)
|
||||
Tags are stored internally in the TypedObject.db_tags m2m field
|
||||
using the category <category_prefix><tag_category>
|
||||
"""
|
||||
self.obj = obj
|
||||
self.prefix = category_prefix.strip().lower() if category_prefix else ""
|
||||
|
||||
def add(self, tag, category=None, data=None):
|
||||
"Add a new tag to the handler"
|
||||
for tag in make_iter(tag):
|
||||
tag = tag.strip().lower() if tag!=None else None
|
||||
category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None
|
||||
data = str(data) if data!=None else None
|
||||
# this will only create tag if no matches existed beforehand (it will overload
|
||||
# data on an existing tag since that is not considered part of making the tag unique)
|
||||
tagobj = Tag.objects.create_tag(key=tag, category=category, data=data)
|
||||
self.obj.db_tags.add(tagobj)
|
||||
|
||||
def remove(self, tag, category=None):
|
||||
"Remove a tag from the handler"
|
||||
for tag in make_iter(tag):
|
||||
tag = tag.strip().lower() if tag!=None else None
|
||||
category = "%s%s" % (self.prefix, category.strip.lower()) if category!=None else None
|
||||
#TODO This does not delete the tag object itself. Maybe it should do that when no
|
||||
# objects reference the tag anymore?
|
||||
tagobj = self.obj.db_tags.filter(db_key=tag, db_category=category)
|
||||
if tagobj:
|
||||
self.obj.remove(tagobj[0])
|
||||
def clear(self):
|
||||
"Remove all tags from the handler"
|
||||
self.obj.db_tags.clear()
|
||||
|
||||
def all(self):
|
||||
"Get all tags in this handler"
|
||||
return [p[0] for p in self.obj.db_tags.all().values_list("db_key")]
|
||||
|
||||
def __str__(self):
|
||||
return ",".join(self.all())
|
||||
def __unicode(self):
|
||||
return u",".join(self.all())
|
||||
|
||||
|
||||
|
||||
class AliasHandler(object):
|
||||
"""
|
||||
Handles alias access and setting. Accessed through TypedObject.aliases.
|
||||
"""
|
||||
def __init__(self, obj, category_prefix="object_"):
|
||||
"""
|
||||
Aliases are alternate names for an entity.
|
||||
Implements the alias handler, using Tags for storage and
|
||||
the <categoryprefix>_alias tag category. It is available
|
||||
as TypedObjects.aliases.
|
||||
"""
|
||||
self.obj = obj
|
||||
self.category = "%salias" % category_prefix
|
||||
|
||||
def add(self, alias):
|
||||
"Add a new nick to the handler"
|
||||
for al in make_iter(alias):
|
||||
if not al or not al.strip():
|
||||
continue
|
||||
al = al.strip()
|
||||
# create a unique tag only if it didn't already exist
|
||||
aliasobj = Tag.objects.create_tag(key=al, category=self.category)
|
||||
self.obj.db_tags.add(aliasobj)
|
||||
|
||||
def remove(self, alias):
|
||||
"Remove alias from handler."
|
||||
for alias in make_iter(alias):
|
||||
aliasobj = self.obj.filter(db_key__iexact=alias.strip(), category=self.category)
|
||||
#TODO note that this doesn't delete the tag itself. We might want to do this when no object
|
||||
# uses it anymore ...
|
||||
self.obj.db_tags.remove(aliasobj)
|
||||
def clear(self):
|
||||
"Clear all aliases from handler"
|
||||
self.obj.db_tags.remove(self.obj.filter(categery=self.category))
|
||||
|
||||
def all(self):
|
||||
"Get all aliases in this handler"
|
||||
return [p[0] for p in self.obj.db_tags.filter(db_category=self.category).values_list("db_key")]
|
||||
|
||||
def __str__(self):
|
||||
return ",".join(self.all())
|
||||
def __unicode(self):
|
||||
return u",".join(self.all())
|
||||
|
||||
|
||||
class NickHandler(object):
|
||||
"""
|
||||
Handles nick access and setting. Accessed through TypedObject.nicks.
|
||||
"""
|
||||
|
||||
def __init__(self, obj, category_prefix="object_"):
|
||||
"""
|
||||
Nicks are alternate names an entity as of ANOTHER entity. The
|
||||
engine will auto-replace nicks under circumstances dictated
|
||||
by the nick category. It uses LiteAttributes for storage.
|
||||
|
||||
The default nick types used by Evennia are:
|
||||
|
||||
|
|
@ -317,67 +462,89 @@ class TypeNickHandler(object):
|
|||
obj - match against object searches
|
||||
channel - used to store own names for channels
|
||||
|
||||
You can define other nicktypes by using the add() method of
|
||||
this handler and set nick_type to whatever you want. It's then
|
||||
up to you to somehow make use of this nick_type in your game
|
||||
(such as for a "recog" system).
|
||||
|
||||
These are all stored interally using categories
|
||||
<category_prefix>nick_inputline etc.
|
||||
"""
|
||||
self.obj = obj
|
||||
self.prefix = "%snick_" % category_prefix.strip().lower() if category_prefix else ""
|
||||
|
||||
def add(self, nick, realname, nick_type="inputline"):
|
||||
def add(self, nick, realname, category="inputline"):
|
||||
"""
|
||||
Assign a new nick for realname.
|
||||
nick_types used by Evennia are
|
||||
category used by Evennia are
|
||||
'inputline', 'player', 'obj' and 'channel'
|
||||
"""
|
||||
if not nick or not nick.strip():
|
||||
return
|
||||
nick = nick.strip()
|
||||
real = realname.strip()
|
||||
query = self.NickClass.objects.filter(db_obj=self.obj, db_nick__iexact=nick, db_type__iexact=nick_type)
|
||||
if query.count():
|
||||
old_nick = query[0]
|
||||
old_nick.db_real = real
|
||||
old_nick.save()
|
||||
else:
|
||||
new_nick = self.NickClass(db_nick=nick, db_real=real, db_type=nick_type, db_obj=self.obj)
|
||||
new_nick.save()
|
||||
def delete(self, nick, nick_type="inputline"):
|
||||
"Removes a previously stored nick"
|
||||
nick = nick.strip()
|
||||
query = self.NickClass.objects.filter(db_obj=self.obj, db_nick__iexact=nick, db_type__iexact=nick_type)
|
||||
if query.count():
|
||||
# remove the found nick(s)
|
||||
query.delete()
|
||||
def get(self, nick=None, nick_type="inputline", obj=None):
|
||||
"""
|
||||
Retrieves a given nick (with a specified nick_type) on an object. If no nick is given, returns a list
|
||||
of all nicks on the object, or the empty list.
|
||||
Defaults to searching the current object.
|
||||
"""
|
||||
if not obj:
|
||||
# defaults to the current object
|
||||
obj = self.obj
|
||||
if nick:
|
||||
query = self.NickClass.objects.filter(db_obj=obj, db_nick__iexact=nick, db_type__iexact=nick_type)
|
||||
query = query.values_list("db_real", flat=True)
|
||||
for nick in make_iter(nick):
|
||||
nick = nick.strip()
|
||||
real = realname
|
||||
nick_type = "%s%s" % (self.prefix, category.strip().lower())
|
||||
query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type)
|
||||
if query.count():
|
||||
return query[0]
|
||||
old_nick = query[0]
|
||||
old_nick.db_data = real
|
||||
old_nick.save()
|
||||
else:
|
||||
return nick
|
||||
else:
|
||||
return self.NickClass.objects.filter(db_obj=obj)
|
||||
def has(self, nick, nick_type="inputline", obj=None):
|
||||
"""
|
||||
Returns true/false if this nick and nick_type is defined on the given
|
||||
object or not. If no obj is given, default to the current object the
|
||||
handler is defined on.
|
||||
new_nick = LiteAttribute(db_key=nick, db_category=nick_type, db_data=real)
|
||||
new_nick.save()
|
||||
self.obj.db_liteattributes.add(new_nick)
|
||||
|
||||
def remove(self, key, category="inputline"):
|
||||
"Removes a previously stored nick"
|
||||
for nick in make_iter(key):
|
||||
nick = nick.strip()
|
||||
nick_type = "%s%s" % (self.prefix, category.strip().lower())
|
||||
query = self.obj.db_liteattributes.filter(db_key__iexact=nick, db_category__iexact=nick_type)
|
||||
if query.count():
|
||||
# remove the found nick(s)
|
||||
self.obj.db_liteattributes.remove(query[0])
|
||||
|
||||
def delete(self, *args, **kwargs):
|
||||
"alias wrapper"
|
||||
self.remove(*args, **kwargs)
|
||||
|
||||
def get(self, key=None, category="inputline"):
|
||||
"""
|
||||
if not obj:
|
||||
obj = self.obj
|
||||
return self.NickClass.objects.filter(db_obj=obj, db_nick__iexact=nick, db_type__iexact=nick_type).count()
|
||||
Retrieves a given nick object based on the input key and category.
|
||||
If no key is given, returns a list of all matching nick
|
||||
objects (LiteAttributes) on the object, or the empty list.
|
||||
"""
|
||||
returns = []
|
||||
for nick in make_iter(key):
|
||||
nick = nick.strip().lower() if nick!=None else None
|
||||
nick_type = "%s%s" % (self.prefix, category.strip().lower())
|
||||
if nick:
|
||||
nicks = _GA(self.obj, "db_liteattributes").filter(db_key=nick, db_category=nick_type)
|
||||
return nicks[0] if nicks else None
|
||||
else:
|
||||
returns.extend(list(self.obj.db_liteattributes.all()))
|
||||
return returns
|
||||
|
||||
def get_replace(self, key, category="inputline", default=None):
|
||||
"""
|
||||
Retrieves a given nick replacement based on the input nick. If
|
||||
given but no matching conversion was found, returns
|
||||
original input or default if given
|
||||
If no nick is given, returns a list of all matching nick
|
||||
objects (LiteAttributes) on the object, or the empty list.
|
||||
"""
|
||||
returns = []
|
||||
for nick in make_iter(key):
|
||||
nick = nick.strip().lower() if nick!=None else None
|
||||
nick_type = "%s%s" % (self.prefix, category.strip().lower())
|
||||
nicks = _GA(self.obj, "db_liteattributes").filter(db_key=nick, db_category=nick_type)
|
||||
default = default if default!=None else nick
|
||||
returns.append(nicks[0].db_data) if nicks else returns.append(default)
|
||||
if len(returns) == 1:
|
||||
return returns[0]
|
||||
return returns
|
||||
|
||||
def all(self):
|
||||
"Get all nicks in this handler"
|
||||
return [p[0] for p in self.obj.db_nicks.filter(db_category=self.category).values_list("db_key")]
|
||||
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------
|
||||
|
|
@ -411,33 +578,43 @@ class TypedObject(SharedMemoryModel):
|
|||
# TypedObject Database Model setup
|
||||
#
|
||||
#
|
||||
# These databse fields are all set using their corresponding properties,
|
||||
# named same as the field, but withtou the db_* prefix.
|
||||
# These databse fields are all accessed and set using their corresponding properties,
|
||||
# named same as the field, but without the db_* prefix (no separate save() call is needed)
|
||||
|
||||
# Main identifier of the object, for searching. Can also
|
||||
# be referenced as 'name'.
|
||||
# Main identifier of the object, for searching. Is accessed with self.key or self.name
|
||||
db_key = models.CharField('key', max_length=255, db_index=True)
|
||||
# This is the python path to the type class this object is tied to
|
||||
# (the type class is what defines what kind of Object this is)
|
||||
db_typeclass_path = models.CharField('typeclass', max_length=255, null=True, help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.")
|
||||
# Creation date
|
||||
# This is the python path to the type class this object is tied to the type class is what defines what kind of Object this is)
|
||||
db_typeclass_path = models.CharField('typeclass', max_length=255, null=True,
|
||||
help_text="this defines what 'type' of entity this is. This variable holds a Python path to a module with a valid Evennia Typeclass.")
|
||||
# Creation date. This is not changed once the object is created.
|
||||
db_date_created = models.DateTimeField('creation date', editable=False, auto_now_add=True)
|
||||
# Permissions (access these through the 'permissions' property)
|
||||
db_permissions = models.CharField('permissions', max_length=255, blank=True, help_text="a comma-separated list of text strings checked by certain locks. They are often used for hierarchies, such as letting a Player have permission 'Wizards', 'Builders' etc. Character objects use 'Players' by default. Most other objects don't have any permissions.")
|
||||
db_permissions = models.CharField('permissions', max_length=255, blank=True,
|
||||
help_text="a comma-separated list of text strings checked by in-game locks. They are often used for hierarchies, such as letting a Player have permission 'Wizards', 'Builders' etc. Character objects use 'Players' by default. Most other objects don't have any permissions.")
|
||||
# Lock storage
|
||||
db_lock_storage = models.TextField('locks', blank=True, help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.")
|
||||
db_lock_storage = models.TextField('locks', blank=True,
|
||||
help_text="locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.")
|
||||
# many2many relationships
|
||||
db_attributes = models.ManyToManyField(Attribute, null=True,
|
||||
help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).')
|
||||
db_liteattributes = models.ManyToManyField(LiteAttribute, null=True,
|
||||
help_text='liteattributes on this object. A LiteAttribute holds a key, a category and a string field for simple lookups.')
|
||||
db_tags = models.ManyToManyField(Tag, null=True,
|
||||
help_text='tags on this object. Tags are simple string markers to identify, group and alias objects.')
|
||||
|
||||
# Database manager
|
||||
objects = managers.TypedObjectManager()
|
||||
|
||||
# object cache and flags
|
||||
# quick on-object typeclass cache for speed
|
||||
_cached_typeclass = None
|
||||
|
||||
# lock handler self.locks
|
||||
def __init__(self, *args, **kwargs):
|
||||
"We must initialize the parent first - important!"
|
||||
SharedMemoryModel.__init__(self, *args, **kwargs)
|
||||
self.locks = LockHandler(self)
|
||||
super(SharedMemoryModel, self).__init__(*args, **kwargs)
|
||||
#SharedMemoryModel.__init__(self, *args, **kwargs)
|
||||
_SA(self, "dbobj", self) # this allows for self-reference
|
||||
_SA(self, "locks", LockHandler(self))
|
||||
|
||||
class Meta:
|
||||
"""
|
||||
|
|
@ -447,6 +624,7 @@ class TypedObject(SharedMemoryModel):
|
|||
verbose_name = "Evennia Database Object"
|
||||
ordering = ['-db_date_created', 'id', 'db_typeclass_path', 'db_key']
|
||||
|
||||
# wrapper
|
||||
# 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()
|
||||
|
|
@ -459,7 +637,8 @@ class TypedObject(SharedMemoryModel):
|
|||
#@property
|
||||
def __key_get(self):
|
||||
"Getter. Allows for value = self.key"
|
||||
return get_field_cache(self, "key")
|
||||
return _GA(self, "db_key")
|
||||
#return get_field_cache(self, "key")
|
||||
#@key.setter
|
||||
def __key_set(self, value):
|
||||
"Setter. Allows for self.key = value"
|
||||
|
|
@ -470,54 +649,44 @@ class TypedObject(SharedMemoryModel):
|
|||
raise Exception("Cannot delete objectdb key!")
|
||||
key = property(__key_get, __key_set, __key_del)
|
||||
|
||||
# name property (wraps db_key too - alias to self.key)
|
||||
#@property
|
||||
def __name_get(self):
|
||||
"Getter. Allows for value = self.name"
|
||||
return get_field_cache(self, "key")
|
||||
#@name.setter
|
||||
def __name_set(self, value):
|
||||
"Setter. Allows for self.name = value"
|
||||
set_field_cache(self, "key", value)
|
||||
#@name.deleter
|
||||
def __name_del(self):
|
||||
"Deleter. Allows for del self.name"
|
||||
raise Exception("Cannot delete name!")
|
||||
# name property (alias to self.key)
|
||||
def __name_get(self): return self.key
|
||||
def __name_set(self, value): self.key = value
|
||||
def __name_del(self): raise Exception("Cannot delete name")
|
||||
name = property(__name_get, __name_set, __name_del)
|
||||
|
||||
# typeclass_path property
|
||||
# typeclass_path property - we manage this separately.
|
||||
#@property
|
||||
def __typeclass_path_get(self):
|
||||
"Getter. Allows for value = self.typeclass_path"
|
||||
return get_field_cache(self, "typeclass_path")
|
||||
#@typeclass_path.setter
|
||||
def __typeclass_path_set(self, value):
|
||||
"Setter. Allows for self.typeclass_path = value"
|
||||
set_field_cache(self, "typeclass_path", value)
|
||||
_SA(self, "_cached_typeclass", None)
|
||||
#@typeclass_path.deleter
|
||||
def __typeclass_path_del(self):
|
||||
"Deleter. Allows for del self.typeclass_path"
|
||||
self.db_typeclass_path = ""
|
||||
self.save()
|
||||
del_field_cache(self, "typeclass_path")
|
||||
_SA(self, "_cached_typeclass", None)
|
||||
typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del)
|
||||
#def __typeclass_path_get(self):
|
||||
# "Getter. Allows for value = self.typeclass_path"
|
||||
# return _GA(self, "db_typeclass_path")
|
||||
##@typeclass_path.setter
|
||||
#def __typeclass_path_set(self, value):
|
||||
# "Setter. Allows for self.typeclass_path = value"
|
||||
# _SA(self, "db_typeclass_path", value)
|
||||
# update_fields = ["db_typeclass_path"] if _GA(self, "_get_pk_val")(_GA(self, "_meta")) is not None else None
|
||||
# _GA(self, "save")(update_fields=update_fields)
|
||||
##@typeclass_path.deleter
|
||||
#def __typeclass_path_del(self):
|
||||
# "Deleter. Allows for del self.typeclass_path"
|
||||
# self.db_typeclass_path = ""
|
||||
# _GA(self, "save")(update_fields=["db_typeclass_path"])
|
||||
#typeclass_path = property(__typeclass_path_get, __typeclass_path_set, __typeclass_path_del)
|
||||
|
||||
# date_created property
|
||||
#@property
|
||||
def __date_created_get(self):
|
||||
"Getter. Allows for value = self.date_created"
|
||||
return get_field_cache(self, "date_created")
|
||||
#@date_created.setter
|
||||
def __date_created_set(self, value):
|
||||
"Setter. Allows for self.date_created = value"
|
||||
raise Exception("Cannot change date_created!")
|
||||
#@date_created.deleter
|
||||
def __date_created_del(self):
|
||||
"Deleter. Allows for del self.date_created"
|
||||
raise Exception("Cannot delete date_created!")
|
||||
date_created = property(__date_created_get, __date_created_set, __date_created_del)
|
||||
#def __date_created_get(self):
|
||||
# "Getter. Allows for value = self.date_created"
|
||||
# return get_field_cache(self, "date_created")
|
||||
##@date_created.setter
|
||||
#def __date_created_set(self, value):
|
||||
# "Setter. Allows for self.date_created = value"
|
||||
# raise Exception("Cannot change date_created!")
|
||||
##@date_created.deleter
|
||||
#def __date_created_del(self):
|
||||
# "Deleter. Allows for del self.date_created"
|
||||
# raise Exception("Cannot delete date_created!")
|
||||
#date_created = property(__date_created_get, __date_created_set, __date_created_del)
|
||||
|
||||
# permissions property
|
||||
#@property
|
||||
|
|
@ -542,18 +711,18 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
# lock_storage property (wraps db_lock_storage)
|
||||
#@property
|
||||
def __lock_storage_get(self):
|
||||
"Getter. Allows for value = self.lock_storage"
|
||||
return get_field_cache(self, "lock_storage")
|
||||
#@lock_storage.setter
|
||||
def __lock_storage_set(self, value):
|
||||
"""Saves the lock_storagetodate. This is usually not called directly, but through self.lock()"""
|
||||
set_field_cache(self, "lock_storage", value)
|
||||
#@lock_storage.deleter
|
||||
def __lock_storage_del(self):
|
||||
"Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
|
||||
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)
|
||||
#def __lock_storage_get(self):
|
||||
# "Getter. Allows for value = self.lock_storage"
|
||||
# return get_field_cache(self, "lock_storage")
|
||||
##@lock_storage.setter
|
||||
#def __lock_storage_set(self, value):
|
||||
# """Saves the lock_storage. This is usually not called directly, but through self.lock()"""
|
||||
# set_field_cache(self, "lock_storage", value)
|
||||
##@lock_storage.deleter
|
||||
#def __lock_storage_del(self):
|
||||
# "Deleter is disabled. Use the lockhandler.delete (self.lock.delete) instead"""
|
||||
# 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)
|
||||
|
||||
|
||||
|
||||
|
|
@ -565,17 +734,15 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
# these are identifiers for fast Attribute access and caching
|
||||
_typeclass_paths = settings.OBJECT_TYPECLASS_PATHS
|
||||
_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, 'dbid') and self.dbid == other.dbid
|
||||
|
||||
def __str__(self):
|
||||
return smart_str("%s" % self.key)
|
||||
return smart_str("%s" % _GA(self, "db_key"))
|
||||
|
||||
def __unicode__(self):
|
||||
return u"%s" % self.key
|
||||
return u"%s" % _GA(self, "db_key")
|
||||
|
||||
def __getattribute__(self, propname):
|
||||
"""
|
||||
|
|
@ -588,6 +755,9 @@ class TypedObject(SharedMemoryModel):
|
|||
try:
|
||||
return _GA(self, propname)
|
||||
except AttributeError:
|
||||
if propname.startswith('_'):
|
||||
# don't relay private/special varname lookups to the typeclass
|
||||
raise AttributeError("private property %s not found on db model (typeclass not searched)." % propname)
|
||||
# check if the attribute exists on the typeclass instead
|
||||
# (we make sure to not incur a loop by not triggering the
|
||||
# typeclass' __getattribute__, since that one would
|
||||
|
|
@ -917,10 +1087,10 @@ class TypedObject(SharedMemoryModel):
|
|||
#
|
||||
|
||||
#
|
||||
# Fully persistent attributes. You usually access these
|
||||
# Fully attr_obj attributes. You usually access these
|
||||
# through the obj.db.attrname method.
|
||||
|
||||
# Helper methods for persistent attributes
|
||||
# Helper methods for attr_obj attributes
|
||||
|
||||
def has_attribute(self, attribute_name):
|
||||
"""
|
||||
|
|
@ -929,10 +1099,9 @@ class TypedObject(SharedMemoryModel):
|
|||
attribute_name: (str) The attribute's name.
|
||||
"""
|
||||
if not get_attr_cache(self, attribute_name):
|
||||
attrib_obj = _GA(self, "_attribute_class").objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)
|
||||
if attrib_obj:
|
||||
set_attr_cache(self, attribute_name, attrib_obj[0])
|
||||
attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name)
|
||||
if attr_obj:
|
||||
set_attr_cache(self, attribute_name, attr_obj[0])
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
|
@ -950,46 +1119,38 @@ class TypedObject(SharedMemoryModel):
|
|||
below to perform access-checked modification of attributes. Lock
|
||||
types checked by secureattr are 'attrread','attredit','attrcreate'.
|
||||
"""
|
||||
attrib_obj = get_attr_cache(self, attribute_name)
|
||||
if not attrib_obj:
|
||||
attrclass = _GA(self, "_attribute_class")
|
||||
# check if attribute already exists.
|
||||
attrib_obj = attrclass.objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)
|
||||
if attrib_obj:
|
||||
# use old attribute
|
||||
attrib_obj = attrib_obj[0]
|
||||
attr_obj = get_attr_cache(self, attribute_name)
|
||||
if not attr_obj:
|
||||
# check if attribute already exists
|
||||
attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name)
|
||||
if attr_obj:
|
||||
# re-use old attribute object
|
||||
attr_obj = attr_obj[0]
|
||||
set_attr_cache(self, attribute_name, attr_obj) # renew cache
|
||||
else:
|
||||
# no match; create new attribute
|
||||
attrib_obj = attrclass(db_key=attribute_name, db_obj=self)
|
||||
# no old attr available; create new (caches automatically)
|
||||
attr_obj = Attribute(db_key=attribute_name)
|
||||
attr_obj.save() # important
|
||||
_GA(self, "db_attributes").add(attr_obj)
|
||||
if lockstring:
|
||||
attrib_obj.locks.add(lockstring)
|
||||
# re-set an old attribute value
|
||||
try:
|
||||
attrib_obj.value = new_value
|
||||
except IntegrityError:
|
||||
# this can happen if the cache was stale and the database object is
|
||||
# missing. If so we need to clean self.hashid from the cache
|
||||
flush_attr_cache(self)
|
||||
self.delete()
|
||||
raise IntegrityError("Attribute could not be saved - object %s was deleted from database." % self.key)
|
||||
set_attr_cache(self, attribute_name, attrib_obj)
|
||||
attr_obj.locks.add(lockstring)
|
||||
# we shouldn't need to fear stale objects, the signalling should catch all cases
|
||||
attr_obj.value = new_value
|
||||
|
||||
def get_attribute_obj(self, attribute_name, default=None):
|
||||
"""
|
||||
Get the actual attribute object named attribute_name
|
||||
"""
|
||||
attrib_obj = get_attr_cache(self, attribute_name)
|
||||
if not attrib_obj:
|
||||
attrib_obj = _GA(self, "_attribute_class").objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)
|
||||
if not attrib_obj:
|
||||
attr_obj = get_attr_cache(self, attribute_name)
|
||||
if not attr_obj:
|
||||
attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name)
|
||||
if not attr_obj:
|
||||
return default
|
||||
set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here
|
||||
return attrib_obj[0]
|
||||
return attrib_obj
|
||||
attr_obj = attr_obj[0] # query evaluated here
|
||||
set_attr_cache(self, attribute_name, attr_obj)
|
||||
return attr_obj
|
||||
|
||||
def get_attribute(self, attribute_name, default=None):
|
||||
def get_attribute(self, attribute_name, default=None, raise_exception=False):
|
||||
"""
|
||||
Returns the value of an attribute on an object. You may need to
|
||||
type cast the returned value from this function since the attribute
|
||||
|
|
@ -997,75 +1158,44 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
attribute_name: (str) The attribute's name.
|
||||
default: What to return if no attribute is found
|
||||
raise_exception (bool) - raise an exception if no object exists instead of returning default.
|
||||
"""
|
||||
attrib_obj = get_attr_cache(self, attribute_name)
|
||||
if not attrib_obj:
|
||||
attrib_obj = _GA(self, "_attribute_class").objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)
|
||||
if not attrib_obj:
|
||||
attr_obj = get_attr_cache(self, attribute_name)
|
||||
if not attr_obj:
|
||||
attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name)
|
||||
if not attr_obj:
|
||||
if raise_exception:
|
||||
raise AttributeError
|
||||
return default
|
||||
set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here
|
||||
return attrib_obj[0].value
|
||||
return attrib_obj.value
|
||||
attr_obj = attr_obj[0] # query is evaluated here
|
||||
set_attr_cache(self, attribute_name, attr_obj)
|
||||
return attr_obj.value
|
||||
|
||||
def get_attribute_raise(self, attribute_name):
|
||||
"""
|
||||
Returns value of an attribute. Raises AttributeError
|
||||
if no match is found.
|
||||
|
||||
attribute_name: (str) The attribute's name.
|
||||
"""
|
||||
attrib_obj = get_attr_cache(self, attribute_name)
|
||||
if not attrib_obj:
|
||||
attrib_obj = _GA(self, "_attribute_class").objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)
|
||||
if not attrib_obj:
|
||||
raise AttributeError
|
||||
set_attr_cache(self, attribute_name, attrib_obj[0]) #query is first evaluated here
|
||||
return attrib_obj[0].value
|
||||
return attrib_obj.value
|
||||
|
||||
def del_attribute(self, attribute_name):
|
||||
def del_attribute(self, attribute_name, raise_exception=False):
|
||||
"""
|
||||
Removes an attribute entirely.
|
||||
|
||||
attribute_name: (str) The attribute's name.
|
||||
raise_exception (bool) - raise exception if attribute to delete
|
||||
could not be found
|
||||
"""
|
||||
attr_obj = get_attr_cache(self, attribute_name)
|
||||
if attr_obj:
|
||||
del_attr_cache(self, attribute_name)
|
||||
attr_obj.delete()
|
||||
else:
|
||||
try:
|
||||
_GA(self, "_attribute_class").objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)[0].delete()
|
||||
except IndexError:
|
||||
pass
|
||||
|
||||
def del_attribute_raise(self, attribute_name):
|
||||
"""
|
||||
Removes and attribute. Raises AttributeError if
|
||||
attribute is not found.
|
||||
|
||||
attribute_name: (str) The attribute's name.
|
||||
"""
|
||||
attr_obj = get_attr_cache(self, attribute_name)
|
||||
if attr_obj:
|
||||
del_attr_cache(self, attribute_name)
|
||||
attr_obj.delete()
|
||||
else:
|
||||
try:
|
||||
_GA(self, "_attribute_class").objects.filter(
|
||||
db_obj=self, db_key__iexact=attribute_name)[0].delete()
|
||||
except IndexError:
|
||||
pass
|
||||
raise AttributeError
|
||||
if not attr_obj:
|
||||
attr_obj = _GA(self, "db_attributes").filter(db_key__iexact=attribute_name)
|
||||
attr_obj = attr_obj[0] if attr_obj else None
|
||||
if not attr_obj:
|
||||
if raise_exception:
|
||||
raise AttributeError
|
||||
return
|
||||
# the post-remove cache signal will auto-delete the attribute as well,
|
||||
# don't call attr_obj.delete() after this.
|
||||
self.db_attributes.remove(attr_obj)
|
||||
|
||||
def get_all_attributes(self):
|
||||
"""
|
||||
Returns all attributes defined on the object.
|
||||
"""
|
||||
return list(_GA(self,"_attribute_class").objects.filter(db_obj=self))
|
||||
return list(_GA(self, "db_attributes").all())
|
||||
|
||||
def attr(self, attribute_name=None, value=None, delete=False):
|
||||
"""
|
||||
|
|
@ -1191,12 +1321,12 @@ class TypedObject(SharedMemoryModel):
|
|||
db = property(__db_get, __db_set, __db_del)
|
||||
|
||||
#
|
||||
# NON-PERSISTENT storage methods
|
||||
# NON-attr_obj storage methods
|
||||
#
|
||||
|
||||
def nattr(self, attribute_name=None, value=None, delete=False):
|
||||
"""
|
||||
This is the equivalence of self.attr but for non-persistent
|
||||
This is the equivalence of self.attr but for non-attr_obj
|
||||
stores. Will not raise error but return None.
|
||||
"""
|
||||
if attribute_name == None:
|
||||
|
|
@ -1222,7 +1352,7 @@ class TypedObject(SharedMemoryModel):
|
|||
#@property
|
||||
def __ndb_get(self):
|
||||
"""
|
||||
A non-persistent store (ndb: NonDataBase). Everything stored
|
||||
A non-attr_obj store (ndb: NonDataBase). Everything stored
|
||||
to this is guaranteed to be cleared when a server is shutdown.
|
||||
Syntax is same as for the _get_db_holder() method and
|
||||
property, e.g. obj.ndb.attr = value etc.
|
||||
|
|
@ -1231,7 +1361,7 @@ class TypedObject(SharedMemoryModel):
|
|||
return self._ndb_holder
|
||||
except AttributeError:
|
||||
class NdbHolder(object):
|
||||
"Holder for storing non-persistent attributes."
|
||||
"Holder for storing non-attr_obj attributes."
|
||||
def get_all(self):
|
||||
return [val for val in self.__dict__.keys()
|
||||
if not val.startswith('_')]
|
||||
|
|
@ -1244,7 +1374,7 @@ class TypedObject(SharedMemoryModel):
|
|||
return None
|
||||
def __setattr__(self, key, value):
|
||||
# hook the oob handler here
|
||||
call_ndb_hooks(self, key, value)
|
||||
#call_ndb_hooks(self, key, value)
|
||||
_SA(self, key, value)
|
||||
self._ndb_holder = NdbHolder()
|
||||
return self._ndb_holder
|
||||
|
|
@ -1273,11 +1403,6 @@ class TypedObject(SharedMemoryModel):
|
|||
"""
|
||||
return self.locks.check(accessing_obj, access_type=access_type, default=default)
|
||||
|
||||
def has_perm(self, accessing_obj, access_type):
|
||||
"Alias to access"
|
||||
logger.log_depmsg("has_perm() is deprecated. Use access() instead.")
|
||||
return self.access(accessing_obj, access_type)
|
||||
|
||||
def check_permstring(self, permstring):
|
||||
"""
|
||||
This explicitly checks if we hold particular permission without involving
|
||||
|
|
@ -1309,3 +1434,7 @@ class TypedObject(SharedMemoryModel):
|
|||
as a new Typeclass instance.
|
||||
"""
|
||||
self.__class__.flush_cached_instance(self)
|
||||
|
||||
|
||||
# connect to attribute cache signal
|
||||
m2m_changed.connect(post_attr_update, sender=TypedObject.db_attributes.through)
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ class TypeClass(object):
|
|||
log_trace("This is probably due to an unsafe reload.")
|
||||
return # ignore delete
|
||||
try:
|
||||
dbobj.del_attribute_raise(propname)
|
||||
dbobj.del_attribute(propname, raise_exception=True)
|
||||
except AttributeError:
|
||||
string = "Object: '%s' not found on %s(#%s), nor on its typeclass %s."
|
||||
raise AttributeError(string % (propname, dbobj,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue