Merge branch 'attribute_refactor' of https://github.com/volundmush/evennia into volundmush-attribute_refactor

This commit is contained in:
Griatch 2020-05-16 15:26:11 +02:00
commit e9e92fab33
6 changed files with 733 additions and 517 deletions

View file

@ -32,7 +32,7 @@ from evennia.server.signals import (
SIGNAL_OBJECT_POST_PUPPET,
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.commands.cmdsethandler import CmdSetHandler
from evennia.utils.optionhandler import OptionHandler
@ -199,7 +199,7 @@ class DefaultAccount(AccountDB, metaclass=TypeclassBase):
@lazy_property
def nicks(self):
return NickHandler(self)
return NickHandler(self, ModelAttributeBackend)
@lazy_property
def sessions(self):

View file

@ -12,7 +12,7 @@ from collections import defaultdict
from django.conf import settings
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.models import ObjectDB
from evennia.scripts.scripthandler import ScriptHandler
@ -225,7 +225,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
@lazy_property
def nicks(self):
return NickHandler(self)
return NickHandler(self, ModelAttributeBackend)
@lazy_property
def sessions(self):

View file

@ -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
are stored on the Portal side)
"""
import weakref
import time
from django.utils import timezone
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.server.session import Session
from evennia.scripts.monitorhandler import MONITOR_HANDLER
from evennia.typeclasses.attributes import AttributeHandler, InMemoryAttributeBackend, DbHolder
_GA = object.__getattribute__
_SA = object.__setattr__
@ -25,124 +25,6 @@ _ANSI = None
# i18n
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
@ -175,6 +57,10 @@ class ServerSession(Session):
cmdset_storage = property(__cmdset_storage_get, __cmdset_storage_set)
@property
def id(self):
return self.sessid
def at_sync(self):
"""
This is called whenever a session has been resynced with the
@ -490,7 +376,7 @@ class ServerSession(Session):
@lazy_property
def nattributes(self):
return NAttributeHandler(self)
return AttributeHandler(self, InMemoryAttributeBackend)
@lazy_property
def attributes(self):
@ -508,7 +394,7 @@ class ServerSession(Session):
try:
return self._ndb_holder
except AttributeError:
self._ndb_holder = NDbHolder(self, "nattrhandler", manager_name="nattributes")
self._ndb_holder = DbHolder(self, "nattrhandler", manager_name="nattributes")
return self._ndb_holder
# @ndb.setter

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,8 @@ from django.urls import reverse
from django.utils.encoding import smart_str
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.utils.idmapper.models import SharedMemoryModel, SharedMemoryModelBase
@ -121,33 +122,6 @@ class TypeclassBase(SharedMemoryModelBase):
signals.pre_delete.connect(remove_attributes_on_delete, sender=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
#
@ -301,7 +275,7 @@ class TypedObject(SharedMemoryModel):
# initialize all handlers in a lazy fashion
@lazy_property
def attributes(self):
return AttributeHandler(self)
return AttributeHandler(self, ModelAttributeBackend)
@lazy_property
def locks(self):
@ -321,7 +295,7 @@ class TypedObject(SharedMemoryModel):
@lazy_property
def nattributes(self):
return NAttributeHandler(self)
return AttributeHandler(self, InMemoryAttributeBackend)
class Meta(object):
"""

View file

@ -26,12 +26,12 @@ class TestAttributes(EvenniaTest):
key = "testattr"
value = "test attr 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.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):
"test 'weird' text type (different in py2 vs py3)"