fix for Python 3.7
parent
357c96c057
commit
7267c6aee6
|
|
@ -195,9 +195,11 @@ class AssetsBundle(object):
|
|||
def clean_attachments(self, type):
|
||||
""" Takes care of deleting any outdated ir.attachment records associated to a bundle before
|
||||
saving a fresh one.
|
||||
|
||||
When `type` is css we need to check that we are deleting a different version (and not *any*
|
||||
version) because css may be paginated and, therefore, may produce multiple attachments for
|
||||
the same bundle's version.
|
||||
|
||||
When `type` is js we need to check that we are deleting a different version (and not *any*
|
||||
version) because, as one of the creates in `save_attachment` can trigger a rollback, the
|
||||
call to `clean_attachments ` is made at the end of the method in order to avoid the rollback
|
||||
|
|
@ -313,16 +315,22 @@ class AssetsBundle(object):
|
|||
(function (message) {
|
||||
if (window.__assetsBundleErrorSeen) return;
|
||||
window.__assetsBundleErrorSeen = true;
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
var alertTimeout = setTimeout(alert.bind(window, message), 0);
|
||||
if (typeof odoo === "undefined") return;
|
||||
|
||||
odoo.define("AssetsBundle.ErrorMessage", function (require) {
|
||||
"use strict";
|
||||
|
||||
var base = require("web_editor.base");
|
||||
var core = require("web.core");
|
||||
var Dialog = require("web.Dialog");
|
||||
|
||||
var _t = core._t;
|
||||
|
||||
clearTimeout(alertTimeout);
|
||||
|
||||
base.ready().then(function () {
|
||||
new Dialog(null, {
|
||||
title: _t("Style error"),
|
||||
|
|
@ -722,4 +730,4 @@ class LessStylesheetAsset(PreprocessedCSS):
|
|||
except IOError:
|
||||
lessc = 'lessc'
|
||||
lesspath = get_resource_path('web', 'static', 'lib', 'bootstrap', 'less')
|
||||
return [lessc, '-', '--no-js', '--no-color', '--include-path=%s' % lesspath]
|
||||
return [lessc, '-', '--no-js', '--no-color', '--include-path=%s' % lesspath]
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ from io import BytesIO
|
|||
from odoo import api, fields, models, _
|
||||
from PIL import Image
|
||||
import babel
|
||||
from lxml import etree
|
||||
|
||||
from odoo.tools import html_escape as escape, posix_to_ldml, safe_eval, float_utils, format_date, pycompat
|
||||
|
||||
import logging
|
||||
|
|
@ -252,7 +254,17 @@ class HTMLConverter(models.AbstractModel):
|
|||
|
||||
@api.model
|
||||
def value_to_html(self, value, options):
|
||||
return pycompat.to_text(value)
|
||||
irQweb = self.env['ir.qweb']
|
||||
# wrap value inside a body and parse it as HTML
|
||||
body = etree.fromstring("<body>%s</body>" % value, etree.HTMLParser(encoding='utf-8'))[0]
|
||||
# use pos processing for all nodes with attributes
|
||||
for element in body.iter():
|
||||
if element.attrib:
|
||||
attrib = OrderedDict(element.attrib)
|
||||
attrib = irQweb._post_processing_att(element.tag, attrib, options.get('template_options'))
|
||||
element.attrib.clear()
|
||||
element.attrib.update(attrib)
|
||||
return etree.tostring(body, encoding='unicode', method='html')[6:-7]
|
||||
|
||||
|
||||
class ImageConverter(models.AbstractModel):
|
||||
|
|
@ -476,7 +488,7 @@ class Contact(models.AbstractModel):
|
|||
'object': value,
|
||||
'options': options
|
||||
}
|
||||
return self.env['ir.qweb'].render('base.contact', val)
|
||||
return self.env['ir.qweb'].render('base.contact', val, **options.get('template_options'))
|
||||
|
||||
|
||||
class QwebView(models.AbstractModel):
|
||||
|
|
|
|||
|
|
@ -37,7 +37,9 @@ class IrQWeb(models.AbstractModel, QWeb):
|
|||
@api.model
|
||||
def render(self, id_or_xml_id, values=None, **options):
|
||||
""" render(id_or_xml_id, values, **options)
|
||||
|
||||
Render the template specified by the given name.
|
||||
|
||||
:param id_or_xml_id: name or etree (see get_template)
|
||||
:param dict values: template values to be used for rendering
|
||||
:param options: used to compile the template (the dict available for the rendering is frozen)
|
||||
|
|
@ -426,4 +428,4 @@ class IrQWeb(models.AbstractModel, QWeb):
|
|||
return ast.Name(id='False', ctx=ast.Load())
|
||||
elif attr in ('true', '1'):
|
||||
return ast.Name(id='True', ctx=ast.Load())
|
||||
return ast.Name(id=str(attr if attr is False else default), ctx=ast.Load())
|
||||
return ast.Name(id=str(attr if attr is False else default), ctx=ast.Load())
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import os.path
|
|||
import re
|
||||
import traceback
|
||||
|
||||
from collections import OrderedDict, Sized, Mapping, defaultdict
|
||||
from collections import OrderedDict, Sized, Mapping
|
||||
from functools import reduce
|
||||
from itertools import tee, count
|
||||
from textwrap import dedent
|
||||
|
|
@ -308,8 +308,9 @@ class QWeb(object):
|
|||
raise e
|
||||
except Exception as e:
|
||||
path = _options['last_path_node']
|
||||
node = element.getroottree().xpath(path)
|
||||
raise QWebException("Error when compiling AST", e, path, etree.tostring(node[0], encoding='unicode'), name)
|
||||
element, document = self.get_template(template, options)
|
||||
node = element.getroottree().xpath(path) if ':' not in path else None
|
||||
raise QWebException("Error when compiling AST", e, path, node and etree.tostring(node[0], encoding='unicode'), name)
|
||||
astmod.body.extend(_options['ast_calls'])
|
||||
|
||||
if 'profile' in options:
|
||||
|
|
@ -344,7 +345,7 @@ class QWeb(object):
|
|||
except Exception as e:
|
||||
path = log['last_path_node']
|
||||
element, document = self.get_template(template, options)
|
||||
node = element.getroottree().xpath(path)
|
||||
node = element.getroottree().xpath(path) if ':' not in path else None
|
||||
raise QWebException("Error to render compiling AST", e, path, node and etree.tostring(node[0], encoding='unicode'), name)
|
||||
|
||||
return _compiled_fn
|
||||
|
|
@ -694,6 +695,80 @@ class QWeb(object):
|
|||
ctx=ctx
|
||||
)
|
||||
|
||||
def _append_attributes(self):
|
||||
# t_attrs = self._post_processing_att(tagName, t_attrs, options)
|
||||
# for name, value in t_attrs.items():
|
||||
# if value or isinstance(value, string_types)):
|
||||
# append(u' ')
|
||||
# append(name)
|
||||
# append(u'="')
|
||||
# append(escape(pycompat.to_text((value)))
|
||||
# append(u'"')
|
||||
return [
|
||||
ast.Assign(
|
||||
targets=[ast.Name(id='t_attrs', ctx=ast.Store())],
|
||||
value=ast.Call(
|
||||
func=ast.Attribute(
|
||||
value=ast.Name(id='self', ctx=ast.Load()),
|
||||
attr='_post_processing_att',
|
||||
ctx=ast.Load()
|
||||
),
|
||||
args=[
|
||||
ast.Name(id='tagName', ctx=ast.Load()),
|
||||
ast.Name(id='t_attrs', ctx=ast.Load()),
|
||||
ast.Name(id='options', ctx=ast.Load()),
|
||||
], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)
|
||||
),
|
||||
ast.For(
|
||||
target=ast.Tuple(elts=[ast.Name(id='name', ctx=ast.Store()), ast.Name(id='value', ctx=ast.Store())], ctx=ast.Store()),
|
||||
iter=ast.Call(
|
||||
func=ast.Attribute(
|
||||
value=ast.Name(id='t_attrs', ctx=ast.Load()),
|
||||
attr='items',
|
||||
ctx=ast.Load()
|
||||
),
|
||||
args=[], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
),
|
||||
body=[ast.If(
|
||||
test=ast.BoolOp(
|
||||
op=ast.Or(),
|
||||
values=[
|
||||
ast.Name(id='value', ctx=ast.Load()),
|
||||
ast.Call(
|
||||
func=ast.Name(id='isinstance', ctx=ast.Load()),
|
||||
args=[
|
||||
ast.Name(id='value', ctx=ast.Load()),
|
||||
ast.Name(id='string_types', ctx=ast.Load())
|
||||
],
|
||||
keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)
|
||||
]
|
||||
),
|
||||
body=[
|
||||
self._append(ast.Str(u' ')),
|
||||
self._append(ast.Name(id='name', ctx=ast.Load())),
|
||||
self._append(ast.Str(u'="')),
|
||||
self._append(ast.Call(
|
||||
func=ast.Name(id='escape', ctx=ast.Load()),
|
||||
args=[ast.Call(
|
||||
func=ast.Name(id='to_text', ctx=ast.Load()),
|
||||
args=[ast.Name(id='value', ctx=ast.Load())], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)),
|
||||
self._append(ast.Str(u'"')),
|
||||
],
|
||||
orelse=[]
|
||||
)],
|
||||
orelse=[]
|
||||
)
|
||||
]
|
||||
|
||||
# order
|
||||
|
||||
def _directives_eval_order(self):
|
||||
|
|
@ -732,7 +807,7 @@ class QWeb(object):
|
|||
if not el.nsmap:
|
||||
unqualified_el_tag = el_tag = el.tag
|
||||
content = self._compile_directive_content(el, options)
|
||||
attrib = el.attrib
|
||||
attrib = self._post_processing_att(el.tag, el.attrib, options)
|
||||
else:
|
||||
# Etree will remove the ns prefixes indirection by inlining the corresponding
|
||||
# nsmap definition into the tag attribute. Restore the tag and prefix here.
|
||||
|
|
@ -762,6 +837,8 @@ class QWeb(object):
|
|||
else:
|
||||
attrib[key] = value
|
||||
|
||||
attrib = self._post_processing_att(el.tag, attrib, options)
|
||||
|
||||
# Update the dict of inherited namespaces before continuing the recursion. Note:
|
||||
# since `options['nsmap']` is a dict (and therefore mutable) and we do **not**
|
||||
# want changes done in deeper recursion to bevisible in earlier ones, we'll pass
|
||||
|
|
@ -870,59 +947,12 @@ class QWeb(object):
|
|||
)))
|
||||
|
||||
if attr_already_created:
|
||||
# for name, value in t_attrs.items():
|
||||
# if value or isinstance(value, basestring)):
|
||||
# append(u' ')
|
||||
# append(name)
|
||||
# append(u'="')
|
||||
# append(escape(to_text((value)))
|
||||
# append(u'"')
|
||||
body.append(ast.For(
|
||||
target=ast.Tuple(elts=[ast.Name(id='name', ctx=ast.Store()), ast.Name(id='value', ctx=ast.Store())], ctx=ast.Store()),
|
||||
iter=ast.Call(
|
||||
func=ast.Attribute(
|
||||
value=ast.Name(id='t_attrs', ctx=ast.Load()),
|
||||
attr='items',
|
||||
ctx=ast.Load()
|
||||
),
|
||||
args=[], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
),
|
||||
body=[ast.If(
|
||||
test=ast.BoolOp(
|
||||
op=ast.Or(),
|
||||
values=[
|
||||
ast.Name(id='value', ctx=ast.Load()),
|
||||
ast.Call(
|
||||
func=ast.Name(id='isinstance', ctx=ast.Load()),
|
||||
args=[
|
||||
ast.Name(id='value', ctx=ast.Load()),
|
||||
ast.Name(id='string_types', ctx=ast.Load())
|
||||
],
|
||||
keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)
|
||||
]
|
||||
),
|
||||
body=[
|
||||
self._append(ast.Str(u' ')),
|
||||
self._append(ast.Name(id='name', ctx=ast.Load())),
|
||||
self._append(ast.Str(u'="')),
|
||||
self._append(ast.Call(
|
||||
func=ast.Name(id='escape', ctx=ast.Load()),
|
||||
args=[ast.Call(
|
||||
func=ast.Name(id='to_text', ctx=ast.Load()),
|
||||
args=[ast.Name(id='value', ctx=ast.Load())], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)], keywords=[],
|
||||
starargs=None, kwargs=None
|
||||
)),
|
||||
self._append(ast.Str(u'"')),
|
||||
],
|
||||
orelse=[]
|
||||
)],
|
||||
orelse=[]
|
||||
))
|
||||
# tagName = $el.tag
|
||||
body.append(ast.Assign(
|
||||
targets=[ast.Name(id='tagName', ctx=ast.Store())],
|
||||
value=ast.Str(el.tag))
|
||||
)
|
||||
body.extend(self._append_attributes())
|
||||
|
||||
return body
|
||||
|
||||
|
|
@ -1512,6 +1542,14 @@ class QWeb(object):
|
|||
atts = OrderedDict(atts)
|
||||
return atts
|
||||
|
||||
def _post_processing_att(self, tagName, atts, options):
|
||||
""" Method called by the compiled code. This method may be overwrited
|
||||
to filter or modify the attributes after they are compiled.
|
||||
|
||||
@returns OrderedDict
|
||||
"""
|
||||
return atts
|
||||
|
||||
def _get_field(self, record, field_name, expression, tagName, field_options, options, values):
|
||||
"""
|
||||
:returns: tuple:
|
||||
|
|
|
|||
Loading…
Reference in New Issue