Completely refactored the Attribute Refactor into a single fresh branch.
This commit is contained in:
parent
770d2e6b43
commit
43ce2285a5
6 changed files with 733 additions and 517 deletions
|
|
@ -32,7 +32,7 @@ from evennia.server.signals import (
|
||||||
SIGNAL_OBJECT_POST_PUPPET,
|
SIGNAL_OBJECT_POST_PUPPET,
|
||||||
SIGNAL_OBJECT_POST_UNPUPPET,
|
SIGNAL_OBJECT_POST_UNPUPPET,
|
||||||
)
|
)
|
||||||
from evennia.typeclasses.attributes import NickHandler
|
from evennia.typeclasses.attributes import NickHandler, ModelAttributeBackend
|
||||||
from evennia.scripts.scripthandler import ScriptHandler
|
from evennia.scripts.scripthandler import ScriptHandler
|
||||||
from evennia.commands.cmdsethandler import CmdSetHandler
|
from evennia.commands.cmdsethandler import CmdSetHandler
|
||||||
from evennia.utils.optionhandler import OptionHandler
|
from evennia.utils.optionhandler import OptionHandler
|
||||||
|
|
@ -199,7 +199,7 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def nicks(self):
|
def nicks(self):
|
||||||
return NickHandler(self)
|
return NickHandler(self, ModelAttributeBackend)
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def sessions(self):
|
def sessions(self):
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from collections import defaultdict
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
||||||
from evennia.typeclasses.models import TypeclassBase
|
from evennia.typeclasses.models import TypeclassBase
|
||||||
from evennia.typeclasses.attributes import NickHandler
|
from evennia.typeclasses.attributes import NickHandler, ModelAttributeBackend
|
||||||
from evennia.objects.manager import ObjectManager
|
from evennia.objects.manager import ObjectManager
|
||||||
from evennia.objects.models import ObjectDB
|
from evennia.objects.models import ObjectDB
|
||||||
from evennia.scripts.scripthandler import ScriptHandler
|
from evennia.scripts.scripthandler import ScriptHandler
|
||||||
|
|
@ -225,7 +225,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def nicks(self):
|
def nicks(self):
|
||||||
return NickHandler(self)
|
return NickHandler(self, ModelAttributeBackend)
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def sessions(self):
|
def sessions(self):
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ connection actually happens (so it's the same for telnet, web, ssh etc).
|
||||||
It is stored on the Server side (as opposed to protocol-specific sessions which
|
It is stored on the Server side (as opposed to protocol-specific sessions which
|
||||||
are stored on the Portal side)
|
are stored on the Portal side)
|
||||||
"""
|
"""
|
||||||
import weakref
|
|
||||||
import time
|
import time
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
|
@ -16,6 +15,7 @@ from evennia.utils.utils import make_iter, lazy_property
|
||||||
from evennia.commands.cmdsethandler import CmdSetHandler
|
from evennia.commands.cmdsethandler import CmdSetHandler
|
||||||
from evennia.server.session import Session
|
from evennia.server.session import Session
|
||||||
from evennia.scripts.monitorhandler import MONITOR_HANDLER
|
from evennia.scripts.monitorhandler import MONITOR_HANDLER
|
||||||
|
from evennia.typeclasses.attributes import AttributeHandler, InMemoryAttributeBackend, DbHolder
|
||||||
|
|
||||||
_GA = object.__getattribute__
|
_GA = object.__getattribute__
|
||||||
_SA = object.__setattr__
|
_SA = object.__setattr__
|
||||||
|
|
@ -25,124 +25,6 @@ _ANSI = None
|
||||||
# i18n
|
# i18n
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
# Handlers for Session.db/ndb operation
|
|
||||||
|
|
||||||
|
|
||||||
class NDbHolder(object):
|
|
||||||
"""Holder for allowing property access of attributes"""
|
|
||||||
|
|
||||||
def __init__(self, obj, name, manager_name="attributes"):
|
|
||||||
_SA(self, name, _GA(obj, manager_name))
|
|
||||||
_SA(self, "name", name)
|
|
||||||
|
|
||||||
def __getattribute__(self, attrname):
|
|
||||||
if attrname == "all":
|
|
||||||
# we allow to overload our default .all
|
|
||||||
attr = _GA(self, _GA(self, "name")).get("all")
|
|
||||||
return attr if attr else _GA(self, "all")
|
|
||||||
return _GA(self, _GA(self, "name")).get(attrname)
|
|
||||||
|
|
||||||
def __setattr__(self, attrname, value):
|
|
||||||
_GA(self, _GA(self, "name")).add(attrname, value)
|
|
||||||
|
|
||||||
def __delattr__(self, attrname):
|
|
||||||
_GA(self, _GA(self, "name")).remove(attrname)
|
|
||||||
|
|
||||||
def get_all(self):
|
|
||||||
return _GA(self, _GA(self, "name")).all()
|
|
||||||
|
|
||||||
all = property(get_all)
|
|
||||||
|
|
||||||
|
|
||||||
class NAttributeHandler(object):
|
|
||||||
"""
|
|
||||||
NAttributeHandler version without recache protection.
|
|
||||||
This stand-alone handler manages non-database saving.
|
|
||||||
It is similar to `AttributeHandler` and is used
|
|
||||||
by the `.ndb` handler in the same way as `.db` does
|
|
||||||
for the `AttributeHandler`.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, obj):
|
|
||||||
"""
|
|
||||||
Initialized on the object
|
|
||||||
"""
|
|
||||||
self._store = {}
|
|
||||||
self.obj = weakref.proxy(obj)
|
|
||||||
|
|
||||||
def has(self, key):
|
|
||||||
"""
|
|
||||||
Check if object has this attribute or not.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key (str): The Nattribute key to check.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
has_nattribute (bool): If Nattribute is set or not.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return key in self._store
|
|
||||||
|
|
||||||
def get(self, key, default=None):
|
|
||||||
"""
|
|
||||||
Get the named key value.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key (str): The Nattribute key to get.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
the value of the Nattribute.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self._store.get(key, default)
|
|
||||||
|
|
||||||
def add(self, key, value):
|
|
||||||
"""
|
|
||||||
Add new key and value.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key (str): The name of Nattribute to add.
|
|
||||||
value (any): The value to store.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._store[key] = value
|
|
||||||
|
|
||||||
def remove(self, key):
|
|
||||||
"""
|
|
||||||
Remove Nattribute from storage.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
key (str): The name of the Nattribute to remove.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if key in self._store:
|
|
||||||
del self._store[key]
|
|
||||||
|
|
||||||
def clear(self):
|
|
||||||
"""
|
|
||||||
Remove all NAttributes from handler.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self._store = {}
|
|
||||||
|
|
||||||
def all(self, return_tuples=False):
|
|
||||||
"""
|
|
||||||
List the contents of the handler.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
return_tuples (bool, optional): Defines if the Nattributes
|
|
||||||
are returns as a list of keys or as a list of `(key, value)`.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
nattributes (list): A list of keys `[key, key, ...]` or a
|
|
||||||
list of tuples `[(key, value), ...]` depending on the
|
|
||||||
setting of `return_tuples`.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if return_tuples:
|
|
||||||
return [(key, value) for (key, value) in self._store.items() if not key.startswith("_")]
|
|
||||||
return [key for key in self._store if not key.startswith("_")]
|
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
# Server Session
|
# Server Session
|
||||||
|
|
@ -175,6 +57,10 @@ class ServerSession(Session):
|
||||||
|
|
||||||
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set)
|
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def id(self):
|
||||||
|
return self.sessid
|
||||||
|
|
||||||
def at_sync(self):
|
def at_sync(self):
|
||||||
"""
|
"""
|
||||||
This is called whenever a session has been resynced with the
|
This is called whenever a session has been resynced with the
|
||||||
|
|
@ -490,7 +376,7 @@ class ServerSession(Session):
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def nattributes(self):
|
def nattributes(self):
|
||||||
return NAttributeHandler(self)
|
return AttributeHandler(self, InMemoryAttributeBackend)
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def attributes(self):
|
def attributes(self):
|
||||||
|
|
@ -508,7 +394,7 @@ class ServerSession(Session):
|
||||||
try:
|
try:
|
||||||
return self._ndb_holder
|
return self._ndb_holder
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self._ndb_holder = NDbHolder(self, "nattrhandler", manager_name="nattributes")
|
self._ndb_holder = DbHolder(self, "nattrhandler", manager_name="nattributes")
|
||||||
return self._ndb_holder
|
return self._ndb_holder
|
||||||
|
|
||||||
# @ndb.setter
|
# @ndb.setter
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -36,7 +36,8 @@ from django.urls import reverse
|
||||||
from django.utils.encoding import smart_str
|
from django.utils.encoding import smart_str
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from evennia.typeclasses.attributes import Attribute, AttributeHandler, NAttributeHandler
|
from evennia.typeclasses.attributes import Attribute, AttributeHandler, ModelAttributeBackend, InMemoryAttributeBackend
|
||||||
|
from evennia.typeclasses.attributes import DbHolder
|
||||||
from evennia.typeclasses.tags import Tag, TagHandler, AliasHandler, PermissionHandler
|
from evennia.typeclasses.tags import Tag, TagHandler, AliasHandler, PermissionHandler
|
||||||
|
|
||||||
from evennia.utils.idmapper.models import SharedMemoryModel, SharedMemoryModelBase
|
from evennia.utils.idmapper.models import SharedMemoryModel, SharedMemoryModelBase
|
||||||
|
|
@ -121,33 +122,6 @@ class TypeclassBase(SharedMemoryModelBase):
|
||||||
signals.pre_delete.connect(remove_attributes_on_delete, sender=new_class)
|
signals.pre_delete.connect(remove_attributes_on_delete, sender=new_class)
|
||||||
return new_class
|
return new_class
|
||||||
|
|
||||||
|
|
||||||
class DbHolder(object):
|
|
||||||
"Holder for allowing property access of attributes"
|
|
||||||
|
|
||||||
def __init__(self, obj, name, manager_name="attributes"):
|
|
||||||
_SA(self, name, _GA(obj, manager_name))
|
|
||||||
_SA(self, "name", name)
|
|
||||||
|
|
||||||
def __getattribute__(self, attrname):
|
|
||||||
if attrname == "all":
|
|
||||||
# we allow to overload our default .all
|
|
||||||
attr = _GA(self, _GA(self, "name")).get("all")
|
|
||||||
return attr if attr else _GA(self, "all")
|
|
||||||
return _GA(self, _GA(self, "name")).get(attrname)
|
|
||||||
|
|
||||||
def __setattr__(self, attrname, value):
|
|
||||||
_GA(self, _GA(self, "name")).add(attrname, value)
|
|
||||||
|
|
||||||
def __delattr__(self, attrname):
|
|
||||||
_GA(self, _GA(self, "name")).remove(attrname)
|
|
||||||
|
|
||||||
def get_all(self):
|
|
||||||
return _GA(self, _GA(self, "name")).all()
|
|
||||||
|
|
||||||
all = property(get_all)
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Main TypedObject abstraction
|
# Main TypedObject abstraction
|
||||||
#
|
#
|
||||||
|
|
@ -301,7 +275,7 @@ class TypedObject(SharedMemoryModel):
|
||||||
# initialize all handlers in a lazy fashion
|
# initialize all handlers in a lazy fashion
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def attributes(self):
|
def attributes(self):
|
||||||
return AttributeHandler(self)
|
return AttributeHandler(self, ModelAttributeBackend)
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def locks(self):
|
def locks(self):
|
||||||
|
|
@ -321,7 +295,7 @@ class TypedObject(SharedMemoryModel):
|
||||||
|
|
||||||
@lazy_property
|
@lazy_property
|
||||||
def nattributes(self):
|
def nattributes(self):
|
||||||
return NAttributeHandler(self)
|
return AttributeHandler(self, InMemoryAttributeBackend)
|
||||||
|
|
||||||
class Meta(object):
|
class Meta(object):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -26,12 +26,12 @@ class TestAttributes(EvenniaTest):
|
||||||
key = "testattr"
|
key = "testattr"
|
||||||
value = "test attr value "
|
value = "test attr value "
|
||||||
self.obj1.attributes.add(key, value)
|
self.obj1.attributes.add(key, value)
|
||||||
self.assertFalse(self.obj1.attributes._cache)
|
self.assertFalse(self.obj1.attributes.backend._cache)
|
||||||
|
|
||||||
self.assertEqual(self.obj1.attributes.get(key), value)
|
self.assertEqual(self.obj1.attributes.get(key), value)
|
||||||
self.obj1.db.testattr = value
|
self.obj1.db.testattr = value
|
||||||
self.assertEqual(self.obj1.db.testattr, value)
|
self.assertEqual(self.obj1.db.testattr, value)
|
||||||
self.assertFalse(self.obj1.attributes._cache)
|
self.assertFalse(self.obj1.attributes.backend._cache)
|
||||||
|
|
||||||
def test_weird_text_save(self):
|
def test_weird_text_save(self):
|
||||||
"test 'weird' text type (different in py2 vs py3)"
|
"test 'weird' text type (different in py2 vs py3)"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue