From 9631a30228e78f8cf1405e28b8415936337fcd55 Mon Sep 17 00:00:00 2001 From: Simon Lejeune Date: Mon, 29 Feb 2016 14:52:30 +0100 Subject: [PATCH] [FIX] ir_qweb: don't use a stylesheet cached by another bundle. An issue could arise if a preprocessed stylesheet asset is present in multiple bundles: the first bundle will cache a version of this file (identified by its url) and the second one will cache another one. The next time the first bundle is rendered in debug mode, it will use the last created record of the asset. This could lead to design issues as, for instance, a less asset could change according to another less asset included in the bundle. We fix this issue by adding the xmlid of the bundle in the url's asset. This fix another inconsistency as the compiled version of an asset is reachable with an url that is not dependent of its bundle, so if the asset is present in multiple bundle it could return different values. Note: this only concern the debug mode --- openerp/addons/base/ir/ir_qweb.py | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py index e3114470c24..e7776161737 100644 --- a/openerp/addons/base/ir/ir_qweb.py +++ b/openerp/addons/base/ir/ir_qweb.py @@ -1340,7 +1340,7 @@ class AssetsBundle(object): preprocessed = True for atype in (SassStylesheetAsset, LessStylesheetAsset): outdated = False - assets = dict((asset.html_url % asset.url, asset) for asset in self.stylesheets if isinstance(asset, atype)) + assets = dict((asset.html_url, asset) for asset in self.stylesheets if isinstance(asset, atype)) if assets: assets_domain = [('url', 'in', assets.keys())] ira_ids = self.registry['ir.attachment'].search(self.cr, uid, assets_domain) @@ -1391,7 +1391,7 @@ class AssetsBundle(object): try: ira = self.registry['ir.attachment'] fname = os.path.basename(asset.url) - url = asset.html_url % asset.url + url = asset.html_url with self.cr.savepoint(): ira.create(self.cr, openerp.SUPERUSER_ID, dict( datas=asset.content.encode('utf8').encode('base64'), @@ -1455,13 +1455,14 @@ class AssetsBundle(object): return error class WebAsset(object): - html_url = '%s' + html_url_format = '%s' def __init__(self, bundle, inline=None, url=None): self.id = str(uuid.uuid4()) self.bundle = bundle self.inline = inline self.url = url + self.html_url_args = url self.cr = bundle.cr self.uid = bundle.uid self.registry = bundle.registry @@ -1474,6 +1475,10 @@ class WebAsset(object): if not inline and not url: raise Exception("An asset should either be inlined or url linked") + @property + def html_url(self): + return self.html_url_format % self.html_url_args + def stat(self): if not (self.inline or self._filename or self._ir_attach): path = filter(None, self.url.split('/')) @@ -1552,7 +1557,7 @@ class JavascriptAsset(WebAsset): def to_html(self): if self.url: - return '' % (self.html_url % self.url) + return '' % (self.html_url) else: return '' % self.with_header() @@ -1612,15 +1617,19 @@ class StylesheetAsset(WebAsset): def to_html(self): media = (' media="%s"' % werkzeug.utils.escape(self.media)) if self.media else '' if self.url: - href = self.html_url % self.url + href = self.html_url return '' % (href, media) else: return '' % (media, self.with_header()) class PreprocessedCSS(StylesheetAsset): - html_url = '%s.css' rx_import = None + def __init__(self, *args, **kw): + super(PreprocessedCSS, self).__init__(*args, **kw) + self.html_url_format = '%%s/%s/%%s.css' % self.bundle.xmlid + self.html_url_args = tuple(self.url.rsplit('/', 1)) + def minify(self): return self.with_header()