From 7a0df5096fa3db227b6e5be475739b942d13c665 Mon Sep 17 00:00:00 2001 From: Christophe Monniez Date: Wed, 22 Jul 2020 14:16:19 +0000 Subject: [PATCH] [FIX] base: fix qweb ast validation for python 3.8.4 As of Python 3.8.4, when `ast.Name` is instantiated with either `True`, `False` and `None`, a ValueError is raised [1][2]. Because of that, QWeb views processing will crash. Replacing `ast.Name` with `ast.Constant` is the proper way to instantiate those constants, and is supported since Python 3.6.0. This fix was tested on Python 3.6, 3.7 and 3.8, and is in 14.0 already. It is now considered for backport in 13.0 because: - 13.0 still represented 75% of the new installations as of September 2020, so if left unpatched it will generate a large number of obscure errors and support tickets for our users. - Ubuntu 20.04 has started to deploy Python 3.8.5 via unattended upgrades in October 2020, replacing 3.8.2, and thus triggers the problem [4]. 1: https://docs.python.org/3/whatsnew/changelog.html#id7 2: https://bugs.python.org/issue40870 3: https://packages.ubuntu.com/focal/python3.8 backport of d73b44a46 using ast.NameConstant (available in python with https://github.com/python/cpython/commit/442f20996dcd994d1024e5cad7f66a4 and deprecated in python 3.8) because python 3.5 doesn't have ast.Constant. closes #59630 Signed-off-by: Olivier Dony (odo) --- odoo/addons/base/models/ir_qweb.py | 8 ++++---- odoo/addons/base/models/qweb.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/odoo/addons/base/models/ir_qweb.py b/odoo/addons/base/models/ir_qweb.py index 18717316f57e4..e0503dea41bae 100644 --- a/odoo/addons/base/models/ir_qweb.py +++ b/odoo/addons/base/models/ir_qweb.py @@ -431,10 +431,10 @@ def _compile_expr(self, expr): def _get_attr_bool(self, attr, default=False): if attr: if attr is True: - return ast.Name(id='True', ctx=ast.Load()) + return ast.NameConstant(True) attr = attr.lower() if attr in ('false', '0'): - return ast.Name(id='False', ctx=ast.Load()) + return ast.NameConstant(False) 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.NameConstant(True) + return ast.NameConstant(attr if attr is False else bool(default)) diff --git a/odoo/addons/base/models/qweb.py b/odoo/addons/base/models/qweb.py index 8eb7a76e7e936..8f4f0a1a93f3e 100644 --- a/odoo/addons/base/models/qweb.py +++ b/odoo/addons/base/models/qweb.py @@ -613,12 +613,12 @@ def _if_content_is_not_Falsy(self, body, orelse): ast.Compare( left=ast.Name(id='content', ctx=ast.Load()), ops=[ast.IsNot()], - comparators=[ast.Name(id='None', ctx=ast.Load())] + comparators=[ast.NameConstant(None)] ), ast.Compare( left=ast.Name(id='content', ctx=ast.Load()), ops=[ast.IsNot()], - comparators=[ast.Name(id='False', ctx=ast.Load())] + comparators=[ast.NameConstant(False)] ) ] ), @@ -1246,7 +1246,7 @@ def _compile_widget(self, el, expression, field_options): keywords=[], starargs=None, kwargs=None ), self._compile_expr0(expression), - ast.Name(id='None', ctx=ast.Load()), + ast.NameConstant(None), ], ctx=ast.Load()) ) ] @@ -1563,7 +1563,7 @@ def _compile_directive_call(self, el, options): if isinstance(key, pycompat.string_types): keys.append(ast.Str(s=key)) elif key is None: - keys.append(ast.Name(id='None', ctx=ast.Load())) + keys.append(ast.NameConstant(None)) values.append(ast.Str(s=value)) # {'nsmap': {None: 'xmlns def'}}