From 730788718547795ad1eeeea4c7e23122c8eed20b Mon Sep 17 00:00:00 2001 From: Griatch Date: Mon, 14 Sep 2020 19:13:18 +0200 Subject: [PATCH] Fix optimized prototype search mechanism. Still no dual db/mod search --- CHANGELOG.md | 4 +--- evennia/prototypes/prototypes.py | 38 ++++++++++++++++---------------- evennia/utils/evmore.py | 12 +++++++--- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d131062da..de062a528a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,9 +38,7 @@ without arguments starts a full interactive Python console. of texts (such as tables). New `justify` bool. Old `justify_kwargs` remains but is now only used to pass extra kwargs into the justify function. - EvMore `text` argument can now also be a list or a queryset. Querysets will be - sliced to only return the required data per page. EvMore takes a new kwarg - `page_formatter` which will be called for each page. This allows to customize - the display of queryset data, build a new EvTable per page etc. + sliced to only return the required data per page. - Improve performance of `find` and `objects` commands on large data sets (strikaco) - New `CHANNEL_HANDLER_CLASS` setting allows for replacing the ChannelHandler entirely. - Made `py` interactive mode support regular quit() and more verbose. diff --git a/evennia/prototypes/prototypes.py b/evennia/prototypes/prototypes.py index cd95468ce8..a6b2965712 100644 --- a/evennia/prototypes/prototypes.py +++ b/evennia/prototypes/prototypes.py @@ -410,22 +410,13 @@ def search_prototype(key=None, tags=None, require_single=False, return_iterators .filter(scriptdb__pk__in=db_ids, db_key="prototype") .values_list("db_value", flat=True) ) - if key: - matches = list(db_matches) + module_prototypes - nmatches = len(matches) - if nmatches > 1: - key = key.lower() - # avoid duplicates if an exact match exist between the two types - filter_matches = [ - mta for mta in matches if mta.get("prototype_key") and mta["prototype_key"] == key - ] - if filter_matches and len(filter_matches) < nmatches: - matches = filter_matches - nmatches = len(matches) - if nmatches != 1 and require_single: - raise KeyError("Found {} matching prototypes.".format(nmatches)) - return matches - elif return_iterators: + if key and require_single: + nmodules = len(module_prototypes) + ndbprots = db_matches.count() + if nmodules + ndbprots != 1: + raise KeyError(f"Found {nmodules + ndbprots} matching prototypes.") + + if return_iterators: # trying to get the entire set of prototypes - we must paginate # the result instead of trying to fetch the entire set at once db_pages = Paginator(db_matches, 20) @@ -479,6 +470,8 @@ class PrototypeEvMore(EvMore): # get use-permissions of readonly attributes (edit is always False) display_tuples = [] + print("page", page) + for prototype in page: lock_use = caller.locks.check_lockstring( caller, prototype.get("prototype_locks", ""), access_type="spawn", default=True @@ -538,16 +531,23 @@ def list_prototypes(caller, key=None, tags=None, show_non_use=False, show_non_ed show_non_edit (bool, optional): Show also prototypes the caller may not edit. session (Session, optional): If given, this is used for display formatting. Returns: - table (EvTable or None): An EvTable representation of the prototypes. None - if no prototypes were found. + PrototypeEvMore: An EvMore subclass optimized for prototype listings. + None: If a `key` was given and no matches was found. In this case the caller + has already been notified. """ # this allows us to pass lists of empty strings tags = [tag for tag in make_iter(tags) if tag] if key is not None: + matches = search_prototype(key, tags) + if not matches: + caller.msg("No prototypes found.", session=session) + return None + if len(matches) < 2: + matches = [matches] # get specific prototype (one value or exception) - return PrototypeEvMore(caller, [search_prototype(key, tags)], + return PrototypeEvMore(caller, matches, session=session, show_non_use=show_non_use, show_non_edit=show_non_edit) diff --git a/evennia/utils/evmore.py b/evennia/utils/evmore.py index 37b64abca2..e623a4fdc5 100644 --- a/evennia/utils/evmore.py +++ b/evennia/utils/evmore.py @@ -248,8 +248,11 @@ class EvMore(object): """ Pretty-print the page. """ - pos = self._npos - text = self.page_formatter(self.paginator(pos)) + pos = 0 + text = "[no content]" + if self._npages > 0: + pos = self._npos + text = self.page_formatter(self.paginator(pos)) if show_footer: page = _DISPLAY.format(text=text, pageno=pos + 1, pagemax=self._npages) else: @@ -447,6 +450,7 @@ class EvMore(object): if inherits_from(inp, "evennia.utils.evtable.EvTable"): # an EvTable self.init_evtable(inp) + self._paginator = self.paginator_index elif isinstance(inp, QuerySet): # a queryset self.init_queryset(inp) @@ -457,13 +461,15 @@ class EvMore(object): elif not isinstance(inp, str): # anything else not a str self.init_iterable(inp) - self._paginator = self.paginator_django + self._paginator = self.paginator_index elif "\f" in inp: # string with \f line-break markers in it self.init_f_str(inp) + self._paginator = self.paginator_index else: # a string self.init_str(inp) + self._paginator = self.paginator_index def paginator(self, pageno): """