1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/patches/patch-cache-pageparams-1.9.diff Sat Mar 29 19:32:26 2014 +0100
1.3 @@ -0,0 +1,167 @@
1.4 +diff -r 5738b78f53b5 MoinMoin/Page.py
1.5 +--- a/MoinMoin/Page.py Sat Nov 30 20:09:43 2013 +0100
1.6 ++++ b/MoinMoin/Page.py Sat Mar 29 16:23:44 2014 +0100
1.7 +@@ -41,6 +41,7 @@
1.8 +
1.9 + from MoinMoin import config, caching, user, util, wikiutil
1.10 + from MoinMoin.logfile import eventlog
1.11 ++from MoinMoin.support.python_compatibility import hash_new
1.12 +
1.13 + def is_cache_exception(e):
1.14 + args = e.args
1.15 +@@ -1254,15 +1255,17 @@
1.16 + request.formatter = old_formatter
1.17 +
1.18 +
1.19 +- def getFormatterName(self):
1.20 ++ def getFormatterName(self, request=None):
1.21 + """ Return a formatter name as used in the caching system
1.22 +
1.23 ++ @param request: the active request (optional)
1.24 + @rtype: string
1.25 + @return: formatter name as used in caching
1.26 + """
1.27 +- if not hasattr(self, 'formatter') or self.formatter is None:
1.28 ++ formatter = getattr(self, 'formatter', None) or request and getattr(request, 'formatter', None)
1.29 ++ if not formatter:
1.30 + return ''
1.31 +- module = self.formatter.__module__
1.32 ++ module = formatter.__module__
1.33 + return module[module.rfind('.') + 1:]
1.34 +
1.35 + def canUseCache(self, parser=None):
1.36 +@@ -1351,9 +1354,12 @@
1.37 +
1.38 + def loadCache(self, request):
1.39 + """ Return page content cache or raises 'CacheNeedsUpdate' """
1.40 +- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item')
1.41 +- attachmentsPath = self.getPagePath('attachments', check_create=0)
1.42 +- if cache.needsUpdate(self._text_filename(), attachmentsPath):
1.43 ++ for with_params in (True, False):
1.44 ++ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item')
1.45 ++ attachmentsPath = self.getPagePath('attachments', check_create=0)
1.46 ++ if not cache.needsUpdate(self._text_filename(), attachmentsPath):
1.47 ++ break
1.48 ++ else:
1.49 + raise Exception('CacheNeedsUpdate')
1.50 +
1.51 + import marshal
1.52 +@@ -1372,7 +1378,7 @@
1.53 + """ Format content into code, update cache and return code """
1.54 + import marshal
1.55 + from MoinMoin.formatter.text_python import Formatter
1.56 +- formatter = Formatter(request, ["page"], self.formatter)
1.57 ++ formatter = Formatter(request, ["page", "pageparams"], self.formatter)
1.58 +
1.59 + # Save request state while formatting page
1.60 + saved_current_lang = request.current_lang
1.61 +@@ -1384,10 +1390,44 @@
1.62 + src = formatter.assemble_code(text)
1.63 + code = compile(src.encode(config.charset),
1.64 + self.page_name.encode(config.charset), 'exec')
1.65 +- cache = caching.CacheEntry(request, self, self.getFormatterName(), scope='item')
1.66 ++ self.enforceCacheLimit(request)
1.67 ++ # Determine whether the parameters/args need to be incorporated into the
1.68 ++ # cache entry key.
1.69 ++ with_params = "pageparams" in formatter.getReportedDependencies()
1.70 ++ cache = caching.CacheEntry(request, self, self.getCacheKey(request, with_params), scope='item')
1.71 + cache.update(marshal.dumps(code))
1.72 + return code
1.73 +
1.74 ++ def enforceCacheLimit(self, request):
1.75 ++ """ Prevent too many cache entries being stored for a page """
1.76 ++ keys = caching.get_cache_list(request, self, 'item')
1.77 ++ try:
1.78 ++ cache_limit = int(getattr(request.cfg, 'page_cache_limit', "10"))
1.79 ++ except ValueError:
1.80 ++ cache_limit = 10
1.81 ++
1.82 ++ if len(keys) >= cache_limit:
1.83 ++ items = [caching.CacheEntry(request, self, key, scope='item') for key in keys]
1.84 ++ item_ages = [(item.mtime(), item) for item in items]
1.85 ++ item_ages.sort()
1.86 ++ for item_age, item in item_ages[:-cache_limit]:
1.87 ++ item.remove()
1.88 ++
1.89 ++ def getCacheKey(self, request, with_params=False, key=None):
1.90 ++ """ Generate a cache key for a page using optional request information """
1.91 ++ key = key or self.getFormatterName(request)
1.92 ++ if with_params and request.args:
1.93 ++ args = request.args.items(True)
1.94 ++ args.sort()
1.95 ++ key_args = []
1.96 ++ for k, v in args:
1.97 ++ if not (k == "action" and v == "refresh"):
1.98 ++ key_args.append("%s=%s" % (k, wikiutil.url_quote(v)))
1.99 ++ arg_str = "&".join(key_args)
1.100 ++ if arg_str:
1.101 ++ key = "%s:%s" % (key, hash_new('sha1', arg_str).hexdigest())
1.102 ++ return key
1.103 ++
1.104 + def _specialPageText(self, request, special_type):
1.105 + """ Output the default page content for new pages.
1.106 +
1.107 +diff -r 5738b78f53b5 MoinMoin/action/refresh.py
1.108 +--- a/MoinMoin/action/refresh.py Sat Nov 30 20:09:43 2013 +0100
1.109 ++++ b/MoinMoin/action/refresh.py Sat Mar 29 16:23:44 2014 +0100
1.110 +@@ -14,11 +14,14 @@
1.111 + arena = request.values.get('arena', 'Page.py')
1.112 + if arena == 'Page.py':
1.113 + arena = Page(request, pagename)
1.114 +- key = request.values.get('key', 'text_html')
1.115 ++ prefix = request.values.get('key', 'text_html')
1.116 +
1.117 + # Remove cache entry (if exists), and send the page
1.118 + from MoinMoin import caching
1.119 +- caching.CacheEntry(request, arena, key, scope='item').remove()
1.120 ++ keys = caching.get_cache_list(request, arena, 'item')
1.121 ++ for key in keys:
1.122 ++ if key.startswith(prefix):
1.123 ++ caching.CacheEntry(request, arena, key, scope='item').remove()
1.124 + caching.CacheEntry(request, arena, "pagelinks", scope='item').remove()
1.125 + request.page.send_page()
1.126 +
1.127 +diff -r 5738b78f53b5 MoinMoin/formatter/text_python.py
1.128 +--- a/MoinMoin/formatter/text_python.py Sat Nov 30 20:09:43 2013 +0100
1.129 ++++ b/MoinMoin/formatter/text_python.py Sat Mar 29 16:23:44 2014 +0100
1.130 +@@ -10,6 +10,7 @@
1.131 +
1.132 + import time
1.133 + from MoinMoin import wikiutil
1.134 ++from MoinMoin.support.python_compatibility import set
1.135 +
1.136 +
1.137 + class Formatter:
1.138 +@@ -40,6 +41,12 @@
1.139 + self.text_cmd_begin = '\nrequest.write('
1.140 + self.text_cmd_end = ')\n'
1.141 +
1.142 ++ # Record dependency requirements of certain content
1.143 ++ self.__dependencies = set()
1.144 ++
1.145 ++ def getReportedDependencies(self):
1.146 ++ return self.__dependencies
1.147 ++
1.148 + def assemble_code(self, text):
1.149 + """inserts the code into the generated text
1.150 + """
1.151 +@@ -186,7 +193,10 @@
1.152 + return self.formatter.div(on, **kw)
1.153 +
1.154 + def macro(self, macro_obj, name, args, markup=None):
1.155 +- if self.__is_static(macro_obj.get_dependencies(name)):
1.156 ++ Dependencies = macro_obj.get_dependencies(name)
1.157 ++ self.__dependencies.update(Dependencies)
1.158 ++
1.159 ++ if self.__is_static(Dependencies):
1.160 + # XXX: why is this necessary??
1.161 + macro_obj.formatter = self
1.162 + return macro_obj.execute(name, args)
1.163 +@@ -204,6 +214,7 @@
1.164 + Dependencies = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name, "Dependencies")
1.165 + except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError):
1.166 + Dependencies = self.defaultDependencies
1.167 ++ self.__dependencies.update(Dependencies)
1.168 +
1.169 + if self.__is_static(Dependencies):
1.170 + return self.formatter.parser(parser_name, lines)