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