# HG changeset patch # User Paul Boddie # Date 1396117946 -3600 # Node ID cfd6f5590cccc42fcf084e9e053295e6c11e33fc # Parent 6cc821092dea17b406e1fdca2768cd73fb9ac59d Updated the caching patches. diff -r 6cc821092dea -r cfd6f5590ccc patches/pageparams-caching-1.8.diff --- a/patches/pageparams-caching-1.8.diff Sat Mar 29 16:29:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -# HG changeset patch -# User Paul Boddie -# Date 1390585706 -3600 -# Node ID 70250fe93a4f946e51eaa63accbb0152054ddab2 -# Parent d57b620213dd68126d2e5800f173d89f0602403a -Added caching support for the "pageparams" dependency where the request -parameters are combined with the page name to make a cache entry. - -diff -r d57b620213dd -r 70250fe93a4f MoinMoin/Page.py ---- a/MoinMoin/Page.py Tue Jul 30 17:41:42 2013 +0200 -+++ b/MoinMoin/Page.py Fri Jan 24 18:48:26 2014 +0100 -@@ -41,6 +41,7 @@ - - from MoinMoin import config, caching, user, util, wikiutil - from MoinMoin.logfile import eventlog -+from MoinMoin.support.python_compatibility import hash_new - - def is_cache_exception(e): - args = e.args -@@ -1336,7 +1337,7 @@ - - def loadCache(self, request): - """ Return page content cache or raises 'CacheNeedsUpdate' """ -- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') - attachmentsPath = self.getPagePath('attachments', check_create=0) - if cache.needsUpdate(self._text_filename(), attachmentsPath): - raise Exception('CacheNeedsUpdate') -@@ -1357,7 +1358,7 @@ - """ Format content into code, update cache and return code """ - import marshal - from MoinMoin.formatter.text_python import Formatter -- formatter = Formatter(request, ["page"], self.formatter) -+ formatter = Formatter(request, ["page", "pageparams"], self.formatter) - - # Save request state while formatting page - saved_current_lang = request.current_lang -@@ -1369,10 +1370,39 @@ - src = formatter.assemble_code(text) - code = compile(src.encode(config.charset), - self.page_name.encode(config.charset), 'exec') -- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') -+ self.enforceCacheLimit(request) -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') - cache.update(marshal.dumps(code)) - return code - -+ def enforceCacheLimit(self, request): -+ """ Prevent too many cache entries being stored for a page """ -+ keys = caching.get_cache_list(request, self, 'item') -+ try: -+ cache_limit = int(getattr(request.cfg, 'page_cache_limit', "10")) -+ except ValueError: -+ cache_limit = 10 -+ -+ if len(keys) >= cache_limit: -+ items = [caching.CacheEntry(request, self, key, scope='item') for key in keys] -+ item_ages = [(item.mtime(), item) for item in items] -+ item_ages.sort() -+ for item_age, item in item_ages[:-cache_limit]: -+ item.remove() -+ -+ def getCacheKey(self, request): -+ """ Generate a cache key for a page using optional request information """ -+ key = self.getFormatterName() -+ if request.args: -+ args = request.args.items() -+ args.sort() -+ key_args = [] -+ for k, v in args: -+ key_args.append("%s=%s" % (k, wikiutil.url_quote(v))) -+ arg_str = "&".join(key_args) -+ key = "%s:%s" % (key, hash_new('sha1', arg_str).hexdigest()) -+ return key -+ - def _specialPageText(self, request, special_type): - """ Output the default page content for new pages. - -# HG changeset patch -# User Paul Boddie -# Date 1390599896 -3600 -# Node ID 02d1fa8951523776357a9a37235ad5c37f42fcc8 -# Parent 70250fe93a4f946e51eaa63accbb0152054ddab2 -Acquire the request formatter name when the page formatter has not yet been set. - -diff -r 70250fe93a4f -r 02d1fa895152 MoinMoin/Page.py ---- a/MoinMoin/Page.py Fri Jan 24 18:48:26 2014 +0100 -+++ b/MoinMoin/Page.py Fri Jan 24 22:44:56 2014 +0100 -@@ -1240,15 +1240,17 @@ - request.formatter = old_formatter - - -- def getFormatterName(self): -+ def getFormatterName(self, request=None): - """ Return a formatter name as used in the caching system - -+ @param request: the active request (optional) - @rtype: string - @return: formatter name as used in caching - """ -- if not hasattr(self, 'formatter') or self.formatter is None: -+ formatter = getattr(self, 'formatter', None) or request and getattr(request, 'formatter', None) -+ if not formatter: - return '' -- module = self.formatter.__module__ -+ module = formatter.__module__ - return module[module.rfind('.') + 1:] - - def canUseCache(self, parser=None): -@@ -1392,7 +1394,7 @@ - - def getCacheKey(self, request): - """ Generate a cache key for a page using optional request information """ -- key = self.getFormatterName() -+ key = self.getFormatterName(request) - if request.args: - args = request.args.items() - args.sort() -# HG changeset patch -# User Paul Boddie -# Date 1390675730 -3600 -# Node ID 561fe9439debfd095753a32d884383c315dde7ec -# Parent 02d1fa8951523776357a9a37235ad5c37f42fcc8 -Added tracking of reported dependencies and prevented generation of specific -cache entries for request parameter combinations when no extension requires or -supports such specific entries. - -diff -r 02d1fa895152 -r 561fe9439deb MoinMoin/Page.py ---- a/MoinMoin/Page.py Fri Jan 24 22:44:56 2014 +0100 -+++ b/MoinMoin/Page.py Sat Jan 25 19:48:50 2014 +0100 -@@ -1339,9 +1339,12 @@ - - def loadCache(self, request): - """ Return page content cache or raises 'CacheNeedsUpdate' """ -- cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') -- attachmentsPath = self.getPagePath('attachments', check_create=0) -- if cache.needsUpdate(self._text_filename(), attachmentsPath): -+ for with_params in (True, False): -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') -+ attachmentsPath = self.getPagePath('attachments', check_create=0) -+ if not cache.needsUpdate(self._text_filename(), attachmentsPath): -+ break -+ else: - raise Exception('CacheNeedsUpdate') - - import marshal -@@ -1373,7 +1376,10 @@ - code = compile(src.encode(config.charset), - self.page_name.encode(config.charset), 'exec') - self.enforceCacheLimit(request) -- cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') -+ # Determine whether the parameters/args need to be incorporated into the -+ # cache entry key. -+ with_params = "pageparams" in formatter.getReportedDependencies() -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') - cache.update(marshal.dumps(code)) - return code - -@@ -1392,10 +1398,10 @@ - for item_age, item in item_ages[:-cache_limit]: - item.remove() - -- def getCacheKey(self, request): -+ def getCacheKey(self, request, with_params=False): - """ Generate a cache key for a page using optional request information """ - key = self.getFormatterName(request) -- if request.args: -+ if with_params and request.args: - args = request.args.items() - args.sort() - key_args = [] -diff -r 02d1fa895152 -r 561fe9439deb MoinMoin/formatter/text_python.py ---- a/MoinMoin/formatter/text_python.py Fri Jan 24 22:44:56 2014 +0100 -+++ b/MoinMoin/formatter/text_python.py Sat Jan 25 19:48:50 2014 +0100 -@@ -10,6 +10,7 @@ - - import time - from MoinMoin import wikiutil -+from MoinMoin.support.python_compatibility import set - - - class Formatter: -@@ -40,6 +41,12 @@ - self.text_cmd_begin = '\nrequest.write(' - self.text_cmd_end = ')\n' - -+ # Record dependency requirements of certain content -+ self.__dependencies = set() -+ -+ def getReportedDependencies(self): -+ return self.__dependencies -+ - def assemble_code(self, text): - """inserts the code into the generated text - """ -@@ -186,7 +193,10 @@ - return self.formatter.div(on, **kw) - - def macro(self, macro_obj, name, args, markup=None): -- if self.__is_static(macro_obj.get_dependencies(name)): -+ Dependencies = macro_obj.get_dependencies(name) -+ self.__dependencies.update(Dependencies) -+ -+ if self.__is_static(Dependencies): - # XXX: why is this necessary?? - macro_obj.formatter = self - return macro_obj.execute(name, args) -@@ -204,6 +214,7 @@ - Dependencies = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name, "Dependencies") - except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError): - Dependencies = self.defaultDependencies -+ self.__dependencies.update(Dependencies) - - if self.__is_static(Dependencies): - return self.formatter.parser(parser_name, lines) diff -r 6cc821092dea -r cfd6f5590ccc patches/pageparams-caching-1.9.diff --- a/patches/pageparams-caching-1.9.diff Sat Mar 29 16:29:52 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -# HG changeset patch -# User Paul Boddie -# Date 1390585938 -3600 -# Node ID 71d9815d2e6f5487ec87c4f5c04e5a156ffd21d3 -# Parent 5738b78f53b540ece0b48efa49b63fa4cbc09be9 -Added caching support for the "pageparams" dependency where the request -parameters are combined with the page name to make a cache entry. - -diff -r 5738b78f53b5 -r 71d9815d2e6f MoinMoin/Page.py ---- a/MoinMoin/Page.py Sat Nov 30 20:09:43 2013 +0100 -+++ b/MoinMoin/Page.py Fri Jan 24 18:52:18 2014 +0100 -@@ -41,6 +41,7 @@ - - from MoinMoin import config, caching, user, util, wikiutil - from MoinMoin.logfile import eventlog -+from MoinMoin.support.python_compatibility import hash_new - - def is_cache_exception(e): - args = e.args -@@ -1351,7 +1352,7 @@ - - def loadCache(self, request): - """ Return page content cache or raises 'CacheNeedsUpdate' """ -- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') - attachmentsPath = self.getPagePath('attachments', check_create=0) - if cache.needsUpdate(self._text_filename(), attachmentsPath): - raise Exception('CacheNeedsUpdate') -@@ -1372,7 +1373,7 @@ - """ Format content into code, update cache and return code """ - import marshal - from MoinMoin.formatter.text_python import Formatter -- formatter = Formatter(request, ["page"], self.formatter) -+ formatter = Formatter(request, ["page", "pageparams"], self.formatter) - - # Save request state while formatting page - saved_current_lang = request.current_lang -@@ -1384,10 +1385,39 @@ - src = formatter.assemble_code(text) - code = compile(src.encode(config.charset), - self.page_name.encode(config.charset), 'exec') -- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') -+ self.enforceCacheLimit(request) -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') - cache.update(marshal.dumps(code)) - return code - -+ def enforceCacheLimit(self, request): -+ """ Prevent too many cache entries being stored for a page """ -+ keys = caching.get_cache_list(request, self, 'item') -+ try: -+ cache_limit = int(getattr(request.cfg, 'page_cache_limit', "10")) -+ except ValueError: -+ cache_limit = 10 -+ -+ if len(keys) >= cache_limit: -+ items = [caching.CacheEntry(request, self, key, scope='item') for key in keys] -+ item_ages = [(item.mtime(), item) for item in items] -+ item_ages.sort() -+ for item_age, item in item_ages[:-cache_limit]: -+ item.remove() -+ -+ def getCacheKey(self, request): -+ """ Generate a cache key for a page using optional request information """ -+ key = self.getFormatterName() -+ if request.args: -+ args = request.args.items() -+ args.sort() -+ key_args = [] -+ for k, v in args: -+ key_args.append("%s=%s" % (k, wikiutil.url_quote(v))) -+ arg_str = "&".join(key_args) -+ key = "%s:%s" % (key, hash_new('sha1', arg_str).hexdigest()) -+ return key -+ - def _specialPageText(self, request, special_type): - """ Output the default page content for new pages. - -# HG changeset patch -# User Paul Boddie -# Date 1390599896 -3600 -# Node ID e3850612c891d5b6468f212acd797413c70fe18f -# Parent 71d9815d2e6f5487ec87c4f5c04e5a156ffd21d3 -Acquire the request formatter name when the page formatter has not yet been set. - -diff -r 71d9815d2e6f -r e3850612c891 MoinMoin/Page.py ---- a/MoinMoin/Page.py Fri Jan 24 18:52:18 2014 +0100 -+++ b/MoinMoin/Page.py Fri Jan 24 22:44:56 2014 +0100 -@@ -1255,15 +1255,17 @@ - request.formatter = old_formatter - - -- def getFormatterName(self): -+ def getFormatterName(self, request=None): - """ Return a formatter name as used in the caching system - -+ @param request: the active request (optional) - @rtype: string - @return: formatter name as used in caching - """ -- if not hasattr(self, 'formatter') or self.formatter is None: -+ formatter = getattr(self, 'formatter', None) or request and getattr(request, 'formatter', None) -+ if not formatter: - return '' -- module = self.formatter.__module__ -+ module = formatter.__module__ - return module[module.rfind('.') + 1:] - - def canUseCache(self, parser=None): -@@ -1407,7 +1409,7 @@ - - def getCacheKey(self, request): - """ Generate a cache key for a page using optional request information """ -- key = self.getFormatterName() -+ key = self.getFormatterName(request) - if request.args: - args = request.args.items() - args.sort() -# HG changeset patch -# User Paul Boddie -# Date 1390675730 -3600 -# Node ID 908ceaf41dbe9f664f0c0813abc7b4c0611022fe -# Parent e3850612c891d5b6468f212acd797413c70fe18f -Added tracking of reported dependencies and prevented generation of specific -cache entries for request parameter combinations when no extension requires or -supports such specific entries. - -diff -r e3850612c891 -r 908ceaf41dbe MoinMoin/Page.py ---- a/MoinMoin/Page.py Fri Jan 24 22:44:56 2014 +0100 -+++ b/MoinMoin/Page.py Sat Jan 25 19:48:50 2014 +0100 -@@ -1354,9 +1354,12 @@ - - def loadCache(self, request): - """ Return page content cache or raises 'CacheNeedsUpdate' """ -- cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') -- attachmentsPath = self.getPagePath('attachments', check_create=0) -- if cache.needsUpdate(self._text_filename(), attachmentsPath): -+ for with_params in (True, False): -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') -+ attachmentsPath = self.getPagePath('attachments', check_create=0) -+ if not cache.needsUpdate(self._text_filename(), attachmentsPath): -+ break -+ else: - raise Exception('CacheNeedsUpdate') - - import marshal -@@ -1388,7 +1391,10 @@ - code = compile(src.encode(config.charset), - self.page_name.encode(config.charset), 'exec') - self.enforceCacheLimit(request) -- cache = caching.CacheEntry(request, self, self.getCacheKey(request), scope='item') -+ # Determine whether the parameters/args need to be incorporated into the -+ # cache entry key. -+ with_params = "pageparams" in formatter.getReportedDependencies() -+ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') - cache.update(marshal.dumps(code)) - return code - -@@ -1407,10 +1413,10 @@ - for item_age, item in item_ages[:-cache_limit]: - item.remove() - -- def getCacheKey(self, request): -+ def getCacheKey(self, request, with_params=False): - """ Generate a cache key for a page using optional request information """ - key = self.getFormatterName(request) -- if request.args: -+ if with_params and request.args: - args = request.args.items() - args.sort() - key_args = [] -diff -r e3850612c891 -r 908ceaf41dbe MoinMoin/formatter/text_python.py ---- a/MoinMoin/formatter/text_python.py Fri Jan 24 22:44:56 2014 +0100 -+++ b/MoinMoin/formatter/text_python.py Sat Jan 25 19:48:50 2014 +0100 -@@ -10,6 +10,7 @@ - - import time - from MoinMoin import wikiutil -+from MoinMoin.support.python_compatibility import set - - - class Formatter: -@@ -40,6 +41,12 @@ - self.text_cmd_begin = '\nrequest.write(' - self.text_cmd_end = ')\n' - -+ # Record dependency requirements of certain content -+ self.__dependencies = set() -+ -+ def getReportedDependencies(self): -+ return self.__dependencies -+ - def assemble_code(self, text): - """inserts the code into the generated text - """ -@@ -186,7 +193,10 @@ - return self.formatter.div(on, **kw) - - def macro(self, macro_obj, name, args, markup=None): -- if self.__is_static(macro_obj.get_dependencies(name)): -+ Dependencies = macro_obj.get_dependencies(name) -+ self.__dependencies.update(Dependencies) -+ -+ if self.__is_static(Dependencies): - # XXX: why is this necessary?? - macro_obj.formatter = self - return macro_obj.execute(name, args) -@@ -204,6 +214,7 @@ - Dependencies = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name, "Dependencies") - except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError): - Dependencies = self.defaultDependencies -+ self.__dependencies.update(Dependencies) - - if self.__is_static(Dependencies): - return self.formatter.parser(parser_name, lines) diff -r 6cc821092dea -r cfd6f5590ccc patches/patch-cache-pageparams-1.8.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/patch-cache-pageparams-1.8.diff Sat Mar 29 19:32:26 2014 +0100 @@ -0,0 +1,168 @@ +diff -r d57b620213dd MoinMoin/Page.py +--- a/MoinMoin/Page.py Tue Jul 30 17:41:42 2013 +0200 ++++ b/MoinMoin/Page.py Sat Mar 29 16:01:13 2014 +0100 +@@ -41,6 +41,7 @@ + + from MoinMoin import config, caching, user, util, wikiutil + from MoinMoin.logfile import eventlog ++from MoinMoin.support.python_compatibility import hash_new + + def is_cache_exception(e): + args = e.args +@@ -1239,15 +1240,17 @@ + request.formatter = old_formatter + + +- def getFormatterName(self): ++ def getFormatterName(self, request=None): + """ Return a formatter name as used in the caching system + ++ @param request: the active request (optional) + @rtype: string + @return: formatter name as used in caching + """ +- if not hasattr(self, 'formatter') or self.formatter is None: ++ formatter = getattr(self, 'formatter', None) or request and getattr(request, 'formatter', None) ++ if not formatter: + return '' +- module = self.formatter.__module__ ++ module = formatter.__module__ + return module[module.rfind('.') + 1:] + + def canUseCache(self, parser=None): +@@ -1336,9 +1339,12 @@ + + def loadCache(self, request): + """ Return page content cache or raises 'CacheNeedsUpdate' """ +- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') +- attachmentsPath = self.getPagePath('attachments', check_create=0) +- if cache.needsUpdate(self._text_filename(), attachmentsPath): ++ for with_params in (True, False): ++ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') ++ attachmentsPath = self.getPagePath('attachments', check_create=0) ++ if not cache.needsUpdate(self._text_filename(), attachmentsPath): ++ break ++ else: + raise Exception('CacheNeedsUpdate') + + import marshal +@@ -1357,7 +1363,7 @@ + """ Format content into code, update cache and return code """ + import marshal + from MoinMoin.formatter.text_python import Formatter +- formatter = Formatter(request, ["page"], self.formatter) ++ formatter = Formatter(request, ["page", "pageparams"], self.formatter) + + # Save request state while formatting page + saved_current_lang = request.current_lang +@@ -1369,10 +1375,45 @@ + src = formatter.assemble_code(text) + code = compile(src.encode(config.charset), + self.page_name.encode(config.charset), 'exec') +- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') ++ self.enforceCacheLimit(request) ++ # Determine whether the parameters/args need to be incorporated into the ++ # cache entry key. ++ with_params = "pageparams" in formatter.getReportedDependencies() ++ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') + cache.update(marshal.dumps(code)) + return code + ++ def enforceCacheLimit(self, request): ++ """ Prevent too many cache entries being stored for a page """ ++ keys = caching.get_cache_list(request, self, 'item') ++ try: ++ cache_limit = int(getattr(request.cfg, 'page_cache_limit', "10")) ++ except ValueError: ++ cache_limit = 10 ++ ++ if len(keys) >= cache_limit: ++ items = [caching.CacheEntry(request, self, key, scope='item') for key in keys] ++ item_ages = [(item.mtime(), item) for item in items] ++ item_ages.sort() ++ for item_age, item in item_ages[:-cache_limit]: ++ item.remove() ++ ++ def getCacheKey(self, request, with_params=False, key=None): ++ """ Generate a cache key for a page using optional request information """ ++ key = key or self.getFormatterName(request) ++ if with_params and request.args: ++ args = request.args.items() ++ args.sort() ++ key_args = [] ++ for k, values in args: ++ for v in values: ++ if not (k == "action" and v == "refresh"): ++ key_args.append("%s=%s" % (k, wikiutil.url_quote(v))) ++ arg_str = "&".join(key_args) ++ if arg_str: ++ key = "%s:%s" % (key, hash_new('sha1', arg_str).hexdigest()) ++ return key ++ + def _specialPageText(self, request, special_type): + """ Output the default page content for new pages. + +diff -r d57b620213dd MoinMoin/action/refresh.py +--- a/MoinMoin/action/refresh.py Tue Jul 30 17:41:42 2013 +0200 ++++ b/MoinMoin/action/refresh.py Sat Mar 29 16:01:13 2014 +0100 +@@ -14,11 +14,14 @@ + arena = request.form.get('arena', ['Page.py'])[0] + if arena == 'Page.py': + arena = Page(request, pagename) +- key = request.form.get('key', ['text_html'])[0] ++ prefix = request.form.get('key', ['text_html'])[0] + + # Remove cache entry (if exists), and send the page + from MoinMoin import caching +- caching.CacheEntry(request, arena, key, scope='item').remove() ++ keys = caching.get_cache_list(request, arena, 'item') ++ for key in keys: ++ if key.startswith(prefix): ++ caching.CacheEntry(request, arena, key, scope='item').remove() + caching.CacheEntry(request, arena, "pagelinks", scope='item').remove() + request.page.send_page() + +diff -r d57b620213dd MoinMoin/formatter/text_python.py +--- a/MoinMoin/formatter/text_python.py Tue Jul 30 17:41:42 2013 +0200 ++++ b/MoinMoin/formatter/text_python.py Sat Mar 29 16:01:13 2014 +0100 +@@ -10,6 +10,7 @@ + + import time + from MoinMoin import wikiutil ++from MoinMoin.support.python_compatibility import set + + + class Formatter: +@@ -40,6 +41,12 @@ + self.text_cmd_begin = '\nrequest.write(' + self.text_cmd_end = ')\n' + ++ # Record dependency requirements of certain content ++ self.__dependencies = set() ++ ++ def getReportedDependencies(self): ++ return self.__dependencies ++ + def assemble_code(self, text): + """inserts the code into the generated text + """ +@@ -186,7 +193,10 @@ + return self.formatter.div(on, **kw) + + def macro(self, macro_obj, name, args, markup=None): +- if self.__is_static(macro_obj.get_dependencies(name)): ++ Dependencies = macro_obj.get_dependencies(name) ++ self.__dependencies.update(Dependencies) ++ ++ if self.__is_static(Dependencies): + # XXX: why is this necessary?? + macro_obj.formatter = self + return macro_obj.execute(name, args) +@@ -204,6 +214,7 @@ + Dependencies = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name, "Dependencies") + except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError): + Dependencies = self.defaultDependencies ++ self.__dependencies.update(Dependencies) + + if self.__is_static(Dependencies): + return self.formatter.parser(parser_name, lines) diff -r 6cc821092dea -r cfd6f5590ccc patches/patch-cache-pageparams-1.9.diff --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/patch-cache-pageparams-1.9.diff Sat Mar 29 19:32:26 2014 +0100 @@ -0,0 +1,167 @@ +diff -r 5738b78f53b5 MoinMoin/Page.py +--- a/MoinMoin/Page.py Sat Nov 30 20:09:43 2013 +0100 ++++ b/MoinMoin/Page.py Sat Mar 29 16:23:44 2014 +0100 +@@ -41,6 +41,7 @@ + + from MoinMoin import config, caching, user, util, wikiutil + from MoinMoin.logfile import eventlog ++from MoinMoin.support.python_compatibility import hash_new + + def is_cache_exception(e): + args = e.args +@@ -1254,15 +1255,17 @@ + request.formatter = old_formatter + + +- def getFormatterName(self): ++ def getFormatterName(self, request=None): + """ Return a formatter name as used in the caching system + ++ @param request: the active request (optional) + @rtype: string + @return: formatter name as used in caching + """ +- if not hasattr(self, 'formatter') or self.formatter is None: ++ formatter = getattr(self, 'formatter', None) or request and getattr(request, 'formatter', None) ++ if not formatter: + return '' +- module = self.formatter.__module__ ++ module = formatter.__module__ + return module[module.rfind('.') + 1:] + + def canUseCache(self, parser=None): +@@ -1351,9 +1354,12 @@ + + def loadCache(self, request): + """ Return page content cache or raises 'CacheNeedsUpdate' """ +- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') +- attachmentsPath = self.getPagePath('attachments', check_create=0) +- if cache.needsUpdate(self._text_filename(), attachmentsPath): ++ for with_params in (True, False): ++ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') ++ attachmentsPath = self.getPagePath('attachments', check_create=0) ++ if not cache.needsUpdate(self._text_filename(), attachmentsPath): ++ break ++ else: + raise Exception('CacheNeedsUpdate') + + import marshal +@@ -1372,7 +1378,7 @@ + """ Format content into code, update cache and return code """ + import marshal + from MoinMoin.formatter.text_python import Formatter +- formatter = Formatter(request, ["page"], self.formatter) ++ formatter = Formatter(request, ["page", "pageparams"], self.formatter) + + # Save request state while formatting page + saved_current_lang = request.current_lang +@@ -1384,10 +1390,44 @@ + src = formatter.assemble_code(text) + code = compile(src.encode(config.charset), + self.page_name.encode(config.charset), 'exec') +- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item') ++ self.enforceCacheLimit(request) ++ # Determine whether the parameters/args need to be incorporated into the ++ # cache entry key. ++ with_params = "pageparams" in formatter.getReportedDependencies() ++ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item') + cache.update(marshal.dumps(code)) + return code + ++ def enforceCacheLimit(self, request): ++ """ Prevent too many cache entries being stored for a page """ ++ keys = caching.get_cache_list(request, self, 'item') ++ try: ++ cache_limit = int(getattr(request.cfg, 'page_cache_limit', "10")) ++ except ValueError: ++ cache_limit = 10 ++ ++ if len(keys) >= cache_limit: ++ items = [caching.CacheEntry(request, self, key, scope='item') for key in keys] ++ item_ages = [(item.mtime(), item) for item in items] ++ item_ages.sort() ++ for item_age, item in item_ages[:-cache_limit]: ++ item.remove() ++ ++ def getCacheKey(self, request, with_params=False, key=None): ++ """ Generate a cache key for a page using optional request information """ ++ key = key or self.getFormatterName(request) ++ if with_params and request.args: ++ args = request.args.items(True) ++ args.sort() ++ key_args = [] ++ for k, v in args: ++ if not (k == "action" and v == "refresh"): ++ key_args.append("%s=%s" % (k, wikiutil.url_quote(v))) ++ arg_str = "&".join(key_args) ++ if arg_str: ++ key = "%s:%s" % (key, hash_new('sha1', arg_str).hexdigest()) ++ return key ++ + def _specialPageText(self, request, special_type): + """ Output the default page content for new pages. + +diff -r 5738b78f53b5 MoinMoin/action/refresh.py +--- a/MoinMoin/action/refresh.py Sat Nov 30 20:09:43 2013 +0100 ++++ b/MoinMoin/action/refresh.py Sat Mar 29 16:23:44 2014 +0100 +@@ -14,11 +14,14 @@ + arena = request.values.get('arena', 'Page.py') + if arena == 'Page.py': + arena = Page(request, pagename) +- key = request.values.get('key', 'text_html') ++ prefix = request.values.get('key', 'text_html') + + # Remove cache entry (if exists), and send the page + from MoinMoin import caching +- caching.CacheEntry(request, arena, key, scope='item').remove() ++ keys = caching.get_cache_list(request, arena, 'item') ++ for key in keys: ++ if key.startswith(prefix): ++ caching.CacheEntry(request, arena, key, scope='item').remove() + caching.CacheEntry(request, arena, "pagelinks", scope='item').remove() + request.page.send_page() + +diff -r 5738b78f53b5 MoinMoin/formatter/text_python.py +--- a/MoinMoin/formatter/text_python.py Sat Nov 30 20:09:43 2013 +0100 ++++ b/MoinMoin/formatter/text_python.py Sat Mar 29 16:23:44 2014 +0100 +@@ -10,6 +10,7 @@ + + import time + from MoinMoin import wikiutil ++from MoinMoin.support.python_compatibility import set + + + class Formatter: +@@ -40,6 +41,12 @@ + self.text_cmd_begin = '\nrequest.write(' + self.text_cmd_end = ')\n' + ++ # Record dependency requirements of certain content ++ self.__dependencies = set() ++ ++ def getReportedDependencies(self): ++ return self.__dependencies ++ + def assemble_code(self, text): + """inserts the code into the generated text + """ +@@ -186,7 +193,10 @@ + return self.formatter.div(on, **kw) + + def macro(self, macro_obj, name, args, markup=None): +- if self.__is_static(macro_obj.get_dependencies(name)): ++ Dependencies = macro_obj.get_dependencies(name) ++ self.__dependencies.update(Dependencies) ++ ++ if self.__is_static(Dependencies): + # XXX: why is this necessary?? + macro_obj.formatter = self + return macro_obj.execute(name, args) +@@ -204,6 +214,7 @@ + Dependencies = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name, "Dependencies") + except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError): + Dependencies = self.defaultDependencies ++ self.__dependencies.update(Dependencies) + + if self.__is_static(Dependencies): + return self.formatter.parser(parser_name, lines)