fix for Python 3.7

develop
Andreas Osim 2020-04-14 11:11:42 +02:00
parent 357c96c057
commit 7267c6aee6
4 changed files with 122 additions and 62 deletions

View File

@ -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"),

View File

@ -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):

View File

@ -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)

View File

@ -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
# tagName = $el.tag
body.append(ast.Assign(
targets=[ast.Name(id='tagName', ctx=ast.Store())],
value=ast.Str(el.tag))
)
]
),
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=[]
))
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: