-
Notifications
You must be signed in to change notification settings - Fork 63
[IMP] adapt code to new simplified safe_eval
API
#265
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[IMP] adapt code to new simplified safe_eval
API
#265
Conversation
upgradeci retry with always only hr in all versions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Minimal comment.
963dd2a
to
decb2d7
Compare
decb2d7
to
5b158c9
Compare
This commit simplifies `safe_eval` which, up until now, allowed passing global and local namespaces. There is no usecase for this anymore. We want safe_eval exec mode to behave like a top-level module scope. `nocopy` is not needed anymore either. It's a relic of when the context could be dynamic (e.g. for already deleted `RecordDictWrapper` or `QWebContext`). Passed in context is always a dict. It will always be mutated with the local eval namespace dict after evaluation. This all makes `safe_eval` API less confusing. See: odoo/enterprise#83818 See: odoo/upgrade-util#265 task-4378806
af3d7ff
to
f0bf867
Compare
This commit simplifies `safe_eval` which, up until now, allowed passing global and local namespaces. There is no usecase for this anymore. We want safe_eval exec mode to behave like a top-level module scope. `nocopy` is not needed anymore either. It's a relic of when the context could be dynamic (e.g. for already deleted `RecordDictWrapper` or `QWebContext`). Passed in context is always a dict. It will always be mutated with the local eval namespace dict after evaluation. This all makes `safe_eval` API less confusing. See: odoo/enterprise#83818 See: odoo/upgrade-util#265 task-4378806
`safe_eval` loose the `nocopy` option. As we rely on it when evaluating expression, we need to reimplement `safe_eval` to do the evaluation using the `SelfPrintEvalContext`. See odoo/odoo#206846 See odoo/enterprise#83818
f0bf867
to
fc5d99f
Compare
if version_gte("saas~18.4"): | ||
import odoo.tools.safe_eval as _safe_eval_mod | ||
|
||
def safe_eval(expr, context=None): | ||
if context is None: | ||
context = SelfPrintEvalContext() | ||
|
||
assert isinstance(expr, (str, bytes)) | ||
assert isinstance(context, SelfPrintEvalContext) | ||
|
||
c = _safe_eval_mod.test_expr(expr, _safe_eval_mod._SAFE_OPCODES, mode="eval", filename=None) | ||
context["__builtins__"] = dict(_safe_eval_mod._BUILTINS) | ||
try: | ||
return _safe_eval_mod.unsafe_eval(c, context, None) | ||
except _safe_eval_mod._BUBBLEUP_EXCEPTIONS: | ||
raise | ||
except Exception as e: | ||
raise ValueError("{!r} while evaluating\n{!r}".format(e, expr)) | ||
finally: | ||
del context["__builtins__"] | ||
else: | ||
try: | ||
from odoo.tools.safe_eval import safe_eval as _safe_eval_func | ||
except ImportError: | ||
from openerp.tools.safe_eval import safe_eval as _safe_eval_func | ||
|
||
def safe_eval(expr, context=None): | ||
if context is None: | ||
context = SelfPrintEvalContext() | ||
assert isinstance(context, SelfPrintEvalContext) | ||
|
||
return _safe_eval_func(expr, context, nocopy=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't we assert in both cases that expr is str ot bytes?
If we can assert it in both then I'd suggest we move the shared part to a toplevel safe_eval
that then calls _safe_eval_impl
with bot expr and context mandatory. Sort of:
if version_gte("saas~18.4"):
import odoo.tools.safe_eval as _safe_eval_mod
def _safe_eval_impl(expr, context):
c = _safe_eval_mod.test_expr(expr, _safe_eval_mod._SAFE_OPCODES, mode="eval", filename=None)
context["__builtins__"] = dict(_safe_eval_mod._BUILTINS)
try:
return _safe_eval_mod.unsafe_eval(c, context, None)
except _safe_eval_mod._BUBBLEUP_EXCEPTIONS:
raise
except Exception as e:
raise ValueError("{!r} while evaluating\n{!r}".format(e, expr))
finally:
del context["__builtins__"]
else:
try:
from odoo.tools.safe_eval import safe_eval as _safe_eval_func
except ImportError:
from openerp.tools.safe_eval import safe_eval as _safe_eval_func
def _safe_eval_impl(expr, context):
return _safe_eval_func(expr, context, nocopy=True)
def safe_eval(expr, context=None):
if context is None:
context = SelfPrintEvalContext()
assert isinstance(expr, (str, bytes))
assert isinstance(context, SelfPrintEvalContext)
return _safe_eval_impl(expr, context)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually compile already checks the type of the source here. It's can either be a string, bytesarray or AST. We already check that the source object is not a codeobject, so I think the assert isinstance(expr, (str, bytes))
is not really needed here
@@ -350,7 +349,7 @@ def adapter(leaf, is_or, negated): | |||
) | |||
for alias_id, defaults_s in cr.fetchall(): | |||
try: | |||
defaults = dict(safe_eval(defaults_s)) # XXX literal_eval should works. | |||
defaults = dict(literal_eval(defaults_s)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential change of behaviour, LGTM just flagging it it new errors start appearing after the merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is OK to merge. Optional comment for extra checks (isinstance) grouped in one place, the rest looks good to me.
@robodoo r+ |
This commit simplifies `safe_eval` which, up until now, allowed passing global and local namespaces. There is no usecase for this anymore. We want safe_eval exec mode to behave like a top-level module scope. `nocopy` is not needed anymore either. It's a relic of when the context could be dynamic (e.g. for already deleted `RecordDictWrapper` or `QWebContext`). Passed in context is always a dict. It will always be mutated with the local eval namespace dict after evaluation. This all makes `safe_eval` API less confusing. See: odoo/enterprise#83818 See: odoo/upgrade-util#265 task-4378806 closes #206846 Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This commit simplifies `safe_eval` which, up until now, allowed passing global and local namespaces. There is no usecase for this anymore. We want safe_eval exec mode to behave like a top-level module scope. `nocopy` is not needed anymore either. It's a relic of when the context could be dynamic (e.g. for already deleted `RecordDictWrapper` or `QWebContext`). Passed in context is always a dict. It will always be mutated with the local eval namespace dict after evaluation. This all makes `safe_eval` API less confusing. See: odoo/enterprise#83818 See: odoo/upgrade-util#265 task-4378806 closes odoo#206846 Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This commit simplifies `safe_eval` which, up until now, allowed passing global and local namespaces. There is no usecase for this anymore. We want safe_eval exec mode to behave like a top-level module scope. `nocopy` is not needed anymore either. It's a relic of when the context could be dynamic (e.g. for already deleted `RecordDictWrapper` or `QWebContext`). Passed in context is always a dict. It will always be mutated with the local eval namespace dict after evaluation. This all makes `safe_eval` API less confusing. See: odoo/enterprise#83818 See: odoo/upgrade-util#265 task-4378806 closes odoo#206846 Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
safe_eval
loose thenocopy
option. As we rely on it when evaluating expression, we need to reimplementsafe_eval
to do the evaluation using theSelfPrintEvalContext
.See odoo/odoo#206846
See odoo/enterprise#83818