Made the rpsystem contrib search handle objects both with- and without sdescs, also allowed to recog objects without a recog handler of their own. Resolves #987.
This commit is contained in:
parent
fd5ed02d7a
commit
674a475786
1 changed files with 52 additions and 29 deletions
|
|
@ -218,6 +218,27 @@ def ordered_permutation_regex(sentence):
|
||||||
regex = r"|".join(sorted(set(solution), key=lambda o:len(o), reverse=True))
|
regex = r"|".join(sorted(set(solution), key=lambda o:len(o), reverse=True))
|
||||||
return regex
|
return regex
|
||||||
|
|
||||||
|
def regex_tuple_from_key_alias(obj):
|
||||||
|
"""
|
||||||
|
This will build a regex tuple for any object, not just from those
|
||||||
|
with sdesc/recog handlers. It's used as a legacy mechanism for
|
||||||
|
being able to mix this contrib with objects not using sdescs, but
|
||||||
|
note that creating the ordered permutation regex dynamically for
|
||||||
|
every object will add computational overhead.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj (Object): This object's key and eventual aliases will
|
||||||
|
be used to build the tuple.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
regex_tuple (tuple): A tuple
|
||||||
|
(ordered_permutation_regex, obj, key/alias)
|
||||||
|
|
||||||
|
"""
|
||||||
|
return (re.compile(r"/%s|%s" % (obj.key, "|".join("/%s" % obj for obj in obj.aliases.all())), _RE_FLAGS),
|
||||||
|
obj,
|
||||||
|
obj.key)
|
||||||
|
|
||||||
|
|
||||||
def parse_language(speaker, emote):
|
def parse_language(speaker, emote):
|
||||||
"""
|
"""
|
||||||
|
|
@ -316,10 +337,13 @@ def parse_sdescs_and_recogs(sender, candidates, string, search_mode=False):
|
||||||
# Load all candidate regex tuples [(regex, obj, sdesc/recog),...]
|
# Load all candidate regex tuples [(regex, obj, sdesc/recog),...]
|
||||||
candidate_regexes = \
|
candidate_regexes = \
|
||||||
[(_RE_SELF_REF, sender, sender.sdesc.get())] + \
|
[(_RE_SELF_REF, sender, sender.sdesc.get())] + \
|
||||||
[sender.recog.get_regex_tuple(obj)
|
[sender.recog.get_regex_tuple(obj) for obj in candidates] + \
|
||||||
for obj in candidates if hasattr(obj, "recog")] + \
|
[obj.sdesc.get_regex_tuple()
|
||||||
[obj.sdesc.get_regex_tuple()
|
for obj in candidates if hasattr(obj, "sdesc")] + \
|
||||||
for obj in candidates if hasattr(obj, "sdesc")]
|
[regex_tuple_from_key_alias(obj) # handle objects without sdescs
|
||||||
|
for obj in candidates if not (hasattr(obj, "recog") and
|
||||||
|
hasattr(obj, "sdesc"))]
|
||||||
|
|
||||||
# filter out non-found data
|
# filter out non-found data
|
||||||
candidate_regexes = [tup for tup in candidate_regexes if tup]
|
candidate_regexes = [tup for tup in candidate_regexes if tup]
|
||||||
|
|
||||||
|
|
@ -495,6 +519,12 @@ class SdescHandler(object):
|
||||||
need to use this since we do a lot preparations on
|
need to use this since we do a lot preparations on
|
||||||
sdescs when updating them, in order for them to be
|
sdescs when updating them, in order for them to be
|
||||||
efficient to search for and query.
|
efficient to search for and query.
|
||||||
|
|
||||||
|
The handler stores data in the following Attributes
|
||||||
|
|
||||||
|
_sdesc - a string
|
||||||
|
_regex - an empty dictionary
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
"""
|
"""
|
||||||
|
|
@ -580,6 +610,13 @@ class RecogHandler(object):
|
||||||
This handler manages the recognition mapping
|
This handler manages the recognition mapping
|
||||||
of an Object.
|
of an Object.
|
||||||
|
|
||||||
|
The handler stores data in Attributes as dictionaries of
|
||||||
|
the following names:
|
||||||
|
|
||||||
|
_recog_ref2recog
|
||||||
|
_recog_obj2recog
|
||||||
|
_recog_obj2regex
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def __init__(self, obj):
|
def __init__(self, obj):
|
||||||
"""
|
"""
|
||||||
|
|
@ -642,10 +679,10 @@ class RecogHandler(object):
|
||||||
|
|
||||||
# mapping #dbref:obj
|
# mapping #dbref:obj
|
||||||
key = "#%i" % obj.id
|
key = "#%i" % obj.id
|
||||||
self.obj.db._recog_ref2recog[key] = recog
|
self.obj.attributes.get("_recog_ref2recog", default={})[key] = recog
|
||||||
self.obj.db._recog_obj2recog[obj] = recog
|
self.obj.attributes.get("_recog_obj2recog", default={})[obj] = recog
|
||||||
regex = ordered_permutation_regex(cleaned_recog)
|
regex = ordered_permutation_regex(cleaned_recog)
|
||||||
self.obj.db._recog_obj2regex[obj] = regex
|
self.obj.attributes.get("_recog_obj2regex", default={})[obj] = regex
|
||||||
# local caching
|
# local caching
|
||||||
self.ref2recog[key] = recog
|
self.ref2recog[key] = recog
|
||||||
self.obj2recog[obj] = recog
|
self.obj2recog[obj] = recog
|
||||||
|
|
@ -879,6 +916,7 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
recog sdesc as alias
|
recog sdesc as alias
|
||||||
|
forget alias
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
recog tall man as Griatch
|
recog tall man as Griatch
|
||||||
|
|
@ -896,8 +934,11 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
|
||||||
if "as" in self.args:
|
if "as" in self.args:
|
||||||
self.sdesc, self.alias = [part.strip() for part in self.args.split(" as ", 2)]
|
self.sdesc, self.alias = [part.strip() for part in self.args.split(" as ", 2)]
|
||||||
elif self.args:
|
elif self.args:
|
||||||
self.sdesc = self.args.strip()
|
# try to split by space instead
|
||||||
self.alias = ""
|
try:
|
||||||
|
self.sdesc, self.alias = [part.strip() for part in self.args.split(None, 1)]
|
||||||
|
except ValueError:
|
||||||
|
self.args = ""
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
"Assign the recog"
|
"Assign the recog"
|
||||||
|
|
@ -935,6 +976,7 @@ class CmdRecog(RPCommand): # assign personal alias to object in room
|
||||||
alias = caller.recog.add(obj, alias)
|
alias = caller.recog.add(obj, alias)
|
||||||
caller.msg("%s will now remember {w%s{n as {w%s{n." % (caller.key, sdesc, alias))
|
caller.msg("%s will now remember {w%s{n as {w%s{n." % (caller.key, sdesc, alias))
|
||||||
|
|
||||||
|
|
||||||
class CmdMask(RPCommand):
|
class CmdMask(RPCommand):
|
||||||
"""
|
"""
|
||||||
Wear a mask
|
Wear a mask
|
||||||
|
|
@ -1014,7 +1056,6 @@ class ContribRPObject(DefaultObject):
|
||||||
self.db.pose = ""
|
self.db.pose = ""
|
||||||
self.db.pose_default = "is here."
|
self.db.pose_default = "is here."
|
||||||
|
|
||||||
|
|
||||||
def search(self, searchdata, **kwargs):
|
def search(self, searchdata, **kwargs):
|
||||||
"""
|
"""
|
||||||
This version of search will pre-parse searchdata for eventual
|
This version of search will pre-parse searchdata for eventual
|
||||||
|
|
@ -1041,7 +1082,7 @@ class ContribRPObject(DefaultObject):
|
||||||
return [self] if "quiet" in kwargs else self
|
return [self] if "quiet" in kwargs else self
|
||||||
|
|
||||||
# sdesc/recog matching
|
# sdesc/recog matching
|
||||||
candidates = self.location.contents
|
candidates = self.location.contents + self.contents
|
||||||
matches = parse_sdescs_and_recogs(self, candidates,
|
matches = parse_sdescs_and_recogs(self, candidates,
|
||||||
_PREFIX + searchdata, search_mode=True)
|
_PREFIX + searchdata, search_mode=True)
|
||||||
nmatches = len(matches)
|
nmatches = len(matches)
|
||||||
|
|
@ -1055,24 +1096,6 @@ class ContribRPObject(DefaultObject):
|
||||||
self.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=searchdata,reflist="\n ".join(reflist)))
|
self.msg(_EMOTE_MULTIMATCH_ERROR.format(ref=searchdata,reflist="\n ".join(reflist)))
|
||||||
return
|
return
|
||||||
|
|
||||||
# patch to handle objects without sdesc (when merging this contrib with a generic
|
|
||||||
# set of objects). Such objects are identified by key anyway and should thus not
|
|
||||||
# be any problem to use the
|
|
||||||
candidates_no_sdesc = [candidate for candidate in candidates if not hasattr(candidate, "sdesc")]
|
|
||||||
if candidates_no_sdesc:
|
|
||||||
# We have some candidates lacking sdesc - since those will fallback to the key
|
|
||||||
# field anyway, we'll allow this search to escalate to the parent
|
|
||||||
kwargs["candidates"] = candidates_no_sdesc
|
|
||||||
match = super(ContribRPObject, self).search(searchdata, **kwargs)
|
|
||||||
if match:
|
|
||||||
# a unique match - return
|
|
||||||
return match
|
|
||||||
else:
|
|
||||||
# no unique match - remove the candidates we
|
|
||||||
# already checked above and (maybe) check the rest below
|
|
||||||
kwargs["candidates"] = [candidate for candidate in candidates
|
|
||||||
if candidate not in candidates_no_sdesc]
|
|
||||||
|
|
||||||
# No matches. At this point we can't pass this on to the
|
# No matches. At this point we can't pass this on to the
|
||||||
# normal search mechanism just like that, since that will lead to a
|
# normal search mechanism just like that, since that will lead to a
|
||||||
# security hole in the sdesc lookup: The normal search
|
# security hole in the sdesc lookup: The normal search
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue