Resolve merge conflicts
This commit is contained in:
commit
74b73c69f9
3 changed files with 64 additions and 29 deletions
|
|
@ -10,7 +10,7 @@
|
||||||
- New `utils.format_grid` for easily displaying long lists of items in a block.
|
- New `utils.format_grid` for easily displaying long lists of items in a block.
|
||||||
- Using `lunr` search indexing for better `help` matching and suggestions. Also improve
|
- Using `lunr` search indexing for better `help` matching and suggestions. Also improve
|
||||||
the main help command's default listing output.
|
the main help command's default listing output.
|
||||||
|
- Added `content_types` indexing to DefaultObject's ContentsHandler. (volund)
|
||||||
|
|
||||||
### Already in master
|
### Already in master
|
||||||
- `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False
|
- `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ Attributes are separate objects that store values persistently onto
|
||||||
the database object. Like everything else, they can be accessed
|
the database object. Like everything else, they can be accessed
|
||||||
transparently through the decorating TypeClass.
|
transparently through the decorating TypeClass.
|
||||||
"""
|
"""
|
||||||
|
from collections import defaultdict
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
@ -42,34 +43,49 @@ class ContentsHandler(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
self._pkcache = {}
|
self._pkcache = set()
|
||||||
self._idcache = obj.__class__.__instance_cache__
|
self._idcache = obj.__class__.__instance_cache__
|
||||||
|
self._typecache = defaultdict(set)
|
||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
"""
|
||||||
|
Retrieves all objects from database. Used for initializing.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Objects (list of ObjectDB)
|
||||||
|
"""
|
||||||
|
return list(self.obj.locations_set.all())
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
"""
|
"""
|
||||||
Re-initialize the content cache
|
Re-initialize the content cache
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._pkcache.update(
|
objects = self.load()
|
||||||
dict((obj.pk, None) for obj in ObjectDB.objects.filter(db_location=self.obj) if obj.pk)
|
self._pkcache = {obj.pk for obj in objects}
|
||||||
)
|
for obj in objects:
|
||||||
|
for ctype in obj._content_types:
|
||||||
|
self._typecache[ctype].add(obj.pk)
|
||||||
|
|
||||||
def get(self, exclude=None):
|
def get(self, exclude=None, content_type=None):
|
||||||
"""
|
"""
|
||||||
Return the contents of the cache.
|
Return the contents of the cache.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
exclude (Object or list of Object): object(s) to ignore
|
exclude (Object or list of Object): object(s) to ignore
|
||||||
|
content_type (str or None): Filter list by a content-type. If None, don't filter.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
objects (list): the Objects inside this location
|
objects (list): the Objects inside this location
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if exclude:
|
if content_type is not None:
|
||||||
pks = [pk for pk in self._pkcache if pk not in [excl.pk for excl in make_iter(exclude)]]
|
pks = self._typecache[content_type]
|
||||||
else:
|
else:
|
||||||
pks = self._pkcache
|
pks = self._pkcache
|
||||||
|
if exclude:
|
||||||
|
pks = pks - {excl.pk for excl in make_iter(exclude)}
|
||||||
try:
|
try:
|
||||||
return [self._idcache[pk] for pk in pks]
|
return [self._idcache[pk] for pk in pks]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
@ -81,7 +97,7 @@ class ContentsHandler(object):
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# this means an actual failure of caching. Return real database match.
|
# this means an actual failure of caching. Return real database match.
|
||||||
logger.log_err("contents cache failed for %s." % self.obj.key)
|
logger.log_err("contents cache failed for %s." % self.obj.key)
|
||||||
return list(ObjectDB.objects.filter(db_location=self.obj))
|
return self.load()
|
||||||
|
|
||||||
def add(self, obj):
|
def add(self, obj):
|
||||||
"""
|
"""
|
||||||
|
|
@ -91,7 +107,9 @@ class ContentsHandler(object):
|
||||||
obj (Object): object to add
|
obj (Object): object to add
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._pkcache[obj.pk] = None
|
self._pkcache.add(obj.pk)
|
||||||
|
for ctype in obj._content_types:
|
||||||
|
self._typecache[ctype].add(obj.pk)
|
||||||
|
|
||||||
def remove(self, obj):
|
def remove(self, obj):
|
||||||
"""
|
"""
|
||||||
|
|
@ -101,7 +119,10 @@ class ContentsHandler(object):
|
||||||
obj (Object): object to remove
|
obj (Object): object to remove
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._pkcache.pop(obj.pk, None)
|
self._pkcache.remove(obj.pk)
|
||||||
|
for ctype in obj._content_types:
|
||||||
|
if obj.pk in self._typecache[ctype]:
|
||||||
|
self._typecache[ctype].remove(obj.pk)
|
||||||
|
|
||||||
def clear(self):
|
def clear(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -109,6 +130,7 @@ class ContentsHandler(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self._pkcache = {}
|
self._pkcache = {}
|
||||||
|
self._typecache = defaultdict(set)
|
||||||
self.init()
|
self.init()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,8 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
without `obj.save()` having to be called explicitly.
|
without `obj.save()` having to be called explicitly.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# Used for sorting / filtering in inventories / room contents.
|
||||||
|
_content_types = ("object",)
|
||||||
|
|
||||||
# lockstring of newly created objects, for easy overloading.
|
# lockstring of newly created objects, for easy overloading.
|
||||||
# Will be formatted with the appropriate attributes.
|
# Will be formatted with the appropriate attributes.
|
||||||
|
|
@ -257,7 +259,7 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
and not self.db_account.attributes.get("_quell")
|
and not self.db_account.attributes.get("_quell")
|
||||||
)
|
)
|
||||||
|
|
||||||
def contents_get(self, exclude=None):
|
def contents_get(self, exclude=None, content_type=None):
|
||||||
"""
|
"""
|
||||||
Returns the contents of this object, i.e. all
|
Returns the contents of this object, i.e. all
|
||||||
objects that has this object set as its location.
|
objects that has this object set as its location.
|
||||||
|
|
@ -266,17 +268,18 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
Args:
|
Args:
|
||||||
exclude (Object): Object to exclude from returned
|
exclude (Object): Object to exclude from returned
|
||||||
contents list
|
contents list
|
||||||
|
content_type (str): A content_type to filter by. None for no
|
||||||
|
filtering.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
contents (list): List of contents of this Object.
|
contents (list): List of contents of this Object.
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
Also available as the `contents` property.
|
Also available as the `contents` property, minus exclusion
|
||||||
|
and filtering.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
con = self.contents_cache.get(exclude=exclude)
|
return self.contents_cache.get(exclude=exclude, content_type=content_type)
|
||||||
# print "contents_get:", self, con, id(self), calledby() # DEBUG
|
|
||||||
return con
|
|
||||||
|
|
||||||
def contents_set(self, *args):
|
def contents_set(self, *args):
|
||||||
"You cannot replace this property"
|
"You cannot replace this property"
|
||||||
|
|
@ -1656,20 +1659,25 @@ class DefaultObject(ObjectDB, metaclass=TypeclassBase):
|
||||||
**kwargs (dict): Arbitrary, optional arguments for users
|
**kwargs (dict): Arbitrary, optional arguments for users
|
||||||
overriding the call (unused by default).
|
overriding the call (unused by default).
|
||||||
"""
|
"""
|
||||||
|
def filter_visible(obj_list):
|
||||||
|
# Helper method to determine if objects are visible to the looker.
|
||||||
|
return [obj for obj in obj_list if obj != looker and obj.access(looker, "view")]
|
||||||
|
|
||||||
if not looker:
|
if not looker:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# get and identify all objects
|
# get and identify all objects
|
||||||
visible = (con for con in self.contents if con != looker and con.access(looker, "view"))
|
exits_list = filter_visible(self.contents_get(content_type='exit'))
|
||||||
exits, users, things = [], [], defaultdict(list)
|
users_list = filter_visible(self.contents_get(content_type='character'))
|
||||||
for con in visible:
|
things_list = filter_visible(self.contents_get(content_type="object"))
|
||||||
key = con.get_display_name(looker)
|
|
||||||
if con.destination:
|
things = defaultdict(list)
|
||||||
exits.append(key)
|
|
||||||
elif con.has_account:
|
for thing in things_list:
|
||||||
users.append("|c%s|n" % key)
|
things[thing.key].append(thing)
|
||||||
else:
|
users = [f"|c{user.key}|n" for user in users_list]
|
||||||
# things can be pluralized
|
exits = [ex.key for ex in exits_list]
|
||||||
things[key].append(con)
|
|
||||||
# get description, build string
|
# get description, build string
|
||||||
string = "|c%s|n\n" % self.get_display_name(looker)
|
string = "|c%s|n\n" % self.get_display_name(looker)
|
||||||
desc = self.db.desc
|
desc = self.db.desc
|
||||||
|
|
@ -2026,7 +2034,9 @@ class DefaultCharacter(DefaultObject):
|
||||||
a character avatar controlled by an account.
|
a character avatar controlled by an account.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# Tuple of types used for indexing inventory contents. Characters generally wouldn't be in
|
||||||
|
# anyone's inventory, but this also governs displays in room contents.
|
||||||
|
_content_types = ("character",)
|
||||||
# lockstring of newly created rooms, for easy overloading.
|
# lockstring of newly created rooms, for easy overloading.
|
||||||
# Will be formatted with the appropriate attributes.
|
# Will be formatted with the appropriate attributes.
|
||||||
lockstring = "puppet:id({character_id}) or pid({account_id}) or perm(Developer) or pperm(Developer);delete:id({account_id}) or perm(Admin)"
|
lockstring = "puppet:id({character_id}) or pid({account_id}) or perm(Developer) or pperm(Developer);delete:id({account_id}) or perm(Admin)"
|
||||||
|
|
@ -2278,6 +2288,9 @@ class DefaultRoom(DefaultObject):
|
||||||
This is the base room object. It's just like any Object except its
|
This is the base room object. It's just like any Object except its
|
||||||
location is always `None`.
|
location is always `None`.
|
||||||
"""
|
"""
|
||||||
|
# A tuple of strings used for indexing this object inside an inventory.
|
||||||
|
# Generally, a room isn't expected to HAVE a location, but maybe in some games?
|
||||||
|
_content_types = ("room",)
|
||||||
|
|
||||||
# lockstring of newly created rooms, for easy overloading.
|
# lockstring of newly created rooms, for easy overloading.
|
||||||
# Will be formatted with the {id} of the creating object.
|
# Will be formatted with the {id} of the creating object.
|
||||||
|
|
@ -2428,7 +2441,7 @@ class DefaultExit(DefaultObject):
|
||||||
exits simply by giving the exit-object's name on its own.
|
exits simply by giving the exit-object's name on its own.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
_content_types = ("exit",)
|
||||||
exit_command = ExitCommand
|
exit_command = ExitCommand
|
||||||
priority = 101
|
priority = 101
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue