Format code with black. Add makefile to run fmt/tests
This commit is contained in:
parent
d00bce9288
commit
c2c7fa311a
299 changed files with 19037 additions and 11611 deletions
|
|
@ -11,10 +11,11 @@ class TagAdmin(admin.ModelAdmin):
|
|||
"""
|
||||
A django Admin wrapper for Tags.
|
||||
"""
|
||||
search_fields = ('db_key', 'db_category', 'db_tagtype')
|
||||
list_display = ('db_key', 'db_category', 'db_tagtype', 'db_data')
|
||||
fields = ('db_key', 'db_category', 'db_tagtype', 'db_data')
|
||||
list_filter = ('db_tagtype',)
|
||||
|
||||
search_fields = ("db_key", "db_category", "db_tagtype")
|
||||
list_display = ("db_key", "db_category", "db_tagtype", "db_data")
|
||||
fields = ("db_key", "db_category", "db_tagtype", "db_data")
|
||||
list_filter = ("db_tagtype",)
|
||||
|
||||
|
||||
class TagForm(forms.ModelForm):
|
||||
|
|
@ -26,18 +27,25 @@ class TagForm(forms.ModelForm):
|
|||
Object's handler, which will handle the creation, change, or deletion of a tag for us, as well
|
||||
as updating the handler's cache so that all changes are instantly updated in-game.
|
||||
"""
|
||||
tag_key = forms.CharField(label='Tag Name',
|
||||
required=True,
|
||||
help_text="This is the main key identifier")
|
||||
tag_category = forms.CharField(label="Category",
|
||||
help_text="Used for grouping tags. Unset (default) gives a category of None",
|
||||
required=False)
|
||||
tag_type = forms.CharField(label="Type",
|
||||
help_text="Internal use. Either unset, \"alias\" or \"permission\"",
|
||||
required=False)
|
||||
tag_data = forms.CharField(label="Data",
|
||||
help_text="Usually unused. Intended for eventual info about the tag itself",
|
||||
required=False)
|
||||
|
||||
tag_key = forms.CharField(
|
||||
label="Tag Name", required=True, help_text="This is the main key identifier"
|
||||
)
|
||||
tag_category = forms.CharField(
|
||||
label="Category",
|
||||
help_text="Used for grouping tags. Unset (default) gives a category of None",
|
||||
required=False,
|
||||
)
|
||||
tag_type = forms.CharField(
|
||||
label="Type",
|
||||
help_text='Internal use. Either unset, "alias" or "permission"',
|
||||
required=False,
|
||||
)
|
||||
tag_data = forms.CharField(
|
||||
label="Data",
|
||||
help_text="Usually unused. Intended for eventual info about the tag itself",
|
||||
required=False,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
fields = ("tag_key", "tag_category", "tag_data", "tag_type")
|
||||
|
|
@ -54,15 +62,15 @@ class TagForm(forms.ModelForm):
|
|||
tagcategory = None
|
||||
tagtype = None
|
||||
tagdata = None
|
||||
if hasattr(self.instance, 'tag'):
|
||||
if hasattr(self.instance, "tag"):
|
||||
tagkey = self.instance.tag.db_key
|
||||
tagcategory = self.instance.tag.db_category
|
||||
tagtype = self.instance.tag.db_tagtype
|
||||
tagdata = self.instance.tag.db_data
|
||||
self.fields['tag_key'].initial = tagkey
|
||||
self.fields['tag_category'].initial = tagcategory
|
||||
self.fields['tag_type'].initial = tagtype
|
||||
self.fields['tag_data'].initial = tagdata
|
||||
self.fields["tag_key"].initial = tagkey
|
||||
self.fields["tag_category"].initial = tagcategory
|
||||
self.fields["tag_type"].initial = tagtype
|
||||
self.fields["tag_data"].initial = tagdata
|
||||
self.instance.tag_key = tagkey
|
||||
self.instance.tag_category = tagcategory
|
||||
self.instance.tag_type = tagtype
|
||||
|
|
@ -78,10 +86,10 @@ class TagForm(forms.ModelForm):
|
|||
# we are spoofing a tag for the Handler that will be called
|
||||
# instance = super().save(commit=False)
|
||||
instance = self.instance
|
||||
instance.tag_key = self.cleaned_data['tag_key']
|
||||
instance.tag_category = self.cleaned_data['tag_category'] or None
|
||||
instance.tag_type = self.cleaned_data['tag_type'] or None
|
||||
instance.tag_data = self.cleaned_data['tag_data'] or None
|
||||
instance.tag_key = self.cleaned_data["tag_key"]
|
||||
instance.tag_category = self.cleaned_data["tag_category"] or None
|
||||
instance.tag_type = self.cleaned_data["tag_type"] or None
|
||||
instance.tag_data = self.cleaned_data["tag_data"] or None
|
||||
return instance
|
||||
|
||||
|
||||
|
|
@ -110,6 +118,7 @@ class TagFormSet(forms.BaseInlineFormSet):
|
|||
else:
|
||||
handler_name = "tags"
|
||||
return getattr(related, handler_name)
|
||||
|
||||
instances = super().save(commit=False)
|
||||
# self.deleted_objects is a list created when super of save is called, we'll remove those
|
||||
for obj in self.deleted_objects:
|
||||
|
|
@ -128,6 +137,7 @@ class TagInline(admin.TabularInline):
|
|||
of the field on that through model which points to the model being used: 'objectdb',
|
||||
'msg', 'accountdb', etc.
|
||||
"""
|
||||
|
||||
# Set this to the through model of your desired M2M when subclassing.
|
||||
model = None
|
||||
form = TagForm
|
||||
|
|
@ -148,6 +158,7 @@ class TagInline(admin.TabularInline):
|
|||
|
||||
class ProxyFormset(formset):
|
||||
pass
|
||||
|
||||
ProxyFormset.related_field = self.related_field
|
||||
return ProxyFormset
|
||||
|
||||
|
|
@ -161,20 +172,26 @@ class AttributeForm(forms.ModelForm):
|
|||
the creation, change, or deletion of an Attribute for us, as well as updating the handler's cache so that all
|
||||
changes are instantly updated in-game.
|
||||
"""
|
||||
attr_key = forms.CharField(label='Attribute Name', required=False, initial="Enter Attribute Name Here")
|
||||
attr_category = forms.CharField(label="Category",
|
||||
help_text="type of attribute, for sorting",
|
||||
required=False,
|
||||
max_length=128)
|
||||
|
||||
attr_key = forms.CharField(
|
||||
label="Attribute Name", required=False, initial="Enter Attribute Name Here"
|
||||
)
|
||||
attr_category = forms.CharField(
|
||||
label="Category", help_text="type of attribute, for sorting", required=False, max_length=128
|
||||
)
|
||||
attr_value = PickledFormField(label="Value", help_text="Value to pickle/save", required=False)
|
||||
attr_type = forms.CharField(label="Type",
|
||||
help_text="Internal use. Either unset (normal Attribute) or \"nick\"",
|
||||
required=False,
|
||||
max_length=16)
|
||||
attr_lockstring = forms.CharField(label="Locks",
|
||||
required=False,
|
||||
help_text="Lock string on the form locktype:lockdef;lockfunc:lockdef;...",
|
||||
widget=forms.Textarea(attrs={"rows": 1, "cols": 8}))
|
||||
attr_type = forms.CharField(
|
||||
label="Type",
|
||||
help_text='Internal use. Either unset (normal Attribute) or "nick"',
|
||||
required=False,
|
||||
max_length=16,
|
||||
)
|
||||
attr_lockstring = forms.CharField(
|
||||
label="Locks",
|
||||
required=False,
|
||||
help_text="Lock string on the form locktype:lockdef;lockfunc:lockdef;...",
|
||||
widget=forms.Textarea(attrs={"rows": 1, "cols": 8}),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
fields = ("attr_key", "attr_value", "attr_category", "attr_lockstring", "attr_type")
|
||||
|
|
@ -193,24 +210,24 @@ class AttributeForm(forms.ModelForm):
|
|||
attr_value = None
|
||||
attr_type = None
|
||||
attr_lockstring = None
|
||||
if hasattr(self.instance, 'attribute'):
|
||||
if hasattr(self.instance, "attribute"):
|
||||
attr_key = self.instance.attribute.db_key
|
||||
attr_category = self.instance.attribute.db_category
|
||||
attr_value = self.instance.attribute.db_value
|
||||
attr_type = self.instance.attribute.db_attrtype
|
||||
attr_lockstring = self.instance.attribute.db_lock_storage
|
||||
self.fields['attr_key'].initial = attr_key
|
||||
self.fields['attr_category'].initial = attr_category
|
||||
self.fields['attr_type'].initial = attr_type
|
||||
self.fields['attr_value'].initial = attr_value
|
||||
self.fields['attr_lockstring'].initial = attr_lockstring
|
||||
self.fields["attr_key"].initial = attr_key
|
||||
self.fields["attr_category"].initial = attr_category
|
||||
self.fields["attr_type"].initial = attr_type
|
||||
self.fields["attr_value"].initial = attr_value
|
||||
self.fields["attr_lockstring"].initial = attr_lockstring
|
||||
self.instance.attr_key = attr_key
|
||||
self.instance.attr_category = attr_category
|
||||
self.instance.attr_value = attr_value
|
||||
|
||||
# prevent from being transformed to str
|
||||
if isinstance(attr_value, (set, _SaverSet)):
|
||||
self.fields['attr_value'].disabled = True
|
||||
self.fields["attr_value"].disabled = True
|
||||
|
||||
self.instance.deserialized_value = from_pickle(attr_value)
|
||||
self.instance.attr_type = attr_type
|
||||
|
|
@ -225,13 +242,13 @@ class AttributeForm(forms.ModelForm):
|
|||
"""
|
||||
# we are spoofing an Attribute for the Handler that will be called
|
||||
instance = self.instance
|
||||
instance.attr_key = self.cleaned_data['attr_key'] or "no_name_entered_for_attribute"
|
||||
instance.attr_category = self.cleaned_data['attr_category'] or None
|
||||
instance.attr_value = self.cleaned_data['attr_value']
|
||||
instance.attr_key = self.cleaned_data["attr_key"] or "no_name_entered_for_attribute"
|
||||
instance.attr_category = self.cleaned_data["attr_category"] or None
|
||||
instance.attr_value = self.cleaned_data["attr_value"]
|
||||
# convert the serialized string value into an object, if necessary, for AttributeHandler
|
||||
instance.attr_value = from_pickle(instance.attr_value)
|
||||
instance.attr_type = self.cleaned_data['attr_type'] or None
|
||||
instance.attr_lockstring = self.cleaned_data['attr_lockstring']
|
||||
instance.attr_type = self.cleaned_data["attr_type"] or None
|
||||
instance.attr_lockstring = self.cleaned_data["attr_lockstring"]
|
||||
return instance
|
||||
|
||||
def clean_attr_value(self):
|
||||
|
|
@ -240,7 +257,7 @@ class AttributeForm(forms.ModelForm):
|
|||
failing on them. Otherwise they will be turned into str.
|
||||
|
||||
"""
|
||||
data = self.cleaned_data['attr_value']
|
||||
data = self.cleaned_data["attr_value"]
|
||||
initial = self.instance.attr_value
|
||||
if isinstance(initial, (set, _SaverSet, datetime)):
|
||||
return initial
|
||||
|
|
@ -264,6 +281,7 @@ class AttributeFormSet(forms.BaseInlineFormSet):
|
|||
else:
|
||||
handler_name = "attributes"
|
||||
return getattr(related, handler_name)
|
||||
|
||||
instances = super().save(commit=False)
|
||||
for obj in self.deleted_objects:
|
||||
# self.deleted_objects is a list created when super of save is called, we'll remove those
|
||||
|
|
@ -276,9 +294,13 @@ class AttributeFormSet(forms.BaseInlineFormSet):
|
|||
value = instance.attr_value
|
||||
|
||||
try:
|
||||
handler.add(instance.attr_key, value,
|
||||
category=instance.attr_category, strattr=False,
|
||||
lockstring=instance.attr_lockstring)
|
||||
handler.add(
|
||||
instance.attr_key,
|
||||
value,
|
||||
category=instance.attr_category,
|
||||
strattr=False,
|
||||
lockstring=instance.attr_lockstring,
|
||||
)
|
||||
except (TypeError, ValueError):
|
||||
# catch errors in nick templates and continue
|
||||
traceback.print_exc()
|
||||
|
|
@ -293,6 +315,7 @@ class AttributeInline(admin.TabularInline):
|
|||
of the field on that through model which points to the model being used: 'objectdb',
|
||||
'msg', 'accountdb', etc.
|
||||
"""
|
||||
|
||||
# Set this to the through model of your desired M2M when subclassing.
|
||||
model = None
|
||||
form = AttributeForm
|
||||
|
|
|
|||
|
|
@ -60,35 +60,51 @@ class Attribute(SharedMemoryModel):
|
|||
#
|
||||
# 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)
|
||||
db_key = models.CharField("key", max_length=255, db_index=True)
|
||||
db_value = PickledObjectField(
|
||||
'value', null=True,
|
||||
"value",
|
||||
null=True,
|
||||
help_text="The data returned when the attribute is accessed. Must be "
|
||||
"written as a Python literal if editing through the admin "
|
||||
"interface. Attribute values which are not Python literals "
|
||||
"cannot be edited through the admin interface.")
|
||||
"written as a Python literal if editing through the admin "
|
||||
"interface. Attribute values which are not Python literals "
|
||||
"cannot be edited through the admin interface.",
|
||||
)
|
||||
db_strvalue = models.TextField(
|
||||
'strvalue', null=True, blank=True,
|
||||
help_text="String-specific storage for quick look-up")
|
||||
"strvalue", null=True, blank=True, help_text="String-specific storage for quick look-up"
|
||||
)
|
||||
db_category = models.CharField(
|
||||
'category', max_length=128, db_index=True, blank=True, null=True,
|
||||
help_text="Optional categorization of attribute.")
|
||||
"category",
|
||||
max_length=128,
|
||||
db_index=True,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Optional categorization of attribute.",
|
||||
)
|
||||
# Lock storage
|
||||
db_lock_storage = models.TextField(
|
||||
'locks', blank=True,
|
||||
help_text="Lockstrings for this object are stored here.")
|
||||
"locks", blank=True, help_text="Lockstrings for this object are stored here."
|
||||
)
|
||||
db_model = models.CharField(
|
||||
'model', max_length=32, db_index=True, blank=True, null=True,
|
||||
"model",
|
||||
max_length=32,
|
||||
db_index=True,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Which model of object this attribute is attached to (A "
|
||||
"natural key like 'objects.objectdb'). You should not change "
|
||||
"this value unless you know what you are doing.")
|
||||
"natural key like 'objects.objectdb'). You should not change "
|
||||
"this value unless you know what you are doing.",
|
||||
)
|
||||
# subclass of Attribute (None or nick)
|
||||
db_attrtype = models.CharField(
|
||||
'attrtype', max_length=16, db_index=True, blank=True, null=True,
|
||||
help_text="Subclass of Attribute (None or nick)")
|
||||
"attrtype",
|
||||
max_length=16,
|
||||
db_index=True,
|
||||
blank=True,
|
||||
null=True,
|
||||
help_text="Subclass of Attribute (None or nick)",
|
||||
)
|
||||
# time stamp
|
||||
db_date_created = models.DateTimeField(
|
||||
'date_created', editable=False, auto_now_add=True)
|
||||
db_date_created = models.DateTimeField("date_created", editable=False, auto_now_add=True)
|
||||
|
||||
# Database manager
|
||||
# objects = managers.AttributeManager()
|
||||
|
|
@ -155,6 +171,7 @@ class Attribute(SharedMemoryModel):
|
|||
def __value_del(self):
|
||||
"""Deleter. Allows for del attr.value. This removes the entire attribute."""
|
||||
self.delete()
|
||||
|
||||
value = property(__value_get, __value_set, __value_del)
|
||||
|
||||
#
|
||||
|
|
@ -169,7 +186,7 @@ class Attribute(SharedMemoryModel):
|
|||
def __repr__(self):
|
||||
return "%s(%s)" % (self.db_key, self.id)
|
||||
|
||||
def access(self, accessing_obj, access_type='read', default=False, **kwargs):
|
||||
def access(self, accessing_obj, access_type="read", default=False, **kwargs):
|
||||
"""
|
||||
Determines if another object has permission to access.
|
||||
|
||||
|
|
@ -195,10 +212,12 @@ class Attribute(SharedMemoryModel):
|
|||
# Handlers making use of the Attribute model
|
||||
#
|
||||
|
||||
|
||||
class AttributeHandler(object):
|
||||
"""
|
||||
Handler for adding Attributes to the object.
|
||||
"""
|
||||
|
||||
_m2m_fieldname = "db_attributes"
|
||||
_attrcreate = "attrcreate"
|
||||
_attredit = "attredit"
|
||||
|
|
@ -218,17 +237,26 @@ class AttributeHandler(object):
|
|||
|
||||
def _fullcache(self):
|
||||
"""Cache all attributes of this object"""
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"attribute__db_model__iexact": self._model,
|
||||
"attribute__db_attrtype": self._attrtype}
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"attribute__db_model__iexact": self._model,
|
||||
"attribute__db_attrtype": self._attrtype,
|
||||
}
|
||||
attrs = [
|
||||
conn.attribute for conn in getattr(
|
||||
self.obj,
|
||||
self._m2m_fieldname).through.objects.filter(
|
||||
**query)]
|
||||
self._cache = dict(("%s-%s" % (to_str(attr.db_key).lower(),
|
||||
attr.db_category.lower() if attr.db_category else None),
|
||||
attr) for attr in attrs)
|
||||
conn.attribute
|
||||
for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)
|
||||
]
|
||||
self._cache = dict(
|
||||
(
|
||||
"%s-%s"
|
||||
% (
|
||||
to_str(attr.db_key).lower(),
|
||||
attr.db_category.lower() if attr.db_category else None,
|
||||
),
|
||||
attr,
|
||||
)
|
||||
for attr in attrs
|
||||
)
|
||||
self._cache_complete = True
|
||||
|
||||
def _getcache(self, key=None, category=None):
|
||||
|
|
@ -276,11 +304,13 @@ class AttributeHandler(object):
|
|||
else:
|
||||
return [] # no such attribute: return an empty list
|
||||
else:
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"attribute__db_model__iexact": self._model,
|
||||
"attribute__db_attrtype": self._attrtype,
|
||||
"attribute__db_key__iexact": key.lower(),
|
||||
"attribute__db_category__iexact": category.lower() if category else None}
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"attribute__db_model__iexact": self._model,
|
||||
"attribute__db_attrtype": self._attrtype,
|
||||
"attribute__db_key__iexact": key.lower(),
|
||||
"attribute__db_category__iexact": category.lower() if category else None,
|
||||
}
|
||||
if not self.obj.pk:
|
||||
return []
|
||||
conn = getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)
|
||||
|
|
@ -303,12 +333,18 @@ class AttributeHandler(object):
|
|||
return [attr for key, attr in self._cache.items() if key.endswith(catkey) and attr]
|
||||
else:
|
||||
# we have to query to make this category up-date in the cache
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"attribute__db_model__iexact": self._model,
|
||||
"attribute__db_attrtype": self._attrtype,
|
||||
"attribute__db_category__iexact": category.lower() if category else None}
|
||||
attrs = [conn.attribute for conn
|
||||
in getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)]
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"attribute__db_model__iexact": self._model,
|
||||
"attribute__db_attrtype": self._attrtype,
|
||||
"attribute__db_category__iexact": category.lower() if category else None,
|
||||
}
|
||||
attrs = [
|
||||
conn.attribute
|
||||
for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(
|
||||
**query
|
||||
)
|
||||
]
|
||||
for attr in attrs:
|
||||
if attr.pk:
|
||||
cachekey = "%s-%s" % (attr.db_key, category)
|
||||
|
|
@ -350,8 +386,11 @@ class AttributeHandler(object):
|
|||
cachekey = "%s-%s" % (key, category)
|
||||
self._cache.pop(cachekey, None)
|
||||
else:
|
||||
self._cache = {key: attrobj for key, attrobj in
|
||||
list(self._cache.items()) if not key.endswith(catkey)}
|
||||
self._cache = {
|
||||
key: attrobj
|
||||
for key, attrobj in list(self._cache.items())
|
||||
if not key.endswith(catkey)
|
||||
}
|
||||
# mark that the category cache is no longer up-to-date
|
||||
self._catcache.pop(catkey, None)
|
||||
self._cache_complete = False
|
||||
|
|
@ -388,9 +427,18 @@ class AttributeHandler(object):
|
|||
ret.extend(bool(attr) for attr in self._getcache(keystr, category))
|
||||
return ret[0] if len(ret) == 1 else ret
|
||||
|
||||
def get(self, key=None, default=None, category=None, return_obj=False,
|
||||
strattr=False, raise_exception=False, accessing_obj=None,
|
||||
default_access=True, return_list=False):
|
||||
def get(
|
||||
self,
|
||||
key=None,
|
||||
default=None,
|
||||
category=None,
|
||||
return_obj=False,
|
||||
strattr=False,
|
||||
raise_exception=False,
|
||||
accessing_obj=None,
|
||||
default_access=True,
|
||||
return_list=False,
|
||||
):
|
||||
"""
|
||||
Get the Attribute.
|
||||
|
||||
|
|
@ -444,9 +492,11 @@ class AttributeHandler(object):
|
|||
|
||||
if accessing_obj:
|
||||
# check 'attrread' locks
|
||||
ret = [attr for attr in ret if attr.access(accessing_obj,
|
||||
self._attrread,
|
||||
default=default_access)]
|
||||
ret = [
|
||||
attr
|
||||
for attr in ret
|
||||
if attr.access(accessing_obj, self._attrread, default=default_access)
|
||||
]
|
||||
if strattr:
|
||||
ret = ret if return_obj else [attr.strvalue for attr in ret if attr]
|
||||
else:
|
||||
|
|
@ -456,8 +506,16 @@ class AttributeHandler(object):
|
|||
return ret if ret else [default] if default is not None else []
|
||||
return ret[0] if ret and len(ret) == 1 else ret or default
|
||||
|
||||
def add(self, key, value, category=None, lockstring="",
|
||||
strattr=False, accessing_obj=None, default_access=True):
|
||||
def add(
|
||||
self,
|
||||
key,
|
||||
value,
|
||||
category=None,
|
||||
lockstring="",
|
||||
strattr=False,
|
||||
accessing_obj=None,
|
||||
default_access=True,
|
||||
):
|
||||
"""
|
||||
Add attribute to object, with optional `lockstring`.
|
||||
|
||||
|
|
@ -479,8 +537,9 @@ class AttributeHandler(object):
|
|||
`attrcreate` is defined on the Attribute in question.
|
||||
|
||||
"""
|
||||
if accessing_obj and not self.obj.access(accessing_obj, self._attrcreate,
|
||||
default=default_access):
|
||||
if accessing_obj and not self.obj.access(
|
||||
accessing_obj, self._attrcreate, default=default_access
|
||||
):
|
||||
# check create access
|
||||
return
|
||||
|
||||
|
|
@ -503,12 +562,14 @@ class AttributeHandler(object):
|
|||
attr_obj.value = value
|
||||
else:
|
||||
# create a new Attribute (no OOB handlers can be notified)
|
||||
kwargs = {"db_key": keystr,
|
||||
"db_category": category,
|
||||
"db_model": self._model,
|
||||
"db_attrtype": self._attrtype,
|
||||
"db_value": None if strattr else to_pickle(value),
|
||||
"db_strvalue": value if strattr else None}
|
||||
kwargs = {
|
||||
"db_key": keystr,
|
||||
"db_category": category,
|
||||
"db_model": self._model,
|
||||
"db_attrtype": self._attrtype,
|
||||
"db_value": None if strattr else to_pickle(value),
|
||||
"db_strvalue": value if strattr else None,
|
||||
}
|
||||
new_attr = Attribute(**kwargs)
|
||||
new_attr.save()
|
||||
getattr(self.obj, self._m2m_fieldname).add(new_attr)
|
||||
|
|
@ -547,7 +608,7 @@ class AttributeHandler(object):
|
|||
|
||||
"""
|
||||
new_attrobjs = []
|
||||
strattr = kwargs.get('strattr', False)
|
||||
strattr = kwargs.get("strattr", False)
|
||||
for tup in args:
|
||||
if not is_iter(tup) or len(tup) < 2:
|
||||
raise RuntimeError("batch_add requires iterables as arguments (got %r)." % tup)
|
||||
|
|
@ -563,7 +624,7 @@ class AttributeHandler(object):
|
|||
attr_obj = attr_objs[0]
|
||||
# update an existing attribute object
|
||||
attr_obj.db_category = category
|
||||
attr_obj.db_lock_storage = lockstring or ''
|
||||
attr_obj.db_lock_storage = lockstring or ""
|
||||
attr_obj.save(update_fields=["db_category", "db_lock_storage"])
|
||||
if strattr:
|
||||
# store as a simple string (will not notify OOB handlers)
|
||||
|
|
@ -574,13 +635,15 @@ class AttributeHandler(object):
|
|||
attr_obj.value = new_value
|
||||
else:
|
||||
# create a new Attribute (no OOB handlers can be notified)
|
||||
kwargs = {"db_key": keystr,
|
||||
"db_category": category,
|
||||
"db_model": self._model,
|
||||
"db_attrtype": self._attrtype,
|
||||
"db_value": None if strattr else to_pickle(new_value),
|
||||
"db_strvalue": new_value if strattr else None,
|
||||
"db_lock_storage": lockstring or ''}
|
||||
kwargs = {
|
||||
"db_key": keystr,
|
||||
"db_category": category,
|
||||
"db_model": self._model,
|
||||
"db_attrtype": self._attrtype,
|
||||
"db_value": None if strattr else to_pickle(new_value),
|
||||
"db_strvalue": new_value if strattr else None,
|
||||
"db_lock_storage": lockstring or "",
|
||||
}
|
||||
new_attr = Attribute(**kwargs)
|
||||
new_attr.save()
|
||||
new_attrobjs.append(new_attr)
|
||||
|
|
@ -589,8 +652,14 @@ class AttributeHandler(object):
|
|||
# Add new objects to m2m field all at once
|
||||
getattr(self.obj, self._m2m_fieldname).add(*new_attrobjs)
|
||||
|
||||
def remove(self, key=None, raise_exception=False, category=None,
|
||||
accessing_obj=None, default_access=True):
|
||||
def remove(
|
||||
self,
|
||||
key=None,
|
||||
raise_exception=False,
|
||||
category=None,
|
||||
accessing_obj=None,
|
||||
default_access=True,
|
||||
):
|
||||
"""
|
||||
Remove attribute or a list of attributes from object.
|
||||
|
||||
|
|
@ -620,8 +689,9 @@ class AttributeHandler(object):
|
|||
"""
|
||||
|
||||
if key is None:
|
||||
self.clear(category=category, accessing_obj=accessing_obj,
|
||||
default_access=default_access)
|
||||
self.clear(
|
||||
category=category, accessing_obj=accessing_obj, default_access=default_access
|
||||
)
|
||||
return
|
||||
|
||||
category = category.strip().lower() if category is not None else None
|
||||
|
|
@ -632,10 +702,9 @@ class AttributeHandler(object):
|
|||
attr_objs = self._getcache(keystr, category)
|
||||
for attr_obj in attr_objs:
|
||||
if not (
|
||||
accessing_obj and not attr_obj.access(
|
||||
accessing_obj,
|
||||
self._attredit,
|
||||
default=default_access)):
|
||||
accessing_obj
|
||||
and not attr_obj.access(accessing_obj, self._attredit, default=default_access)
|
||||
):
|
||||
try:
|
||||
attr_obj.delete()
|
||||
except AssertionError:
|
||||
|
|
@ -672,9 +741,11 @@ class AttributeHandler(object):
|
|||
attrs = self._cache.values()
|
||||
|
||||
if accessing_obj:
|
||||
[attr.delete() for attr in attrs
|
||||
if attr and
|
||||
attr.access(accessing_obj, self._attredit, default=default_access)]
|
||||
[
|
||||
attr.delete()
|
||||
for attr in attrs
|
||||
if attr and attr.access(accessing_obj, self._attredit, default=default_access)
|
||||
]
|
||||
else:
|
||||
[attr.delete() for attr in attrs if attr and attr.pk]
|
||||
self._cache = {}
|
||||
|
|
@ -700,11 +771,13 @@ class AttributeHandler(object):
|
|||
"""
|
||||
if not self._cache_complete:
|
||||
self._fullcache()
|
||||
attrs = sorted([attr for attr in self._cache.values() if attr],
|
||||
key=lambda o: o.id)
|
||||
attrs = sorted([attr for attr in self._cache.values() if attr], key=lambda o: o.id)
|
||||
if accessing_obj:
|
||||
return [attr for attr in attrs
|
||||
if attr.access(accessing_obj, self._attredit, default=default_access)]
|
||||
return [
|
||||
attr
|
||||
for attr in attrs
|
||||
if attr.access(accessing_obj, self._attredit, default=default_access)
|
||||
]
|
||||
else:
|
||||
return attrs
|
||||
|
||||
|
|
@ -815,6 +888,7 @@ class NickHandler(AttributeHandler):
|
|||
They also always use the `strvalue` fields for their data.
|
||||
|
||||
"""
|
||||
|
||||
_attrtype = "nick"
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -858,8 +932,11 @@ class NickHandler(AttributeHandler):
|
|||
else:
|
||||
retval = super().get(key=key, category=category, **kwargs)
|
||||
if retval:
|
||||
return retval[3] if isinstance(retval, tuple) else \
|
||||
[tup[3] for tup in make_iter(retval)]
|
||||
return (
|
||||
retval[3]
|
||||
if isinstance(retval, tuple)
|
||||
else [tup[3] for tup in make_iter(retval)]
|
||||
)
|
||||
return None
|
||||
|
||||
def add(self, key, replacement, category="inputline", **kwargs):
|
||||
|
|
@ -879,8 +956,7 @@ class NickHandler(AttributeHandler):
|
|||
nick_regex, nick_template = initialize_nick_templates(key + " $1", replacement + " $1")
|
||||
else:
|
||||
nick_regex, nick_template = initialize_nick_templates(key, replacement)
|
||||
super().add(key, (nick_regex, nick_template, key, replacement),
|
||||
category=category, **kwargs)
|
||||
super().add(key, (nick_regex, nick_template, key, replacement), category=category, **kwargs)
|
||||
|
||||
def remove(self, key, category="inputline", **kwargs):
|
||||
"""
|
||||
|
|
@ -917,12 +993,24 @@ class NickHandler(AttributeHandler):
|
|||
"""
|
||||
nicks = {}
|
||||
for category in make_iter(categories):
|
||||
nicks.update({nick.key: nick for nick in make_iter(
|
||||
self.get(category=category, return_obj=True)) if nick and nick.key})
|
||||
nicks.update(
|
||||
{
|
||||
nick.key: nick
|
||||
for nick in make_iter(self.get(category=category, return_obj=True))
|
||||
if nick and nick.key
|
||||
}
|
||||
)
|
||||
if include_account and self.obj.has_account:
|
||||
for category in make_iter(categories):
|
||||
nicks.update({nick.key: nick for nick in make_iter(self.obj.account.nicks.get(
|
||||
category=category, return_obj=True)) if nick and nick.key})
|
||||
nicks.update(
|
||||
{
|
||||
nick.key: nick
|
||||
for nick in make_iter(
|
||||
self.obj.account.nicks.get(category=category, return_obj=True)
|
||||
)
|
||||
if nick and nick.key
|
||||
}
|
||||
)
|
||||
for key, nick in nicks.items():
|
||||
nick_regex, template, _, _ = nick.value
|
||||
regex = self._regex_cache.get(nick_regex)
|
||||
|
|
|
|||
|
|
@ -11,23 +11,27 @@ from evennia.utils.utils import make_iter, variable_from_module
|
|||
from evennia.typeclasses.attributes import Attribute
|
||||
from evennia.typeclasses.tags import Tag
|
||||
|
||||
__all__ = ("TypedObjectManager", )
|
||||
__all__ = ("TypedObjectManager",)
|
||||
_GA = object.__getattribute__
|
||||
_Tag = None
|
||||
|
||||
|
||||
# Managers
|
||||
|
||||
|
||||
class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
||||
"""
|
||||
Common ObjectManager for all dbobjects.
|
||||
|
||||
"""
|
||||
|
||||
# common methods for all typed managers. These are used
|
||||
# in other methods. Returns querysets.
|
||||
|
||||
# Attribute manager methods
|
||||
def get_attribute(self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None):
|
||||
def get_attribute(
|
||||
self, key=None, category=None, value=None, strvalue=None, obj=None, attrtype=None
|
||||
):
|
||||
"""
|
||||
Return Attribute objects by key, by category, by value, by
|
||||
strvalue, by object (it is stored on) or with a combination of
|
||||
|
|
@ -69,8 +73,10 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
# no reason to make strvalue/value mutually exclusive at this level
|
||||
query.append(("attribute__db_value", value))
|
||||
return Attribute.objects.filter(
|
||||
pk__in=self.model.db_attributes.through.objects.filter(
|
||||
**dict(query)).values_list("attribute_id", flat=True))
|
||||
pk__in=self.model.db_attributes.through.objects.filter(**dict(query)).values_list(
|
||||
"attribute_id", flat=True
|
||||
)
|
||||
)
|
||||
|
||||
def get_nick(self, key=None, category=None, value=None, strvalue=None, obj=None):
|
||||
"""
|
||||
|
|
@ -91,7 +97,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
nicks (list): The matching Nicks.
|
||||
|
||||
"""
|
||||
return self.get_attribute(key=key, category=category, value=value, strvalue=strvalue, obj=obj)
|
||||
return self.get_attribute(
|
||||
key=key, category=category, value=value, strvalue=strvalue, obj=obj
|
||||
)
|
||||
|
||||
def get_by_attribute(self, key=None, category=None, value=None, strvalue=None, attrtype=None):
|
||||
"""
|
||||
|
|
@ -149,7 +157,6 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
# Tag manager methods
|
||||
|
||||
|
||||
def get_tag(self, key=None, category=None, obj=None, tagtype=None, global_search=False):
|
||||
"""
|
||||
Return Tag objects by key, by category, by object (it is
|
||||
|
|
@ -194,8 +201,10 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
if category:
|
||||
query.append(("tag__db_category", category))
|
||||
return Tag.objects.filter(
|
||||
pk__in=self.model.db_tags.through.objects.filter(
|
||||
**dict(query)).values_list("tag_id", flat=True))
|
||||
pk__in=self.model.db_tags.through.objects.filter(**dict(query)).values_list(
|
||||
"tag_id", flat=True
|
||||
)
|
||||
)
|
||||
|
||||
def get_permission(self, key=None, category=None, obj=None):
|
||||
"""
|
||||
|
|
@ -259,8 +268,11 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
n_categories = len(categories)
|
||||
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
query = self.filter(db_tags__db_tagtype__iexact=tagtype,
|
||||
db_tags__db_model__iexact=dbmodel).distinct().order_by('id')
|
||||
query = (
|
||||
self.filter(db_tags__db_tagtype__iexact=tagtype, db_tags__db_model__iexact=dbmodel)
|
||||
.distinct()
|
||||
.order_by("id")
|
||||
)
|
||||
|
||||
if n_keys > 0:
|
||||
# keys and/or categories given
|
||||
|
|
@ -270,11 +282,14 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
cat = categories[0]
|
||||
categories = [cat for _ in range(n_keys)]
|
||||
elif 1 < n_categories < n_keys:
|
||||
raise IndexError("get_by_tag needs a single category or a list of categories "
|
||||
"the same length as the list of tags.")
|
||||
raise IndexError(
|
||||
"get_by_tag needs a single category or a list of categories "
|
||||
"the same length as the list of tags."
|
||||
)
|
||||
for ikey, key in enumerate(keys):
|
||||
query = query.filter(db_tags__db_key__iexact=key,
|
||||
db_tags__db_category__iexact=categories[ikey])
|
||||
query = query.filter(
|
||||
db_tags__db_key__iexact=key, db_tags__db_category__iexact=categories[ikey]
|
||||
)
|
||||
else:
|
||||
# only one or more categories given
|
||||
for category in categories:
|
||||
|
|
@ -336,8 +351,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
# try to get old tag
|
||||
|
||||
dbmodel = self.model.__dbclass__.__name__.lower()
|
||||
tag = self.get_tag(key=key, category=category, tagtype=tagtype,
|
||||
global_search=True)
|
||||
tag = self.get_tag(key=key, category=category, tagtype=tagtype, global_search=True)
|
||||
if tag and data is not None:
|
||||
# get tag from list returned by get_tag
|
||||
tag = tag[0]
|
||||
|
|
@ -354,7 +368,8 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
db_category=category.strip().lower() if category and key is not None else None,
|
||||
db_data=data,
|
||||
db_model=dbmodel,
|
||||
db_tagtype=tagtype.strip().lower() if tagtype is not None else None)
|
||||
db_tagtype=tagtype.strip().lower() if tagtype is not None else None,
|
||||
)
|
||||
tag.save()
|
||||
return make_iter(tag)[0]
|
||||
|
||||
|
|
@ -378,7 +393,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
if reqhash and not (isinstance(dbref, str) and dbref.startswith("#")):
|
||||
return None
|
||||
if isinstance(dbref, str):
|
||||
dbref = dbref.lstrip('#')
|
||||
dbref = dbref.lstrip("#")
|
||||
try:
|
||||
if int(dbref) < 0:
|
||||
return None
|
||||
|
|
@ -449,10 +464,9 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
|||
|
||||
"""
|
||||
dbtotals = {}
|
||||
typeclass_paths = set(self.values_list('db_typeclass_path', flat=True))
|
||||
typeclass_paths = set(self.values_list("db_typeclass_path", flat=True))
|
||||
for typeclass_path in typeclass_paths:
|
||||
dbtotals[typeclass_path] = \
|
||||
self.filter(db_typeclass_path=typeclass_path).count()
|
||||
dbtotals[typeclass_path] = self.filter(db_typeclass_path=typeclass_path).count()
|
||||
return dbtotals
|
||||
|
||||
def typeclass_search(self, typeclass, include_children=False, include_parents=False):
|
||||
|
|
@ -539,30 +553,30 @@ class TypeclassManager(TypedObjectManager):
|
|||
for ipart, part in enumerate(querysplit):
|
||||
key, rest = part, ""
|
||||
if ":" in part:
|
||||
key, rest = part.split(':', 1)
|
||||
key, rest = part.split(":", 1)
|
||||
# tags are on the form tag or tag:category
|
||||
if key.startswith('tag=='):
|
||||
if key.startswith("tag=="):
|
||||
plustags.append((key[5:], rest))
|
||||
continue
|
||||
elif key.startswith('tag!='):
|
||||
elif key.startswith("tag!="):
|
||||
negtags.append((key[5:], rest))
|
||||
continue
|
||||
# attrs are on the form attr:value or attr:value:category
|
||||
elif rest:
|
||||
value, category = rest, ""
|
||||
if ":" in rest:
|
||||
value, category = rest.split(':', 1)
|
||||
if key.startswith('attr=='):
|
||||
value, category = rest.split(":", 1)
|
||||
if key.startswith("attr=="):
|
||||
plusattrs.append((key[7:], value, category))
|
||||
continue
|
||||
elif key.startswith('attr!='):
|
||||
elif key.startswith("attr!="):
|
||||
negattrs.append((key[7:], value, category))
|
||||
continue
|
||||
# if we get here, we are entering a key search criterion which
|
||||
# we assume is one word.
|
||||
queries.append(part)
|
||||
# build query from components
|
||||
query = ' '.join(queries)
|
||||
query = " ".join(queries)
|
||||
# TODO
|
||||
|
||||
def get(self, *args, **kwargs):
|
||||
|
|
@ -663,7 +677,11 @@ class TypeclassManager(TypedObjectManager):
|
|||
Returns:
|
||||
Annotated queryset.
|
||||
"""
|
||||
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).annotate(*args, **kwargs)
|
||||
return (
|
||||
super(TypeclassManager, self)
|
||||
.filter(db_typeclass_path=self.model.path)
|
||||
.annotate(*args, **kwargs)
|
||||
)
|
||||
|
||||
def values(self, *args, **kwargs):
|
||||
"""
|
||||
|
|
@ -675,7 +693,11 @@ class TypeclassManager(TypedObjectManager):
|
|||
Returns:
|
||||
Queryset of values dictionaries, just filtered by typeclass first.
|
||||
"""
|
||||
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).values(*args, **kwargs)
|
||||
return (
|
||||
super(TypeclassManager, self)
|
||||
.filter(db_typeclass_path=self.model.path)
|
||||
.values(*args, **kwargs)
|
||||
)
|
||||
|
||||
def values_list(self, *args, **kwargs):
|
||||
"""
|
||||
|
|
@ -687,7 +709,11 @@ class TypeclassManager(TypedObjectManager):
|
|||
Returns:
|
||||
Queryset of value_list tuples, just filtered by typeclass first.
|
||||
"""
|
||||
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).values_list(*args, **kwargs)
|
||||
return (
|
||||
super(TypeclassManager, self)
|
||||
.filter(db_typeclass_path=self.model.path)
|
||||
.values_list(*args, **kwargs)
|
||||
)
|
||||
|
||||
def _get_subclasses(self, cls):
|
||||
"""
|
||||
|
|
@ -717,8 +743,9 @@ class TypeclassManager(TypedObjectManager):
|
|||
on the model base used.
|
||||
|
||||
"""
|
||||
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)]
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
kwargs.update({"db_typeclass_path__in": paths})
|
||||
return super().get(**kwargs)
|
||||
|
||||
|
|
@ -738,8 +765,9 @@ class TypeclassManager(TypedObjectManager):
|
|||
|
||||
"""
|
||||
# query, including all subclasses
|
||||
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)]
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
kwargs.update({"db_typeclass_path__in": paths})
|
||||
return super().filter(*args, **kwargs)
|
||||
|
||||
|
|
@ -752,6 +780,7 @@ class TypeclassManager(TypedObjectManager):
|
|||
objects (list): The objects found.
|
||||
|
||||
"""
|
||||
paths = [self.model.path] + ["%s.%s" % (cls.__module__, cls.__name__)
|
||||
for cls in self._get_subclasses(self.model)]
|
||||
paths = [self.model.path] + [
|
||||
"%s.%s" % (cls.__module__, cls.__name__) for cls in self._get_subclasses(self.model)
|
||||
]
|
||||
return super().all().filter(db_typeclass_path__in=paths)
|
||||
|
|
|
|||
|
|
@ -8,54 +8,156 @@ import evennia.utils.picklefield
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
dependencies = []
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Attribute',
|
||||
name="Attribute",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('db_key', models.CharField(max_length=255, verbose_name='key', db_index=True)),
|
||||
('db_value', evennia.utils.picklefield.PickledObjectField(help_text='The data returned when the attribute is accessed. Must be written as a Python literal if editing through the admin interface. Attribute values which are not Python literals cannot be edited through the admin interface.', null=True, verbose_name='value')),
|
||||
('db_strvalue', models.TextField(help_text='String-specific storage for quick look-up', null=True, verbose_name='strvalue', blank=True)),
|
||||
('db_category', models.CharField(max_length=128, blank=True, help_text='Optional categorization of attribute.', null=True, verbose_name='category', db_index=True)),
|
||||
('db_lock_storage', models.TextField(help_text='Lockstrings for this object are stored here.', verbose_name='locks', blank=True)),
|
||||
('db_model', models.CharField(max_length=32, blank=True, help_text='Which model of object this attribute is attached to (A natural key like objects.dbobject). You should not change this value unless you know what you are doing.', null=True, verbose_name='model', db_index=True)),
|
||||
('db_attrtype', models.CharField(max_length=16, blank=True, help_text='Subclass of Attribute (None or nick)', null=True, verbose_name='attrtype', db_index=True)),
|
||||
('db_date_created', models.DateTimeField(auto_now_add=True, verbose_name='date_created')),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID", serialize=False, auto_created=True, primary_key=True
|
||||
),
|
||||
),
|
||||
("db_key", models.CharField(max_length=255, verbose_name="key", db_index=True)),
|
||||
(
|
||||
"db_value",
|
||||
evennia.utils.picklefield.PickledObjectField(
|
||||
help_text="The data returned when the attribute is accessed. Must be written as a Python literal if editing through the admin interface. Attribute values which are not Python literals cannot be edited through the admin interface.",
|
||||
null=True,
|
||||
verbose_name="value",
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_strvalue",
|
||||
models.TextField(
|
||||
help_text="String-specific storage for quick look-up",
|
||||
null=True,
|
||||
verbose_name="strvalue",
|
||||
blank=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_category",
|
||||
models.CharField(
|
||||
max_length=128,
|
||||
blank=True,
|
||||
help_text="Optional categorization of attribute.",
|
||||
null=True,
|
||||
verbose_name="category",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_lock_storage",
|
||||
models.TextField(
|
||||
help_text="Lockstrings for this object are stored here.",
|
||||
verbose_name="locks",
|
||||
blank=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_model",
|
||||
models.CharField(
|
||||
max_length=32,
|
||||
blank=True,
|
||||
help_text="Which model of object this attribute is attached to (A natural key like objects.dbobject). You should not change this value unless you know what you are doing.",
|
||||
null=True,
|
||||
verbose_name="model",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_attrtype",
|
||||
models.CharField(
|
||||
max_length=16,
|
||||
blank=True,
|
||||
help_text="Subclass of Attribute (None or nick)",
|
||||
null=True,
|
||||
verbose_name="attrtype",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_date_created",
|
||||
models.DateTimeField(auto_now_add=True, verbose_name="date_created"),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Evennia Attribute',
|
||||
},
|
||||
options={"verbose_name": "Evennia Attribute"},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tag',
|
||||
name="Tag",
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('db_key', models.CharField(help_text='tag identifier', max_length=255, null=True, verbose_name='key', db_index=True)),
|
||||
('db_category', models.CharField(help_text='tag category', max_length=64, null=True, verbose_name='category', db_index=True)),
|
||||
('db_data', models.TextField(help_text='optional data field with extra information. This is not searched for.', null=True, verbose_name='data', blank=True)),
|
||||
('db_model', models.CharField(help_text='database model to Tag', max_length=32, null=True, verbose_name='model', db_index=True)),
|
||||
('db_tagtype', models.CharField(help_text='overall type of Tag', max_length=16, null=True, verbose_name='tagtype', db_index=True)),
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
verbose_name="ID", serialize=False, auto_created=True, primary_key=True
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_key",
|
||||
models.CharField(
|
||||
help_text="tag identifier",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="key",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_category",
|
||||
models.CharField(
|
||||
help_text="tag category",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="category",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_data",
|
||||
models.TextField(
|
||||
help_text="optional data field with extra information. This is not searched for.",
|
||||
null=True,
|
||||
verbose_name="data",
|
||||
blank=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_model",
|
||||
models.CharField(
|
||||
help_text="database model to Tag",
|
||||
max_length=32,
|
||||
null=True,
|
||||
verbose_name="model",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
"db_tagtype",
|
||||
models.CharField(
|
||||
help_text="overall type of Tag",
|
||||
max_length=16,
|
||||
null=True,
|
||||
verbose_name="tagtype",
|
||||
db_index=True,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Tag',
|
||||
},
|
||||
options={"verbose_name": "Tag"},
|
||||
bases=(models.Model,),
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='tag',
|
||||
unique_together=set([('db_key', 'db_category', 'db_tagtype')]),
|
||||
name="tag", unique_together=set([("db_key", "db_category", "db_tagtype")])
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='tag',
|
||||
index_together=set([('db_key', 'db_category', 'db_tagtype')]),
|
||||
name="tag", index_together=set([("db_key", "db_category", "db_tagtype")])
|
||||
),
|
||||
]
|
||||
# if we are using Oracle, we need to remove the AlterIndexTogether operation
|
||||
# since Oracle seems to create its own index already at AlterUniqueTogether, meaning
|
||||
# there is a conflict (see issue #732).
|
||||
if settings.DATABASES['default']['ENGINE'] == "django.db.backends.oracle":
|
||||
if settings.DATABASES["default"]["ENGINE"] == "django.db.backends.oracle":
|
||||
del operations[3]
|
||||
|
|
|
|||
|
|
@ -7,14 +7,21 @@ from django.db import models, migrations
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0001_initial'),
|
||||
('auth', '0007_alter_validators_add_error_messages')
|
||||
("typeclasses", "0001_initial"),
|
||||
("auth", "0007_alter_validators_add_error_messages"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_model',
|
||||
field=models.CharField(max_length=32, blank=True, help_text="Which model of object this attribute is attached to (A natural key like 'objects.dbobject'). You should not change this value unless you know what you are doing.", null=True, verbose_name='model', db_index=True),
|
||||
),
|
||||
model_name="attribute",
|
||||
name="db_model",
|
||||
field=models.CharField(
|
||||
max_length=32,
|
||||
blank=True,
|
||||
help_text="Which model of object this attribute is attached to (A natural key like 'objects.dbobject'). You should not change this value unless you know what you are doing.",
|
||||
null=True,
|
||||
verbose_name="model",
|
||||
db_index=True,
|
||||
),
|
||||
)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -8,107 +8,64 @@ import evennia.accounts.manager
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('objects', '0005_auto_20150403_2339'),
|
||||
('scripts', '0007_auto_20150403_2339'),
|
||||
('accounts', '0004_auto_20150403_2339'),
|
||||
('typeclasses', '0002_auto_20150109_0913'),
|
||||
("objects", "0005_auto_20150403_2339"),
|
||||
("scripts", "0007_auto_20150403_2339"),
|
||||
("accounts", "0004_auto_20150403_2339"),
|
||||
("typeclasses", "0002_auto_20150109_0913"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='DefaultObject',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('objects.objectdb',),
|
||||
name="DefaultObject", fields=[], options={"proxy": True}, bases=("objects.objectdb",)
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DefaultAccount',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('accounts.accountdb',),
|
||||
managers=[
|
||||
('objects', evennia.accounts.manager.AccountManager()),
|
||||
],
|
||||
name="DefaultAccount",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("accounts.accountdb",),
|
||||
managers=[("objects", evennia.accounts.manager.AccountManager())],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='ScriptBase',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('scripts.scriptdb',),
|
||||
name="ScriptBase", fields=[], options={"proxy": True}, bases=("scripts.scriptdb",)
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DefaultCharacter',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.defaultobject',),
|
||||
name="DefaultCharacter",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("typeclasses.defaultobject",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DefaultExit',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.defaultobject',),
|
||||
name="DefaultExit",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("typeclasses.defaultobject",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DefaultGuest',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.defaultaccount',),
|
||||
managers=[
|
||||
('objects', evennia.accounts.manager.AccountManager()),
|
||||
],
|
||||
name="DefaultGuest",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("typeclasses.defaultaccount",),
|
||||
managers=[("objects", evennia.accounts.manager.AccountManager())],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DefaultRoom',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.defaultobject',),
|
||||
name="DefaultRoom",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("typeclasses.defaultobject",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DefaultScript',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.scriptbase',),
|
||||
name="DefaultScript",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("typeclasses.scriptbase",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='DoNothing',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.defaultscript',),
|
||||
name="DoNothing",
|
||||
fields=[],
|
||||
options={"proxy": True},
|
||||
bases=("typeclasses.defaultscript",),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Store',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
},
|
||||
bases=('typeclasses.defaultscript',),
|
||||
name="Store", fields=[], options={"proxy": True}, bases=("typeclasses.defaultscript",)
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,13 +7,23 @@ from django.db import migrations, models
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0003_defaultcharacter_defaultexit_defaultguest_defaultobject_defaultplayer_defaultroom_defaultscript_dono'),
|
||||
(
|
||||
"typeclasses",
|
||||
"0003_defaultcharacter_defaultexit_defaultguest_defaultobject_defaultplayer_defaultroom_defaultscript_dono",
|
||||
)
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_model',
|
||||
field=models.CharField(max_length=32, blank=True, help_text="Which model of object this attribute is attached to (A natural key like 'objects.objectdb'). You should not change this value unless you know what you are doing.", null=True, verbose_name='model', db_index=True),
|
||||
),
|
||||
model_name="attribute",
|
||||
name="db_model",
|
||||
field=models.CharField(
|
||||
max_length=32,
|
||||
blank=True,
|
||||
help_text="Which model of object this attribute is attached to (A natural key like 'objects.objectdb'). You should not change this value unless you know what you are doing.",
|
||||
null=True,
|
||||
verbose_name="model",
|
||||
db_index=True,
|
||||
),
|
||||
)
|
||||
]
|
||||
|
|
|
|||
|
|
@ -22,11 +22,9 @@ def update_nicks(apps, schema_editor):
|
|||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0004_auto_20151101_1759'),
|
||||
('comms', '0010_auto_20161206_1912'),
|
||||
('help', '0001_initial')
|
||||
("typeclasses", "0004_auto_20151101_1759"),
|
||||
("comms", "0010_auto_20161206_1912"),
|
||||
("help", "0001_initial"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_nicks)
|
||||
]
|
||||
operations = [migrations.RunPython(update_nicks)]
|
||||
|
|
|
|||
|
|
@ -7,41 +7,37 @@ from django.db import migrations
|
|||
|
||||
def update_tags_with_dbmodel(apps, schema_editor):
|
||||
|
||||
ObjectDB = apps.get_model('objects', 'ObjectDB')
|
||||
ObjectDB = apps.get_model("objects", "ObjectDB")
|
||||
for obj in ObjectDB.objects.all():
|
||||
obj.db_attributes.all().update(db_model="objectdb")
|
||||
obj.db_tags.all().update(db_model="objectdb")
|
||||
|
||||
AccountDB = apps.get_model('accounts', 'AccountDB')
|
||||
AccountDB = apps.get_model("accounts", "AccountDB")
|
||||
for obj in AccountDB.objects.all():
|
||||
obj.db_attributes.all().update(db_model="accountdb")
|
||||
obj.db_tags.all().update(db_model="accountdb")
|
||||
|
||||
ScriptDB = apps.get_model('scripts', 'ScriptDB')
|
||||
ScriptDB = apps.get_model("scripts", "ScriptDB")
|
||||
for obj in ScriptDB.objects.all():
|
||||
obj.db_attributes.all().update(db_model="scriptdb")
|
||||
obj.db_tags.all().update(db_model="scriptdb")
|
||||
|
||||
ChannelDB = apps.get_model('comms', 'ChannelDB')
|
||||
ChannelDB = apps.get_model("comms", "ChannelDB")
|
||||
for obj in ChannelDB.objects.all():
|
||||
obj.db_attributes.all().update(db_model="channeldb")
|
||||
obj.db_tags.all().update(db_model="channeldb")
|
||||
|
||||
HelpEntry = apps.get_model('help', 'HelpEntry')
|
||||
HelpEntry = apps.get_model("help", "HelpEntry")
|
||||
for obj in HelpEntry.objects.all():
|
||||
obj.db_tags.all().update(db_model="helpentry")
|
||||
|
||||
Msg = apps.get_model('comms', 'Msg')
|
||||
Msg = apps.get_model("comms", "Msg")
|
||||
for obj in Msg.objects.all():
|
||||
obj.db_tags.all().update(db_model="msg")
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0005_auto_20160625_1812'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0005_auto_20160625_1812")]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_tags_with_dbmodel)
|
||||
]
|
||||
operations = [migrations.RunPython(update_tags_with_dbmodel)]
|
||||
|
|
|
|||
|
|
@ -7,79 +7,103 @@ from django.db import migrations
|
|||
|
||||
def update_tags_with_dbmodel(apps, schema_editor):
|
||||
|
||||
Tag = apps.get_model('typeclasses', 'Tag')
|
||||
Tag = apps.get_model("typeclasses", "Tag")
|
||||
|
||||
ObjectDB = apps.get_model('objects', 'ObjectDB')
|
||||
ObjectDB = apps.get_model("objects", "ObjectDB")
|
||||
for obj in ObjectDB.objects.all().exclude(db_tags__db_model="objectdb"):
|
||||
for tag in obj.db_tags.all().exclude(db_model="objectdb"):
|
||||
obj.db_tags.remove(tag)
|
||||
newtag = Tag(db_key=tag.db_key, db_category=tag.db_category,
|
||||
db_data=tag.db_data, db_tagtype=tag.db_tagtype, db_model="objectdb")
|
||||
newtag = Tag(
|
||||
db_key=tag.db_key,
|
||||
db_category=tag.db_category,
|
||||
db_data=tag.db_data,
|
||||
db_tagtype=tag.db_tagtype,
|
||||
db_model="objectdb",
|
||||
)
|
||||
newtag.save()
|
||||
obj.db_tags.add(newtag)
|
||||
|
||||
AccountDB = apps.get_model('accounts', 'AccountDB')
|
||||
AccountDB = apps.get_model("accounts", "AccountDB")
|
||||
for obj in AccountDB.objects.all().exclude(db_tags__db_model="accountdb"):
|
||||
for tag in obj.db_tags.all().exclude(db_model="accountdb"):
|
||||
obj.db_tags.remove(tag)
|
||||
newtag = Tag(db_key=tag.db_key, db_category=tag.db_category,
|
||||
db_data=tag.db_data, db_tagtype=tag.db_tagtype, db_model="accountdb")
|
||||
newtag = Tag(
|
||||
db_key=tag.db_key,
|
||||
db_category=tag.db_category,
|
||||
db_data=tag.db_data,
|
||||
db_tagtype=tag.db_tagtype,
|
||||
db_model="accountdb",
|
||||
)
|
||||
newtag.save()
|
||||
obj.db_tags.add(newtag)
|
||||
|
||||
ScriptDB = apps.get_model('scripts', 'ScriptDB')
|
||||
ScriptDB = apps.get_model("scripts", "ScriptDB")
|
||||
for obj in ScriptDB.objects.all().exclude(db_tags__db_model="scriptdb"):
|
||||
for tag in obj.db_tags.all().exclude(db_model="scriptdb"):
|
||||
obj.db_tags.remove(tag)
|
||||
newtag = Tag(db_key=tag.db_key, db_category=tag.db_category,
|
||||
db_data=tag.db_data, db_tagtype=tag.db_tagtype, db_model="scriptdb")
|
||||
newtag = Tag(
|
||||
db_key=tag.db_key,
|
||||
db_category=tag.db_category,
|
||||
db_data=tag.db_data,
|
||||
db_tagtype=tag.db_tagtype,
|
||||
db_model="scriptdb",
|
||||
)
|
||||
newtag.save()
|
||||
obj.db_tags.add(newtag)
|
||||
|
||||
ChannelDB = apps.get_model('comms', 'ChannelDB')
|
||||
ChannelDB = apps.get_model("comms", "ChannelDB")
|
||||
for obj in ChannelDB.objects.all().exclude(db_tags__db_model="channeldb"):
|
||||
for tag in obj.db_tags.all().exclude(db_model="channeldb"):
|
||||
obj.db_tags.remove(tag)
|
||||
newtag = Tag(db_key=tag.db_key, db_category=tag.db_category,
|
||||
db_data=tag.db_data, db_tagtype=tag.db_tagtype, db_model="channeldb")
|
||||
newtag = Tag(
|
||||
db_key=tag.db_key,
|
||||
db_category=tag.db_category,
|
||||
db_data=tag.db_data,
|
||||
db_tagtype=tag.db_tagtype,
|
||||
db_model="channeldb",
|
||||
)
|
||||
newtag.save()
|
||||
obj.db_tags.add(newtag)
|
||||
|
||||
HelpEntry = apps.get_model('help', 'HelpEntry')
|
||||
HelpEntry = apps.get_model("help", "HelpEntry")
|
||||
for obj in HelpEntry.objects.all().exclude(db_tags__db_model="helpentry"):
|
||||
for tag in obj.db_tags.all().exclude(db_model="helpentry"):
|
||||
obj.db_tags.remove(tag)
|
||||
newtag = Tag(db_key=tag.db_key, db_category=tag.db_category,
|
||||
db_data=tag.db_data, db_tagtype=tag.db_tagtype, db_model="helpentry")
|
||||
newtag = Tag(
|
||||
db_key=tag.db_key,
|
||||
db_category=tag.db_category,
|
||||
db_data=tag.db_data,
|
||||
db_tagtype=tag.db_tagtype,
|
||||
db_model="helpentry",
|
||||
)
|
||||
newtag.save()
|
||||
obj.db_tags.add(newtag)
|
||||
|
||||
Msg = apps.get_model('comms', 'Msg')
|
||||
Msg = apps.get_model("comms", "Msg")
|
||||
for obj in Msg.objects.all().exclude(db_tags__db_model="msg"):
|
||||
for tag in obj.db_tags.all().exclude(db_model="msg"):
|
||||
obj.db_tags.remove(tag)
|
||||
newtag = Tag(db_key=tag.db_key, db_category=tag.db_category,
|
||||
db_data=tag.db_data, db_tagtype=tag.db_tagtype, db_model="msg")
|
||||
newtag = Tag(
|
||||
db_key=tag.db_key,
|
||||
db_category=tag.db_category,
|
||||
db_data=tag.db_data,
|
||||
db_tagtype=tag.db_tagtype,
|
||||
db_model="msg",
|
||||
)
|
||||
newtag.save()
|
||||
obj.db_tags.add(newtag)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0006_auto_add_dbmodel_value_for_tags_attributes'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0006_auto_add_dbmodel_value_for_tags_attributes")]
|
||||
|
||||
operations = [
|
||||
|
||||
migrations.AlterUniqueTogether(
|
||||
name='tag',
|
||||
unique_together=set([('db_key', 'db_category', 'db_tagtype', 'db_model')]),
|
||||
name="tag", unique_together=set([("db_key", "db_category", "db_tagtype", "db_model")])
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='tag',
|
||||
index_together=set([('db_key', 'db_category', 'db_tagtype', 'db_model')]),
|
||||
name="tag", index_together=set([("db_key", "db_category", "db_tagtype", "db_model")])
|
||||
),
|
||||
|
||||
migrations.RunPython(update_tags_with_dbmodel)
|
||||
migrations.RunPython(update_tags_with_dbmodel),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -9,9 +9,15 @@ from django.db import migrations
|
|||
def update_perms_and_locks(apps, schema_editor):
|
||||
|
||||
# update all permissions
|
||||
Tag = apps.get_model('typeclasses', 'Tag')
|
||||
perm_map = {"guests": "guest", "players": "player", "playerhelpers": "helper",
|
||||
"builders": "builder", "wizards": "admin", "immortals": "developer"}
|
||||
Tag = apps.get_model("typeclasses", "Tag")
|
||||
perm_map = {
|
||||
"guests": "guest",
|
||||
"players": "player",
|
||||
"playerhelpers": "helper",
|
||||
"builders": "builder",
|
||||
"wizards": "admin",
|
||||
"immortals": "developer",
|
||||
}
|
||||
|
||||
for perm in Tag.objects.filter(db_tagtype="permission"):
|
||||
if perm.db_key in perm_map:
|
||||
|
|
@ -19,10 +25,15 @@ def update_perms_and_locks(apps, schema_editor):
|
|||
perm.save(update_fields=("db_key",))
|
||||
|
||||
# update all locks on all entities
|
||||
apps_models = [("objects", "ObjectDB"), ("accounts", "AccountDB"), ("scripts", "ScriptDB"),
|
||||
("comms", "ChannelDB")]
|
||||
p_reg = re.compile(r"(?<=perm\()(\w+)(?=\))|(?<=perm_above\()(\w+)(?=\))",
|
||||
re.IGNORECASE + re.UNICODE)
|
||||
apps_models = [
|
||||
("objects", "ObjectDB"),
|
||||
("accounts", "AccountDB"),
|
||||
("scripts", "ScriptDB"),
|
||||
("comms", "ChannelDB"),
|
||||
]
|
||||
p_reg = re.compile(
|
||||
r"(?<=perm\()(\w+)(?=\))|(?<=perm_above\()(\w+)(?=\))", re.IGNORECASE + re.UNICODE
|
||||
)
|
||||
|
||||
def _sub(match):
|
||||
perm = match.group(1)
|
||||
|
|
@ -35,16 +46,11 @@ def update_perms_and_locks(apps, schema_editor):
|
|||
repl_lock = p_reg.sub(_sub, orig_lock)
|
||||
if repl_lock != orig_lock:
|
||||
obj.db_lock_storage = repl_lock
|
||||
obj.save(update_fields=('db_lock_storage',))
|
||||
obj.save(update_fields=("db_lock_storage",))
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0007_tag_migrations_may_be_slow'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0007_tag_migrations_may_be_slow")]
|
||||
|
||||
operations = [
|
||||
|
||||
migrations.RunPython(update_perms_and_locks)
|
||||
]
|
||||
operations = [migrations.RunPython(update_perms_and_locks)]
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ def _case_sensitive_replace(string, old, new):
|
|||
`old` has been replaced with `new`, retaining case.
|
||||
|
||||
"""
|
||||
|
||||
def repl(match):
|
||||
current = match.group()
|
||||
# treat multi-word sentences word-by-word
|
||||
|
|
@ -41,12 +42,12 @@ def _case_sensitive_replace(string, old, new):
|
|||
all_upper = False
|
||||
# special cases - keep remaing case)
|
||||
if new_word.lower() in CASE_WORD_EXCEPTIONS:
|
||||
result.append(new_word[ind + 1:])
|
||||
result.append(new_word[ind + 1 :])
|
||||
# append any remaining characters from new
|
||||
elif all_upper:
|
||||
result.append(new_word[ind + 1:].upper())
|
||||
result.append(new_word[ind + 1 :].upper())
|
||||
else:
|
||||
result.append(new_word[ind + 1:].lower())
|
||||
result.append(new_word[ind + 1 :].lower())
|
||||
out.append("".join(result))
|
||||
# if we have more new words than old ones, just add them verbatim
|
||||
out.extend([new_word for ind, new_word in enumerate(new_words) if ind >= len(old_words)])
|
||||
|
|
@ -61,45 +62,41 @@ def _case_sensitive_replace(string, old, new):
|
|||
|
||||
def update_typeclasses(apps, schema_editor):
|
||||
|
||||
ObjectDB = apps.get_model('objects', 'ObjectDB')
|
||||
AccountDB = apps.get_model('accounts', 'AccountDB')
|
||||
ScriptDB = apps.get_model('scripts', 'ScriptDB')
|
||||
ChannelDB = apps.get_model('comms', 'ChannelDB')
|
||||
Attributes = apps.get_model('typeclasses', 'Attribute')
|
||||
Tags = apps.get_model('typeclasses', 'Tag')
|
||||
ObjectDB = apps.get_model("objects", "ObjectDB")
|
||||
AccountDB = apps.get_model("accounts", "AccountDB")
|
||||
ScriptDB = apps.get_model("scripts", "ScriptDB")
|
||||
ChannelDB = apps.get_model("comms", "ChannelDB")
|
||||
Attributes = apps.get_model("typeclasses", "Attribute")
|
||||
Tags = apps.get_model("typeclasses", "Tag")
|
||||
|
||||
for obj in ObjectDB.objects.all():
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, 'player', 'account')
|
||||
obj.db_cmdset_storage = _case_sensitive_replace(obj.db_cmdset_storage, 'player', 'account')
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, 'player', 'account')
|
||||
obj.save(update_fields=['db_typeclass_path', 'db_cmdset_storage', 'db_lock_storage'])
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
|
||||
obj.db_cmdset_storage = _case_sensitive_replace(obj.db_cmdset_storage, "player", "account")
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
|
||||
obj.save(update_fields=["db_typeclass_path", "db_cmdset_storage", "db_lock_storage"])
|
||||
for obj in AccountDB.objects.all():
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, 'player', 'account')
|
||||
obj.db_cmdset_storage = _case_sensitive_replace(obj.db_cmdset_storage, 'player', 'account')
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, 'player', 'account')
|
||||
obj.save(update_fields=['db_typeclass_path', 'db_cmdset_storage', 'db_lock_storage'])
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
|
||||
obj.db_cmdset_storage = _case_sensitive_replace(obj.db_cmdset_storage, "player", "account")
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
|
||||
obj.save(update_fields=["db_typeclass_path", "db_cmdset_storage", "db_lock_storage"])
|
||||
for obj in ScriptDB.objects.all():
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, 'player', 'account')
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, 'player', 'account')
|
||||
obj.save(update_fields=['db_typeclass_path', 'db_lock_storage'])
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
|
||||
obj.save(update_fields=["db_typeclass_path", "db_lock_storage"])
|
||||
for obj in ChannelDB.objects.all():
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, 'player', 'account')
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, 'player', 'account')
|
||||
obj.save(update_fields=['db_typeclass_path', 'db_lock_storage'])
|
||||
for obj in Attributes.objects.filter(db_model='playerdb'):
|
||||
obj.db_model = 'accountdb'
|
||||
obj.save(update_fields=['db_model'])
|
||||
for obj in Tags.objects.filter(db_model='playerdb'):
|
||||
obj.db_model = 'accountdb'
|
||||
obj.save(update_fields=['db_model'])
|
||||
obj.db_typeclass_path = _case_sensitive_replace(obj.db_typeclass_path, "player", "account")
|
||||
obj.db_lock_storage = _case_sensitive_replace(obj.db_lock_storage, "player", "account")
|
||||
obj.save(update_fields=["db_typeclass_path", "db_lock_storage"])
|
||||
for obj in Attributes.objects.filter(db_model="playerdb"):
|
||||
obj.db_model = "accountdb"
|
||||
obj.save(update_fields=["db_model"])
|
||||
for obj in Tags.objects.filter(db_model="playerdb"):
|
||||
obj.db_model = "accountdb"
|
||||
obj.save(update_fields=["db_model"])
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0008_lock_and_perm_rename'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0008_lock_and_perm_rename")]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(update_typeclasses),
|
||||
]
|
||||
operations = [migrations.RunPython(update_typeclasses)]
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from django.db import migrations, connection
|
|||
|
||||
_ENGINE = None
|
||||
|
||||
|
||||
def _table_exists(db_cursor, tablename):
|
||||
"Returns bool if table exists or not"
|
||||
return tablename in connection.introspection.table_names()
|
||||
|
|
@ -15,6 +16,7 @@ def _drop_table(db_cursor, table_name):
|
|||
global _ENGINE
|
||||
if not _ENGINE:
|
||||
from django.conf import settings
|
||||
|
||||
try:
|
||||
_ENGINE = settings.DATABASES["default"]["ENGINE"]
|
||||
except KeyError:
|
||||
|
|
@ -47,10 +49,6 @@ def drop_tables(apps, schema_migrator):
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0009_rename_player_cmdsets_typeclasses'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0009_rename_player_cmdsets_typeclasses")]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(drop_tables)
|
||||
]
|
||||
operations = [migrations.RunPython(drop_tables)]
|
||||
|
|
|
|||
|
|
@ -7,104 +7,145 @@ import evennia.utils.picklefield
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0010_delete_old_player_tables'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0010_delete_old_player_tables")]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='DefaultAccount',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DefaultCharacter',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DefaultExit',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DefaultGuest',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DefaultObject',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DefaultRoom',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DefaultScript',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DoNothing',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='ScriptBase',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Store',
|
||||
migrations.DeleteModel(name="DefaultAccount"),
|
||||
migrations.DeleteModel(name="DefaultCharacter"),
|
||||
migrations.DeleteModel(name="DefaultExit"),
|
||||
migrations.DeleteModel(name="DefaultGuest"),
|
||||
migrations.DeleteModel(name="DefaultObject"),
|
||||
migrations.DeleteModel(name="DefaultRoom"),
|
||||
migrations.DeleteModel(name="DefaultScript"),
|
||||
migrations.DeleteModel(name="DoNothing"),
|
||||
migrations.DeleteModel(name="ScriptBase"),
|
||||
migrations.DeleteModel(name="Store"),
|
||||
migrations.AlterField(
|
||||
model_name="attribute",
|
||||
name="db_attrtype",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="Subclass of Attribute (None or nick)",
|
||||
max_length=16,
|
||||
null=True,
|
||||
verbose_name="attrtype",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_attrtype',
|
||||
field=models.CharField(blank=True, db_index=True, help_text='Subclass of Attribute (None or nick)', max_length=16, null=True, verbose_name='attrtype'),
|
||||
model_name="attribute",
|
||||
name="db_category",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="Optional categorization of attribute.",
|
||||
max_length=128,
|
||||
null=True,
|
||||
verbose_name="category",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_category',
|
||||
field=models.CharField(blank=True, db_index=True, help_text='Optional categorization of attribute.', max_length=128, null=True, verbose_name='category'),
|
||||
model_name="attribute",
|
||||
name="db_date_created",
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name="date_created"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_date_created',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='date_created'),
|
||||
model_name="attribute",
|
||||
name="db_key",
|
||||
field=models.CharField(db_index=True, max_length=255, verbose_name="key"),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_key',
|
||||
field=models.CharField(db_index=True, max_length=255, verbose_name='key'),
|
||||
model_name="attribute",
|
||||
name="db_lock_storage",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="Lockstrings for this object are stored here.",
|
||||
verbose_name="locks",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_lock_storage',
|
||||
field=models.TextField(blank=True, help_text='Lockstrings for this object are stored here.', verbose_name='locks'),
|
||||
model_name="attribute",
|
||||
name="db_model",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
help_text="Which model of object this attribute is attached to (A natural key like 'objects.objectdb'). You should not change this value unless you know what you are doing.",
|
||||
max_length=32,
|
||||
null=True,
|
||||
verbose_name="model",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_model',
|
||||
field=models.CharField(blank=True, db_index=True, help_text="Which model of object this attribute is attached to (A natural key like 'objects.objectdb'). You should not change this value unless you know what you are doing.", max_length=32, null=True, verbose_name='model'),
|
||||
model_name="attribute",
|
||||
name="db_strvalue",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="String-specific storage for quick look-up",
|
||||
null=True,
|
||||
verbose_name="strvalue",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_strvalue',
|
||||
field=models.TextField(blank=True, help_text='String-specific storage for quick look-up', null=True, verbose_name='strvalue'),
|
||||
model_name="attribute",
|
||||
name="db_value",
|
||||
field=evennia.utils.picklefield.PickledObjectField(
|
||||
help_text="The data returned when the attribute is accessed. Must be written as a Python literal if editing through the admin interface. Attribute values which are not Python literals cannot be edited through the admin interface.",
|
||||
null=True,
|
||||
verbose_name="value",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='attribute',
|
||||
name='db_value',
|
||||
field=evennia.utils.picklefield.PickledObjectField(help_text='The data returned when the attribute is accessed. Must be written as a Python literal if editing through the admin interface. Attribute values which are not Python literals cannot be edited through the admin interface.', null=True, verbose_name='value'),
|
||||
model_name="tag",
|
||||
name="db_category",
|
||||
field=models.CharField(
|
||||
db_index=True,
|
||||
help_text="tag category",
|
||||
max_length=64,
|
||||
null=True,
|
||||
verbose_name="category",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='db_category',
|
||||
field=models.CharField(db_index=True, help_text='tag category', max_length=64, null=True, verbose_name='category'),
|
||||
model_name="tag",
|
||||
name="db_data",
|
||||
field=models.TextField(
|
||||
blank=True,
|
||||
help_text="optional data field with extra information. This is not searched for.",
|
||||
null=True,
|
||||
verbose_name="data",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='db_data',
|
||||
field=models.TextField(blank=True, help_text='optional data field with extra information. This is not searched for.', null=True, verbose_name='data'),
|
||||
model_name="tag",
|
||||
name="db_key",
|
||||
field=models.CharField(
|
||||
db_index=True,
|
||||
help_text="tag identifier",
|
||||
max_length=255,
|
||||
null=True,
|
||||
verbose_name="key",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='db_key',
|
||||
field=models.CharField(db_index=True, help_text='tag identifier', max_length=255, null=True, verbose_name='key'),
|
||||
model_name="tag",
|
||||
name="db_model",
|
||||
field=models.CharField(
|
||||
db_index=True,
|
||||
help_text="database model to Tag",
|
||||
max_length=32,
|
||||
null=True,
|
||||
verbose_name="model",
|
||||
),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='db_model',
|
||||
field=models.CharField(db_index=True, help_text='database model to Tag', max_length=32, null=True, verbose_name='model'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='tag',
|
||||
name='db_tagtype',
|
||||
field=models.CharField(db_index=True, help_text='overall type of Tag', max_length=16, null=True, verbose_name='tagtype'),
|
||||
model_name="tag",
|
||||
name="db_tagtype",
|
||||
field=models.CharField(
|
||||
db_index=True,
|
||||
help_text="overall type of Tag",
|
||||
max_length=16,
|
||||
null=True,
|
||||
verbose_name="tagtype",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from evennia.utils.utils import to_bytes
|
|||
|
||||
|
||||
def forwards(apps, schema_editor):
|
||||
Attribute = apps.get_model('typeclasses', 'Attribute')
|
||||
Attribute = apps.get_model("typeclasses", "Attribute")
|
||||
for attr in Attribute.objects.all():
|
||||
# we need to re-assign the Attribute it's own value to make sure pickle switches from v2 to v4,
|
||||
# otherwise we will not be able to search db by-value.
|
||||
|
|
@ -19,10 +19,6 @@ def forwards(apps, schema_editor):
|
|||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('typeclasses', '0011_auto_20190128_1820'),
|
||||
]
|
||||
dependencies = [("typeclasses", "0011_auto_20190128_1820")]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forwards, migrations.RunPython.noop),
|
||||
]
|
||||
operations = [migrations.RunPython(forwards, migrations.RunPython.noop)]
|
||||
|
|
|
|||
|
|
@ -44,12 +44,10 @@ from evennia.server.signals import SIGNAL_TYPED_OBJECT_POST_RENAME
|
|||
|
||||
from evennia.typeclasses import managers
|
||||
from evennia.locks.lockhandler import LockHandler
|
||||
from evennia.utils.utils import (
|
||||
is_iter, inherits_from, lazy_property,
|
||||
class_from_module)
|
||||
from evennia.utils.utils import is_iter, inherits_from, lazy_property, class_from_module
|
||||
from evennia.utils.logger import log_trace
|
||||
|
||||
__all__ = ("TypedObject", )
|
||||
__all__ = ("TypedObject",)
|
||||
|
||||
TICKER_HANDLER = None
|
||||
|
||||
|
|
@ -61,6 +59,7 @@ _SA = object.__setattr__
|
|||
|
||||
# signal receivers. Connected in __new__
|
||||
|
||||
|
||||
def call_at_first_save(sender, instance, created, **kwargs):
|
||||
"""
|
||||
Receives a signal just after the object is saved.
|
||||
|
|
@ -107,9 +106,11 @@ class TypeclassBase(SharedMemoryModelBase):
|
|||
|
||||
# typeclass proxy setup
|
||||
if "Meta" not in attrs:
|
||||
|
||||
class Meta(object):
|
||||
proxy = True
|
||||
app_label = attrs.get("__applabel__", "typeclasses")
|
||||
|
||||
attrs["Meta"] = Meta
|
||||
attrs["Meta"].proxy = True
|
||||
|
||||
|
|
@ -124,27 +125,29 @@ class TypeclassBase(SharedMemoryModelBase):
|
|||
class DbHolder(object):
|
||||
"Holder for allowing property access of attributes"
|
||||
|
||||
def __init__(self, obj, name, manager_name='attributes'):
|
||||
def __init__(self, obj, name, manager_name="attributes"):
|
||||
_SA(self, name, _GA(obj, manager_name))
|
||||
_SA(self, 'name', name)
|
||||
_SA(self, "name", name)
|
||||
|
||||
def __getattribute__(self, attrname):
|
||||
if attrname == 'all':
|
||||
if attrname == "all":
|
||||
# we allow to overload our default .all
|
||||
attr = _GA(self, _GA(self, 'name')).get("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)
|
||||
return _GA(self, _GA(self, "name")).get(attrname)
|
||||
|
||||
def __setattr__(self, attrname, value):
|
||||
_GA(self, _GA(self, 'name')).add(attrname, value)
|
||||
_GA(self, _GA(self, "name")).add(attrname, value)
|
||||
|
||||
def __delattr__(self, attrname):
|
||||
_GA(self, _GA(self, 'name')).remove(attrname)
|
||||
_GA(self, _GA(self, "name")).remove(attrname)
|
||||
|
||||
def get_all(self):
|
||||
return _GA(self, _GA(self, 'name')).all()
|
||||
return _GA(self, _GA(self, "name")).all()
|
||||
|
||||
all = property(get_all)
|
||||
|
||||
|
||||
#
|
||||
# Main TypedObject abstraction
|
||||
#
|
||||
|
|
@ -180,21 +183,32 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
# 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)
|
||||
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
|
||||
# typeclass 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.")
|
||||
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)
|
||||
db_date_created = models.DateTimeField("creation date", editable=False, auto_now_add=True)
|
||||
# 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,
|
||||
help_text='attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).')
|
||||
db_tags = models.ManyToManyField(Tag,
|
||||
help_text='tags on this object. Tags are simple string markers to identify, group and alias objects.')
|
||||
db_attributes = models.ManyToManyField(
|
||||
Attribute,
|
||||
help_text="attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).",
|
||||
)
|
||||
db_tags = models.ManyToManyField(
|
||||
Tag,
|
||||
help_text="tags on this object. Tags are simple string markers to identify, group and alias objects.",
|
||||
)
|
||||
|
||||
# Database manager
|
||||
objects = managers.TypedObjectManager()
|
||||
|
|
@ -207,7 +221,9 @@ class TypedObject(SharedMemoryModel):
|
|||
def set_class_from_typeclass(self, typeclass_path=None):
|
||||
if typeclass_path:
|
||||
try:
|
||||
self.__class__ = class_from_module(typeclass_path, defaultpaths=settings.TYPECLASS_PATHS)
|
||||
self.__class__ = class_from_module(
|
||||
typeclass_path, defaultpaths=settings.TYPECLASS_PATHS
|
||||
)
|
||||
except Exception:
|
||||
log_trace()
|
||||
try:
|
||||
|
|
@ -241,7 +257,10 @@ class TypedObject(SharedMemoryModel):
|
|||
self.__class__ = class_from_module("evennia.objects.objects.DefaultObject")
|
||||
self.__dbclass__ = class_from_module("evennia.objects.models.ObjectDB")
|
||||
self.db_typeclass_path = "evennia.objects.objects.DefaultObject"
|
||||
log_trace("Critical: Class %s of %s is not a valid typeclass!\nTemporarily falling back to %s." % (err_class, self, self.__class__))
|
||||
log_trace(
|
||||
"Critical: Class %s of %s is not a valid typeclass!\nTemporarily falling back to %s."
|
||||
% (err_class, self, self.__class__)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
"""
|
||||
|
|
@ -307,9 +326,10 @@ class TypedObject(SharedMemoryModel):
|
|||
"""
|
||||
Django setup info.
|
||||
"""
|
||||
|
||||
abstract = True
|
||||
verbose_name = "Evennia Database Object"
|
||||
ordering = ['-db_date_created', 'id', 'db_typeclass_path', 'db_key']
|
||||
ordering = ["-db_date_created", "id", "db_typeclass_path", "db_key"]
|
||||
|
||||
# wrapper
|
||||
# Wrapper properties to easily set database fields. These are
|
||||
|
|
@ -329,6 +349,7 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
def __name_del(self):
|
||||
raise Exception("Cannot delete name")
|
||||
|
||||
name = property(__name_get, __name_set, __name_del)
|
||||
|
||||
# key property (overrides's the idmapper's db_key for the at_rename hook)
|
||||
|
|
@ -366,7 +387,7 @@ class TypedObject(SharedMemoryModel):
|
|||
def __repr__(self):
|
||||
return "%s" % self.db_key
|
||||
|
||||
#@property
|
||||
# @property
|
||||
def __dbid_get(self):
|
||||
"""
|
||||
Caches and returns the unique id of the object.
|
||||
|
|
@ -379,9 +400,10 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
def __dbid_del(self):
|
||||
raise Exception("dbid cannot be deleted!")
|
||||
|
||||
dbid = property(__dbid_get, __dbid_set, __dbid_del)
|
||||
|
||||
#@property
|
||||
# @property
|
||||
def __dbref_get(self):
|
||||
"""
|
||||
Returns the object's dbref on the form #NN.
|
||||
|
|
@ -393,6 +415,7 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
def __dbref_del(self):
|
||||
raise Exception("dbref cannot be deleted!")
|
||||
|
||||
dbref = property(__dbref_get, __dbref_set, __dbref_del)
|
||||
|
||||
def at_idmapper_flush(self):
|
||||
|
|
@ -455,7 +478,9 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
if isinstance(typeclass, str):
|
||||
typeclass = [typeclass] + ["%s.%s" % (prefix, typeclass) for prefix in settings.TYPECLASS_PATHS]
|
||||
typeclass = [typeclass] + [
|
||||
"%s.%s" % (prefix, typeclass) for prefix in settings.TYPECLASS_PATHS
|
||||
]
|
||||
else:
|
||||
typeclass = [typeclass.path]
|
||||
|
||||
|
|
@ -465,10 +490,18 @@ class TypedObject(SharedMemoryModel):
|
|||
return selfpath in typeclass
|
||||
else:
|
||||
# check parent chain
|
||||
return any(hasattr(cls, "path") and cls.path in typeclass for cls in self.__class__.mro())
|
||||
return any(
|
||||
hasattr(cls, "path") and cls.path in typeclass for cls in self.__class__.mro()
|
||||
)
|
||||
|
||||
def swap_typeclass(self, new_typeclass, clean_attributes=False,
|
||||
run_start_hooks="all", no_default=True, clean_cmdsets=False):
|
||||
def swap_typeclass(
|
||||
self,
|
||||
new_typeclass,
|
||||
clean_attributes=False,
|
||||
run_start_hooks="all",
|
||||
no_default=True,
|
||||
clean_cmdsets=False,
|
||||
):
|
||||
"""
|
||||
This performs an in-situ swap of the typeclass. This means
|
||||
that in-game, this object will suddenly be something else.
|
||||
|
|
@ -513,9 +546,11 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
if inherits_from(self, "evennia.scripts.models.ScriptDB"):
|
||||
if self.interval > 0:
|
||||
raise RuntimeError("Cannot use swap_typeclass on time-dependent "
|
||||
"Script '%s'.\nStop and start a new Script of the "
|
||||
"right type instead." % self.key)
|
||||
raise RuntimeError(
|
||||
"Cannot use swap_typeclass on time-dependent "
|
||||
"Script '%s'.\nStop and start a new Script of the "
|
||||
"right type instead." % self.key
|
||||
)
|
||||
|
||||
self.typeclass_path = new_typeclass.path
|
||||
self.__class__ = new_typeclass
|
||||
|
|
@ -536,7 +571,7 @@ class TypedObject(SharedMemoryModel):
|
|||
self.cmdset.clear()
|
||||
self.cmdset.remove_default()
|
||||
|
||||
if run_start_hooks == 'all':
|
||||
if run_start_hooks == "all":
|
||||
# fake this call to mimic the first save
|
||||
self.at_first_save()
|
||||
elif run_start_hooks:
|
||||
|
|
@ -547,7 +582,9 @@ class TypedObject(SharedMemoryModel):
|
|||
# Lock / permission methods
|
||||
#
|
||||
|
||||
def access(self, accessing_obj, access_type='read', default=False, no_superuser_bypass=False, **kwargs):
|
||||
def access(
|
||||
self, accessing_obj, access_type="read", default=False, no_superuser_bypass=False, **kwargs
|
||||
):
|
||||
"""
|
||||
Determines if another object has permission to access this one.
|
||||
|
||||
|
|
@ -565,8 +602,12 @@ class TypedObject(SharedMemoryModel):
|
|||
use it to feed to its hook methods.
|
||||
|
||||
"""
|
||||
return self.locks.check(accessing_obj, access_type=access_type, default=default,
|
||||
no_superuser_bypass=no_superuser_bypass)
|
||||
return self.locks.check(
|
||||
accessing_obj,
|
||||
access_type=access_type,
|
||||
default=default,
|
||||
no_superuser_bypass=no_superuser_bypass,
|
||||
)
|
||||
|
||||
def check_permstring(self, permstring):
|
||||
"""
|
||||
|
|
@ -581,7 +622,11 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
if hasattr(self, "account"):
|
||||
if self.account and self.account.is_superuser and not self.account.attributes.get("_quell"):
|
||||
if (
|
||||
self.account
|
||||
and self.account.is_superuser
|
||||
and not self.account.attributes.get("_quell")
|
||||
):
|
||||
return True
|
||||
else:
|
||||
if self.is_superuser and not self.attributes.get("_quell"):
|
||||
|
|
@ -597,8 +642,11 @@ class TypedObject(SharedMemoryModel):
|
|||
if perm in _PERMISSION_HIERARCHY:
|
||||
# check if we have a higher hierarchy position
|
||||
ppos = _PERMISSION_HIERARCHY.index(perm)
|
||||
return any(True for hpos, hperm in enumerate(_PERMISSION_HIERARCHY)
|
||||
if hperm in perms and hpos > ppos)
|
||||
return any(
|
||||
True
|
||||
for hpos, hperm in enumerate(_PERMISSION_HIERARCHY)
|
||||
if hperm in perms and hpos > ppos
|
||||
)
|
||||
# we ignore pluralization (english only)
|
||||
if perm.endswith("s"):
|
||||
return self.check_permstring(perm[:-1])
|
||||
|
|
@ -634,7 +682,7 @@ class TypedObject(SharedMemoryModel):
|
|||
# Attribute storage
|
||||
#
|
||||
|
||||
#@property db
|
||||
# @property db
|
||||
def __db_get(self):
|
||||
"""
|
||||
Attribute handler wrapper. Allows for the syntax
|
||||
|
|
@ -650,27 +698,28 @@ class TypedObject(SharedMemoryModel):
|
|||
try:
|
||||
return self._db_holder
|
||||
except AttributeError:
|
||||
self._db_holder = DbHolder(self, 'attributes')
|
||||
self._db_holder = DbHolder(self, "attributes")
|
||||
return self._db_holder
|
||||
|
||||
#@db.setter
|
||||
# @db.setter
|
||||
def __db_set(self, value):
|
||||
"Stop accidentally replacing the db object"
|
||||
string = "Cannot assign directly to db object! "
|
||||
string += "Use db.attr=value instead."
|
||||
raise Exception(string)
|
||||
|
||||
#@db.deleter
|
||||
# @db.deleter
|
||||
def __db_del(self):
|
||||
"Stop accidental deletion."
|
||||
raise Exception("Cannot delete the db object!")
|
||||
|
||||
db = property(__db_get, __db_set, __db_del)
|
||||
|
||||
#
|
||||
# Non-persistent (ndb) storage
|
||||
#
|
||||
|
||||
#@property ndb
|
||||
# @property ndb
|
||||
def __ndb_get(self):
|
||||
"""
|
||||
A non-attr_obj store (ndb: NonDataBase). Everything stored
|
||||
|
|
@ -681,20 +730,21 @@ class TypedObject(SharedMemoryModel):
|
|||
try:
|
||||
return self._ndb_holder
|
||||
except AttributeError:
|
||||
self._ndb_holder = DbHolder(self, "nattrhandler", manager_name='nattributes')
|
||||
self._ndb_holder = DbHolder(self, "nattrhandler", manager_name="nattributes")
|
||||
return self._ndb_holder
|
||||
|
||||
#@db.setter
|
||||
# @db.setter
|
||||
def __ndb_set(self, value):
|
||||
"Stop accidentally replacing the ndb object"
|
||||
string = "Cannot assign directly to ndb object! "
|
||||
string += "Use ndb.attr=value instead."
|
||||
raise Exception(string)
|
||||
|
||||
#@db.deleter
|
||||
# @db.deleter
|
||||
def __ndb_del(self):
|
||||
"Stop accidental deletion."
|
||||
raise Exception("Cannot delete the ndb object!")
|
||||
|
||||
ndb = property(__ndb_get, __ndb_set, __ndb_del)
|
||||
|
||||
def get_display_name(self, looker, **kwargs):
|
||||
|
|
@ -719,7 +769,7 @@ class TypedObject(SharedMemoryModel):
|
|||
builders.
|
||||
|
||||
"""
|
||||
if self.access(looker, access_type='controls'):
|
||||
if self.access(looker, access_type="controls"):
|
||||
return "{}(#{})".format(self.name, self.id)
|
||||
return self.name
|
||||
|
||||
|
|
@ -773,8 +823,9 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
content_type = ContentType.objects.get_for_model(self.__class__)
|
||||
return reverse("admin:%s_%s_change" % (content_type.app_label,
|
||||
content_type.model), args=(self.id,))
|
||||
return reverse(
|
||||
"admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def web_get_create_url(cls):
|
||||
|
|
@ -803,9 +854,9 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
try:
|
||||
return reverse('%s-create' % slugify(cls._meta.verbose_name))
|
||||
return reverse("%s-create" % slugify(cls._meta.verbose_name))
|
||||
except:
|
||||
return '#'
|
||||
return "#"
|
||||
|
||||
def web_get_detail_url(self):
|
||||
"""
|
||||
|
|
@ -834,10 +885,12 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
try:
|
||||
return reverse('%s-detail' % slugify(self._meta.verbose_name),
|
||||
kwargs={'pk': self.pk, 'slug': slugify(self.name)})
|
||||
return reverse(
|
||||
"%s-detail" % slugify(self._meta.verbose_name),
|
||||
kwargs={"pk": self.pk, "slug": slugify(self.name)},
|
||||
)
|
||||
except:
|
||||
return '#'
|
||||
return "#"
|
||||
|
||||
def web_get_puppet_url(self):
|
||||
"""
|
||||
|
|
@ -866,10 +919,12 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
try:
|
||||
return reverse('%s-puppet' % slugify(self._meta.verbose_name),
|
||||
kwargs={'pk': self.pk, 'slug': slugify(self.name)})
|
||||
return reverse(
|
||||
"%s-puppet" % slugify(self._meta.verbose_name),
|
||||
kwargs={"pk": self.pk, "slug": slugify(self.name)},
|
||||
)
|
||||
except:
|
||||
return '#'
|
||||
return "#"
|
||||
|
||||
def web_get_update_url(self):
|
||||
"""
|
||||
|
|
@ -898,10 +953,12 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
try:
|
||||
return reverse('%s-update' % slugify(self._meta.verbose_name),
|
||||
kwargs={'pk': self.pk, 'slug': slugify(self.name)})
|
||||
return reverse(
|
||||
"%s-update" % slugify(self._meta.verbose_name),
|
||||
kwargs={"pk": self.pk, "slug": slugify(self.name)},
|
||||
)
|
||||
except:
|
||||
return '#'
|
||||
return "#"
|
||||
|
||||
def web_get_delete_url(self):
|
||||
"""
|
||||
|
|
@ -929,10 +986,12 @@ class TypedObject(SharedMemoryModel):
|
|||
|
||||
"""
|
||||
try:
|
||||
return reverse('%s-delete' % slugify(self._meta.verbose_name),
|
||||
kwargs={'pk': self.pk, 'slug': slugify(self.name)})
|
||||
return reverse(
|
||||
"%s-delete" % slugify(self._meta.verbose_name),
|
||||
kwargs={"pk": self.pk, "slug": slugify(self.name)},
|
||||
)
|
||||
except:
|
||||
return '#'
|
||||
return "#"
|
||||
|
||||
# Used by Django Sites/Admin
|
||||
get_absolute_url = web_get_detail_url
|
||||
|
|
|
|||
|
|
@ -18,11 +18,11 @@ from evennia.utils.utils import to_str, make_iter
|
|||
|
||||
_TYPECLASS_AGGRESSIVE_CACHE = settings.TYPECLASS_AGGRESSIVE_CACHE
|
||||
|
||||
#------------------------------------------------------------
|
||||
# ------------------------------------------------------------
|
||||
#
|
||||
# Tags
|
||||
#
|
||||
#------------------------------------------------------------
|
||||
# ------------------------------------------------------------
|
||||
|
||||
|
||||
class Tag(models.Model):
|
||||
|
|
@ -48,40 +48,55 @@ class Tag(models.Model):
|
|||
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_index=True)
|
||||
db_category = models.CharField('category', max_length=64, null=True,
|
||||
help_text="tag category", db_index=True)
|
||||
db_data = models.TextField('data', null=True, blank=True,
|
||||
help_text="optional data field with extra information. This is not searched for.")
|
||||
|
||||
db_key = models.CharField(
|
||||
"key", max_length=255, null=True, help_text="tag identifier", db_index=True
|
||||
)
|
||||
db_category = models.CharField(
|
||||
"category", max_length=64, null=True, help_text="tag category", db_index=True
|
||||
)
|
||||
db_data = models.TextField(
|
||||
"data",
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text="optional data field with extra information. This is not searched for.",
|
||||
)
|
||||
# this is "objectdb" etc. Required behind the scenes
|
||||
db_model = models.CharField('model', max_length=32, null=True, help_text="database model to Tag", db_index=True)
|
||||
db_model = models.CharField(
|
||||
"model", max_length=32, null=True, help_text="database model to Tag", db_index=True
|
||||
)
|
||||
# this is None, alias or permission
|
||||
db_tagtype = models.CharField('tagtype', max_length=16, null=True, help_text="overall type of Tag", db_index=True)
|
||||
db_tagtype = models.CharField(
|
||||
"tagtype", max_length=16, null=True, help_text="overall type of Tag", db_index=True
|
||||
)
|
||||
|
||||
class Meta(object):
|
||||
"Define Django meta options"
|
||||
verbose_name = "Tag"
|
||||
unique_together = (('db_key', 'db_category', 'db_tagtype', 'db_model'),)
|
||||
index_together = (('db_key', 'db_category', 'db_tagtype', 'db_model'),)
|
||||
unique_together = (("db_key", "db_category", "db_tagtype", "db_model"),)
|
||||
index_together = (("db_key", "db_category", "db_tagtype", "db_model"),)
|
||||
|
||||
def __lt__(self, other):
|
||||
return str(self) < str(other)
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return str("<Tag: %s%s>" % (self.db_key, "(category:%s)" % self.db_category if self.db_category else ""))
|
||||
return str(
|
||||
"<Tag: %s%s>"
|
||||
% (self.db_key, "(category:%s)" % self.db_category if self.db_category else "")
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Handlers making use of the Tags model
|
||||
#
|
||||
|
||||
|
||||
class TagHandler(object):
|
||||
"""
|
||||
Generic tag-handler. Accessed via TypedObject.tags.
|
||||
|
||||
"""
|
||||
|
||||
_m2m_fieldname = "db_tags"
|
||||
_tagtype = None
|
||||
|
||||
|
|
@ -106,13 +121,26 @@ class TagHandler(object):
|
|||
|
||||
def _fullcache(self):
|
||||
"Cache all tags of this object"
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype}
|
||||
tags = [conn.tag for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)]
|
||||
self._cache = dict(("%s-%s" % (to_str(tag.db_key).lower(),
|
||||
tag.db_category.lower() if tag.db_category else None),
|
||||
tag) for tag in tags)
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype,
|
||||
}
|
||||
tags = [
|
||||
conn.tag
|
||||
for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)
|
||||
]
|
||||
self._cache = dict(
|
||||
(
|
||||
"%s-%s"
|
||||
% (
|
||||
to_str(tag.db_key).lower(),
|
||||
tag.db_category.lower() if tag.db_category else None,
|
||||
),
|
||||
tag,
|
||||
)
|
||||
for tag in tags
|
||||
)
|
||||
self._cache_complete = True
|
||||
|
||||
def _getcache(self, key=None, category=None):
|
||||
|
|
@ -150,11 +178,13 @@ class TagHandler(object):
|
|||
if tag:
|
||||
return [tag] # return cached entity
|
||||
else:
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype,
|
||||
"tag__db_key__iexact": key.lower(),
|
||||
"tag__db_category__iexact": category.lower() if category else None}
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype,
|
||||
"tag__db_key__iexact": key.lower(),
|
||||
"tag__db_category__iexact": category.lower() if category else None,
|
||||
}
|
||||
conn = getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query)
|
||||
if conn:
|
||||
tag = conn[0].tag
|
||||
|
|
@ -169,12 +199,18 @@ class TagHandler(object):
|
|||
return [tag for key, tag in self._cache.items() if key.endswith(catkey)]
|
||||
else:
|
||||
# we have to query to make this category up-date in the cache
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype,
|
||||
"tag__db_category__iexact": category.lower() if category else None}
|
||||
tags = [conn.tag for conn in getattr(self.obj,
|
||||
self._m2m_fieldname).through.objects.filter(**query)]
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype,
|
||||
"tag__db_category__iexact": category.lower() if category else None,
|
||||
}
|
||||
tags = [
|
||||
conn.tag
|
||||
for conn in getattr(self.obj, self._m2m_fieldname).through.objects.filter(
|
||||
**query
|
||||
)
|
||||
]
|
||||
for tag in tags:
|
||||
cachekey = "%s-%s" % (tag.db_key, category)
|
||||
self._cache[cachekey] = tag
|
||||
|
|
@ -262,8 +298,9 @@ class TagHandler(object):
|
|||
# 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 = self.obj.__class__.objects.create_tag(key=tagstr, category=category, data=data,
|
||||
tagtype=self._tagtype)
|
||||
tagobj = self.obj.__class__.objects.create_tag(
|
||||
key=tagstr, category=category, data=data, tagtype=self._tagtype
|
||||
)
|
||||
getattr(self.obj, self._m2m_fieldname).add(tagobj)
|
||||
self._setcache(tagstr, category, tagobj)
|
||||
|
||||
|
|
@ -293,8 +330,12 @@ class TagHandler(object):
|
|||
ret = []
|
||||
for keystr in make_iter(key):
|
||||
# note - the _getcache call removes case sensitivity for us
|
||||
ret.extend([tag if return_tagobj else to_str(tag.db_key)
|
||||
for tag in self._getcache(keystr, category)])
|
||||
ret.extend(
|
||||
[
|
||||
tag if return_tagobj else to_str(tag.db_key)
|
||||
for tag in self._getcache(keystr, category)
|
||||
]
|
||||
)
|
||||
if return_list:
|
||||
return ret if ret else [default] if default is not None else []
|
||||
return ret[0] if len(ret) == 1 else (ret if ret else default)
|
||||
|
|
@ -328,9 +369,8 @@ class TagHandler(object):
|
|||
# that when no objects reference the tag anymore (but how to check)?
|
||||
# For now, tags are never deleted, only their connection to objects.
|
||||
tagobj = getattr(self.obj, self._m2m_fieldname).filter(
|
||||
db_key=tagstr, db_category=category,
|
||||
db_model=self._model,
|
||||
db_tagtype=self._tagtype)
|
||||
db_key=tagstr, db_category=category, db_model=self._model, db_tagtype=self._tagtype
|
||||
)
|
||||
if tagobj:
|
||||
getattr(self.obj, self._m2m_fieldname).remove(tagobj[0])
|
||||
self._delcache(key, category)
|
||||
|
|
@ -347,9 +387,11 @@ class TagHandler(object):
|
|||
"""
|
||||
if not self._cache_complete:
|
||||
self._fullcache()
|
||||
query = {"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype}
|
||||
query = {
|
||||
"%s__id" % self._model: self._objid,
|
||||
"tag__db_model": self._model,
|
||||
"tag__db_tagtype": self._tagtype,
|
||||
}
|
||||
if category:
|
||||
query["tag__db_category"] = category.strip().lower()
|
||||
getattr(self.obj, self._m2m_fieldname).through.objects.filter(**query).delete()
|
||||
|
|
@ -376,7 +418,7 @@ class TagHandler(object):
|
|||
self._fullcache()
|
||||
tags = sorted(self._cache.values())
|
||||
if return_key_and_category:
|
||||
# return tuple (key, category)
|
||||
# return tuple (key, category)
|
||||
return [(to_str(tag.db_key), tag.db_category) for tag in tags]
|
||||
elif return_objs:
|
||||
return tags
|
||||
|
|
@ -422,6 +464,7 @@ class AliasHandler(TagHandler):
|
|||
A handler for the Alias Tag type.
|
||||
|
||||
"""
|
||||
|
||||
_tagtype = "alias"
|
||||
|
||||
|
||||
|
|
@ -430,4 +473,5 @@ class PermissionHandler(TagHandler):
|
|||
A handler for the Permission Tag type.
|
||||
|
||||
"""
|
||||
|
||||
_tagtype = "permission"
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@ from evennia.utils.test_resources import EvenniaTest
|
|||
|
||||
class TestAttributes(EvenniaTest):
|
||||
def test_attrhandler(self):
|
||||
key = 'testattr'
|
||||
value = 'test attr value '
|
||||
key = "testattr"
|
||||
value = "test attr value "
|
||||
self.obj1.attributes.add(key, value)
|
||||
self.assertEqual(self.obj1.attributes.get(key), value)
|
||||
self.obj1.db.testattr = value
|
||||
|
|
@ -22,13 +22,13 @@ class TestAttributes(EvenniaTest):
|
|||
def test_weird_text_save(self):
|
||||
"test 'weird' text type (different in py2 vs py3)"
|
||||
from django.utils.safestring import SafeText
|
||||
key = 'test attr 2'
|
||||
value = SafeText('test attr value 2')
|
||||
|
||||
key = "test attr 2"
|
||||
value = SafeText("test attr value 2")
|
||||
self.obj1.attributes.add(key, value)
|
||||
self.assertEqual(self.obj1.attributes.get(key), value)
|
||||
|
||||
|
||||
|
||||
class TestTypedObjectManager(EvenniaTest):
|
||||
def _manager(self, methodname, *args, **kwargs):
|
||||
return list(getattr(self.obj1.__class__.objects, methodname)(*args, **kwargs))
|
||||
|
|
@ -53,7 +53,7 @@ class TestTypedObjectManager(EvenniaTest):
|
|||
|
||||
def test_get_by_tag_and_category(self):
|
||||
self.obj1.tags.add("tag5", "category1")
|
||||
self.obj1.tags.add("tag6", )
|
||||
self.obj1.tags.add("tag6")
|
||||
self.obj1.tags.add("tag7", "category1")
|
||||
self.obj1.tags.add("tag6", "category3")
|
||||
self.obj1.tags.add("tag7", "category4")
|
||||
|
|
@ -65,14 +65,19 @@ class TestTypedObjectManager(EvenniaTest):
|
|||
self.assertEqual(self._manager("get_by_tag", "tag5", "category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", "tag6", "category1"), [])
|
||||
self.assertEqual(self._manager("get_by_tag", "tag6", "category3"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag5", "tag6"],
|
||||
["category1", "category3"]), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", ["tag5", "tag7"],
|
||||
"category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag5", "tag6"], ["category1", "category3"]),
|
||||
[self.obj1, self.obj2],
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", ["tag5", "tag7"], "category1"), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", category="category1"), [self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category="category2"), [self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category=["category1", "category3"]),
|
||||
[self.obj1, self.obj2])
|
||||
self.assertEqual(self._manager("get_by_tag", category=["category1", "category2"]),
|
||||
[self.obj2])
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category1", "category3"]), [self.obj1, self.obj2]
|
||||
)
|
||||
self.assertEqual(
|
||||
self._manager("get_by_tag", category=["category1", "category2"]), [self.obj2]
|
||||
)
|
||||
self.assertEqual(self._manager("get_by_tag", category=["category5", "category4"]), [])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue