Mercurial > wikked
changeset 447:8ca8c2713c92
web: Optimize the page resolver.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Wed, 03 Jan 2018 01:04:53 -0800 |
parents | 47690e0c55e6 |
children | c78eaebced8b |
files | wikked/resolver.py wikked/webimpl/edit.py |
diffstat | 2 files changed, 49 insertions(+), 27 deletions(-) [+] |
line wrap: on
line diff
--- a/wikked/resolver.py Wed Jan 03 00:58:22 2018 -0800 +++ b/wikked/resolver.py Wed Jan 03 01:04:53 2018 -0800 @@ -12,6 +12,27 @@ logger = logging.getLogger(__name__) +re_wiki_tag = re.compile( + r'^<div class="wiki-(?P<name>[a-z]+)"' + r'(?P<opts>( data-wiki-([a-z]+)="([^"]+)")*)' + r'>(?P<value>.*)</div>$', + flags=re.MULTILINE) +re_wiki_tag_attr = re.compile( + r'data-wiki-(?P<name>[a-z]+)="(?P<value>[^"]+)"') +re_wiki_link = re.compile( + r'<a class="wiki-link(?P<isedit>-edit)?" ' + r'data-wiki-url="(?P<url>[^"]+)"') + +re_wiki_include_param = re.compile( + r'<div class="wiki-param" ' + r'data-name="(?P<name>\w[\w\d]*)?">' + r'(?P<value>.*?)</div>') + +re_wiki_query_param = re.compile( + r'(^|\|)\s*(?P<name>(__)?[a-zA-Z][a-zA-Z0-9_\-]+)\s*=(?P<value>[^\|]+)') +re_wiki_query_template_ref = re.compile(r'^\[\[.*\]\]$') +re_wiki_query_local_meta = re.compile(r'^__[a-zA-Z][a-zA-Z0-9_\-]+$') + class FormatterNotFound(Exception): """ An exception raised when not formatter is found for the @@ -108,12 +129,13 @@ } def __init__(self, page, ctx=None, parameters=None, page_getter=None, - pages_meta_getter=None): + pages_meta_getter=None, can_use_resolved_meta=False): self.page = page self.ctx = ctx or ResolveContext(page) self.parameters = parameters self.page_getter = page_getter or self._getPage self.pages_meta_getter = pages_meta_getter or self._getPagesMeta + self.can_use_resolved_meta = can_use_resolved_meta self.output = None self.env = None @@ -146,7 +168,7 @@ return self.wiki.db.getPage(url, fields=fields) def _getPagesMeta(self): - fields = ['url', 'title', 'local_meta'] + fields = ['url', 'title', 'local_meta', 'meta'] return self.wiki.db.getPages(fields=fields) def _unsafeRun(self): @@ -178,9 +200,7 @@ meta_value = m.group('value') meta_opts = {} if m.group('opts'): - for c in re.finditer( - r'data-wiki-(?P<name>[a-z]+)="(?P<value>[^"]+)"', - m.group('opts')): + for c in re_wiki_tag_attr.finditer(m.group('opts')): opt_name = c.group('name') opt_value = c.group('value') meta_opts[opt_name] = opt_value @@ -190,13 +210,7 @@ return resolver(meta_opts, meta_value) return '' - final_text = re.sub( - r'^<div class="wiki-(?P<name>[a-z]+)"' - r'(?P<opts>( data-wiki-([a-z]+)="([^"]+)")*)' - r'>(?P<value>.*)</div>$', - repl2, - final_text, - flags=re.MULTILINE) + final_text = re_wiki_tag.sub(repl2, final_text) # If this is the root page, with all the includes resolved and # collapsed into one text, we need to run the final steps. @@ -229,11 +243,7 @@ return ('<a class="wiki-link missing" data-wiki-url="%s" ' 'href="%s"' % (quoted_url, actual_url)) - final_text = re.sub( - r'<a class="wiki-link(?P<isedit>-edit)?" ' - r'data-wiki-url="(?P<url>[^"]+)"', - repl1, - final_text) + final_text = re_wiki_link.sub(repl1, final_text) # Format the text. formatter = self._getFormatter(self.page.extension) @@ -275,10 +285,7 @@ # We do not, however, run them through the formatting -- this # will be done in one pass when everything is gathered on the # root page. - arg_pattern = (r'<div class="wiki-param" ' - r'data-name="(?P<name>\w[\w\d]*)?">' - r'(?P<value>.*?)</div>') - for i, m in enumerate(re.finditer(arg_pattern, args)): + for i, m in enumerate(re_wiki_include_param.finditer(args)): value = m.group('value').strip() value = html_unescape(value) value = self._renderTemplate(value, self.parameters, @@ -319,9 +326,7 @@ # Parse the query. parameters = dict(self.default_parameters) meta_query = {} - arg_pattern = r"(^|\|)\s*(?P<name>(__)?[a-zA-Z][a-zA-Z0-9_\-]+)\s*="\ - r"(?P<value>[^\|]+)" - for m in re.finditer(arg_pattern, query): + for m in re_wiki_query_param.finditer(query): key = m.group('name').lower() if key in parameters: parameters[key] = m.group('value') @@ -383,7 +388,7 @@ def _valueOrPageText(self, value, with_url=False): stripped_value = value.strip() - if re.match(r'^\[\[.*\]\]$', stripped_value): + if re_wiki_query_template_ref.match(stripped_value): include_url = stripped_value[2:-2] try: page = self.page_getter(include_url) @@ -394,7 +399,7 @@ return (page.url, page.text) return page.text - if re.match(r'^__[a-zA-Z][a-zA-Z0-9_\-]+$', stripped_value): + if re_wiki_query_local_meta.match(stripped_value): meta = self.page.getLocalMeta(stripped_value) if with_url: return (None, meta) @@ -405,6 +410,21 @@ return value def _isPageMatch(self, page, name, value, level=0): + # If we can use the resolved meta properties of the page, this is + # a lot easier, since we just, well, check that. + if self.can_use_resolved_meta: + actual = page.getMeta(name) + if (actual is not None and + ((type(actual) is list and value in actual) or + (actual == value))): + return True + return False + + # Can't use the resolved meta properties, for instance because we have + # a bunch of other resolvers like us busy resolving the other pages' + # properties, and so we don't know which ones are ready or not. + # We'll need to parse pages "manually". + # # Check the page's local meta properties. meta_keys = [name] if level > 0:
--- a/wikked/webimpl/edit.py Wed Jan 03 00:58:22 2018 -0800 +++ b/wikked/webimpl/edit.py Wed Jan 03 01:04:53 2018 -0800 @@ -101,7 +101,9 @@ def preview_edited_page(wiki, url, raw_text): dummy = DummyPage(wiki, url, raw_text) - resolver = PageResolver(dummy) + # We can pass `can_use_resolved_meta` since we know we have the only + # resolver running right now... this will speed things up dramatically. + resolver = PageResolver(dummy, can_use_resolved_meta=True) dummy._setExtendedData(resolver.run()) return dummy.text