Fix unittest warnings caused by lunr
This commit is contained in:
parent
537948561a
commit
a96332e9c3
2 changed files with 92 additions and 24 deletions
|
|
@ -6,8 +6,6 @@ set. The normal, database-tied help system is used for collaborative
|
||||||
creation of other help topics such as RP help or game-world aides.
|
creation of other help topics such as RP help or game-world aides.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from lunr import lunr
|
|
||||||
from lunr.exceptions import QueryParseError
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from evennia.utils.utils import fill, dedent
|
from evennia.utils.utils import fill, dedent
|
||||||
|
|
@ -16,7 +14,12 @@ from evennia.help.models import HelpEntry
|
||||||
from evennia.utils import create, evmore
|
from evennia.utils import create, evmore
|
||||||
from evennia.utils.ansi import ANSIString
|
from evennia.utils.ansi import ANSIString
|
||||||
from evennia.utils.eveditor import EvEditor
|
from evennia.utils.eveditor import EvEditor
|
||||||
from evennia.utils.utils import string_suggestions, class_from_module, inherits_from, format_grid
|
from evennia.utils.utils import (
|
||||||
|
string_suggestions,
|
||||||
|
class_from_module,
|
||||||
|
inherits_from,
|
||||||
|
format_grid,
|
||||||
|
)
|
||||||
|
|
||||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
HELP_MORE = settings.HELP_MORE
|
HELP_MORE = settings.HELP_MORE
|
||||||
|
|
@ -27,6 +30,9 @@ __all__ = ("CmdHelp", "CmdSetHelp")
|
||||||
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
||||||
_SEP = "|C" + "-" * _DEFAULT_WIDTH + "|n"
|
_SEP = "|C" + "-" * _DEFAULT_WIDTH + "|n"
|
||||||
|
|
||||||
|
_LUNR = None
|
||||||
|
_LUNR_EXCEPTION = None
|
||||||
|
|
||||||
|
|
||||||
class HelpCategory:
|
class HelpCategory:
|
||||||
def __init__(self, key):
|
def __init__(self, key):
|
||||||
|
|
@ -34,7 +40,13 @@ class HelpCategory:
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def search_index_entry(self):
|
def search_index_entry(self):
|
||||||
return {"key": str(self), "aliases": "", "category": self.key, "tags": "", "text": ""}
|
return {
|
||||||
|
"key": str(self),
|
||||||
|
"aliases": "",
|
||||||
|
"category": self.key,
|
||||||
|
"tags": "",
|
||||||
|
"text": "",
|
||||||
|
}
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"Category: {self.key}"
|
return f"Category: {self.key}"
|
||||||
|
|
@ -47,30 +59,42 @@ class HelpCategory:
|
||||||
|
|
||||||
|
|
||||||
def help_search_with_index(query, candidate_entries, suggestion_maxnum=5):
|
def help_search_with_index(query, candidate_entries, suggestion_maxnum=5):
|
||||||
|
"""
|
||||||
|
Lunr-powered fast index search and suggestion wrapper
|
||||||
|
"""
|
||||||
|
global _LUNR, _LUNR_EXCEPTION
|
||||||
|
if not _LUNR:
|
||||||
|
# we have to delay-load lunr because it messes with logging if it's imported
|
||||||
|
# before twisted's logging has been set up
|
||||||
|
from lunr import lunr as _LUNR
|
||||||
|
from lunr.exceptions import QueryParseError as _LUNR_EXCEPTION
|
||||||
|
|
||||||
indx = [cnd.search_index_entry for cnd in candidate_entries]
|
indx = [cnd.search_index_entry for cnd in candidate_entries]
|
||||||
mapping = {indx[ix]["key"]: cand for ix, cand in enumerate(candidate_entries)}
|
mapping = {indx[ix]["key"]: cand for ix, cand in enumerate(candidate_entries)}
|
||||||
|
|
||||||
search_index = lunr(
|
search_index = _LUNR(
|
||||||
ref="key",
|
ref="key",
|
||||||
fields=[
|
fields=[
|
||||||
{"field_name": "key", "boost": 10,},
|
{"field_name": "key", "boost": 10},
|
||||||
{"field_name": "aliases", "boost": 9,},
|
{"field_name": "aliases", "boost": 9},
|
||||||
{"field_name": "category", "boost": 8,},
|
{"field_name": "category", "boost": 8},
|
||||||
{"field_name": "tags", "boost": 5},
|
{"field_name": "tags", "boost": 5},
|
||||||
{"field_name": "text", "boost": 1,},
|
{"field_name": "text", "boost": 1},
|
||||||
],
|
],
|
||||||
documents=indx,
|
documents=indx,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
matches = search_index.search(query)[:suggestion_maxnum]
|
matches = search_index.search(query)[:suggestion_maxnum]
|
||||||
except QueryParseError:
|
except _LUNR_EXCEPTION:
|
||||||
# this is a user-input problem
|
# this is a user-input problem
|
||||||
matches = []
|
matches = []
|
||||||
|
|
||||||
# matches (objs), suggestions (strs)
|
# matches (objs), suggestions (strs)
|
||||||
return (
|
return (
|
||||||
[mapping[match["ref"]] for match in matches],
|
[mapping[match["ref"]] for match in matches],
|
||||||
[str(match["ref"]) for match in matches], # + f" (score {match['score']})") # good debug
|
[
|
||||||
|
str(match["ref"]) for match in matches
|
||||||
|
], # + f" (score {match['score']})") # good debug
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -116,7 +140,10 @@ class CmdHelp(Command):
|
||||||
if type(self).help_more:
|
if type(self).help_more:
|
||||||
usemore = True
|
usemore = True
|
||||||
|
|
||||||
if self.session and self.session.protocol_key in ("websocket", "ajax/comet"):
|
if self.session and self.session.protocol_key in (
|
||||||
|
"websocket",
|
||||||
|
"ajax/comet",
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
options = self.account.db._saved_webclient_options
|
options = self.account.db._saved_webclient_options
|
||||||
if options and options["helppopup"]:
|
if options and options["helppopup"]:
|
||||||
|
|
@ -150,7 +177,9 @@ class CmdHelp(Command):
|
||||||
if title:
|
if title:
|
||||||
string += "|CHelp for |w%s|n" % title
|
string += "|CHelp for |w%s|n" % title
|
||||||
if aliases:
|
if aliases:
|
||||||
string += " |C(aliases: %s|C)|n" % ("|C,|n ".join("|w%s|n" % ali for ali in aliases))
|
string += " |C(aliases: %s|C)|n" % (
|
||||||
|
"|C,|n ".join("|w%s|n" % ali for ali in aliases)
|
||||||
|
)
|
||||||
if help_text:
|
if help_text:
|
||||||
string += "\n%s" % dedent(help_text.rstrip())
|
string += "\n%s" % dedent(help_text.rstrip())
|
||||||
if suggested:
|
if suggested:
|
||||||
|
|
@ -177,15 +206,22 @@ class CmdHelp(Command):
|
||||||
category_str = f"-- {category.title()} "
|
category_str = f"-- {category.title()} "
|
||||||
grid.append(
|
grid.append(
|
||||||
ANSIString(
|
ANSIString(
|
||||||
category_clr + category_str + "-" * (width - len(category_str)) + topic_clr
|
category_clr
|
||||||
|
+ category_str
|
||||||
|
+ "-" * (width - len(category_str))
|
||||||
|
+ topic_clr
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
verbatim_elements.append(len(grid) - 1)
|
verbatim_elements.append(len(grid) - 1)
|
||||||
|
|
||||||
entries = sorted(set(hdict_cmds.get(category, []) + hdict_db.get(category, [])))
|
entries = sorted(
|
||||||
|
set(hdict_cmds.get(category, []) + hdict_db.get(category, []))
|
||||||
|
)
|
||||||
grid.extend(entries)
|
grid.extend(entries)
|
||||||
|
|
||||||
gridrows = format_grid(grid, width, sep=" ", verbatim_elements=verbatim_elements)
|
gridrows = format_grid(
|
||||||
|
grid, width, sep=" ", verbatim_elements=verbatim_elements
|
||||||
|
)
|
||||||
gridrows = ANSIString("\n").join(gridrows)
|
gridrows = ANSIString("\n").join(gridrows)
|
||||||
return gridrows
|
return gridrows
|
||||||
|
|
||||||
|
|
@ -257,7 +293,9 @@ class CmdHelp(Command):
|
||||||
# retrieve all available commands and database topics
|
# retrieve all available commands and database topics
|
||||||
all_cmds = [cmd for cmd in cmdset if self.check_show_help(cmd, caller)]
|
all_cmds = [cmd for cmd in cmdset if self.check_show_help(cmd, caller)]
|
||||||
all_topics = [
|
all_topics = [
|
||||||
topic for topic in HelpEntry.objects.all() if topic.access(caller, "view", default=True)
|
topic
|
||||||
|
for topic in HelpEntry.objects.all()
|
||||||
|
if topic.access(caller, "view", default=True)
|
||||||
]
|
]
|
||||||
all_categories = list(
|
all_categories = list(
|
||||||
set(
|
set(
|
||||||
|
|
@ -282,7 +320,11 @@ class CmdHelp(Command):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Try to access a particular help entry or category
|
# Try to access a particular help entry or category
|
||||||
entries = [cmd for cmd in all_cmds if cmd] + list(HelpEntry.objects.all()) + all_categories
|
entries = (
|
||||||
|
[cmd for cmd in all_cmds if cmd]
|
||||||
|
+ list(HelpEntry.objects.all())
|
||||||
|
+ all_categories
|
||||||
|
)
|
||||||
|
|
||||||
for match_query in [f"{query}~1", f"{query}*"]:
|
for match_query in [f"{query}~1", f"{query}*"]:
|
||||||
# We first do an exact word-match followed by a start-by query
|
# We first do an exact word-match followed by a start-by query
|
||||||
|
|
@ -407,14 +449,19 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg("You have to define a topic!")
|
self.msg("You have to define a topic!")
|
||||||
return
|
return
|
||||||
topicstrlist = topicstr.split(";")
|
topicstrlist = topicstr.split(";")
|
||||||
topicstr, aliases = (topicstrlist[0], topicstrlist[1:] if len(topicstr) > 1 else [])
|
topicstr, aliases = (
|
||||||
|
topicstrlist[0],
|
||||||
|
topicstrlist[1:] if len(topicstr) > 1 else [],
|
||||||
|
)
|
||||||
aliastxt = ("(aliases: %s)" % ", ".join(aliases)) if aliases else ""
|
aliastxt = ("(aliases: %s)" % ", ".join(aliases)) if aliases else ""
|
||||||
old_entry = None
|
old_entry = None
|
||||||
|
|
||||||
# check if we have an old entry with the same name
|
# check if we have an old entry with the same name
|
||||||
try:
|
try:
|
||||||
for querystr in topicstrlist:
|
for querystr in topicstrlist:
|
||||||
old_entry = HelpEntry.objects.find_topicmatch(querystr) # also search by alias
|
old_entry = HelpEntry.objects.find_topicmatch(
|
||||||
|
querystr
|
||||||
|
) # also search by alias
|
||||||
if old_entry:
|
if old_entry:
|
||||||
old_entry = list(old_entry)[0]
|
old_entry = list(old_entry)[0]
|
||||||
break
|
break
|
||||||
|
|
@ -436,7 +483,11 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
|
||||||
helpentry = old_entry
|
helpentry = old_entry
|
||||||
else:
|
else:
|
||||||
helpentry = create.create_help_entry(
|
helpentry = create.create_help_entry(
|
||||||
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases
|
topicstr,
|
||||||
|
self.rhs,
|
||||||
|
category=category,
|
||||||
|
locks=lockstring,
|
||||||
|
aliases=aliases,
|
||||||
)
|
)
|
||||||
self.caller.db._editing_help = helpentry
|
self.caller.db._editing_help = helpentry
|
||||||
|
|
||||||
|
|
@ -453,7 +504,9 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
|
||||||
if "append" in switches or "merge" in switches or "extend" in switches:
|
if "append" in switches or "merge" in switches or "extend" in switches:
|
||||||
# merge/append operations
|
# merge/append operations
|
||||||
if not old_entry:
|
if not old_entry:
|
||||||
self.msg("Could not find topic '%s'. You must give an exact name." % topicstr)
|
self.msg(
|
||||||
|
"Could not find topic '%s'. You must give an exact name." % topicstr
|
||||||
|
)
|
||||||
return
|
return
|
||||||
if not self.rhs:
|
if not self.rhs:
|
||||||
self.msg("You must supply text to append/merge.")
|
self.msg("You must supply text to append/merge.")
|
||||||
|
|
@ -500,7 +553,9 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
|
||||||
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases
|
topicstr, self.rhs, category=category, locks=lockstring, aliases=aliases
|
||||||
)
|
)
|
||||||
if new_entry:
|
if new_entry:
|
||||||
self.msg("Topic '%s'%s was successfully created." % (topicstr, aliastxt))
|
self.msg(
|
||||||
|
"Topic '%s'%s was successfully created." % (topicstr, aliastxt)
|
||||||
|
)
|
||||||
if "edit" in switches:
|
if "edit" in switches:
|
||||||
# open the line editor to edit the helptext
|
# open the line editor to edit the helptext
|
||||||
self.caller.db._editing_help = new_entry
|
self.caller.db._editing_help = new_entry
|
||||||
|
|
@ -515,5 +570,6 @@ class CmdSetHelp(COMMAND_DEFAULT_CLASS):
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.msg(
|
self.msg(
|
||||||
"Error when creating topic '%s'%s! Contact an admin." % (topicstr, aliastxt)
|
"Error when creating topic '%s'%s! Contact an admin."
|
||||||
|
% (topicstr, aliastxt)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -265,6 +265,18 @@ class TestGeneral(CommandTest):
|
||||||
|
|
||||||
|
|
||||||
class TestHelp(CommandTest):
|
class TestHelp(CommandTest):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
# we need to set up a logger here since lunr takes over the logger otherwise
|
||||||
|
import logging
|
||||||
|
logging.basicConfig(level=logging.ERROR)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
super().tearDown()
|
||||||
|
import logging
|
||||||
|
logging.disable(level=logging.ERROR)
|
||||||
|
|
||||||
def test_help(self):
|
def test_help(self):
|
||||||
self.call(help.CmdHelp(), "", "Admin", cmdset=CharacterCmdSet())
|
self.call(help.CmdHelp(), "", "Admin", cmdset=CharacterCmdSet())
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue